1<?php
2
3
4namespace ComboStrap\Meta\Field;
5
6
7use ComboStrap\ExceptionCompile;
8use ComboStrap\ExceptionNotFound;
9use ComboStrap\FileSystems;
10use ComboStrap\FirstRasterImage;
11use ComboStrap\LogUtility;
12use ComboStrap\MarkupPath;
13use ComboStrap\Meta\Api\Metadata;
14use ComboStrap\Meta\Api\MetadataTabular;
15use ComboStrap\Meta\Store\MetadataDokuWikiStore;
16use ComboStrap\MetaManagerForm;
17use ComboStrap\PageImageUsage;
18use ComboStrap\WikiPath;
19
20/**
21 * @deprecated
22 */
23class PageImages extends MetadataTabular
24{
25
26
27    const CANONICAL = "page:image";
28    public const PROPERTY_NAME = 'images';
29    public const PERSISTENT_NAME = 'images';
30
31    /**
32     * The name should be plural, this one was not
33     */
34    const OLD_PROPERTY_NAME = "image";
35
36
37    /**
38     * PageImages constructor.
39     */
40    public function __construct()
41    {
42        parent::__construct();
43    }
44
45
46    public static function createForPage(MarkupPath $page): PageImages
47    {
48        return (new PageImages())
49            ->setResource($page);
50
51    }
52
53    public static function create(): PageImages
54    {
55        return new PageImages();
56    }
57
58
59    /**
60     * @param $persistentValue
61     * @return PageImage[]
62     * @throws ExceptionCompile
63     */
64    public function toPageImageArray($persistentValue): array
65    {
66
67        if ($persistentValue === null) {
68            return [];
69        }
70
71        /**
72         * @var MarkupPath $page ;
73         */
74        $page = $this->getResource();
75
76        if (is_array($persistentValue)) {
77            $images = [];
78            foreach ($persistentValue as $key => $value) {
79                $usage = null;
80                if (is_numeric($key)) {
81                    if (is_array($value)) {
82                        if (isset($value[PageImageUsage::PERSISTENT_NAME])) {
83                            $usage = $value[PageImageUsage::PERSISTENT_NAME];
84                            if (is_string($usage)) {
85                                $usage = explode(",", $usage);
86                            }
87                        }
88                        $imagePath = $value[PageImagePath::PERSISTENT_NAME];
89                    } else {
90                        $imagePath = $value;
91                    }
92                } else {
93                    $imagePath = $key;
94                    if (is_array($value) && isset($value[PageImageUsage::PERSISTENT_NAME])) {
95                        $usage = $value[PageImageUsage::PERSISTENT_NAME];
96                        if (!is_array($usage)) {
97                            $usage = explode(",", $usage);;
98                        }
99                    }
100                }
101                WikiPath::addRootSeparatorIfNotPresent($imagePath);
102                $imagePathObject = WikiPath::createMediaPathFromPath($imagePath);
103                $pageImage = PageImage::create($imagePathObject, $page);
104                if ($usage !== null) {
105                    $pageImage->setUsages($usage);
106                }
107                $images[$imagePath] = $pageImage;
108
109            }
110            return $images;
111        } else {
112            /**
113             * A single path image
114             */
115            WikiPath::addRootSeparatorIfNotPresent($persistentValue);
116            $imagePathObject = WikiPath::createMediaPathFromPath($persistentValue);
117            $images = [$persistentValue => PageImage::create($imagePathObject, $page)];
118        }
119
120        return $images;
121
122    }
123
124
125    /**
126     * @throws ExceptionCompile
127     */
128    public function setFromStoreValue($value): Metadata
129    {
130        $this->setFromStoreValueWithoutException($value);
131        $this->checkImageExistence();
132        return $this;
133    }
134
135
136    static public function getCanonical(): string
137    {
138        return self::CANONICAL;
139    }
140
141    static public function getName(): string
142    {
143        return self::PROPERTY_NAME;
144    }
145
146    static public function getPersistentName(): string
147    {
148        return self::PERSISTENT_NAME;
149    }
150
151    /**
152     * @throws ExceptionCompile
153     */
154    public function toStoreValue(): ?array
155    {
156        $this->buildCheck();
157        if (!\action_plugin_combo_linkmove::isMoveOperation()) {
158            $this->checkImageExistence();
159        }
160        return parent::toStoreValue();
161    }
162
163    public function toStoreDefaultValue(): ?array
164    {
165        return null;
166    }
167
168    static public function getPersistenceType(): string
169    {
170        return MetadataDokuWikiStore::PERSISTENT_DOKUWIKI_KEY;
171    }
172
173
174    /**
175     * @return PageImage[]
176     */
177    public function getValueAsPageImages(): array
178    {
179        $this->buildCheck();
180
181        try {
182            $rows = parent::getValue();
183        } catch (ExceptionNotFound $e) {
184            return [];
185        }
186        $pageImages = [];
187        foreach ($rows as $row) {
188            /**
189             * @var PageImagePath $pageImagePath
190             */
191            $pageImagePath = $row[PageImagePath::getPersistentName()];
192            try {
193                $pageImagePathValue = $pageImagePath->getValue();
194            } catch (ExceptionNotFound $e) {
195                LogUtility::internalError("The page path didn't have any values in the rows", self::CANONICAL);
196                continue;
197            }
198            $pageImage = PageImage::create($pageImagePathValue, $this->getResource());
199
200            /**
201             * @var PageImageUsage $pageImageUsage
202             */
203            $pageImageUsage = $row[PageImageUsage::getPersistentName()] ?? null;
204            if ($pageImageUsage !== null) {
205                try {
206                    $usages = $pageImageUsage->getValue();
207                    $pageImage->setUsages($usages);
208                } catch (ExceptionNotFound $e) {
209                    // ok, no images
210                } catch (ExceptionCompile $e) {
211                    LogUtility::internalError("Bad Usage value. Should not happen on get. Error: " . $e->getMessage(), self::CANONICAL, $e);
212                }
213            }
214            $pageImages[] = $pageImage;
215        }
216        return $pageImages;
217    }
218
219    /**
220     * @throws ExceptionCompile
221     */
222    public function addImage(string $wikiImagePath, $usages = null): PageImages
223    {
224
225        $pageImagePath = PageImagePath::createFromParent($this)->setFromStoreValue($wikiImagePath);
226        $row[PageImagePath::getPersistentName()] = $pageImagePath;
227        if ($usages !== null) {
228            $pageImageUsage = PageImageUsage::createFromParent($this)
229                ->setFromStoreValue($usages);
230            $row[PageImageUsage::getPersistentName()] = $pageImageUsage;
231        }
232        $this->rows[] = $row;
233
234        /**
235         * What fucked up is fucked up
236         * The runtime {@link Doku_Renderer_metadata::_recordMediaUsage()}
237         * ```
238         * meta['relation']['media'][$src] = $exist
239         * ```
240         * is only set when parsing to add page to the index
241         */
242        return $this;
243    }
244
245
246    static public function getTab(): string
247    {
248        return MetaManagerForm::TAB_IMAGE_VALUE;
249    }
250
251
252    static public function getDescription(): string
253    {
254        return "The illustrative images of the page";
255    }
256
257    static public function getLabel(): string
258    {
259        return "Page Images";
260    }
261
262
263    static public function isMutable(): bool
264    {
265        /**
266         * Deprecated, storage is frozen
267         * We don't take it anymore
268         */
269        return false;
270    }
271
272    /**
273     *
274     * We check the existence of the image also when persisting,
275     * not when building
276     * because when moving a media, the images does not exist any more
277     *
278     * We can then build the the pageimages with non-existing images
279     * but we can't save
280     *
281     * @throws ExceptionCompile
282     */
283    private function checkImageExistence()
284    {
285        foreach ($this->getValueAsPageImages() as $pageImage) {
286            if (!FileSystems::exists($pageImage->getImagePath())) {
287                throw new ExceptionCompile("The image ({$pageImage->getImagePath()}) does not exist", $this->getCanonical());
288            }
289        }
290    }
291
292
293    static function getChildrenClass(): array
294    {
295        return [PageImagePath::class, PageImageUsage::class];
296    }
297
298    public function getUidClass(): string
299    {
300        return PageImagePath::class;
301    }
302
303
304    /**
305     * @return array|array[] - the default row
306     */
307    public function getDefaultValue(): array
308    {
309
310        $pageImagePath = null;
311        // Not really the default value but yeah
312        try {
313            $firstImage = FirstRasterImage::createForPage($this->getResource())->getValue();
314            $pageImagePath = PageImagePath::createFromParent($this)->setFromStoreValueWithoutException($firstImage);
315        } catch (ExceptionNotFound $e) {
316            // no first image
317        }
318        $pageImageUsage = PageImageUsage::createFromParent($this)->setFromStoreValueWithoutException([PageImageUsage::DEFAULT]);
319        return [
320            [
321                PageImagePath::getPersistentName() => $pageImagePath,
322                PageImageUsage::getPersistentName() => $pageImageUsage
323            ]
324        ];
325
326    }
327
328    public static function getOldPersistentNames(): array
329    {
330        return [self::OLD_PROPERTY_NAME];
331    }
332
333    /**
334     * @param array $data
335     * @return void
336     *
337     * Trick to advertise the image
338     * saved in {@link \ComboStrap\Meta\Api\Metadata}
339     * if the frontmatter is not used
340     *
341     */
342    public function modifyMetaDokuWikiArray(array &$data)
343    {
344        $pageImages = $this->getValueAsPageImages();
345        foreach ($pageImages as $pageImage) {
346            /**
347             * {@link Doku_Renderer_metadata::_recordMediaUsage()}
348             */
349            $dokuPath = $pageImage->getImagePath();
350            $data[MetadataDokuWikiStore::CURRENT_METADATA]['relation']['media'][$dokuPath->getWikiId()] = FileSystems::exists($dokuPath);
351        }
352
353    }
354
355
356}
357