1<?php 2/** 3 * DokuWiki Plugin Clipboard Utils 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)* 6 * @author Jean-Marc Boulade <jean-marc@boulade.com> 7 * @version 2021-09-08 8 */ 9 10// must be run within Dokuwiki 11if ( !defined( 'DOKU_INC' ) ) die(); 12//dbglog(sprintf("LOADING '%s'\n",__FILE__)); 13 14if ( !defined( 'DOKU_PLUGIN' ) ) define( 'DOKU_PLUGIN', DOKU_INC.'lib/plugins/' ); 15require_once DOKU_PLUGIN.'syntax.php'; 16 17class syntax_plugin_clipboardutils extends DokuWiki_Syntax_Plugin { 18 var $c; 19 20 function getType() { return 'substition';} 21 //function getPType() { return 'block';} 22 function getSort() { return 999; } 23 24 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 25 /** 26 * Ensure class initialisation. 27 */ 28 public function assertInit() { 29 if (!is_array($this->c)) { 30 $this->c =array( 31 'url_icons' => 'lib/plugins/clipboardutils/images/' 32 ); 33 } 34 } 35 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 36 /** 37 * Connect lookup pattern to lexer. 38 * 39 * @param string $mode Parser mode 40 */ 41 public function connectTo($mode) { 42 $this->assertInit(); 43 //dbglog(sprintf("%s('%s')\n",__METHOD__,$mode)); 44 $this->Lexer->addSpecialPattern('<(?:clipb?)\b.*?>.*?</clipb>', $mode, 'plugin_clipboardutils'); 45 } 46 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 47 /** 48 * Handle matches of the clippy syntax 49 * 50 * @param string $match The match of the syntax 51 * @param int $state The state of the handler 52 * @param int $pos The position in the document 53 * @param Doku_Handler $handler The handler 54 * @return array Data for the renderer 55 */ 56 public function handle($match, $state, $pos, Doku_Handler $handler) { 57 //dbglog(sprintf("%s('%s') %s\n",__METHOD__,$state,print_r($match,TRUE))); 58 $data =array('state' => $state, 'match' => $match, 'matchv' => htmlentities($match), 'pos' => $pos, 'att' => array()); 59 if (preg_match('/<(?:clipb?)\b(.*?)>(.*?)<\/clipb>/s',$match,$m)) { 60 $data['m'] =$m; 61 $data['value'] =$m[2]; 62 if (($str =trim($m[1])) != '') { 63 $data['att_string'] =$str; 64 foreach(preg_split('/[;\s]/',$str) as $el) { 65 if (preg_match('/(\w+)\s*[=:]\s*(.*)$/',trim($el),$m2)) { 66 $key =strtolower($m2[1]); 67 switch($key) { 68 case 't' : $key ='type'; break; 69 case 'f' : $key ='format'; break; 70 case 'i' : $key ='icon'; break; 71 } 72 $data['att'][$key] =$m2[2]; 73 } 74 } 75 } 76 } else $data['error'] =TRUE; 77 if (!isset($data['att']['type'])) { 78 if (!empty($data['att']['format'])) $data['att']['type'] ='format'; 79 else $data['att']['type'] =$this->getConf('defaultype'); 80 } 81 return $data; 82 } 83 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 84 /** 85 * For debug purpose 86 */ 87 public function debugArrayString($data, $level =0) { 88 $pad =str_pad('',$level*2,' '); 89 foreach($data as $key => $value) { 90 $str .=$pad . $key; 91 if (is_array($value)) { 92 $sep =str_pad('',80,'-'); 93 $str .=' : IS an ARRAY :' . PHP_EOL . $sep . PHP_EOL; 94 $str .=$this->debugArrayString($value,$level+1) . $sep . PHP_EOL;; 95 } else { 96 $str .=' : "' . htmlentities($value) . '"' . PHP_EOL; 97 } 98 } 99 return $str; 100 } 101 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 102 /** 103 * For debug purpose 104 */ 105 public function debugDataString($data) { 106 $str =''; 107 if (!is_array($data) || count($data) < 1) { 108 $str .='--- EMPTY VALUE ---' . PHP_EOL; 109 } else { 110 $str .=$this->debugArrayString($data); 111 } 112 return $str; 113 } 114 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 115 /** 116 * Get icon url from $data 117 * 118 * @param array $data The original data from the handler() function 119 * @return string with url of icon. 120 */ 121 public function GetIconFromData($data) { 122 $this->assertInit(); 123 if (!empty($data['att']['icon'])) $icon =$data['att']['icon']; 124 else $icon =$this->getConf('icon'); 125 if ($icon == '') $icon ='copy1.png'; 126 if (strpos($icon,'.') === FALSE) $icon .='.png'; 127 return $this->c['url_icons'] . $icon; 128 } 129 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 130 /** 131 * Render a 'type' of output from $data 132 * 133 * @param array $data The original data from the handler() function 134 * @param array $type Override the $data['type']. 135 * @return string to add $renderer->doc. 136 */ 137 public function GetStringFromData(Doku_Renderer $renderer, $data, $type ='-') { 138 $str =''; 139 if ($type == '-') $type =(empty($data['att']['type'])) ? '' : $data['att']['type']; 140 $type =strtolower(trim($type)); 141 switch($type) { 142 // Les types de base : 143 case 'c' : 144 case 'clic' : // Le texte que l'on clique pour le copier dans le presse papier. 145 $str .='<span class="clipu-c vclipu" data-clipboard-text="' . $data['value'] . '">' . $renderer->_xmlEntities($data['value']) .'</span>'; 146 break; 147 case 'i' : 148 case 'icon' : // Une icone cliquable 149 $str .='<span class="bclipu"><img class="clipu-c bclipu" data-clipboard-text="' . $data['value'] . '" src="' . $this->GetIconFromData($data) . '"></span>'; 150 break; 151 case 't' : 152 case 'text' : // le texte brut sans autre fonctionalités 153 $str .=$renderer->_xmlEntities($data['value']); 154 break; 155 case 'f' : 156 // LE type multiple : 157 case 'format' : // Un ensemble de formats 158 $f_str =(empty($data['att']['format'])) ? 'i' : $data['att']['format']; 159 if (strpos($f_str,',') !== FALSE) $formats =explode(',',$f_str); 160 else $formats =str_split($f_str); 161 $cpt_format =0; 162 foreach($formats as $format) { 163 $format =strtolower($format); 164 switch($format) { 165 case '' : // on évite un certain nombre de type non compatible. 166 case '-' : 167 case 'f' : 168 case 'f' : 169 case 'format' : 170 break; 171 default : 172 $value =$this->GetStringFromData($renderer,$data,$format); 173 if (!empty($value)) { 174 if ($cpt_format > 0) $str .=' '; 175 $str .=$value; 176 $cpt_format++; 177 } 178 break; 179 } 180 } 181 break; 182 // Les types composés : 183 case 'ti' : 184 case 'texticon' : // Le text avec l'icone cliquable. 185 $str .=$this->GetStringFromData($renderer,$data,'t') . ' ' . $this->GetStringFromData($renderer,$data,'i'); 186 break; 187 case 'it' : 188 case 'icontext' : // L'icone cliquable d'abord et le text derrière. 189 $str .=$this->GetStringFromData($renderer,$data,'i') . ' ' . $this->GetStringFromData($renderer,$data,'t'); 190 break; 191 case 'ci' : 192 case 'clicicon' : // Le textcliquable ET l'icone cliquable. 193 $str .=$this->GetStringFromData($renderer,$data,'c') . ' ' . $this->GetStringFromData($renderer,$data,'i'); 194 break; 195 case 'ic' : 196 case 'iconclic' : // L'icone cliquable d'abord et le text derrière. 197 $str .=$this->GetStringFromData($renderer,$data,'i') . ' ' . $this->GetStringFromData($renderer,$data,'c'); 198 break; 199 // Les types pour le debogage : 200 case 'debug' : 201 $str .='<pre>' . print_r($conf,TRUE) . '</pre>'; 202 break; 203 case 'data' : 204 $str .= '<pre>'. $this->debugDataString($data) .'</pre>'; 205 break; 206 } 207 return $str; 208 } 209 // -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 210 /** 211 * Render xhtml output or metadata 212 * 213 * @param string $mode Renderer mode 214 * @param Doku_Renderer $renderer The renderer 215 * @param array $data The data from the handler() function 216 * @return bool If rendering was successful. 217 */ 218 public function render($mode, Doku_Renderer $renderer, $data) { 219 global $conf; 220 221 if ( $mode != 'xhtml' ) return false; 222 if (!is_array($data) || !isset($data['state'])) return false; 223 $renderer->doc .=$this->GetStringFromData($renderer,$data,'-'); 224 return true; 225 } 226} 227 228