xref: /plugin/combo/ComboStrap/PageUrlPath.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1*c3437056SNickeau<?php
2*c3437056SNickeau
3*c3437056SNickeau
4*c3437056SNickeaunamespace ComboStrap;
5*c3437056SNickeau
6*c3437056SNickeau
7*c3437056SNickeauuse Slug;
8*c3437056SNickeau
9*c3437056SNickeau/**
10*c3437056SNickeau * Class PageUrlPath
11*c3437056SNickeau * @package ComboStrap
12*c3437056SNickeau *
13*c3437056SNickeau *
14*c3437056SNickeau * The path (ie id attribute in the url) in a absolute format (ie with root)
15*c3437056SNickeau *
16*c3437056SNickeau * url path: name for ns + slug (title) + page id
17*c3437056SNickeau * or
18*c3437056SNickeau * url path: canonical path + page id
19*c3437056SNickeau * or
20*c3437056SNickeau * url path: page path + page id
21*c3437056SNickeau *
22*c3437056SNickeau *
23*c3437056SNickeau *   - slug
24*c3437056SNickeau *   - hierarchical slug
25*c3437056SNickeau *   - permanent canonical path (page id)
26*c3437056SNickeau *   - canonical path
27*c3437056SNickeau *   - permanent page path (page id)
28*c3437056SNickeau *   - page path
29*c3437056SNickeau *
30*c3437056SNickeau * This is not the URL of the page but of the generated HTML web page (Ie {@link HtmlDocument}) with all pages (slots)
31*c3437056SNickeau */
32*c3437056SNickeauclass PageUrlPath extends MetadataWikiPath
33*c3437056SNickeau{
34*c3437056SNickeau
35*c3437056SNickeau    /**
36*c3437056SNickeau     *
37*c3437056SNickeau     * The page id is separated in the URL with a "-"
38*c3437056SNickeau     * and not the standard "/"
39*c3437056SNickeau     * because in the devtool or any other tool, they takes
40*c3437056SNickeau     * the last part of the path as name.
41*c3437056SNickeau     *
42*c3437056SNickeau     * The name would be the short page id `22h2s2j4`
43*c3437056SNickeau     * and would have therefore no signification
44*c3437056SNickeau     *
45*c3437056SNickeau     * Instead the name is `metadata-manager-22h2s2j4`
46*c3437056SNickeau     * we can see then a page description, even order on it
47*c3437056SNickeau     */
48*c3437056SNickeau    public const PAGE_ID_URL_SEPARATOR = "-";
49*c3437056SNickeau    /**
50*c3437056SNickeau     * The canonical page for the page url
51*c3437056SNickeau     */
52*c3437056SNickeau    public const CANONICAL = "page:url";
53*c3437056SNickeau    const PROPERTY_NAME = "page-url-path";
54*c3437056SNickeau
55*c3437056SNickeau    public static function createForPage(Page $page)
56*c3437056SNickeau    {
57*c3437056SNickeau        return (new PageUrlPath())
58*c3437056SNickeau            ->setResource($page);
59*c3437056SNickeau    }
60*c3437056SNickeau
61*c3437056SNickeau    public static function getShortEncodedPageIdFromUrlId($lastPartName)
62*c3437056SNickeau    {
63*c3437056SNickeau        $lastPosition = strrpos($lastPartName, PageUrlPath::PAGE_ID_URL_SEPARATOR);
64*c3437056SNickeau        if ($lastPosition === false) {
65*c3437056SNickeau            return null;
66*c3437056SNickeau        }
67*c3437056SNickeau        return substr($lastPartName, $lastPosition + 1);
68*c3437056SNickeau    }
69*c3437056SNickeau
70*c3437056SNickeau    public function getTab(): string
71*c3437056SNickeau    {
72*c3437056SNickeau        return MetaManagerForm::TAB_REDIRECTION_VALUE;
73*c3437056SNickeau    }
74*c3437056SNickeau
75*c3437056SNickeau    public function getValue(): ?string
76*c3437056SNickeau    {
77*c3437056SNickeau
78*c3437056SNickeau        $page = $this->getResource();
79*c3437056SNickeau        if (!($page instanceof Page)) {
80*c3437056SNickeau            LogUtility::msg("The Url Path is not implemented for the resource type (" . $page->getType() . ")");
81*c3437056SNickeau            return null;
82*c3437056SNickeau        }
83*c3437056SNickeau
84*c3437056SNickeau        /**
85*c3437056SNickeau         * Type of Url
86*c3437056SNickeau         */
87*c3437056SNickeau        $urlType = PageUrlType::getOrCreateForPage($page)->getValue();
88*c3437056SNickeau        $urlTypeDefault = PageUrlType::getOrCreateForPage($page)->getDefaultValue();
89*c3437056SNickeau        if ($urlType === $urlTypeDefault) {
90*c3437056SNickeau            return null;
91*c3437056SNickeau        }
92*c3437056SNickeau        return $this->getUrlPathFromType($urlType);
93*c3437056SNickeau
94*c3437056SNickeau    }
95*c3437056SNickeau
96*c3437056SNickeau
97*c3437056SNickeau    public function getDescription(): string
98*c3437056SNickeau    {
99*c3437056SNickeau        return "The path used in the page url";
100*c3437056SNickeau    }
101*c3437056SNickeau
102*c3437056SNickeau    public function getLabel(): string
103*c3437056SNickeau    {
104*c3437056SNickeau        return "Url Path";
105*c3437056SNickeau    }
106*c3437056SNickeau
107*c3437056SNickeau    static public function getName(): string
108*c3437056SNickeau    {
109*c3437056SNickeau        return self::PROPERTY_NAME;
110*c3437056SNickeau    }
111*c3437056SNickeau
112*c3437056SNickeau    public function getPersistenceType(): string
113*c3437056SNickeau    {
114*c3437056SNickeau        return Metadata::DERIVED_METADATA;
115*c3437056SNickeau    }
116*c3437056SNickeau
117*c3437056SNickeau    public function getMutable(): bool
118*c3437056SNickeau    {
119*c3437056SNickeau        return false;
120*c3437056SNickeau    }
121*c3437056SNickeau
122*c3437056SNickeau    public function getDefaultValue()
123*c3437056SNickeau    {
124*c3437056SNickeau
125*c3437056SNickeau        $urlTypeDefault = PageUrlType::getOrCreateForPage($this->getResource())->getDefaultValue();
126*c3437056SNickeau        return $this->getUrlPathFromType($urlTypeDefault);
127*c3437056SNickeau
128*c3437056SNickeau    }
129*c3437056SNickeau
130*c3437056SNickeau    public function getCanonical(): string
131*c3437056SNickeau    {
132*c3437056SNickeau        return self::CANONICAL;
133*c3437056SNickeau    }
134*c3437056SNickeau
135*c3437056SNickeau
136*c3437056SNickeau    private
137*c3437056SNickeau    function toPermanentUrlPath(string $id): string
138*c3437056SNickeau    {
139*c3437056SNickeau        return $id . self::PAGE_ID_URL_SEPARATOR . $this->getPageIdAbbrUrlEncoded();
140*c3437056SNickeau    }
141*c3437056SNickeau
142*c3437056SNickeau    /**
143*c3437056SNickeau     * Add a one letter checksum
144*c3437056SNickeau     * to verify that this is a page id abbr
145*c3437056SNickeau     * ( and not to hit the index for nothing )
146*c3437056SNickeau     * @return string
147*c3437056SNickeau     */
148*c3437056SNickeau    public
149*c3437056SNickeau    function getPageIdAbbrUrlEncoded(): ?string
150*c3437056SNickeau    {
151*c3437056SNickeau        $page = $this->getPage();
152*c3437056SNickeau        if ($page->getPageIdAbbr() == null) return null;
153*c3437056SNickeau        $abbr = $page->getPageIdAbbr();
154*c3437056SNickeau        return self::encodePageId($abbr);
155*c3437056SNickeau    }
156*c3437056SNickeau
157*c3437056SNickeau    /**
158*c3437056SNickeau     * Add a checksum character to the page id
159*c3437056SNickeau     * to check if it's a page id that we get in the url
160*c3437056SNickeau     * @param string $pageId
161*c3437056SNickeau     * @return string
162*c3437056SNickeau     */
163*c3437056SNickeau    public static function encodePageId(string $pageId): string
164*c3437056SNickeau    {
165*c3437056SNickeau        return self::getPageIdChecksumCharacter($pageId) . $pageId;
166*c3437056SNickeau    }
167*c3437056SNickeau
168*c3437056SNickeau    /**
169*c3437056SNickeau     * @param string $encodedPageId
170*c3437056SNickeau     * @return string|null return the decoded page id or null if it's not an encoded page id
171*c3437056SNickeau     */
172*c3437056SNickeau    public static function decodePageId(string $encodedPageId): ?string
173*c3437056SNickeau    {
174*c3437056SNickeau        if (empty($encodedPageId)) return null;
175*c3437056SNickeau        $checkSum = $encodedPageId[0];
176*c3437056SNickeau        $extractedEncodedPageId = substr($encodedPageId, 1);
177*c3437056SNickeau        $calculatedCheckSum = self::getPageIdChecksumCharacter($extractedEncodedPageId);
178*c3437056SNickeau        if ($calculatedCheckSum == null) return null;
179*c3437056SNickeau        if ($calculatedCheckSum != $checkSum) return null;
180*c3437056SNickeau        return $extractedEncodedPageId;
181*c3437056SNickeau    }
182*c3437056SNickeau
183*c3437056SNickeau    /**
184*c3437056SNickeau     * @param string $pageId
185*c3437056SNickeau     * @return string|null - the checksum letter or null if this is not a page id
186*c3437056SNickeau     */
187*c3437056SNickeau    public static function getPageIdChecksumCharacter(string $pageId): ?string
188*c3437056SNickeau    {
189*c3437056SNickeau        $total = 0;
190*c3437056SNickeau        for ($i = 0; $i < strlen($pageId); $i++) {
191*c3437056SNickeau            $letter = $pageId[$i];
192*c3437056SNickeau            $pos = strpos(PageId::PAGE_ID_ALPHABET, $letter);
193*c3437056SNickeau            if ($pos === false) {
194*c3437056SNickeau                return null;
195*c3437056SNickeau            }
196*c3437056SNickeau            $total += $pos;
197*c3437056SNickeau        }
198*c3437056SNickeau        $checkSum = $total % strlen(PageId::PAGE_ID_ALPHABET);
199*c3437056SNickeau        return PageId::PAGE_ID_ALPHABET[$checkSum];
200*c3437056SNickeau    }
201*c3437056SNickeau
202*c3437056SNickeau    /**
203*c3437056SNickeau     * Utility to change the type of the resource
204*c3437056SNickeau     * @return Page|null
205*c3437056SNickeau     */
206*c3437056SNickeau    private function getPage(): ?Page
207*c3437056SNickeau    {
208*c3437056SNickeau        $resource = $this->getResource();
209*c3437056SNickeau        if ($resource instanceof Page) {
210*c3437056SNickeau            return $resource;
211*c3437056SNickeau        }
212*c3437056SNickeau        return null;
213*c3437056SNickeau    }
214*c3437056SNickeau
215*c3437056SNickeau    private function getUrlPathFromType(?string $urlType)
216*c3437056SNickeau    {
217*c3437056SNickeau        $page = $this->getResource();
218*c3437056SNickeau        if((!$page instanceof Page)){
219*c3437056SNickeau            LogUtility::msg("The url path is only for page resources", LogUtility::LVL_MSG_ERROR, $this->getCanonical());
220*c3437056SNickeau            return null;
221*c3437056SNickeau        }
222*c3437056SNickeau
223*c3437056SNickeau        $pagePath = $page->getPath()->toString();
224*c3437056SNickeau        switch ($urlType) {
225*c3437056SNickeau            case PageUrlType::CONF_VALUE_PAGE_PATH:
226*c3437056SNickeau                // the default
227*c3437056SNickeau                return $pagePath;
228*c3437056SNickeau            case PageUrlType::CONF_VALUE_PERMANENT_PAGE_PATH:
229*c3437056SNickeau                return $this->toPermanentUrlPath($pagePath);
230*c3437056SNickeau            case PageUrlType::CONF_VALUE_CANONICAL_PATH:
231*c3437056SNickeau                return $page->getCanonicalOrDefault();
232*c3437056SNickeau            case PageUrlType::CONF_VALUE_PERMANENT_CANONICAL_PATH:
233*c3437056SNickeau                return $this->toPermanentUrlPath($page->getCanonicalOrDefault());
234*c3437056SNickeau            case PageUrlType::CONF_VALUE_SLUG:
235*c3437056SNickeau                return $this->toPermanentUrlPath($page->getSlugOrDefault());
236*c3437056SNickeau            case PageUrlType::CONF_VALUE_HIERARCHICAL_SLUG:
237*c3437056SNickeau                $urlPath = $page->getSlugOrDefault();
238*c3437056SNickeau                while (($parentPage = $page->getParentPage()) != null) {
239*c3437056SNickeau                    if(!$parentPage->isRootHomePage()) {
240*c3437056SNickeau                        $urlPath = Slug::toSlugPath($parentPage->getNameOrDefault()) . $urlPath;
241*c3437056SNickeau                    }
242*c3437056SNickeau                }
243*c3437056SNickeau                return $this->toPermanentUrlPath($urlPath);
244*c3437056SNickeau            case PageUrlType::CONF_VALUE_HOMED_SLUG:
245*c3437056SNickeau                $urlPath = $page->getSlugOrDefault();
246*c3437056SNickeau                if (($parentPage = $page->getParentPage()) != null) {
247*c3437056SNickeau                    if(!$parentPage->isRootHomePage()) {
248*c3437056SNickeau                        $urlPath = Slug::toSlugPath($parentPage->getNameOrDefault()) . $urlPath;
249*c3437056SNickeau                    }
250*c3437056SNickeau                }
251*c3437056SNickeau                return $this->toPermanentUrlPath($urlPath);
252*c3437056SNickeau            default:
253*c3437056SNickeau                LogUtility::msg("The url type ($urlType) is unknown and was unexpected", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME);
254*c3437056SNickeau                return null;
255*c3437056SNickeau        }
256*c3437056SNickeau    }
257*c3437056SNickeau
258*c3437056SNickeau}
259