1<?php
2
3
4namespace ComboStrap;
5
6
7class Canonical extends MetadataWikiPath
8{
9
10    public const PROPERTY_NAME = "canonical";
11    public const CANONICAL = "canonical";
12
13    /**
14     * The auto-canonical feature does not create any canonical value on the file system
15     * but creates a canonical in the database (where the {@link \action_plugin_combo_router}
16     * takes its information and it enables to route via a calculated canonical
17     * (ie the {@link Canonical::getDefaultValue()}
18     */
19    public const CONF_CANONICAL_LAST_NAMES_COUNT = 'MinimalNamesCountForAutomaticCanonical';
20
21    public static function createForPage(Page $page): Canonical
22    {
23        return (new Canonical())
24            ->setResource($page);
25
26    }
27
28    public function getTab(): string
29    {
30        return MetaManagerForm::TAB_REDIRECTION_VALUE;
31    }
32
33    public function getDescription(): string
34    {
35        return "The canonical path is a short unique path for the page (used in named permalink)";
36    }
37
38    public function getLabel(): string
39    {
40        return "Canonical Path";
41    }
42
43    public static function getName(): string
44    {
45        return self::PROPERTY_NAME;
46    }
47
48    public function getPersistenceType(): string
49    {
50        return MetadataDokuWikiStore::PERSISTENT_METADATA;
51    }
52
53    public function getMutable(): bool
54    {
55        return true;
56    }
57
58    public function getDefaultValue(): ?string
59    {
60        /**
61         * The last part of the id as canonical
62         */
63        // How many last parts are taken into account in the canonical processing (2 by default)
64        $canonicalLastNamesCount = PluginUtility::getConfValue(self::CONF_CANONICAL_LAST_NAMES_COUNT, 0);
65        if ($canonicalLastNamesCount > 0) {
66            /**
67             * Takes the last names part
68             */
69            $namesOriginal = $this->getResource()->getPath()->getNames();
70            /**
71             * Delete the identical names at the end
72             * To resolve this problem
73             * The page (viz:viz) and the page (data:viz:viz) have the same canonical.
74             * The page (viz:viz) will get the canonical viz
75             * The page (data:viz) will get the canonical  data:viz
76             */
77            $i = sizeof($namesOriginal) - 1;
78            $names = $namesOriginal;
79            while ($namesOriginal[$i] == $namesOriginal[$i - 1]) {
80                unset($names[$i]);
81                $i--;
82                if ($i <= 0) {
83                    break;
84                }
85            }
86            /**
87             * Minimal length check
88             */
89            $namesLength = sizeof($names);
90            if ($namesLength > $canonicalLastNamesCount) {
91                $names = array_slice($names, $namesLength - $canonicalLastNamesCount);
92            }
93            /**
94             * If this is a `start` page, delete the name
95             * ie javascript:start will become javascript
96             * (Not a home page)
97             */
98            if ($this->getResource()->isStartPage()) {
99                $names = array_slice($names, 0, $namesLength - 1);
100            }
101            $calculatedCanonical = implode(":", $names);
102            DokuPath::addRootSeparatorIfNotPresent($calculatedCanonical);
103            return $calculatedCanonical;
104        }
105        return null;
106    }
107
108    public function getCanonical(): string
109    {
110        return self::CANONICAL;
111    }
112
113
114}
115