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