1<?php 2/** 3 * DokuWiki Plugin strata (Action Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Brend Wanders <b.wanders@utwente.nl> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die('Meh.'); 11 12/** 13 * This action component exists to allow the definition of 14 * the type autoloader. 15 */ 16class action_plugin_strata extends DokuWiki_Action_Plugin { 17 18 /** 19 * Register function called by DokuWiki to allow us 20 * to register events we're interested in. 21 * 22 * @param controller object the controller to register with 23 */ 24 public function register(Doku_Event_Handler $controller) { 25 $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_io_page_write'); 26 $controller->register_hook('PARSER_METADATA_RENDER', 'BEFORE', $this, '_parser_metadata_render_before'); 27 $controller->register_hook('STRATA_PREVIEW_METADATA_RENDER', 'BEFORE', $this, '_parser_metadata_render_before'); 28 $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, '_preview_before'); 29 $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, '_preview_after'); 30 31 $controller->register_hook('PARSER_METADATA_RENDER', 'AFTER', $this, '_parser_metadata_render_after'); 32 $controller->register_hook('STRATA_PREVIEW_METADATA_RENDER', 'AFTER', $this, '_parser_metadata_render_after'); 33 } 34 35 36 /** 37 * Triggers before preview xhtml render, 38 * allows plugins to metadata render on the preview. 39 */ 40 public function _preview_before(&$event, $param) { 41 global $ACT; 42 global $TEXT; 43 global $SUF; 44 global $PRE; 45 global $ID; 46 global $METADATA_RENDERERS; 47 48 if($ACT == 'preview') { 49 $triples =& plugin_load('helper', 'strata_triples'); 50 $triples->beginPreview(); 51 52 $text = $PRE.$TEXT.$SUF; 53 $orig = p_read_metadata($ID); 54 55 // store the original metadata in the global $METADATA_RENDERERS so p_set_metadata can use it 56 $METADATA_RENDERERS[$ID] =& $orig; 57 58 // add an extra key for the event - to tell event handlers the page whose metadata this is 59 $orig['page'] = $ID; 60 $evt = new Doku_Event('STRATA_PREVIEW_METADATA_RENDER', $orig); 61 if ($evt->advise_before()) { 62 // get instructions 63 $instructions = p_get_instructions($text); 64 if(is_null($instructions)){ 65 unset($METADATA_RENDERERS[$ID]); 66 return null; // something went wrong with the instructions 67 } 68 69 // set up the renderer 70 $renderer = new renderer_plugin_strata(); 71 $renderer->meta =& $orig['current']; 72 $renderer->persistent =& $orig['persistent']; 73 74 // loop through the instructions 75 foreach ($instructions as $instruction){ 76 // execute the callback against the renderer 77 call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]); 78 } 79 80 $evt->result = array('current'=>&$renderer->meta,'persistent'=>&$renderer->persistent); 81 } 82 $evt->advise_after(); 83 84 // clean up 85 unset($METADATA_RENDERERS[$ID]); 86 } 87 } 88 89 90 public function _preview_after(&$event, $param) { 91 global $ACT; 92 93 if($ACT == 'preview') { 94 $triples =& plugin_load('helper', 'strata_triples'); 95 $triples->endPreview(); 96 } 97 } 98 99 /** 100 * Triggered whenever a page is written. We need to handle 101 * this event because metadata is not rendered if a page is removed. 102 */ 103 public function _io_page_write(&$event, $param) { 104 // only remove triples if page is a new revision, or if it is removed 105 if($event->data[3] == false || $event->data[0][1] == '') { 106 $id = ltrim($event->data[1].':'.$event->data[2],':'); 107 $this->_purge_data($id); 108 } 109 } 110 111 /** 112 * Triggered before metadata is going to be rendered. We 113 * remove triples previously generated by the page that is going to 114 * be rendered so we don't get duplicate entries. 115 */ 116 public function _parser_metadata_render_before(&$event, $param) { 117 $this->_purge_data($event->data['page']); 118 } 119 120 /** 121 * Triggered after metadata has been rendered. 122 * We check the fixTitle flag, and if it is present, we 123 * add the entry title. 124 */ 125 public function _parser_metadata_render_after(&$event, $param) { 126 $id = $event->data['page']; 127 128 $current =& $event->data['current']; 129 130 if(isset($current['strata']['fixTitle']) && $current['strata']['fixTitle']) { 131 // get helpers 132 $triples =& plugin_load('helper', 'strata_triples'); 133 $util =& plugin_load('helper', 'strata_util'); 134 135 $title = $current['title'] ?? null; 136 if(!$title) { 137 $title = noNS($id); 138 } 139 140 $title = $util->loadType('text')->normalize($title,''); 141 142 $triples->addTriple($id, $util->getTitleKey(), $title, $id); 143 } 144 } 145 146 /** 147 * Purges the data for a single page id. 148 * 149 * @param id string the page that needs to be purged 150 */ 151 private function _purge_data($id) { 152 // get triples helper 153 $triples =& plugin_load('helper', 'strata_triples'); 154 155 // remove all triples defined in this graph 156 $triples->removeTriples(null,null,null,$id); 157 } 158} 159 160/** 161 * Strata 'pluggable' autoloader. This function is responsible 162 * for autoloading classes that should be pluggable by external 163 * plugins. 164 * 165 * @param fullname string the name of the class to load 166 */ 167function plugin_strata_autoload($fullname) { 168 static $classes = null; 169 if(is_null($classes)) $classes = array( 170 'strata_exception' => DOKU_PLUGIN.'strata/lib/strata_exception.php', 171 'strata_querytree_visitor' => DOKU_PLUGIN.'strata/lib/strata_querytree_visitor.php', 172 'plugin_strata_type' => DOKU_PLUGIN.'strata/lib/strata_type.php', 173 'plugin_strata_aggregate' => DOKU_PLUGIN.'strata/lib/strata_aggregate.php', 174 ); 175 176 if(isset($classes[$fullname])) { 177 require_once($classes[$fullname]); 178 return; 179 } 180 181 // only load matching components 182 if(preg_match('/^plugin_strata_(type|aggregate)_(.*)$/',$fullname, $matches)) { 183 // use descriptive names 184 list(,$kind,$name) = $matches; 185 186 // glob to find the required file 187 $filenames = glob(DOKU_PLUGIN."*/{$kind}s/{$name}.php"); 188 if($filenames === false || count($filenames) == 0) { 189 // if we have no file, fake an implementation 190 eval("class $fullname extends plugin_strata_{$kind} { };"); 191 } else { 192 // include the file 193 require_once $filenames[0]; 194 // If the class still does not exist, the required file does not define the class, so we fall back 195 // to the default 196 if(!class_exists($fullname)) { 197 eval("class $fullname extends plugin_strata_{$kind} { };"); 198 } 199 } 200 201 return; 202 } 203} 204 205// register autoloader with SPL loader stack 206spl_autoload_register('plugin_strata_autoload'); 207