1<?php 2 3use dokuwiki\Search\Indexer; 4 5/** 6 * DokuWiki Plugin PageTitle; Action component 7 * 8 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 9 * @author Satoshi Sahara <sahara.satoshi@gmail.com> 10 */ 11class action_plugin_pagetitle extends DokuWiki_Action_Plugin 12{ 13 /** 14 * register the event handlers 15 */ 16 public function register(Doku_Event_Handler $controller) { 17 //$controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'deleteObsoletedSingleClass'); 18 $controller->register_hook('INDEXER_VERSION_GET', 'BEFORE', $this, '_indexer_version'); 19 $controller->register_hook('INDEXER_PAGE_ADD', 'BEFORE', $this, '_indexer_pagetitle'); 20 $controller->register_hook('PARSER_METADATA_RENDER', 'AFTER', $this, '_parser_render'); 21 $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, '_prepare_cache'); 22 } 23 24 /** 25 * Delete syntax.php which is obsoleted since multi-components syntax structure 26 */ 27 public function deleteObsoletedSingleClass(Doku_Event $event) 28 { 29 $legacyFile = dirname(__FILE__).'/syntax.php'; 30 if (file_exists($legacyFile)) { unlink($legacyFile); } 31 } 32 33 34 /** 35 * INDEXER_VERSION_GET 36 * Set a version string to the metadata index so that 37 * the index will be re-created when the version increased 38 */ 39 public function _indexer_version(Doku_Event $event, $param) 40 { 41 $event->data['plgin_pagetitle'] = '1.'.$this->getConf('usePersistent'); 42 } 43 44 /** 45 * INDEXER_PAGE_ADD 46 * Add id of the page to metadata index, relevant pages should be found 47 * in data/index/plugin_pagetitle_w.idx file 48 */ 49 public function _indexer_pagetitle(Doku_Event $event, $param) 50 { 51 $metadata = p_get_metadata($event->data['page'], 'plugin pagetitle'); 52 $id = $metadata['title'] ?? null; 53 if ($id) { 54 $event->data['metadata']['plugin_pagetitle'] = $id; 55 } 56 } 57 58 59 /** 60 * PAESER_METADATA_RENDER 61 * Use this event to update/reflesh metadata they may have set elseware. 62 * The page metadata is passed including both the current and persistent arrays. 63 */ 64 public function _parser_render(Doku_Event $event, $param) 65 { 66 global $ID; 67 68 /* 69 * The PageTitle plugin will overwrite "title" metadata of the page 70 * with "pagetitle" specified in page source. The page must be rendered 71 * first in xhtml mode to get pagetitle and to stote it on metadata 72 * storage. 73 74 * Each metadata storage (.meta file) may be expired or refleshed by 75 * DokuWiki or any plugins at elsewhere in any stage. For example, 76 * metadata will be expired when main config modified. DokuWiki will set 77 * again title metadata through calls p_get_first_heading() depending on 78 * $conf['useheading"] setting. 79 * 80 * Since page text is not changed, instruction and xhtml cache files are 81 * used to set title metadata, there is no chance to handle/render page 82 * source to get pagetitle and to overwite title metadata. 83 * Therfore, the value of "title" metadata will remain wrong with that 84 * pagetitle plugin intended. 85 * 86 * For the purpose to trigger PageTitle plugin's renderer, we tentatively 87 * set $ID as "title" to tell DokuWiki caching mechanism so that old 88 * cache need to be purged and metadata must be rebuild again. 89 */ 90 91 $meta =& $event->data['current']; 92 $persistent =& $event->data['persistent']; 93 94 // check metadata index whether pagetitle had used in the wiki page 95 $pages = $this->getIndexer()->getPages('plugin_pagetitle'); 96 $pageTitled = in_array($ID, $pages); 97 98 if (!$pageTitled) return; 99 100 // check whether page has rendered by pagetitle plugin 101 if (!isset($meta['plugin']['pagetitle'])) { 102 // tentatively assign full id as page title, just to distinguish 103 // with normal setting noNS($ID) and to purge .meta file later 104 $meta['title'] = $ID; 105 } 106 107 // unnecessary persistent metadata should be removed in syntax component, 108 // however it may be possible to remove it here 109 if (!$this->getConf('usePersistent')) { 110 unset($persistent['title']); 111 } 112 } 113 114 /** 115 * PARSER_CACHE_USE 116 * prepare the cache object for default _useCache action 117 */ 118 public function _prepare_cache(Doku_Event $event, $param) 119 { 120 $cache =& $event->data; 121 122 // we're only interested in wiki pages 123 if (!isset($cache->page)) return; 124 125 // check dependency for hierarchical breadcrumbs 126 if ($cache->mode == 'xhtml') { 127 $metadata = p_get_metadata($cache->page, 'plugin pagetitle'); 128 if (isset($metadata['youarehere'])) { 129 isset($helper) || $helper = $this->loadHelper('pagetitle'); 130 $html = $helper->html_youarehere(1, $cache->page, $traces); 131 array_pop($traces); 132 $depends = []; 133 foreach ($traces as $id) { 134 $depends[] = wikiFN($id, '', false); 135 } 136 $cache->depends['files'] = array_merge((array)$cache->depends['files'], $depends); 137 } 138 } 139 140 // check metadata index whether pagetitle had used in the wiki page 141 $pages = $this->getIndexer()->getPages('plugin_pagetitle'); 142 $pageTitled = in_array($cache->page, $pages); 143 144 if (!$pageTitled) return; 145 146 // check title metadata whether cache files should be purged 147 $title = p_get_metadata($cache->page, 'title', METADATA_DONT_RENDER); 148 switch ($cache->mode) { 149 case 'i': // instruction cache 150 $request = ($title == $cache->page); 151 break; 152 case 'metadata': // metadata cache? 153 $request = ($title == $cache->page); 154 break; 155 case 'xhtml': // xhtml cache 156 $request = ($title == $cache->page); 157 break; 158 } 159 // request purge if necessary 160 $cache->depends['purge'] = $request; 161 } 162 163 // compatibility 164 private function getIndexer() 165 { 166 return is_callable([Indexer::class, 'getInstance']) 167 ? Indexer::getInstance() 168 : idx_get_indexer(); 169 } 170 171} 172