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