1<?php
2if(!defined('DOKU_INC')) die();
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
4require_once(DOKU_PLUGIN.'syntax.php');
5
6class syntax_plugin_pubchem extends DokuWiki_Syntax_Plugin {
7  var $ncbi;
8  var $imgCache;
9  var $xmlCache;
10  var $summaryURL='';
11  var $downloadURL='';
12  var $chemProperty = array();
13
14  function syntax_plugin_pubchem(){
15    $this->name = 'pubchem';
16    if (!class_exists('plugin_cache'))
17        @require_once(DOKU_PLUGIN.$this->name.'/classes/cache.php');
18    if (!class_exists('rcsb')||!class_exists('ncbi')||!class_exists('xml'))
19        @require_once(DOKU_PLUGIN.$this->name.'/classes/sciencedb.php');
20    $this->ncbi        = new ncbi();
21    $this->imgCache    = new plugin_cache($this->name,'',"png");
22    $this->xmlCache    = new plugin_cache($this->name,'',"xml.gz");
23
24    $this->summaryURL  = 'http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=';
25    $this->downloadURL = 'http://pubchem.ncbi.nlm.nih.gov/image/imgsrv.fcgi?t=%s&cid=%s';
26  }
27  function getType(){ return 'substition'; }
28  function getSort(){ return 159; }
29
30  // Connect
31  function connectTo($mode){
32    $this->Lexer->addSpecialPattern('\{\{pubchem>[^}]*\}\}',$mode,'plugin_pubchem');
33  }
34
35  // Handling lexer
36  function handle($match, $state, $pos, Doku_Handler $handler){
37    $match = substr($match,10,-2);
38    return array($state,explode(':',$match));
39  }
40
41/**
42  * Render PubChem image and link
43  */
44  function render($mode, Doku_Renderer $renderer, $data){
45    if ($mode!='xhtml') return false;
46    global $pubchem_cache;
47    if(!is_array($pubchem_cache)) $pubchem_cache=array();
48
49    list($state, $match) = $data;
50    list($cmd,$cid) = $match;
51    $cmd = strtolower($cmd);
52    if(strpos($cid,'|')!==false){
53      list($cid,$title)=explode('|',$cid);
54    }
55    // Commands without CID
56    switch($cmd){
57        case 'searchbox':
58            $renderer->doc .= file_get_contents(DOKU_PLUGIN.$this->name.'/pubchem_search_box.htm').NL;
59            return true;
60        case 'clear':
61            $this->xmlCache->ClearCache();
62            $renderer->doc .= 'Cleared.';
63            return true;
64        case 'remove_dir':
65            $this->xmlCache->RemoveDir();
66            $renderer->doc .= 'Directory cleared.';
67            return true;
68        default:
69            if(!$cid){
70              $renderer->doc.='<div class="plugin_cmd">'.sprintf($this->getLang('plugin_cmd_not_found'),$cmd).'</div>';
71              return true;
72            }
73     }
74    // Commands with CID
75    if (!is_numeric($cid)){
76        $renderer->doc .= sprintf($this->getLang('pubchem_invalid_cid'),$cid);
77        return false;
78    }
79    if(!is_array($pubchem_cache[$cid])) $this->getProperties($cid);
80    switch($cmd){
81        case 'link':
82            $renderer->doc .= '<a target=_blank ';
83            $renderer->doc .= 'href="'.$this->summaryURL.$cid.'" title="Go to PubChem site" class="pubchem_link">'.$cid.'</a>'.NL;
84            return true;
85        case 'summaryxml':
86            $xml = $this->getPubchemXml($cid);
87            if ($xml===false){return true;}
88            $renderer->doc .= '<pre>'.htmlspecialchars($xml).'</pre>';
89            return true;
90        case 'iupac':
91            $renderer->doc.= $pubchem_cache[$cid]['iupac'];
92            return true;
93        case 'formula':
94            $renderer->doc.=$pubchem_cache[$cid]['formula'];
95            return true;
96        case 'mw':
97            $renderer->doc.=$pubchem_cache[$cid]['weight'];
98            return true;
99        case 'xlogp':
100            $renderer->doc.=$pubehcm_cache[$cid]['xlogp'];
101            return true;
102        default:
103            $mode = $cmd[0]; // s or l
104            $id = $cid.$mode;
105            $filename = $this->imgCache->GetMediaPath($id);
106            if(!is_readable($filename)){
107                $url = sprintf($this->downloadURL,$mode,$cid);
108                io_download($url,$filename);
109            }
110            if(strpos($cmd,'template')!==false){
111                if (empty($pubchem_cache[$cid]['iupac'])){
112                    $this->getProperties($cid);
113                }
114                $renderer->doc.='<div class="left" style="padding:10px;">';
115                $renderer->table_open(2);
116                $this->_name_row($renderer,$cid,$pubchem_cache[$cid]['iupac'],$title);
117                $this->_row($renderer,$this->getLang('mol_formula'),$pubchem_cache[$cid]['formula']);
118                $this->_row($renderer,$this->getLang('mol_weight'),$pubchem_cache[$cid]['weight']);
119                $this->_row($renderer,'LogP',$pubchem_cache[$cid]['xlogp']);
120                $renderer->table_close();
121                $renderer->doc.='</div><div class="left">';
122                $renderer->doc .= $this->getImageHtml($cid,$mode);
123                $renderer->doc.='</div><div class="clearfix"></div>'.DOKU_LF;
124            }else{
125                $renderer->doc .= $this->getImageHtml($cid,$mode);
126            }
127            return true;
128    }
129    // Command was not found..
130    $renderer->doc.='<div class="plugin_cmd">'.sprintf($this->getLang('plugin_cmd_not_found'),$cmd).'</div>';
131    return true;
132  }
133
134/**
135  * Get PubChem image description
136  */
137  function getImageHtml($cid,$mode){
138        $tag .= '<div class="pubchem_imgbox"><a href="'.$this->summaryURL.$cid.'" target=_blank>';
139        $tag .= '<img src = "'.$this->imgCache->GetMediaLink($cid.$mode).'" class="media" ';
140        $tag .= 'alt="PubChem image '.$cid.'" ';
141        $tag .= 'title="CID:'.$cid.'  Click to PubChem page"/></a></div>';
142        return $tag;
143  }
144
145 /**
146  * Get properties from XML data
147  * @param string $cid
148  * @return boolean
149  */
150  function getProperties($cid){
151    $xml = $this->getPubchemXml($cid);
152    if ($xml===false){return true;}
153    $x = new Xml;
154    $XmlClass = $x->GetXmlObject($xml);
155    $xmls = $XmlClass[0]->next;
156    for($i=0;$i<count($xmls);$i++){
157      if ($xmls[$i]->tag=="PC-Compound_props"){
158        $props = $xmls[$i]->next;
159        for($j=0;$j<count($props);$j++){
160          $infodata = $props[$j]->next;
161
162          $info_name1 = $infodata[0]->next[0]->next[0]->value;
163          $info_name2 = $infodata[0]->next[0]->next[1]->value;
164          $info_value = $infodata[1]->next[0]->value;
165
166          switch($info_name1){
167            case "Molecular Formula":
168              $this->chemProperty[$cid]['formula']=$this->getChemFormat($info_value);
169              break;
170            case "IUPAC Name":
171              if ($info_name2=="Preferred"||$info_name2=="Allowed"){
172                if(strlen($info_value)>50){ $info_value = str_replace("-","- ",$info_value);}
173                $this->chemProperty[$cid]['iupac'] = $info_value;
174              }
175              break;
176            case "Molecular Weight":
177              $this->chemProperty[$cid]['weight'] = $info_value;
178              break;
179            case "Log P":
180              $this->chemProperty[$cid]['xlogp'] = $info_value;
181              break;
182            case "SMILES":
183              $this->chemProperty[$cid]['smiles'] = $info_value;
184              break;
185          }
186        }
187      }
188    }
189    global $pubchem_cache;
190    $pubchem_cache[$cid] = $this->chemProperty[$cid];
191  }
192 /**
193  * Get PubChem XML
194  */
195  function getPubchemXml($cid){
196    global $conf;
197    $xml = $this->ncbi->GetPubchemXml($cid);
198    if (!empty($xml)){
199      $filepath = $this->xmlCache->GetMediaPath($cid);
200      if(io_saveFile($filepath,$xml)){
201        chmod($filepath,$conf['fmode']);
202      }
203      return $xml;
204    }else{
205      return false;
206    }
207  }
208 /**
209  * Get chemical format.
210  */
211  function getChemFormat($raw){
212    $pattern = array("/[\|]?([0-9]*\+|[0-9]*\-)/","/([A-Z]|[A-Z][a-z]|\)|\])([0-9]+)/");
213    $replace = array("<sup>\${1}</sup>","\${1}<sub>\${2}</sub>");
214    return preg_replace($pattern,$replace,$raw);
215  }
216  /**
217   * table name row for a template
218   * @param Doku_Renderer $renderer
219   * @param string $cid
220   * @param string $iupac
221   * @param string $title
222   */
223  function _name_row(&$renderer,$cid,$iupac='',$title=''){
224      $renderer->tablerow_open();
225      $renderer->tableheader_open();
226      $renderer->doc.=($title!='')?$this->getLang('mol_name'):'CID';
227      $renderer->tableheader_close();
228      $renderer->tablecell_open();
229      $renderer->doc.=($title!='')?$title:$cid;
230      if($iupac){
231          $renderer->footnote_open();
232          $renderer->doc.=$iupac;
233          $renderer->footnote_close();
234      }
235      $renderer->tablecell_close();
236      $renderer->tablerow_close();
237  }
238
239  /**
240   * Render table row for a template
241   * @param Doku_Renderer $renderer
242   * @param string $head
243   * @param string $cell
244   */
245  function _row(&$renderer,$head,$cell){
246      if(empty($cell))return;
247      $renderer->tablerow_open();
248      $renderer->tableheader_open();
249      $renderer->doc.=$head;
250      $renderer->tableheader_close();
251      $renderer->tablecell_open();
252      $renderer->doc.=$cell;
253      $renderer->tablecell_close();
254      $renderer->tablerow_close();
255  }
256
257}
258?>
259