1<?php 2/** 3 * DokuWiki ApexCharts Plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Karl Nickel <kazozaagir@gmail.com> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12class syntax_plugin_achart extends DokuWiki_Syntax_Plugin { 13 /** 14 * @return string Syntax mode type 15 */ 16 public function getType() { 17 return 'substition'; 18 } 19 /** 20 * @return string Paragraph type 21 */ 22 public function getPType() { 23 return 'block'; 24 } 25 /** 26 * @return int Sort order - Low numbers go before high numbers 27 */ 28 public function getSort() { 29 return 200; 30 } 31 32 /** 33 * Connect lookup pattern to lexer. 34 * 35 * @param string $mode Parser mode 36 */ 37 public function connectTo($mode) { 38 $this->Lexer->addSpecialPattern('<achart.+?</achart>',$mode,'plugin_achart'); 39 } 40 41 /** 42 * Handle matches of the achart syntax 43 * 44 * @param string $match The match of the syntax 45 * @param int $state The state of the handler 46 * @param int $pos The position in the document 47 * @param Doku_Handler $handler The handler 48 * @return array Data for the renderer 49 */ 50 public function handle($match, $state, $pos, Doku_Handler $handler){ 51 $match = substr(trim($match), 7, -10); 52 list($opts, $adata) = explode('>', $match, 2); 53 preg_match_all('/(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?/', $opts, $matches, PREG_SET_ORDER); 54 $opts = array( 55 'width' => $this->getConf('width'), 56 'height' => $this->getConf('height'), 57 'align' => $this->getConf('align'), 58 'url' => null, 59 ); 60 foreach($matches as $m) { 61 $opts[strtolower($m[1])] = $m[2]; 62 } 63 64 $adata = preg_replace_callback( 65 '#//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"#ms', 66 function($matches){ 67 $m = $matches[0]; 68 return substr($m, 0, 1)==='/' ? ' ' : $m; 69 }, $adata 70 ); // remove comments (respecting quoted strings) 71 $adata = explode("\n", $adata); 72 $adata = implode("", array_map('trim', $adata)); 73 $chartid = uniqid('__achart_'); 74 //$adata = base64_encode($adata); 75 76 return array($chartid, $adata, $opts); 77 } 78 79 /** 80 * Render xhtml output or metadata 81 * 82 * @param string $mode Renderer mode (supported modes: xhtml) 83 * @param Doku_Renderer $renderer The renderer 84 * @param array $data The data from the handler() function 85 * @return bool If rendering was successful. 86 */ 87 public function render($mode, Doku_Renderer $renderer, $data) { 88 if($mode != 'xhtml') return false; 89 90 list($chartid, $adata, $opts) = $data; 91 $resize = ''; 92 $align = ''; 93 $file = ''; 94 foreach($opts as $n => $v) { 95 if(in_array($n, array('width','height')) && $v) { 96 $resize .= $n.':'.hsc($v).';'; 97 } elseif($n=='align' && in_array($v, array('left','right','center'))) { 98 $align = 'media'.$v; 99 } elseif ($n=='url' && $v) { 100 $file = $v; 101 } 102 } 103 104 if (!empty($file)) { 105 // Check for csv files 106 if($file !== '' && !preg_match('/^https?:\/\//i', $file)) { 107 $file = cleanID($file); 108 if(!strlen(getNS($file))) { 109 $file = $INFO['namespace'] . ':' . $file; 110 } 111 } 112 // Load csv files 113 if(preg_match('/^https?:\/\//i', $file)) { 114 $http = new DokuHTTPClient(); 115 $content = $http->get($file); 116 try { 117 if($content === false) 118 throw new \Exception('Chart cannot be displayed ! Failed to fetch remote CSV file'); 119 } catch (\Exception $e) { 120 msg(hsc($e->getMessage()), -1); 121 return false; 122 } 123 } else { 124 $fileNS = getNS($file); 125 $file = mediaFN($file); 126 try { 127 if(auth_quickaclcheck($fileNS . ':*') < AUTH_READ) 128 throw new \Exception('Chart cannot be displayed ! Access denied to CSV file'); 129 if(!file_exists($file)) 130 throw new \Exception('Chart cannot be displayed ! Requested local CSV file does not exist'); 131 } catch (\Exception $e) { 132 msg(hsc($e->getMessage()), -1); 133 return false; 134 } 135 } 136 // If not valid UTF-8 is given we assume ISO-8859-1 137 if(!utf8_check($file)) $file = utf8_encode($file); 138 /* 139 * Converts CSV to JSON 140 */ 141 //Read the csv and return as array 142 error_reporting(0); 143 $data = array_map('str_getcsv', file($file)); 144 //Get the first raw as the key 145 $keys = array_shift($data); 146 //Add label to each value 147 $newArray = array_map(function($values) use ($keys){ 148 return array_combine($keys, $values); 149 }, $data); 150 151 // Print it out as JSON 152 $csvData[]= array_combine(array('data'),array($newArray)); 153 //Remove on given data in syntax{.....} 154 $newAdata=substr($adata, 1, strlen($adata) - 2); 155 $jsonData = array('series'=> $csvData,'config'=>$newAdata); 156 #unset($jsondata['config']); 157 $newJson=json_encode($jsonData,JSON_NUMERIC_CHECK); 158 $newJson = preg_replace(array('/("series")/i') , "series",$newJson); 159 $newJson = preg_replace(array('/("data")/i') , "data",$newJson); 160 $newJson = preg_replace(array('/("config":")/i') , "",$newJson); 161 $newJson = preg_replace(array('/(}")/i') , "}",$newJson); 162 //Remove escaping slashes 163 $newJson = str_replace('\\','',$newJson); 164 } 165 166 #print_r ($newJson); 167 if(!empty($file)) {$chartData = $newJson;} else {$chartData = $adata;}; 168 if($align) $resize = ' style="'.$resize.'padding: 2px;border: 1px solid #eee;margin:3px 2px;"'; 169 if($ClassAttr) $ClassAttr = ' class="'.$ClassAttr.'"'; 170 171 $renderer->doc .= '<div id="'.$chartid.'"'.$ClassAttr.$resize.' data-achart="'.base64_encode($chartData).'"></div>'."\n"; 172 173 return true; 174 } 175} 176