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