1<?php
2
3use ComboStrap\CacheManager;
4use ComboStrap\CacheMenuItem;
5use ComboStrap\CacheReportHtmlDataBlockArray;
6use ComboStrap\ExecutionContext;
7use ComboStrap\Http;
8use ComboStrap\Identity;
9use ComboStrap\IFetcher;
10use ComboStrap\PluginUtility;
11use ComboStrap\SiteConfig;
12
13require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
14
15/**
16 * Can we use the parser cache
17 *
18 *
19 *
20 */
21class action_plugin_combo_cache extends DokuWiki_Action_Plugin
22{
23
24
25    const CANONICAL = "cache";
26    const STATIC_SCRIPT_NAMES = ["/lib/exe/jquery.php", "/lib/exe/js.php", "/lib/exe/css.php"];
27
28
29    /**
30     * @param Doku_Event_Handler $controller
31     */
32    function register(Doku_Event_Handler $controller)
33    {
34
35        /**
36         * Create a {@link \ComboStrap\CacheResult}
37         */
38        $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'createCacheResult', array());
39
40
41        /**
42         * To add the cache result in the HTML
43         */
44        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addCacheLogHtmlDataBlock', array());
45
46
47        /**
48         * To delete the VARY on css.php, jquery.php, js.php
49         */
50        $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'deleteVaryFromStaticGeneratedResources', array());
51
52
53        /**
54         * Add a icon in the page tools menu
55         * https://www.dokuwiki.org/devel:event:menu_items_assembly
56         */
57        $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addMenuItem');
58
59    }
60
61    /**
62     *
63     * @param Doku_Event $event
64     * @param $params
65     */
66    function createCacheResult(Doku_Event $event, $params)
67    {
68
69        /**
70         * To log the cache used by bar
71         * @var \dokuwiki\Cache\CacheParser $data
72         */
73        $data = $event->data;
74        $slotId = $data->page;
75        if (empty($slotId)) {
76            // on edit mode, the page is emtpy
77            return;
78        }
79        $cacheReporter = CacheManager::getFromContextExecution()->getCacheResultsForSlot($slotId);
80        $cacheReporter->setData($event);
81
82
83    }
84
85
86    /**
87     * Add cache data to the rendered html page
88     * @param Doku_Event $event
89     * @param $params
90     */
91    function addCacheLogHtmlDataBlock(Doku_Event $event, $params)
92    {
93
94        $isPublic = ExecutionContext::getActualOrCreateFromEnv()
95            ->isPublicationAction();
96        if (!$isPublic) {
97            return;
98        }
99        $cacheSlotResults = CacheReportHtmlDataBlockArray::getFromContext();
100        $cacheJson = \ComboStrap\Json::createFromArray($cacheSlotResults);
101
102        if (PluginUtility::isDevOrTest()) {
103            $result = $cacheJson->toPrettyJsonString();
104        } else {
105            $result = $cacheJson->toMinifiedJsonString();
106        }
107
108        $event->data["script"][] = array(
109            "type" => CacheReportHtmlDataBlockArray::APPLICATION_COMBO_CACHE_JSON,
110            "_data" => $result,
111        );
112
113
114    }
115
116
117    /**
118     * Delete the Vary header
119     * @param Doku_Event $event
120     * @param $params
121     */
122    public static function deleteVaryFromStaticGeneratedResources(Doku_Event $event, $params)
123    {
124
125        $script = $_SERVER["SCRIPT_NAME"];
126        if (in_array($script, self::STATIC_SCRIPT_NAMES)) {
127            // To be extra sure, they must have the buster key
128            if (isset($_REQUEST[IFetcher::CACHE_BUSTER_KEY])) {
129                self::deleteVaryHeader();
130            }
131        }
132
133    }
134
135    /**
136     *
137     * No Vary: Cookie
138     * Introduced at
139     * https://github.com/splitbrain/dokuwiki/issues/1594
140     * But cache problem at:
141     * https://github.com/splitbrain/dokuwiki/issues/2520
142     *
143     */
144    public static function deleteVaryHeader(): void
145    {
146        if (SiteConfig::getConfValue(action_plugin_combo_staticresource::CONF_STATIC_CACHE_ENABLED, 1)) {
147            Http::removeHeaderIfPresent("Vary");
148        }
149    }
150
151
152    function addMenuItem(Doku_Event $event, $param)
153    {
154
155        /**
156         * The `view` property defines the menu that is currently built
157         * https://www.dokuwiki.org/devel:menus
158         * If this is not the page menu, return
159         */
160        if ($event->data['view'] != 'page') return;
161
162        global $INFO;
163        $exists = $INFO['exists'] ?? null;
164        if (!$exists) {
165            return;
166        }
167        /**
168         * Cache is for manager
169         */
170        if (!Identity::isManager()) {
171            return;
172        }
173        array_splice($event->data['items'], -1, 0, array(new CacheMenuItem()));
174
175
176    }
177
178}
179