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