1<?php 2 3 4use ComboStrap\Api\ApiRouter; 5use ComboStrap\ArrayUtility; 6use ComboStrap\ExceptionNotFound; 7use ComboStrap\ExecutionContext; 8use ComboStrap\Identity; 9use ComboStrap\PluginUtility; 10 11 12/** 13 * Class action_plugin_combo_css 14 * Delete Backend CSS for front-end 15 * 16 * Bug: 17 * * https://datacadamia.comlighthouse - no interwiki 18 * 19 * A call to /lib/exe/css.php?t=template&tseed=time() 20 * 21 * * t is the template 22 * 23 * * tseed is md5 of modified time of the below config file set at {@link tpl_metaheaders()} 24 * 25 * * conf/dokuwiki.php 26 * * conf/local.php 27 * * conf/local.protected.php 28 * * conf/tpl/strap/style.ini 29 * 30 */ 31class action_plugin_combo_css extends DokuWiki_Action_Plugin 32{ 33 34 /** 35 * If anonymous 36 */ 37 const CONF_ENABLE_MINIMAL_FRONTEND_STYLESHEET = 'enableMinimalFrontEndStylesheet'; 38 /** 39 * If anonymous 40 */ 41 const CONF_DISABLE_DOKUWIKI_STYLESHEET = 'disableDokuwikiStylesheet'; 42 43 /** 44 * Anonymous or not 45 */ 46 const ANONYMOUS_KEY = 'ano'; 47 /** 48 * Combo theme or not 49 */ 50 const COMBO_THEME_ENABLED_KEY = "combo-theme-enabled"; 51 52 /** 53 * When anonymous, apply a minimal frontend optimization ? 54 * (ie without Jquery used mostly for admin, ...) 55 */ 56 const ANONYMOUS_MINIMAL_FRONT_KEY = "minimal-front"; 57 58 59 /** 60 * List of excluded plugin 61 */ 62 const EXCLUDED_PLUGINS = array( 63 "acl", 64 "authplain", 65 "changes", 66 "config", 67 "extension", 68 "info", 69 "move", 70 "popularity", 71 "revert", 72 "safefnrecode", 73 "searchindex", 74 "sqlite", 75 "upgrade", 76 "usermanager" 77 ); 78 79 80 81 /** 82 * Registers a callback function for a given event 83 * 84 * @param Doku_Event_Handler $controller DokuWiki's event controller object 85 * @return void 86 * 87 * To fire this event 88 * * Ctrl+Shift+R to disable browser cache 89 * 90 */ 91 public function register(Doku_Event_Handler $controller) 92 { 93 94 $requestScript = PluginUtility::getRequestScript(); 95 switch ($requestScript) { 96 case "css.php": 97 /** 98 * The process follows the following steps: 99 * * With CSS_STYLES_INCLUDED, you choose the file that you want 100 * * then with CSS_CACHE_USE, you can change the cache key name 101 */ 102 $controller->register_hook('CSS_STYLES_INCLUDED', 'BEFORE', $this, 'handle_front_css_styles'); 103 $controller->register_hook('CSS_CACHE_USE', 'BEFORE', $this, 'handle_css_cache'); 104 break; 105 case "doku.php": 106 /** 107 * Add property to the css URL to create multiple CSS file: 108 * * public/private (anonymous/loggedIn) 109 */ 110 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_css_metaheader'); 111 break; 112 } 113 114 115 } 116 117 /** 118 * @param Doku_Event $event 119 * @param $param 120 * 121 * Add query parameter to the CSS header call. ie 122 * <link rel="preload" href="/lib/exe/css.php?t=template&tseed=8e31090353c8fcf80aa6ff0ea9bf3746" as="style"> 123 * to indicate if the page that calls the css is from a user that is logged in or not: 124 * * public vs private 125 * * ie frontend vs backend 126 */ 127 public function handle_css_metaheader(Doku_Event &$event, $param) 128 { 129 130 $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 131 $config = $executionContext->getConfig(); 132 $disableDokuwikiStylesheetConf = $config->getBooleanValue(self::CONF_DISABLE_DOKUWIKI_STYLESHEET, false); 133 $isExecutingTheme = $executionContext->isExecutingPageTemplate(); 134 135 $disableDokuwikiStylesheet = $disableDokuwikiStylesheetConf && $isExecutingTheme; 136 137 138 $links = &$event->data['link']; 139 foreach ($links as $key => &$link) { 140 141 $pos = strpos($link['href'], 'css.php'); 142 if ($pos === false) { 143 continue; 144 } 145 146 if (Identity::isAnonymous()) { 147 148 if ($disableDokuwikiStylesheet) { 149 unset($links[$key]); 150 return; 151 } 152 153 $link['href'] .= '&' . self::ANONYMOUS_KEY; 154 $isEnabledMinimalFrontEnd = ExecutionContext::getActualOrCreateFromEnv() 155 ->getConfig() 156 ->getBooleanValue(self::CONF_ENABLE_MINIMAL_FRONTEND_STYLESHEET, 1); 157 158 if($isEnabledMinimalFrontEnd){ 159 $link['href'] .= '&' . self::ANONYMOUS_MINIMAL_FRONT_KEY; 160 } 161 } 162 163 if ($executionContext->isExecutingPageTemplate()) { 164 $link['href'] .= '&' . self::COMBO_THEME_ENABLED_KEY; 165 } 166 167 168 169 } 170 171 } 172 173 /** 174 * 175 * @param Doku_Event $event event object by reference 176 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 177 * handler was registered] 178 * @return void 179 * 180 * Change the key of the cache. 181 * 182 * The default key can be seen in the {@link css_out()} function 183 * when a new cache is created (ie new cache(key,ext) 184 * 185 * This is only called when this is a front call, see {@link register()} 186 * 187 * @see <a href="https://github.com/i-net-software/dokuwiki-plugin-lightweightcss/blob/master/action.php#L122">Credits</a> 188 */ 189 public function handle_css_cache(Doku_Event &$event, $param) 190 { 191 192 /** 193 * Add Anonymous and comboTheme in the cache key 194 * if present 195 */ 196 $keys = [self::ANONYMOUS_KEY, self::COMBO_THEME_ENABLED_KEY, self::ANONYMOUS_MINIMAL_FRONT_KEY]; 197 $foundKeys = []; 198 foreach ($keys as $key) { 199 if (ApiRouter::hasRequestParameter($key)) { 200 $foundKeys[] = $key; 201 } 202 } 203 if (empty($foundKeys)) { 204 return; 205 } 206 207 /** 208 * Add Anonymous and comboTheme in the cache key 209 * if present 210 */ 211 $event->data->key .= implode('.', $foundKeys); 212 $event->data->cache = getCacheName($event->data->key, $event->data->ext); 213 214 215 } 216 217 /** 218 * Handle the front CSS script list. The script would be fit to do even more stuff / types 219 * but handles only admin and default currently. 220 * 221 * @param Doku_Event $event event object by reference 222 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 223 * handler was registered] 224 * @return void 225 */ 226 public function handle_front_css_styles(Doku_Event &$event, $param) 227 { 228 229 $isAnonymous = ApiRouter::hasRequestParameter(self::ANONYMOUS_KEY); 230 $isThemeEnabled = ApiRouter::hasRequestParameter(self::COMBO_THEME_ENABLED_KEY); 231 $isMinimalFrontEnd = ApiRouter::hasRequestParameter(self::ANONYMOUS_MINIMAL_FRONT_KEY); 232 if (!$isAnonymous && !$isThemeEnabled) { 233 return; 234 } 235 236 237 238 /** 239 * There is one call by: 240 * * mediatype (ie screen, all, print, speech) 241 * * and one call for the dokuwiki default 242 */ 243 switch ($event->data['mediatype']) { 244 245 case 'print': 246 case 'screen': 247 case 'all': 248 $filteredDataFiles = array(); 249 $files = $event->data['files']; 250 foreach ($files as $file => $fileDirectory) { 251 252 // template style 253 if ($isThemeEnabled && strpos($fileDirectory, 'lib/tpl')) { 254 continue; 255 } 256 257 // Lib styles 258 if (($isThemeEnabled || $isMinimalFrontEnd) && strpos($fileDirectory, 'lib/styles')) { 259 // Geshi (syntax highlighting) and basic style of doku, we don't keep. 260 continue; 261 } 262 263 // No Css from lib scripts 264 // Jquery is here 265 if (($isThemeEnabled || $isMinimalFrontEnd) && $isAnonymous && strpos($fileDirectory, 'lib/scripts')) { 266 // Jquery is needed for admin (not anonymous) 267 // scripts\jquery\jquery-ui-theme\smoothness.css 268 continue; 269 } 270 271 if (($isThemeEnabled || $isMinimalFrontEnd)) { 272 // Excluded 273 $isExcluded = false; 274 foreach (self::EXCLUDED_PLUGINS as $plugin) { 275 if (strpos($file, 'lib/plugins/' . $plugin)) { 276 $isExcluded = true; 277 break; 278 } 279 } 280 if (!$isExcluded) { 281 $filteredDataFiles[$file] = $fileDirectory; 282 } 283 } 284 } 285 286 $event->data['files'] = $filteredDataFiles; 287 288 break; 289 290 case 'speech': 291 if (!PluginUtility::isTest()) { 292 $event->preventDefault(); 293 } 294 break; 295 case 'DW_DEFAULT': 296 // Interwiki styles are here, we keep (in the lib/css.php file) 297 break; 298 299 } 300 } 301 302 303} 304 305 306