*/ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); $dataEntryFile = DOKU_PLUGIN.'data/syntax/entry.php'; if(file_exists($dataEntryFile)){ require_once $dataEntryFile; } else { msg('datatemplate: Cannot find Data plugin.', -1); return; } class syntax_plugin_datatemplate_entry extends syntax_plugin_data_entry { /** * @var $dthlp helper_plugin_data will hold the data helper plugin */ var $dthlp = null; /** * Constructor. Load helper plugin */ function __construct(){ $this->dthlp = plugin_load('helper', 'data'); if(!$this->dthlp) msg('Loading the data helper failed. Make sure the data plugin is installed.',-1); } /** * Connect pattern to lexer */ function connectTo($mode) { $this->Lexer->addSpecialPattern('----+ *datatemplateentry(?: [ a-zA-Z0-9_]*)?-+\n.*?\n----+', $mode,'plugin_datatemplate_entry'); } /** * Handle the match - parse the data */ function handle($match, $state, $pos, Doku_Handler $handler){ // The parser of the parent class should have nicely parsed all // parameters. We want to extract the template parameter and treat // it separately. // strip datatemplateentry to get right classes $match = preg_replace('/datatemplateentry/', '', $match, 1); $data = parent::handle($match, $state, $pos, $handler); if(array_key_exists('template', $data['cols'])) { unset($data['cols']['template']); $data['template'] = $data['data']['template']; unset($data['data']['template']); } if(array_key_exists('template', $data)) { $data['instructions'] = $this->_getInstructions($data); } return $data; } /** * Create output or save the data */ function render($format, Doku_Renderer $renderer, $data) { global $ID; switch ($format){ case 'xhtml': /** @var $renderer Doku_Renderer_xhtml */ $this->_showData($data,$renderer); return true; case 'metadata': /** @var $renderer Doku_Renderer_metadata */ $this->_saveRendereredData($data,$ID,$renderer); return true; case 'plugin_data_edit': /** @var $renderer Doku_Renderer_plugin_data_edit */ $this->_editData($data, $renderer); return true; default: return false; } } /** * Get template file name and check existance and access rights. * * @param string $template value of 'template' key in entry * @return int|string * 0 if the file does not exist * -1 if no permission to read the file * the file name otherwise */ function _getFile($template) { global $ID; $wikipage = preg_split('/\#/u', $template, 2); resolve_pageid(getNS($ID), $wikipage[0], $exists); $file = wikiFN($wikipage[0]); if (!@file_exists($file)) return 0; if (auth_quickaclcheck($wikipage[0]) < 1) return -1; return $file; } /** * Generate wiki output from instructions * * @param $data array as returned by handle() * @param &$R Doku_Renderer_xhtml * @return bool|void */ function _showData($data, &$R) { if(!array_key_exists('template', $data)) { // If keyword "template" not present, we can leave // the rendering to the parent class. parent::_showData($data, $R); return true; } // Treat possible errors first if($data['instructions'] == 0) { $R->doc .= '
'; $R->doc .= "Template {$data['template']} not found. "; $R->internalLink($data['template'], '[Click here to create it]'); $R->doc .= '
'; return true; } elseif ($data['instructions'] == -1) { $R->doc .= '
No permissions to view the template
'; return true; } // embed the included page $R->doc .= '
'; // render the instructructions on the fly $text = p_render('xhtml', $data['instructions'], $info); // remove toc, section edit buttons and category tags $patterns = array('!
.*?(
\n
)!s', '##e', '!
.*?
!s'); $replace = array('','',''); $text = preg_replace($patterns,$replace,$text); $R->doc .= $text; $R->doc .= ''; return true; } /** * Read and process template file and return wiki instructions. * Passes through the return value of _getFile if the file does not exist or cannot be accessed. * If no template was specified, return empty array. * * @param array $data return of handle() * @return bool|int|string * 0 if the template file does not exist * -1 if no permission to read the template file * otherwise the template page as list of instructions with replacements performed */ function _getInstructions($data){ // Get the raw file, and parse it into its instructions. This could be cached... maybe. $file = $this->_getFile($data['template']); if(!is_string($file)) return $file; $rawFile = io_readfile($file); $replacers['raw_keys'] = array(); $replacers['raw_vals'] = array(); $replacers['keys'] = array(); $replacers['vals'] = array(); foreach($data['data'] as $key => $val){ if($val == '' || !count($val)) continue; $replacers['keys'][] = "@@" . $key . "@@"; $replacers['raw_keys'][] = "@@!" . $key . "@@"; if(is_array($val)){ $cnt = count($val); $ret = ''; $ret_raw = ''; for ($i=0; $i<$cnt; $i++){ $ret .= $this->_formatData($data['cols'][$key], $val[$i]); $ret_raw .= $val[$i]; if($i < $cnt - 1) { $ret .= ', '; $ret_raw .= ', '; } } $replacers['vals'][] = $ret; $replacers['raw_vals'][] = $ret_raw; } else { $replacers['vals'][] = $this->_formatData($data['cols'][$key], $val); $replacers['raw_vals'][] = $val; } } // First do raw replacements $raw = str_replace($replacers['raw_keys'], $replacers['raw_vals'], $rawFile); $raw = str_replace($replacers['keys'], $replacers['vals'], $raw); $raw = preg_replace('/@@.*?@@/', '', $raw); $instr = p_get_instructions($raw); return $instr; } /** * The data plugin defines this function in its helper class with the purpose * to output XHTML code for the different column types. * We want to let the dokuwiki renderer generate the required output, such * that also metadata is handled correctly. Hence, we will try to translate * each column type to the corresponding dokuwiki syntax. * * @param array $column * @param string $value value of column. * @return string DokuWiki syntax interpretation of value */ function _formatData($column, $value){ $vals = explode("\n",$value); $outs = array(); foreach($vals as $val){ $val = trim($val); if($val=='') continue; $type = $column['type']; if (is_array($type)) $type = $type['type']; switch($type){ case 'page': $val = $this->dthlp->_addPrePostFixes($column['type'], $val); $outs[] = '[[' . $val. ']]'; break; case 'pageid': case 'title': list($id,$title) = explode('|',$val,2); $id = $this->dthlp->_addPrePostFixes($column['type'], $id); $outs[] = '[[' . $id . '|' . $title . ']]'; break; case 'nspage': // no prefix/postfix here $val = ':'.$column['key'].":$val"; $outs[] = '[[' . $val . ']]'; break; case 'mail': list($id,$title) = explode(' ',$val,2); $id = $this->dthlp->_addPrePostFixes($column['type'], $id); $outs[] = '[[' . $id . '|' . $title . ']]'; break; case 'url': $val = $this->dthlp->_addPrePostFixes($column['type'], $val); $outs[] = '[[' . $val . ']]'; break; case 'tag': #todo not handled by datatemplate so far $outs[] = ''.hsc($val).''; break; case 'wiki': $val = $this->dthlp->_addPrePostFixes($column['type'], $val); $outs[] = $val; break; default: $val = $this->dthlp->_addPrePostFixes($column['type'], $val); if(substr($type,0,3) == 'img'){ $sz = (int) substr($type,3); if(!$sz) $sz = 40; $title = $column['key'].': '.basename(str_replace(':','/',$val)); $outs[] = '{{' . $val. ($sz ? '?'.$sz:'') .'|'.$title. '}}'; }else{ $outs[] = $val; } } //todo add type 'timestamp' ... returns html.. } return join(', ',$outs); } /** * Save date to the database * * We are overriding this function to properly generate the metadata for * the parsed template, such that page title and table of contents are * correct. */ function _saveRendereredData($data,$id,&$renderer){ if(!array_key_exists('template', $data)) { parent::_saveData($data, $id, $renderer->meta['title']); return; } $file = $this->_getFile($data['template']); $instr = $data['instructions']; // If for some reason there are no instructions, don't do anything // (Maybe for cache handling one should hand the template file name to the // metadata, even though the file does not exist) if(!is_string($file)) parent::_saveData($data, $id, $renderer->meta['title']); $renderer->meta['relation']['haspart'][$file] = array('owner'=>$this->getPluginName()); // Remove document_start and document_end from instructions array_shift($instr); array_pop($instr); // loop through the instructions for($i = 0; $i < count($instr); $i++) { call_user_func_array(array($renderer, $instr[$i][0]), $instr[$i][1]); } parent::_saveData($data, $id, $renderer->meta['title']); } } /* Local Variables: */ /* c-basic-offset: 4 */ /* End: */