xref: /template/strap/ComboStrap/CacheManager.php (revision c3437056399326d621a01da73b649707fbb0ae69)
137748cd8SNickeau<?php
237748cd8SNickeau
337748cd8SNickeau
437748cd8SNickeaunamespace ComboStrap;
537748cd8SNickeau
637748cd8SNickeau
737748cd8SNickeauuse dokuwiki\Cache\CacheParser;
837748cd8SNickeau
937748cd8SNickeauclass CacheManager
1037748cd8SNickeau{
1137748cd8SNickeau
1237748cd8SNickeau    const RESULT_STATUS = 'result';
1337748cd8SNickeau    const DATE_MODIFIED = 'ftime';
14*c3437056SNickeau    public const APPLICATION_COMBO_CACHE_JSON = "application/combo+cache+json";
1537748cd8SNickeau
1637748cd8SNickeau    /**
17*c3437056SNickeau     * @var CacheManager
1837748cd8SNickeau     */
19*c3437056SNickeau    private static $cacheManager;
20*c3437056SNickeau
21*c3437056SNickeau    /**
22*c3437056SNickeau     * Just an utility variable to tracks the cache result of each slot
23*c3437056SNickeau     * @var array the processed slot by:
24*c3437056SNickeau     *   * requested page id, (to avoid inconsistency  on multiple page run in one test)
25*c3437056SNickeau     *   * slot id
26*c3437056SNickeau     */
27*c3437056SNickeau    private $cacheResults = array();
2837748cd8SNickeau
2937748cd8SNickeau
3037748cd8SNickeau    /**
3137748cd8SNickeau     * @return CacheManager
3237748cd8SNickeau     */
33*c3437056SNickeau    public static function getOrCreate(): CacheManager
3437748cd8SNickeau    {
35*c3437056SNickeau        if (self::$cacheManager === null) {
36*c3437056SNickeau            self::$cacheManager = new CacheManager();
3737748cd8SNickeau        }
38*c3437056SNickeau        return self::$cacheManager;
3937748cd8SNickeau    }
4037748cd8SNickeau
4137748cd8SNickeau
4237748cd8SNickeau    /**
4337748cd8SNickeau     * In test, we may run more than once
4437748cd8SNickeau     * This function delete the cache manager
4537748cd8SNickeau     * and is called when Dokuwiki close (ie {@link \action_plugin_combo_cache::close()})
4637748cd8SNickeau     */
47*c3437056SNickeau    public static function reset()
4837748cd8SNickeau    {
4937748cd8SNickeau
50*c3437056SNickeau        self::$cacheManager = null;
5137748cd8SNickeau
5237748cd8SNickeau    }
5337748cd8SNickeau
5437748cd8SNickeau    /**
55*c3437056SNickeau     * Keep track of the parsed slot (ie page in page)
56*c3437056SNickeau     * @param $slotId
5737748cd8SNickeau     * @param $result
5837748cd8SNickeau     * @param CacheParser $cacheParser
5937748cd8SNickeau     */
60*c3437056SNickeau    public function addSlotForRequestedPage($slotId, $result, CacheParser $cacheParser)
6137748cd8SNickeau    {
62*c3437056SNickeau
63*c3437056SNickeau        $requestedPageSlotResults = &$this->getCacheSlotResultsForRequestedPage();
64*c3437056SNickeau
65*c3437056SNickeau
66*c3437056SNickeau        if (!isset($requestedPageSlotResults[$slotId])) {
67*c3437056SNickeau            $requestedPageSlotResults[$slotId] = [];
6837748cd8SNickeau        }
69*c3437056SNickeau
7037748cd8SNickeau        /**
7137748cd8SNickeau         * Metadata and other rendering may occurs
7237748cd8SNickeau         * recursively in one request
7337748cd8SNickeau         *
7437748cd8SNickeau         * We record only the first one because the second call one will use the first
7537748cd8SNickeau         * one
7637748cd8SNickeau         */
77*c3437056SNickeau        if (!isset($requestedPageSlotResults[$slotId][$cacheParser->mode])) {
7837748cd8SNickeau            $date = null;
7937748cd8SNickeau            if (file_exists($cacheParser->cache)) {
8037748cd8SNickeau                $date = Iso8601Date::createFromTimestamp(filemtime($cacheParser->cache))->getDateTime();
8137748cd8SNickeau            }
82*c3437056SNickeau            $requestedPageSlotResults[$slotId][$cacheParser->mode] = [
8337748cd8SNickeau                self::RESULT_STATUS => $result,
8437748cd8SNickeau                self::DATE_MODIFIED => $date
8537748cd8SNickeau            ];
8637748cd8SNickeau        }
8737748cd8SNickeau
8837748cd8SNickeau    }
8937748cd8SNickeau
90*c3437056SNickeau    public function getXhtmlCacheSlotResultsForRequestedPage(): array
9137748cd8SNickeau    {
92*c3437056SNickeau        $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage();
93*c3437056SNickeau        if ($cacheSlotResultsForRequestedPage === null) {
94*c3437056SNickeau            return [];
95*c3437056SNickeau        }
9637748cd8SNickeau        $xhtmlRenderResult = [];
97*c3437056SNickeau        foreach ($cacheSlotResultsForRequestedPage as $slotId => $modes) {
9837748cd8SNickeau            foreach ($modes as $mode => $values) {
9937748cd8SNickeau                if ($mode === "xhtml") {
100*c3437056SNickeau                    $xhtmlRenderResult[$slotId] = $values[self::RESULT_STATUS];
10137748cd8SNickeau                }
10237748cd8SNickeau            }
10337748cd8SNickeau        }
10437748cd8SNickeau        return $xhtmlRenderResult;
10537748cd8SNickeau    }
10637748cd8SNickeau
107*c3437056SNickeau    private function &getCacheSlotResultsForRequestedPage(): ?array
10837748cd8SNickeau    {
109*c3437056SNickeau        $requestedPage = $this->getRequestedPage();
110*c3437056SNickeau        $requestedPageSlotResults = &$this->cacheResults[$requestedPage];
111*c3437056SNickeau        if (!isset($requestedPageSlotResults)) {
112*c3437056SNickeau            $requestedPageSlotResults = [];
113*c3437056SNickeau        }
114*c3437056SNickeau        return $requestedPageSlotResults;
11537748cd8SNickeau    }
11637748cd8SNickeau
117*c3437056SNickeau    public function isCacheLogPresentForSlot($slotId, $mode): bool
11837748cd8SNickeau    {
119*c3437056SNickeau        $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage();
120*c3437056SNickeau        return isset($cacheSlotResultsForRequestedPage[$slotId][$mode]);
121*c3437056SNickeau    }
122*c3437056SNickeau
123*c3437056SNickeau
124*c3437056SNickeau    /**
125*c3437056SNickeau     * @return array - a array that will be transformed as json HTML data block
126*c3437056SNickeau     * to be included in a HTML page
127*c3437056SNickeau     */
128*c3437056SNickeau    public function getCacheSlotResultsAsHtmlDataBlockArray(): array
129*c3437056SNickeau    {
130*c3437056SNickeau        $htmlDataBlock = [];
131*c3437056SNickeau        $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage();
132*c3437056SNickeau        if ($cacheSlotResultsForRequestedPage === null) {
133*c3437056SNickeau            LogUtility::msg("No page slot results were found");
134*c3437056SNickeau            return [];
135*c3437056SNickeau        }
136*c3437056SNickeau        foreach ($cacheSlotResultsForRequestedPage as $pageId => $resultByFormat) {
137*c3437056SNickeau            foreach ($resultByFormat as $format => $result) {
138*c3437056SNickeau                $modifiedDate = $result[self::DATE_MODIFIED];
139*c3437056SNickeau                if ($modifiedDate !== null) {
140*c3437056SNickeau                    $modifiedDate = Iso8601Date::createFromDateTime($modifiedDate)->toString();
141*c3437056SNickeau                }
142*c3437056SNickeau                $htmlDataBlock[$pageId][$format] = [
143*c3437056SNickeau                    self::RESULT_STATUS => $result[self::RESULT_STATUS],
144*c3437056SNickeau                    "mtime" => $modifiedDate
145*c3437056SNickeau                ];
146*c3437056SNickeau            }
147*c3437056SNickeau
148*c3437056SNickeau        }
149*c3437056SNickeau        return $htmlDataBlock;
150*c3437056SNickeau    }
151*c3437056SNickeau
152*c3437056SNickeau    private function getRequestedPage()
153*c3437056SNickeau    {
154*c3437056SNickeau        global $_REQUEST;
155*c3437056SNickeau        $requestedPage = $_REQUEST[DokuwikiId::DOKUWIKI_ID_ATTRIBUTE];
156*c3437056SNickeau
157*c3437056SNickeau        if ($requestedPage !== null) {
158*c3437056SNickeau            return $requestedPage;
159*c3437056SNickeau        }
160*c3437056SNickeau
161*c3437056SNickeau        /**
162*c3437056SNickeau         * We are not on a HTTP request
163*c3437056SNickeau         * but may be on a {@link Page::renderMetadataAndFlush() metadata rendering request}
164*c3437056SNickeau         */
165*c3437056SNickeau        global $ID;
166*c3437056SNickeau        if ($ID !== null) {
167*c3437056SNickeau            return $ID;
168*c3437056SNickeau        }
169*c3437056SNickeau
170*c3437056SNickeau        if(PluginUtility::isTest()) {
171*c3437056SNickeau            /**
172*c3437056SNickeau             * {@link p_get_metadata()} check the cache and is used
173*c3437056SNickeau             * also in several place such as {@link feed.php}
174*c3437056SNickeau             * where we don't have any influence
175*c3437056SNickeau             */
176*c3437056SNickeau            LogUtility::msg("The requested page should be known to register a page cache result");
177*c3437056SNickeau        }
178*c3437056SNickeau        return "unknown";
179*c3437056SNickeau    }
180*c3437056SNickeau
181*c3437056SNickeau    public function isEmpty(): bool
182*c3437056SNickeau    {
183*c3437056SNickeau        return sizeof($this->cacheResults) === 0;
18437748cd8SNickeau    }
18537748cd8SNickeau
18637748cd8SNickeau
18737748cd8SNickeau}
188