1<?php
2
3
4namespace ComboStrap;
5
6use dokuwiki\Cache\Cache;
7
8/**
9 * Class Cache
10 * A wrapper around {@link \dokuwiki\Cache\Cache}
11 * @package ComboStrap
12 * that takes into account the arguments / properties of the media
13 * to create the cache file
14 */
15class CacheMedia
16{
17    /**
18     * Cache
19     * values:
20     *   * cache
21     *   * nocache
22     *   * recache
23     */
24    const CACHE_KEY = 'cache';
25    const CACHE_DEFAULT_VALUE = "cache";
26    /**
27     * buster got the same value
28     * that the `rev` attribute (ie mtime)
29     * We don't use rev as cache buster because Dokuwiki still thinks
30     * that this is an old file and search in the attic
31     * as seen in the function {@link mediaFN()}
32     *
33     * The value used by Dokuwiki for the buster is tseed.
34     */
35    const CACHE_BUSTER_KEY = "tseed";
36
37    /**
38     * @var LocalPath
39     */
40    private $path;
41    /**
42     * @var Cache
43     */
44    private $fileCache;
45    private $maxAge;
46
47
48    /**
49     * Cache constructor.
50     */
51    public function __construct(Path $path, TagAttributes $tagAttributes)
52    {
53
54        $this->path = $path;
55
56        if ($path instanceof DokuPath) {
57            $this->path = $path->toLocalPath();
58        }
59        /**
60         * Cache Key Construction
61         */
62        $cacheKey = $this->path->toAbsolutePath()->toString();
63        foreach ($tagAttributes->getComponentAttributes() as $name => $value) {
64
65            /**
66             * The cache attribute are not part of the key
67             * obviously
68             */
69            if (in_array($name, [
70                CacheMedia::CACHE_KEY,
71                CacheMedia::CACHE_BUSTER_KEY,
72            ])) {
73                continue;
74            }
75
76            /**
77             * Normalize name (from w to width)
78             */
79            $name = TagAttributes::AttributeNameFromDokuwikiToCombo($name);
80
81            $cacheKey .= "&" . $name . "=" . $value;
82
83        }
84
85        /**
86         * Cache Attribute
87         */
88        $cacheParameter = $tagAttributes->getValue(self::CACHE_KEY, self::CACHE_DEFAULT_VALUE);
89        /**
90         * Cache transformation
91         * From Image cache value (https://www.dokuwiki.org/images#caching)
92         * to {@link CacheMedia::setMaxAgeInSec()}
93         */
94        switch ($cacheParameter) {
95            case "nocache":
96                $cacheParameter = 0;
97                break;
98            case "recache":
99                global $conf;
100                $cacheParameter = $conf['cachetime'];
101                break;
102            case "cache":
103            default:
104                $cacheParameter = -1;
105                break;
106        }
107        $this->setMaxAgeInSec($cacheParameter);
108
109
110        $this->fileCache = new Cache($cacheKey, ".{$this->path->getExtension()}");
111
112    }
113
114    public static function createFromPath(Path $path, $tagAttributes = null): CacheMedia
115    {
116        if ($tagAttributes == null) {
117            $tagAttributes = TagAttributes::createEmpty();
118        }
119        return new CacheMedia($path, $tagAttributes);
120    }
121
122
123    /**
124     * Cache file depends on code version and configuration
125     * @return bool
126     */
127    public function isCacheUsable()
128    {
129        if ($this->maxAge == 0) {
130            return false;
131        } else {
132            $files = [];
133            if ($this->path->getExtension() === "svg") {
134                // svg generation depends on configuration
135                $files = getConfigFiles('main');
136                $files[] = Site::getComboHome()->resolve("ComboStrap")->resolve("SvgDocument.php")->toString();
137                $files[] = Site::getComboHome()->resolve("ComboStrap")->resolve( "XmlDocument.php")->toString();
138            }
139            $files[] = $this->path->toAbsolutePath()->toString();
140            $files[] = Site::getComboHome()->resolve("plugin.info.txt");
141            $dependencies = array('files' => $files);
142            if ($this->maxAge != null) {
143                $dependencies['age'] = $this->maxAge;
144            }
145            return $this->fileCache->useCache($dependencies);
146        }
147    }
148
149    public function setMaxAgeInSec($maxAge)
150    {
151
152        /**
153         * Got the Dokuwiki Rule
154         * from
155         * https://www.dokuwiki.org/devel:event:fetch_media_status
156         */
157        if ($maxAge < 0) {
158            // cache forever
159            $this->maxAge = PHP_INT_MAX;
160        } elseif ($maxAge == 0) {
161            // never cache
162            $this->maxAge = 0;
163        } else {
164            $this->maxAge = $maxAge;
165        }
166    }
167
168    public function storeCache($content)
169    {
170        $this->fileCache->storeCache($content);
171    }
172
173    public function getFile(): LocalPath
174    {
175        return LocalPath::createFromPath($this->fileCache->cache);
176    }
177
178
179}
180