1<?php 2 3/** 4 * DokuWiki Plugin struct (Syntax Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr, Michael Große <dokuwiki@cosmocode.de> 8 */ 9 10use dokuwiki\plugin\struct\meta\AccessTable; 11use dokuwiki\plugin\struct\meta\Assignments; 12use dokuwiki\plugin\struct\meta\StructException; 13 14class syntax_plugin_struct_output extends DokuWiki_Syntax_Plugin 15{ 16 17 protected $hasBeenRendered = false; 18 19 const XHTML_OPEN = '<div id="plugin__struct_output">'; 20 const XHTML_CLOSE = '</div>'; 21 22 /** 23 * Class names of renderers which should NOT render struct data. 24 * All descendants are also blacklisted. 25 */ 26 const BLACKLIST_RENDERER = array('Doku_Renderer_metadata'); 27 28 /** 29 * Regexp to check on which actions the struct data may be rendered 30 */ 31 const WHITELIST_ACTIONS = '/^(show|export_.*)$/'; 32 33 /** 34 * @return string Syntax mode type 35 */ 36 public function getType() 37 { 38 return 'substition'; 39 } 40 41 /** 42 * @return string Paragraph type 43 */ 44 public function getPType() 45 { 46 return 'block'; 47 } 48 49 /** 50 * @return int Sort order - Low numbers go before high numbers 51 */ 52 public function getSort() 53 { 54 return 155; 55 } 56 57 /** 58 * Connect lookup pattern to lexer. 59 * 60 * We do not connect any pattern here, because the call to this plugin is not 61 * triggered from syntax but our action component 62 * 63 * @asee action_plugin_struct_output 64 * @param string $mode Parser mode 65 */ 66 public function connectTo($mode) 67 { 68 } 69 70 /** 71 * Handle matches of the struct syntax 72 * 73 * @param string $match The match of the syntax 74 * @param int $state The state of the handler 75 * @param int $pos The position in the document 76 * @param Doku_Handler $handler The handler 77 * @return array Data for the renderer 78 */ 79 public function handle($match, $state, $pos, Doku_Handler $handler) 80 { 81 // this is never called 82 return array(); 83 } 84 85 /** 86 * Render schema data 87 * 88 * Currently completely renderer agnostic 89 * 90 * @param string $mode Renderer mode 91 * @param Doku_Renderer $R The renderer 92 * @param array $data The data from the handler() function 93 * @return bool If rendering was successful. 94 */ 95 public function render($mode, Doku_Renderer $R, $data) 96 { 97 global $ACT; 98 global $ID; 99 global $INFO; 100 global $REV; 101 102 foreach (self::BLACKLIST_RENDERER as $blacklisted) { 103 if ($R instanceof $blacklisted) { 104 return true; 105 } 106 } 107 if ($ID != $INFO['id']) return true; 108 if (!$INFO['exists']) return true; 109 if ($this->hasBeenRendered) return true; 110 if (!preg_match(self::WHITELIST_ACTIONS, act_clean($ACT))) return true; 111 112 // do not render the output twice on the same page, e.g. when another page has been included 113 $this->hasBeenRendered = true; 114 try { 115 $assignments = Assignments::getInstance(); 116 } catch (StructException $e) { 117 return false; 118 } 119 $tables = $assignments->getPageAssignments($ID); 120 if (!$tables) return true; 121 122 if ($mode == 'xhtml') $R->doc .= self::XHTML_OPEN; 123 124 $hasdata = false; 125 foreach ($tables as $table) { 126 try { 127 // use the current time if no revision is specified, otherwise we can't access page data 128 $ts = $REV ?: time(); 129 $schemadata = AccessTable::byTableName($table, $ID, $ts); 130 } catch (StructException $ignored) { 131 continue; // no such schema at this revision 132 } 133 $schemadata->optionSkipEmpty(true); 134 $data = $schemadata->getData(); 135 if (!count($data)) continue; 136 $hasdata = true; 137 138 $R->table_open(); 139 140 $R->tablethead_open(); 141 $R->tablerow_open(); 142 $R->tableheader_open(2); 143 $R->cdata($schemadata->getSchema()->getTranslatedLabel()); 144 $R->tableheader_close(); 145 $R->tablerow_close(); 146 $R->tablethead_close(); 147 148 $R->tabletbody_open(); 149 foreach ($data as $field) { 150 $R->tablerow_open(); 151 $R->tableheader_open(); 152 $R->cdata($field->getColumn()->getTranslatedLabel()); 153 $R->tableheader_close(); 154 $R->tablecell_open(); 155 if ($mode == 'xhtml') { 156 $R->doc = substr($R->doc, 0, -1) . 157 ' data-struct="' . hsc($field->getColumn()->getFullQualifiedLabel()) . 158 '">'; 159 } 160 $field->render($R, $mode); 161 $R->tablecell_close(); 162 $R->tablerow_close(); 163 } 164 $R->tabletbody_close(); 165 $R->table_close(); 166 } 167 168 if ($mode == 'xhtml') $R->doc .= self::XHTML_CLOSE; 169 170 // if no data has been output, remove empty wrapper again 171 if ($mode == 'xhtml' && !$hasdata) { 172 $R->doc = substr($R->doc, 0, -1 * strlen(self::XHTML_OPEN . self::XHTML_CLOSE)); 173 } 174 175 return true; 176 } 177} 178 179// vim:ts=4:sw=4:et: 180