1<?php 2/** 3 * DokuWiki Plugin wst (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Vitalie Ciubotaru <vitalie@ciubotaru.tk> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 12if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 13if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14 15class syntax_plugin_wst_template extends DokuWiki_Syntax_Plugin { 16 /** 17 * @return string Syntax mode type 18 */ 19 public function getType() { 20 return 'substition';//maybe switch to 'container' 21 } 22 /** 23 * @return string Paragraph type 24 */ 25 public function getPType() { 26 return 'normal'; //? 27 } 28 /** 29 * @return int Sort order - Low numbers go before high numbers 30 */ 31 public function getSort() { 32 return 319; // should go before Doku_Parser_Mode_media 320 33 } 34 /** 35 * Connect lookup pattern to lexer. 36 * 37 * @param string $mode Parser mode 38 */ 39 public function connectTo($mode) { 40 $this->Lexer->addSpecialPattern('\{\{[W|w][S|s][T|t]>(?:(?:[^\}]*?\{.*?\}\})|.*?)+?\}\}', $mode, 'plugin_wst_template'); 41 } 42 43/** 44 public function postConnect() { 45 $this->Lexer->addExitPattern('\}\}', 'plugin_wst'); 46 } 47**/ 48 /** 49 * Handle matches of the wst syntax 50 * 51 * @param string $match The match of the syntax 52 * @param int $state The state of the handler 53 * @param int $pos The position in the document 54 * @param Doku_Handler $handler The handler 55 * @return array Data for the renderer 56 */ 57 public function handle($match, $state, $pos, Doku_Handler $handler){ 58 if (empty($match)) return false; 59 $template_arguments = array(); 60 $dump = trim(substr($match, 6, -2)); // remove curly brackets and "wst:" keyword 61 $dump = preg_replace_callback('/\{\{(((?!(\{\{|\}\})).*?|(?R))*)\}\}/', function($match) {return str_replace('|', '{{!}}', $match[0]);}, $dump); 62 $dump = explode('|', $dump); // split template name and arguments 63 $template_name = $dump[0]; 64 array_splice($dump, 0, 1); // leave only arguments (if any) 65 if ($dump) { 66 $template_arguments = array(); 67 foreach ($dump as $key => $value) { 68 // cases with {{Template:X|key1=value1|key2=value2}} 69 if (strpos($value, '=') !== false) { 70 $tmp = explode("=", $value); 71 $template_arguments[trim($tmp[0])] = trim($tmp[1]); 72 } 73 // cases with {{Template:X|value1|value2}}, same as 1=value1 74 // start from 1, not 0 75 else $template_arguments[$key+1] = trim($value); 76 } 77 } 78 $template_arguments = str_replace('{{!}}', '|', $template_arguments); 79 $template = $this->get_template($template_name); 80 if (!$template) return; 81 $template_text = $this->replace_args($template, $template_arguments); 82 return $template_text; 83 } 84 85 /** 86 * Render xhtml output or metadata 87 * 88 * @param string $mode Renderer mode (supported modes: xhtml) 89 * @param Doku_Renderer $renderer The renderer 90 * @param array $data The data from the handler() function 91 * @return bool If rendering was successful. 92 */ 93 public function render($mode, Doku_Renderer $renderer, $data) { 94 if($mode != 'xhtml') return false; 95 if (!$data) return false; 96 $renderer->doc .= $renderer->render_text($data, 'xhtml'); 97 return true; 98 } 99 100 function get_template($name) { 101 /** 102 * by default, a page from namespace specified in $conf['namespace'] will be loaded 103 * To override this, prepend a colon to $name 104 **/ 105 $template = rawWiki((substr($name, 0, 1) == ":") || ($this->getConf('namespace') == '') ? substr($name, 1) : $this->getConf('namespace') . ":" . $name); 106 if (!$template) return false; 107 $template = preg_replace('/<noinclude>.*?<\/noinclude>/s', '', $template); 108 $template = preg_replace('/<includeonly>|<\/includeonly>/', '', $template); 109 return $template; 110 } 111 112 function replace_args($template_text, $args) { 113 $keys = array_keys($args); 114 foreach ($keys as $key) { 115 $template_text = str_replace('{{{' . $key . '}}}', $args[$key], $template_text); 116 } 117 // replace mising arguments with a placeholder 118 $template_text = preg_replace('/\{\{\{.*?\}\}\}/', $this->getLang('missing_argument'), $template_text); 119 return $template_text; 120 } 121} 122 123