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