xref: /plugin/combo/ComboStrap/Canonical.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1<?php
2
3
4namespace ComboStrap;
5
6
7use action_plugin_combo_metaprocessing;
8use ComboStrap\Meta\Api\Metadata;
9use ComboStrap\Meta\Api\MetadataText;
10use ComboStrap\Meta\Api\MetadataWikiPath;
11use ComboStrap\Meta\Store\MetadataDokuWikiStore;
12use ComboStrap\Web\Url;
13use ComboStrap\Web\UrlEndpoint;
14
15
16class Canonical extends MetadataWikiPath
17{
18
19    public const PROPERTY_NAME = "canonical";
20    public const CANONICAL = "canonical";
21
22    /**
23     * The auto-canonical feature does not create any canonical value on the file system
24     * but creates a canonical in the database (where the {@link \action_plugin_combo_router}
25     * takes its information and it enables to route via a calculated canonical
26     * (ie the {@link Canonical::getDefaultValue()}
27     */
28    public const CONF_CANONICAL_LAST_NAMES_COUNT = 'MinimalNamesCountForAutomaticCanonical';
29
30    public static function createForPage(MarkupPath $page): Canonical
31    {
32        return (new Canonical())
33            ->setResource($page);
34
35    }
36
37    /**
38     * @return WikiPath
39     * @throws ExceptionNotFound
40     */
41    public function getValueOrDefault(): WikiPath
42    {
43        try {
44            return $this->getValue();
45        } catch (ExceptionNotFound $e) {
46            return $this->getDefaultValue();
47        }
48    }
49
50
51    public static function getTab(): string
52    {
53        return MetaManagerForm::TAB_REDIRECTION_VALUE;
54    }
55
56    public static function getDescription(): string
57    {
58        return "The canonical path is a short unique path for the page (used in named permalink)";
59    }
60
61    public static function getLabel(): string
62    {
63        return "Canonical Path";
64    }
65
66    public static function getName(): string
67    {
68        return self::PROPERTY_NAME;
69    }
70
71    public static function getPersistenceType(): string
72    {
73        return MetadataDokuWikiStore::PERSISTENT_DOKUWIKI_KEY;
74    }
75
76    public static function isMutable(): bool
77    {
78        return true;
79    }
80
81    public static function createFromValue(string $canonical): Canonical
82    {
83        /** @noinspection PhpIncompatibleReturnTypeInspection */
84        return (new Canonical())
85            ->setValue($canonical);
86    }
87
88
89    /**
90     * @return WikiPath
91     * @throws ExceptionNotFound
92     */
93    public function getDefaultValue(): WikiPath
94    {
95
96        $resourceCombo = $this->getResource();
97        if (!($resourceCombo instanceof MarkupPath)) {
98            throw new ExceptionNotFound("No default value for other resources than page");
99        }
100
101        /**
102         * The last part of the id as canonical
103         */
104        // How many last parts are taken into account in the canonical processing (2 by default)
105        $canonicalLastNamesCount = SiteConfig::getConfValue(self::CONF_CANONICAL_LAST_NAMES_COUNT, 0);
106        if ($canonicalLastNamesCount <= 0) {
107            throw new ExceptionNotFound("Default canonical value is not enabled, no default canonical");
108        }
109
110        /**
111         * Takes the last names part
112         */
113        $namesOriginal = $this->getResource()->getPathObject()->getNamesWithoutExtension();
114        /**
115         * Delete the identical names at the end
116         * To resolve this problem
117         * The page (viz:viz) and the page (data:viz:viz) have the same canonical.
118         * The page (viz:viz) will get the canonical viz
119         * The page (data:viz) will get the canonical  data:viz
120         */
121        $i = sizeof($namesOriginal) - 1;
122        $names = $namesOriginal;
123        while ($namesOriginal[$i] == $namesOriginal[$i - 1]) {
124            unset($names[$i]);
125            $i--;
126            if ($i <= 0) {
127                break;
128            }
129        }
130        /**
131         * Minimal length check
132         */
133        $namesLength = sizeof($names);
134        if ($namesLength > $canonicalLastNamesCount) {
135            $names = array_slice($names, $namesLength - $canonicalLastNamesCount);
136        }
137        /**
138         * If this is a `start` page, delete the name
139         * ie javascript:start will become javascript
140         * (Not a home page)
141         *
142         * We don't use the {@link MarkupPath::isIndexPage()}
143         * because the path `ns:ns` is also an index if the
144         * page `ns:start` does not exists
145         */
146        if ($resourceCombo->getPathObject()->getLastNameWithoutExtension() === Site::getIndexPageName()) {
147            $names = array_slice($names, 0, $namesLength - 1);
148        }
149        $calculatedCanonical = implode(":", $names);
150        WikiPath::addRootSeparatorIfNotPresent($calculatedCanonical);
151        try {
152            return WikiPath::createMarkupPathFromPath($calculatedCanonical);
153        } catch (ExceptionBadArgument $e) {
154            LogUtility::internalError("A canonical should not be the root, should not happen", self::CANONICAL);
155            throw new ExceptionNotFound();
156        }
157
158    }
159
160    public static function getCanonical(): string
161    {
162        return self::CANONICAL;
163    }
164
165
166    public static function getDrive(): string
167    {
168        return WikiPath::MARKUP_DRIVE;
169    }
170
171    public static function isOnForm(): bool
172    {
173        return true;
174    }
175
176
177    /**
178     * The Url of the local web server
179     * @throws ExceptionNotFound
180     */
181    public function getLocalUrl(): Url
182    {
183        return UrlEndpoint::createDokuUrl()
184            ->addQueryParameter(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE, $this->getValue()->getWikiId());
185    }
186
187    /**
188     *
189     * @return Url - the url of the combostrap web server for documentation
190     * @throws ExceptionNotFound
191     */
192    public function getComboStrapUrlForDocumentation(): Url
193    {
194        $path = $this->getValue()->toAbsoluteId();
195        $path = str_replace(":", "/", $path);
196        try {
197            return Url::createFromString(PluginUtility::$INFO_PLUGIN['url'])
198                ->setPath($path);
199        } catch (ExceptionBadArgument|ExceptionBadSyntax $e) {
200            $message = "The url in the plugin info file seems to be broken.";
201            LogUtility::internalError($message, self::CANONICAL, $e);
202            throw new ExceptionNotFound($message);
203        }
204    }
205
206}
207