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\Value; 11use dokuwiki\Extension\SyntaxPlugin; 12use dokuwiki\Extension\Event; 13use dokuwiki\plugin\struct\meta\AccessTable; 14use dokuwiki\plugin\struct\meta\Assignments; 15use dokuwiki\plugin\struct\meta\StructException; 16 17class syntax_plugin_struct_output extends SyntaxPlugin 18{ 19 protected $hasBeenRendered = false; 20 21 protected const XHTML_OPEN = '<div id="plugin__struct_output">'; 22 protected const XHTML_CLOSE = '</div>'; 23 24 /** 25 * Regexp to check on which actions the struct data may be rendered 26 */ 27 protected const WHITELIST_ACTIONS = '/^(show|export_.*)$/'; 28 29 /** 30 * @return string Syntax mode type 31 */ 32 public function getType() 33 { 34 return 'substition'; 35 } 36 37 /** 38 * @return string Paragraph type 39 */ 40 public function getPType() 41 { 42 return 'block'; 43 } 44 45 /** 46 * @return int Sort order - Low numbers go before high numbers 47 */ 48 public function getSort() 49 { 50 return 155; 51 } 52 53 /** 54 * Connect lookup pattern to lexer. 55 * 56 * We do not connect any pattern here, because the call to this plugin is not 57 * triggered from syntax but our action component 58 * 59 * @asee action_plugin_struct_output 60 * @param string $mode Parser mode 61 */ 62 public function connectTo($mode) 63 { 64 } 65 66 /** 67 * Handle matches of the struct syntax 68 * 69 * @param string $match The match of the syntax 70 * @param int $state The state of the handler 71 * @param int $pos The position in the document 72 * @param Doku_Handler $handler The handler 73 * @return array Data for the renderer 74 */ 75 public function handle($match, $state, $pos, Doku_Handler $handler) 76 { 77 // this is never called 78 return []; 79 } 80 81 /** 82 * Render schema data 83 * 84 * Currently completely renderer agnostic 85 * 86 * @param string $format Renderer format 87 * @param Doku_Renderer $renderer The renderer 88 * @param array $data The data from the handler() function 89 * @return bool If rendering was successful. 90 */ 91 public function render($format, Doku_Renderer $renderer, $data) 92 { 93 global $ACT; 94 global $ID; 95 global $INFO; 96 global $REV; 97 98 foreach (helper_plugin_struct::BLACKLIST_RENDERER as $blacklisted) { 99 if ($renderer instanceof $blacklisted) { 100 return true; 101 } 102 } 103 if (!isset($INFO['id']) || ($ID != $INFO['id'])) return true; 104 if (!$INFO['exists']) return true; 105 if ($this->hasBeenRendered) return true; 106 if (!preg_match(self::WHITELIST_ACTIONS, act_clean($ACT))) return true; 107 108 // do not render the output twice on the same page, e.g. when another page has been included 109 $this->hasBeenRendered = true; 110 try { 111 $assignments = Assignments::getInstance(); 112 } catch (StructException $e) { 113 return false; 114 } 115 $tables = $assignments->getPageAssignments($ID); 116 if (!$tables) return true; 117 118 if ($format == 'xhtml') $renderer->doc .= self::XHTML_OPEN; 119 120 $hasdata = false; 121 foreach ($tables as $table) { 122 try { 123 $schemadata = AccessTable::getPageAccess($table, $ID, (int)$REV); 124 } catch (StructException $ignored) { 125 continue; // no such schema at this revision 126 } 127 128 $rendercontext = [ 129 'renderer' => $renderer, 130 'format' => $format, 131 'meta' => p_get_metadata($ID), 132 'schemadata' => $schemadata, 133 'hasdata' => &$hasdata 134 ]; 135 136 $event = new Event( 137 'PLUGIN_STRUCT_RENDER_SCHEMA_DATA', 138 $rendercontext 139 ); 140 $event->trigger([$this, 'renderSchemaData']); 141 } 142 143 if ($format == 'xhtml') $renderer->doc .= self::XHTML_CLOSE; 144 145 // if no data has been output, remove empty wrapper again 146 if ($format == 'xhtml' && !$hasdata) { 147 $renderer->doc = substr($renderer->doc, 0, -1 * strlen(self::XHTML_OPEN . self::XHTML_CLOSE)); 148 } 149 150 return true; 151 } 152 153 /** 154 * Default schema data rendering (simple table view) 155 * 156 * @param array The render context including renderer and data 157 */ 158 public function renderSchemaData($rendercontext) 159 { 160 $schemadata = $rendercontext['schemadata']; 161 $renderer = $rendercontext['renderer']; 162 $format = $rendercontext['format']; 163 164 $schemadata->optionSkipEmpty(true); 165 $data = $schemadata->getData(); 166 if (!count($data)) 167 return; 168 169 $rendercontext['hasdata'] = true; 170 171 if ($format == 'xhtml') { 172 $renderer->doc .= '<div class="struct_output_' . $schemadata->getSchema()->getTable() . '">'; 173 } 174 175 $renderer->table_open(); 176 $renderer->tablethead_open(); 177 $renderer->tablerow_open(); 178 $renderer->tableheader_open(2); 179 $renderer->cdata($schemadata->getSchema()->getTranslatedLabel()); 180 $renderer->tableheader_close(); 181 $renderer->tablerow_close(); 182 $renderer->tablethead_close(); 183 184 $renderer->tabletbody_open(); 185 foreach ($data as $field) { 186 /** @var Value $field */ 187 $renderer->tablerow_open(); 188 if ($format == 'xhtml') { 189 // add data attributes to the row for inline editing 190 $renderer->doc = substr(trim($renderer->doc), 0, -1); // remove the last > 191 $renderer->doc .= ' data-pid="' . hsc($schemadata->getPid()) . '"'; 192 $renderer->doc .= ' data-rev="' . hsc($schemadata->getTimestamp()) . '"'; 193 $renderer->doc .= ' data-rid="' . hsc($schemadata->getRid()) . '"'; 194 $renderer->doc .= ' data-field="' . hsc($field->getColumn()->getFullQualifiedLabel()) . '"'; 195 $renderer->doc .= '">'; 196 } 197 198 $renderer->tableheader_open(); 199 $renderer->cdata($field->getColumn()->getTranslatedLabel()); 200 $renderer->tableheader_close(); 201 $renderer->tablecell_open(); 202 if ($format == 'xhtml') { 203 $renderer->doc = substr($renderer->doc, 0, -1) . 204 ' data-struct="' . hsc($field->getColumn()->getFullQualifiedLabel()) . 205 '">'; 206 } 207 $field->render($renderer, $format); 208 $renderer->tablecell_close(); 209 $renderer->tablerow_close(); 210 } 211 $renderer->tabletbody_close(); 212 $renderer->table_close(); 213 214 if ($format == 'xhtml') { 215 $renderer->doc .= '</div>'; 216 } 217 } 218} 219 220// vim:ts=4:sw=4:et: 221