1<?php 2 3use ComboStrap\LogUtility; 4use ComboStrap\PluginUtility; 5use ComboStrap\Site; 6use ComboStrap\SnippetManager; 7use dokuwiki\Cache\CacheRenderer; 8 9if (!defined('DOKU_INC')) die(); 10 11/** 12 * 13 * 14 * Add the snippet needed by the components 15 * 16 */ 17class action_plugin_combo_snippets extends DokuWiki_Action_Plugin 18{ 19 20 const COMBO_CACHE_PREFIX = "combo:cache:"; 21 22 /** 23 * @var bool - to trace if the header output was called 24 */ 25 private $headerOutputWasCalled = false; 26 27 function __construct() 28 { 29 // enable direct access to language strings 30 // ie $this->lang 31 $this->setupLocale(); 32 } 33 34 public function register(Doku_Event_Handler $controller) 35 { 36 37 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array()); 38 $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array()); 39 $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'componentSnippetContent', array()); 40 41 42 $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'barParsed', array()); 43 44 } 45 46 /** 47 * Reset variable 48 * Otherwise in test, when we call it two times, it just fail 49 */ 50 function close(){ 51 52 $this->headerOutputWasCalled = false; 53 54 /** 55 * Fighting the fact that in 7.2, 56 * there is still a cache 57 */ 58 PluginUtility::initSnippetManager(); 59 60 } 61 62 /** 63 * Dokuwiki has already a canonical methodology 64 * https://www.dokuwiki.org/canonical 65 * 66 * @param $event 67 */ 68 function componentSnippetHead($event) 69 { 70 71 72 global $ID; 73 if (empty($ID)) { 74 return; 75 } 76 77 /** 78 * Advertise that the header output was called 79 * If the user is using another template 80 * than strap that does not put the component snippet 81 * in the head 82 * Used in 83 */ 84 $this->headerOutputWasCalled = true; 85 86 $snippetManager = PluginUtility::getSnippetManager(); 87 88 /** 89 * For each processed bar in the page 90 * * retrieve the snippets from the cache or store the process one 91 * * add the cache information in meta 92 */ 93 $bars = $snippetManager->getBarsOfPage(); 94 foreach ($bars as $bar => $servedFromCache) { 95 96 // Add cache meta for info 97 $event->data["meta"][] = array("name" => self::COMBO_CACHE_PREFIX . $bar, "content" => var_export($servedFromCache, true)); 98 99 // Get or store the data 100 $cache = new \dokuwiki\Cache\Cache($bar, "snippet"); 101 102 // if the bar was served from the cache 103 if ($servedFromCache) { 104 // Retrieve snippets from previous run 105 106 $data = $cache->retrieveCache(); 107 108 if (!empty($data)) { 109 $snippets = unserialize($data); 110 $snippetManager->addSnippetsFromCacheForBar($bar, $snippets); 111 112 if (Site::debugIsOn()) { 113 LogUtility::log2file("Snippet cache file {$cache->cache} used", LogUtility::LVL_MSG_DEBUG); 114 $event->data['script'][] = array( 115 "type" => "application/json", 116 "_data" => json_encode($snippets), 117 "class" => "combo-snippet-cache-" . str_replace(":", "-", $bar)); 118 } 119 120 } 121 } else { 122 $snippets = $snippetManager->getSnippetsForBar($bar); 123 if(!empty($snippets)) { 124 $cache->storeCache(serialize($snippets)); 125 } 126 } 127 128 } 129 130 /** 131 * tags 132 */ 133 foreach ($snippetManager->getTags() as $component => $tags) { 134 foreach ($tags as $tagType => $tagRows) { 135 foreach ($tagRows as $tagRow) { 136 $tagRow["class"] = SnippetManager::getClassFromTag($component);; 137 $event->data[$tagType][] = $tagRow; 138 } 139 } 140 } 141 142 /** 143 * Css 144 */ 145 foreach ($snippetManager->getCss() as $component => $snippet) { 146 $event->data['style'][] = array( 147 "class" => SnippetManager::getClassFromTag($component), 148 "_data" => $snippet 149 ); 150 } 151 152 /** 153 * Javascript 154 */ 155 foreach ($snippetManager->getJavascript() as $component => $snippet) { 156 $event->data['script'][] = array( 157 "class" => SnippetManager::getClassFromTag($component), 158 "type" => "text/javascript", 159 "_data" => $snippet 160 ); 161 } 162 163 164 $snippetManager->close(); 165 166 } 167 168 /** 169 * Used if the template does not run the content 170 * before the calling of the header as strap does. 171 * 172 * In this case, the {@link \ComboStrap\SnippetManager::close()} has 173 * not run, and the snippets are still in memory. 174 * 175 * We store them in the HTML and they 176 * follows then the HTML cache of DokuWiki 177 * @param $event 178 */ 179 function componentSnippetContent($event) 180 { 181 182 183 /** 184 * Run only if the header output was already called 185 */ 186 if ($this->headerOutputWasCalled) { 187 188 $snippetManager = PluginUtility::getSnippetManager(); 189 190 /** 191 * tags 192 */ 193 foreach ($snippetManager->getTags() as $component => $tags) { 194 foreach ($tags as $tagType => $tagRows) { 195 foreach ($tagRows as $tagRow) { 196 $class = SnippetManager::getClassFromTag($component); 197 $event->data .= "<$tagType class=\"$class\""; 198 foreach ($tagRow as $attributeName => $attributeValue) { 199 if ($attributeName != "_data") { 200 $event->data .= " $attributeName=\"$attributeValue\""; 201 } else { 202 $content = $attributeValue; 203 } 204 } 205 $event->data .= ">"; 206 if (!empty($content)) { 207 $event->data .= $content; 208 } 209 $event->data .= "</$tagType>"; 210 } 211 } 212 } 213 214 /** 215 * Css 216 */ 217 foreach ($snippetManager->getCss() as $component => $snippet) { 218 219 $class = SnippetManager::getClassFromTag($component); 220 $event->data .= "<style class=\"$class\">$snippet</style>" . DOKU_LF; 221 222 } 223 224 /** 225 * Javascript 226 */ 227 foreach ($snippetManager->getJavascript() as $component => $snippet) { 228 $class = SnippetManager::getClassFromTag($component); 229 $event->data .= "<script class=\"$class\" type=\"text/javascript\">$snippet</script>" . DOKU_LF; 230 } 231 232 $snippetManager->close(); 233 234 /** 235 * Set the value back 236 */ 237 $this->headerOutputWasCalled = false; 238 239 } 240 241 } 242 243 244 /** 245 * 246 * @param $event 247 */ 248 function barParsed($event) 249 { 250 $data = $event->data; 251 if ($data->mode == "xhtml") { 252 253 /* @var CacheRenderer $data */ 254 $page = $data->page; 255 $cached = $event->result; 256 PluginUtility::getSnippetManager()->addBar($page, $cached); 257 258 } 259 260 261 } 262 263 264} 265