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