1<?php 2 3use ComboStrap\CacheManager; 4use ComboStrap\ExceptionCombo; 5use ComboStrap\HtmlDocument; 6use ComboStrap\LogUtility; 7use ComboStrap\Page; 8use ComboStrap\PluginUtility; 9use ComboStrap\RenderUtility; 10use ComboStrap\SnippetManager; 11 12if (!defined('DOKU_INC')) die(); 13 14/** 15 * 16 * 17 * Add the snippet needed by the components 18 * 19 */ 20class action_plugin_combo_snippets extends DokuWiki_Action_Plugin 21{ 22 23 const CLASS_SNIPPET_IN_CONTENT = "snippet-content-combo"; 24 25 /** 26 * @var bool - to trace if the header output was called 27 */ 28 private $headerOutputWasCalled = false; 29 30 function __construct() 31 { 32 // enable direct access to language strings 33 // ie $this->lang 34 $this->setupLocale(); 35 } 36 37 public function register(Doku_Event_Handler $controller) 38 { 39 40 /** 41 * To add the snippets in the header 42 */ 43 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array()); 44 45 /** 46 * To add the snippets in the content 47 * if they have not been added to the header 48 * 49 * Not https://www.dokuwiki.org/devel:event:tpl_content_display TPL_ACT_RENDER 50 * or https://www.dokuwiki.org/devel:event:tpl_act_render 51 * because it works only for the main content 52 * in {@link tpl_content()} 53 * 54 * We use 55 * https://www.dokuwiki.org/devel:event:renderer_content_postprocess 56 * that is in {@link p_render()} and takes into account also the slot page. 57 */ 58 $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'componentSnippetContent', array()); 59 60 /** 61 * To reset the value 62 */ 63 $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array()); 64 65 66 } 67 68 /** 69 * Reset variable 70 * Otherwise in test, when we call it two times, it just fail 71 */ 72 function close() 73 { 74 75 $this->headerOutputWasCalled = false; 76 77 /** 78 * Fighting the fact that in 7.2, 79 * there is still a cache 80 */ 81 SnippetManager::reset(); 82 83 } 84 85 /** 86 * Dokuwiki has already a canonical methodology 87 * https://www.dokuwiki.org/canonical 88 * 89 * @param $event 90 */ 91 function componentSnippetHead($event) 92 { 93 94 95 global $ID; 96 if (empty($ID)) { 97 98 global $_SERVER; 99 $scriptName = $_SERVER['SCRIPT_NAME']; 100 101 /** 102 * If this is an ajax call, return 103 * only if this not from webcode 104 */ 105 if (strpos($scriptName, "/lib/exe/ajax.php") !== false) { 106 global $_REQUEST; 107 $call = $_REQUEST['call']; 108 if ($call != action_plugin_combo_webcode::CALL_ID) { 109 return; 110 } 111 } else if (!(strpos($scriptName, "/lib/exe/detail.php") !== false)) { 112 /** 113 * Image page has an header and footer that may needs snippet 114 * We return only if this is not a image/detail page 115 */ 116 return; 117 } 118 } 119 120 /** 121 * Advertise that the header output was called 122 * If the user is using another template 123 * than strap that does not put the component snippet 124 * in the head 125 * Used in 126 */ 127 $this->headerOutputWasCalled = true; 128 129 $snippetManager = PluginUtility::getSnippetManager(); 130 131 /** 132 * For each processed slot in the page, retrieve the snippets 133 */ 134 $cacheReporters = CacheManager::getOrCreate()->getCacheResults(); 135 if ($cacheReporters !== null) { 136 foreach ($cacheReporters as $cacheReporter) { 137 138 foreach ($cacheReporter->getResults() as $report) { 139 140 if ($report->getMode() !== HtmlDocument::mode) { 141 continue; 142 } 143 144 $slotId = $report->getSlotId(); 145 Page::createPageFromId($slotId) 146 ->getHtmlDocument() 147 ->loadSnippets(); 148 149 } 150 151 152 } 153 } 154 /** 155 * Snippets 156 * (Slot and request snippets) 157 */ 158 try { 159 $allSnippets = $snippetManager->getAllSnippetsToDokuwikiArray(); 160 } catch (ExceptionCombo $e) { 161 LogUtility::msg("Error: We couldn't add the snippets in the head. Error: {$e->getMessage()}"); 162 return; 163 } 164 foreach ($allSnippets as $tagType => $tags) { 165 166 foreach ($tags as $tag) { 167 $event->data[$tagType][] = $tag; 168 } 169 170 } 171 172 $snippetManager->close(); 173 174 } 175 176 /** 177 * Used if the template does not run the content 178 * before the calling of the header as strap does. 179 * 180 * In this case, the {@link \ComboStrap\SnippetManager::close()} has 181 * not run, and the snippets are still in memory. 182 * 183 * We store them in the HTML and they 184 * follows then the HTML cache of DokuWiki 185 * @param $event 186 */ 187 function componentSnippetContent($event) 188 { 189 190 $format = $event->data[0]; 191 if ($format !== "xhtml") { 192 return; 193 } 194 195 /** 196 * Add snippet in the content 197 * - if the header output was already called 198 * - if this is not a page rendering (ie an admin rendering) 199 * for instance, the upgrade plugin call {@link p_cached_output()} on local file 200 */ 201 global $ACT; 202 if ($ACT === RenderUtility::DYNAMIC_RENDERING) { 203 return; 204 } 205 $putSnippetInContent = 206 $this->headerOutputWasCalled 207 || 208 ($ACT !== "show" && $ACT !== null); // admin page rendering 209 if ($putSnippetInContent) { 210 211 $snippetManager = PluginUtility::getSnippetManager(); 212 $xhtmlContent = &$event->data[1]; 213 try { 214 $snippets = $snippetManager->getAllSnippetsToDokuwikiArray(); 215 } catch (ExceptionCombo $e) { 216 LogUtility::msg("Error: We couldn't add the snippets in the content. Error: {$e->getMessage()}"); 217 return; 218 } 219 if (sizeof($snippets) > 0) { 220 221 $class = self::CLASS_SNIPPET_IN_CONTENT; 222 $xhtmlContent .= "<div class=\"$class\">\n"; 223 foreach ($snippets as $htmlElement => $tags) { 224 225 foreach ($tags as $tag) { 226 $xhtmlContent .= DOKU_LF . "<$htmlElement"; 227 $attributes = ""; 228 $content = null; 229 230 /** 231 * This code runs in editing mode 232 * or if the template is not strap 233 * No preload is then supported 234 */ 235 if ($htmlElement === "link") { 236 $relValue = $tag["rel"]; 237 $relAs = $tag["as"]; 238 if ($relValue === "preload") { 239 if ($relAs === "style") { 240 $tag["rel"] = "stylesheet"; 241 unset($tag["as"]); 242 } 243 } 244 } 245 246 /** 247 * Print 248 */ 249 foreach ($tag as $attributeName => $attributeValue) { 250 if ($attributeName !== "_data") { 251 $attributes .= " $attributeName=\"$attributeValue\""; 252 } else { 253 $content = $attributeValue; 254 } 255 } 256 $xhtmlContent .= "$attributes>"; 257 if (!empty($content)) { 258 $xhtmlContent .= $content; 259 } 260 $xhtmlContent .= "</$htmlElement>" . DOKU_LF; 261 } 262 263 } 264 $xhtmlContent .= "</div>\n"; 265 266 } 267 268 $snippetManager->close(); 269 270 } 271 272 } 273 274 275} 276