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('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'componentSnippetContent', array()); 39 40 41 $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'barParsed', array()); 42 43 } 44 45 /** 46 * Dokuwiki has already a canonical methodology 47 * https://www.dokuwiki.org/canonical 48 * 49 * @param $event 50 */ 51 function componentSnippetHead($event) 52 { 53 54 55 global $ID; 56 if (empty($ID)) { 57 return; 58 } 59 60 /** 61 * Advertise that the header output was called 62 * If the user is using another template 63 * than strap that does not put the component snippet 64 * in the head 65 * Used in 66 */ 67 $this->headerOutputWasCalled = true; 68 69 $snippetManager = PluginUtility::getSnippetManager(); 70 71 /** 72 * For each processed bar in the page 73 * * retrieve the snippets from the cache or store the process one 74 * * add the cache information in meta 75 */ 76 $bars = $snippetManager->getBarsOfPage(); 77 foreach ($bars as $bar => $servedFromCache) { 78 79 // Add cache meta for info 80 $event->data["meta"][] = array("name" => self::COMBO_CACHE_PREFIX . $bar, "content" => var_export($servedFromCache, true)); 81 82 // Get or store the data 83 $cache = new \dokuwiki\Cache\Cache($bar, "snippet"); 84 85 // if the bar was served from the cache 86 if ($servedFromCache) { 87 // Retrieve snippets from previous run 88 89 $data = $cache->retrieveCache(); 90 91 if (!empty($data)) { 92 $snippets = unserialize($data); 93 $snippetManager->addSnippetsFromCacheForBar($bar, $snippets); 94 95 if (Site::debugIsOn()) { 96 LogUtility::log2file("Snippet cache file {$cache->cache} used", LogUtility::LVL_MSG_DEBUG); 97 $event->data['script'][] = array( 98 "type" => "application/json", 99 "_data" => json_encode($snippets), 100 "class" => "combo-snippet-cache-" . str_replace(":", "-", $bar)); 101 } 102 103 } 104 } else { 105 $snippets = $snippetManager->getSnippetsForBar($bar); 106 if(!empty($snippets)) { 107 $cache->storeCache(serialize($snippets)); 108 } 109 } 110 111 } 112 113 /** 114 * tags 115 */ 116 foreach ($snippetManager->getTags() as $component => $tags) { 117 foreach ($tags as $tagType => $tagRows) { 118 foreach ($tagRows as $tagRow) { 119 $tagRow["class"] = SnippetManager::getClassFromTag($component);; 120 $event->data[$tagType][] = $tagRow; 121 } 122 } 123 } 124 125 /** 126 * Css 127 */ 128 foreach ($snippetManager->getCss() as $component => $snippet) { 129 $event->data['style'][] = array( 130 "class" => SnippetManager::getClassFromTag($component), 131 "_data" => $snippet 132 ); 133 } 134 135 /** 136 * Javascript 137 */ 138 foreach ($snippetManager->getJavascript() as $component => $snippet) { 139 $event->data['script'][] = array( 140 "class" => SnippetManager::getClassFromTag($component), 141 "type" => "text/javascript", 142 "_data" => $snippet 143 ); 144 } 145 146 147 $snippetManager->close(); 148 149 } 150 151 /** 152 * Used if the template does not run the content 153 * before the calling of the header as strap does. 154 * 155 * In this case, the {@link \ComboStrap\SnippetManager::close()} has 156 * not run, and the snippets are still in memory. 157 * 158 * We store them in the HTML and they 159 * follows then the HTML cache of DokuWiki 160 * @param $event 161 */ 162 function componentSnippetContent($event) 163 { 164 165 166 /** 167 * Run only if the header output was already called 168 */ 169 if ($this->headerOutputWasCalled) { 170 171 $snippetManager = PluginUtility::getSnippetManager(); 172 173 /** 174 * tags 175 */ 176 foreach ($snippetManager->getTags() as $component => $tags) { 177 foreach ($tags as $tagType => $tagRows) { 178 foreach ($tagRows as $tagRow) { 179 $class = SnippetManager::getClassFromTag($component); 180 $event->data .= "<$tagType class=\"$class\""; 181 foreach ($tagRow as $attributeName => $attributeValue) { 182 if ($attributeName != "_data") { 183 $event->data .= " $attributeName=\"$attributeValue\""; 184 } else { 185 $content = $attributeValue; 186 } 187 } 188 $event->data .= ">"; 189 if (!empty($content)) { 190 $event->data .= $content; 191 } 192 $event->data .= "</$tagType>"; 193 } 194 } 195 } 196 197 /** 198 * Css 199 */ 200 foreach ($snippetManager->getCss() as $component => $snippet) { 201 202 $class = SnippetManager::getClassFromTag($component); 203 $event->data .= "<style class=\"$class\">$snippet</style>" . DOKU_LF; 204 205 } 206 207 /** 208 * Javascript 209 */ 210 foreach ($snippetManager->getJavascript() as $component => $snippet) { 211 $class = SnippetManager::getClassFromTag($component); 212 $event->data .= "<script class=\"$class\" type=\"text/javascript\">$snippet</script>" . DOKU_LF; 213 } 214 215 $snippetManager->close(); 216 217 /** 218 * Set the value back 219 */ 220 $this->headerOutputWasCalled = false; 221 222 } 223 224 } 225 226 227 /** 228 * 229 * @param $event 230 */ 231 function barParsed($event) 232 { 233 $data = $event->data; 234 if ($data->mode == "xhtml") { 235 236 /* @var CacheRenderer $data */ 237 $page = $data->page; 238 $cached = $event->result; 239 PluginUtility::getSnippetManager()->addBar($page, $cached); 240 241 } 242 243 244 } 245 246 247} 248