1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeaunamespace ComboStrap; 4*04fd306cSNickeau 5*04fd306cSNickeau 6*04fd306cSNickeauuse ComboStrap\Api\QualityMessageHandler; 7*04fd306cSNickeauuse ComboStrap\Meta\Api\Metadata; 8*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataBoolean; 9*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataStore; 10*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataStoreAbs; 11*04fd306cSNickeauuse ComboStrap\Meta\Field\Alias; 12*04fd306cSNickeauuse ComboStrap\Meta\Field\Aliases; 13*04fd306cSNickeauuse ComboStrap\Meta\Field\AliasType; 14*04fd306cSNickeauuse ComboStrap\Meta\Field\PageH1; 15*04fd306cSNickeauuse ComboStrap\Meta\Field\PageImage; 16*04fd306cSNickeauuse ComboStrap\Meta\Field\PageImages; 17*04fd306cSNickeauuse ComboStrap\Meta\Field\PageTemplateName; 18*04fd306cSNickeauuse ComboStrap\Meta\Field\Region; 19*04fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore; 20*04fd306cSNickeauuse ComboStrap\Web\Url; 21*04fd306cSNickeauuse ComboStrap\Web\UrlEndpoint; 22*04fd306cSNickeauuse DateTime; 23*04fd306cSNickeauuse dokuwiki\ChangeLog\ChangeLog; 24*04fd306cSNickeauuse Exception; 25*04fd306cSNickeauuse renderer_plugin_combo_analytics; 26*04fd306cSNickeau 27*04fd306cSNickeau 28*04fd306cSNickeau/** 29*04fd306cSNickeau * 30*04fd306cSNickeau * A markup is a logical unit that represents a markup file. 31*04fd306cSNickeau * 32*04fd306cSNickeau * It has its own file system {@link MarkupFileSystem} explained in the 33*04fd306cSNickeau * https://combostrap.com/page/system (or system.txt file). 34*04fd306cSNickeau * ie the {@link Path::getParent()} is not the same than on an normal file system. 35*04fd306cSNickeau * 36*04fd306cSNickeau * This should be an extension of {@link WikiPath} but for now, we are not extending {@link WikiPath} 37*04fd306cSNickeau * for the following old reasons: 38*04fd306cSNickeau * * we want to be able to return a {@link MarkupPath} in the {@link MarkupPath::getParent()} function 39*04fd306cSNickeau * otherwise if we do, we get a hierarchical error. 40*04fd306cSNickeau * * we can then accepts also {@link LocalPath} 41*04fd306cSNickeau * 42*04fd306cSNickeau * But because this is a {@link ResourceCombo}, we see tht this is part of the {@link WikiPath} 43*04fd306cSNickeau * system with an {@link ResourceCombo::getUid()} unique uid. 44*04fd306cSNickeau * 45*04fd306cSNickeau * We should find a way to be able to create a wiki path with a {@link LocalPath} 46*04fd306cSNickeau * via the {@link WikiPath::getDrive()} ? 47*04fd306cSNickeau * 48*04fd306cSNickeau */ 49*04fd306cSNickeauclass MarkupPath extends PathAbs implements ResourceCombo, Path 50*04fd306cSNickeau{ 51*04fd306cSNickeau 52*04fd306cSNickeau const CANONICAL_PAGE = "markup"; 53*04fd306cSNickeau 54*04fd306cSNickeau 55*04fd306cSNickeau const TYPE = "page"; 56*04fd306cSNickeau 57*04fd306cSNickeau /** 58*04fd306cSNickeau * @var Canonical 59*04fd306cSNickeau */ 60*04fd306cSNickeau private $canonical; 61*04fd306cSNickeau /** 62*04fd306cSNickeau * @var PageH1 63*04fd306cSNickeau */ 64*04fd306cSNickeau private $h1; 65*04fd306cSNickeau /** 66*04fd306cSNickeau * @var ResourceName 67*04fd306cSNickeau */ 68*04fd306cSNickeau private $pageName; 69*04fd306cSNickeau /** 70*04fd306cSNickeau * @var PageType 71*04fd306cSNickeau */ 72*04fd306cSNickeau private $type; 73*04fd306cSNickeau /** 74*04fd306cSNickeau * @var PageTitle $title 75*04fd306cSNickeau */ 76*04fd306cSNickeau private $title; 77*04fd306cSNickeau 78*04fd306cSNickeau private $uidObject; 79*04fd306cSNickeau 80*04fd306cSNickeau private LowQualityPageOverwrite $canBeOfLowQuality; 81*04fd306cSNickeau /** 82*04fd306cSNickeau * @var Region 83*04fd306cSNickeau */ 84*04fd306cSNickeau private $region; 85*04fd306cSNickeau /** 86*04fd306cSNickeau * @var Lang 87*04fd306cSNickeau */ 88*04fd306cSNickeau private $lang; 89*04fd306cSNickeau /** 90*04fd306cSNickeau * @var PageId 91*04fd306cSNickeau */ 92*04fd306cSNickeau private $pageId; 93*04fd306cSNickeau 94*04fd306cSNickeau /** 95*04fd306cSNickeau * @var LowQualityCalculatedIndicator 96*04fd306cSNickeau */ 97*04fd306cSNickeau private $lowQualityIndicatorCalculated; 98*04fd306cSNickeau 99*04fd306cSNickeau /** 100*04fd306cSNickeau * @var PageTemplateName 101*04fd306cSNickeau */ 102*04fd306cSNickeau private $layout; 103*04fd306cSNickeau /** 104*04fd306cSNickeau * @var Aliases 105*04fd306cSNickeau */ 106*04fd306cSNickeau private $aliases; 107*04fd306cSNickeau /** 108*04fd306cSNickeau * @var Slug a slug path 109*04fd306cSNickeau */ 110*04fd306cSNickeau private $slug; 111*04fd306cSNickeau 112*04fd306cSNickeau 113*04fd306cSNickeau /** 114*04fd306cSNickeau * @var QualityDynamicMonitoringOverwrite 115*04fd306cSNickeau */ 116*04fd306cSNickeau private $qualityMonitoringIndicator; 117*04fd306cSNickeau 118*04fd306cSNickeau /** 119*04fd306cSNickeau * @var string the alias used to build this page 120*04fd306cSNickeau */ 121*04fd306cSNickeau private $buildAliasPath; 122*04fd306cSNickeau /** 123*04fd306cSNickeau * @var PagePublicationDate 124*04fd306cSNickeau */ 125*04fd306cSNickeau private $publishedDate; 126*04fd306cSNickeau /** 127*04fd306cSNickeau * @var StartDate 128*04fd306cSNickeau */ 129*04fd306cSNickeau private $startDate; 130*04fd306cSNickeau /** 131*04fd306cSNickeau * @var EndDate 132*04fd306cSNickeau */ 133*04fd306cSNickeau private $endDate; 134*04fd306cSNickeau /** 135*04fd306cSNickeau * @var PageImages 136*04fd306cSNickeau */ 137*04fd306cSNickeau private $pageImages; 138*04fd306cSNickeau 139*04fd306cSNickeau private PageKeywords $keywords; 140*04fd306cSNickeau /** 141*04fd306cSNickeau * @var CacheExpirationFrequency 142*04fd306cSNickeau */ 143*04fd306cSNickeau private $cacheExpirationFrequency; 144*04fd306cSNickeau /** 145*04fd306cSNickeau * @var CacheExpirationDate 146*04fd306cSNickeau */ 147*04fd306cSNickeau private $cacheExpirationDate; 148*04fd306cSNickeau /** 149*04fd306cSNickeau * 150*04fd306cSNickeau * @var LdJson 151*04fd306cSNickeau */ 152*04fd306cSNickeau private $ldJson; 153*04fd306cSNickeau 154*04fd306cSNickeau 155*04fd306cSNickeau /** 156*04fd306cSNickeau * @var PageDescription $description 157*04fd306cSNickeau */ 158*04fd306cSNickeau private $description; 159*04fd306cSNickeau /** 160*04fd306cSNickeau * @var CreationDate 161*04fd306cSNickeau */ 162*04fd306cSNickeau private $creationTime; 163*04fd306cSNickeau /** 164*04fd306cSNickeau * @var Locale 165*04fd306cSNickeau */ 166*04fd306cSNickeau private $locale; 167*04fd306cSNickeau /** 168*04fd306cSNickeau * @var ModificationDate 169*04fd306cSNickeau */ 170*04fd306cSNickeau private $modifiedTime; 171*04fd306cSNickeau /** 172*04fd306cSNickeau * @var PageUrlPath 173*04fd306cSNickeau */ 174*04fd306cSNickeau private $pageUrlPath; 175*04fd306cSNickeau /** 176*04fd306cSNickeau * @var MetadataStore|string 177*04fd306cSNickeau */ 178*04fd306cSNickeau private $readStore; 179*04fd306cSNickeau 180*04fd306cSNickeau /** 181*04fd306cSNickeau * @var Path - {@link MarkupPath} has other hierachy system in regards with parent 182*04fd306cSNickeau * May be we just should extends {@link WikiPath} but it was a way to be able to locate 183*04fd306cSNickeau * default markup path file that were not in any drive 184*04fd306cSNickeau * TODO: Just extends WikiPath and add private drive when data should be accessed locally ? 185*04fd306cSNickeau */ 186*04fd306cSNickeau private Path $path; 187*04fd306cSNickeau 188*04fd306cSNickeau /** 189*04fd306cSNickeau * Page constructor. 190*04fd306cSNickeau * 191*04fd306cSNickeau */ 192*04fd306cSNickeau public function __construct(Path $path) 193*04fd306cSNickeau { 194*04fd306cSNickeau 195*04fd306cSNickeau $this->path = $path; 196*04fd306cSNickeau if (FileSystems::isDirectory($path)) { 197*04fd306cSNickeau $this->setCorrectPathForDirectoryToIndexPage(); 198*04fd306cSNickeau } 199*04fd306cSNickeau $this->buildPropertiesFromFileSystem(); 200*04fd306cSNickeau 201*04fd306cSNickeau } 202*04fd306cSNickeau 203*04fd306cSNickeau /** 204*04fd306cSNickeau * The current running rendering markup 205*04fd306cSNickeau * @throws ExceptionNotFound 206*04fd306cSNickeau */ 207*04fd306cSNickeau public static function createPageFromExecutingId(): MarkupPath 208*04fd306cSNickeau { 209*04fd306cSNickeau $wikiPath = WikiPath::createExecutingMarkupWikiPath(); 210*04fd306cSNickeau return self::createPageFromPathObject($wikiPath); 211*04fd306cSNickeau } 212*04fd306cSNickeau 213*04fd306cSNickeau 214*04fd306cSNickeau public static function createMarkupFromId($id): MarkupPath 215*04fd306cSNickeau { 216*04fd306cSNickeau return new MarkupPath(WikiPath::createMarkupPathFromId($id)); 217*04fd306cSNickeau } 218*04fd306cSNickeau 219*04fd306cSNickeau /** 220*04fd306cSNickeau * @param string $path - relative or absolute 221*04fd306cSNickeau * @return MarkupPath 222*04fd306cSNickeau */ 223*04fd306cSNickeau public static function createMarkupFromStringPath(string $path): MarkupPath 224*04fd306cSNickeau { 225*04fd306cSNickeau $wikiPath = WikiPath::createMarkupPathFromPath($path); 226*04fd306cSNickeau return new MarkupPath($wikiPath); 227*04fd306cSNickeau 228*04fd306cSNickeau } 229*04fd306cSNickeau 230*04fd306cSNickeau /** 231*04fd306cSNickeau * @return MarkupPath - the requested page 232*04fd306cSNickeau * @throws ExceptionNotFound 233*04fd306cSNickeau */ 234*04fd306cSNickeau public static function createFromRequestedPage(): MarkupPath 235*04fd306cSNickeau { 236*04fd306cSNickeau $path = WikiPath::createRequestedPagePathFromRequest(); 237*04fd306cSNickeau return MarkupPath::createPageFromPathObject($path); 238*04fd306cSNickeau } 239*04fd306cSNickeau 240*04fd306cSNickeau 241*04fd306cSNickeau public static function createPageFromPathObject(Path $path): MarkupPath 242*04fd306cSNickeau { 243*04fd306cSNickeau if ($path instanceof MarkupPath) { 244*04fd306cSNickeau return $path; 245*04fd306cSNickeau } 246*04fd306cSNickeau return new MarkupPath($path); 247*04fd306cSNickeau } 248*04fd306cSNickeau 249*04fd306cSNickeau 250*04fd306cSNickeau /** 251*04fd306cSNickeau * 252*04fd306cSNickeau * @throws ExceptionBadSyntax - if this is not a 253*04fd306cSNickeau * @deprecated just pass a namespace path to the page creation and you will get the index page in return 254*04fd306cSNickeau */ 255*04fd306cSNickeau public static function getIndexPageFromNamespace(string $namespacePath): MarkupPath 256*04fd306cSNickeau { 257*04fd306cSNickeau WikiPath::checkNamespacePath($namespacePath); 258*04fd306cSNickeau 259*04fd306cSNickeau return MarkupPath::createMarkupFromId($namespacePath); 260*04fd306cSNickeau } 261*04fd306cSNickeau 262*04fd306cSNickeau 263*04fd306cSNickeau static function createPageFromAbsoluteId($qualifiedPath): MarkupPath 264*04fd306cSNickeau { 265*04fd306cSNickeau $path = WikiPath::createMarkupPathFromId($qualifiedPath); 266*04fd306cSNickeau return new MarkupPath($path); 267*04fd306cSNickeau } 268*04fd306cSNickeau 269*04fd306cSNickeau 270*04fd306cSNickeau /** 271*04fd306cSNickeau * 272*04fd306cSNickeau * @throws ExceptionCompile 273*04fd306cSNickeau */ 274*04fd306cSNickeau public 275*04fd306cSNickeau function setCanonical($canonical): MarkupPath 276*04fd306cSNickeau { 277*04fd306cSNickeau $this->canonical 278*04fd306cSNickeau ->setValue($canonical) 279*04fd306cSNickeau ->sendToWriteStore(); 280*04fd306cSNickeau return $this; 281*04fd306cSNickeau } 282*04fd306cSNickeau 283*04fd306cSNickeau 284*04fd306cSNickeau /** 285*04fd306cSNickeau * @return bool true if this is a fragment markup 286*04fd306cSNickeau */ 287*04fd306cSNickeau public function isSlot(): bool 288*04fd306cSNickeau { 289*04fd306cSNickeau $slotNames = SlotSystem::getSlotNames(); 290*04fd306cSNickeau try { 291*04fd306cSNickeau $name = $this->getPathObject()->getLastNameWithoutExtension(); 292*04fd306cSNickeau } catch (ExceptionNotFound $e) { 293*04fd306cSNickeau // root case 294*04fd306cSNickeau return false; 295*04fd306cSNickeau } 296*04fd306cSNickeau return in_array($name, $slotNames, true); 297*04fd306cSNickeau } 298*04fd306cSNickeau 299*04fd306cSNickeau /** 300*04fd306cSNickeau * @return bool true if this is the side slot 301*04fd306cSNickeau */ 302*04fd306cSNickeau public function isSideSlot(): bool 303*04fd306cSNickeau { 304*04fd306cSNickeau $slotNames = SlotSystem::getSidebarName(); 305*04fd306cSNickeau try { 306*04fd306cSNickeau $name = $this->getPathObject()->getLastNameWithoutExtension(); 307*04fd306cSNickeau } catch (ExceptionNotFound $e) { 308*04fd306cSNickeau // root case 309*04fd306cSNickeau return false; 310*04fd306cSNickeau } 311*04fd306cSNickeau return $name === $slotNames; 312*04fd306cSNickeau } 313*04fd306cSNickeau 314*04fd306cSNickeau /** 315*04fd306cSNickeau * @return bool true if this is the main 316*04fd306cSNickeau */ 317*04fd306cSNickeau public function isMainHeaderFooterSlot(): bool 318*04fd306cSNickeau { 319*04fd306cSNickeau 320*04fd306cSNickeau $slotNames = [SlotSystem::getMainHeaderSlotName(), SlotSystem::getMainFooterSlotName()]; 321*04fd306cSNickeau try { 322*04fd306cSNickeau $name = $this->getPathObject()->getLastNameWithoutExtension(); 323*04fd306cSNickeau } catch (ExceptionNotFound $e) { 324*04fd306cSNickeau // root case 325*04fd306cSNickeau return false; 326*04fd306cSNickeau } 327*04fd306cSNickeau 328*04fd306cSNickeau return in_array($name, $slotNames, true); 329*04fd306cSNickeau } 330*04fd306cSNickeau 331*04fd306cSNickeau 332*04fd306cSNickeau /** 333*04fd306cSNickeau * Return a canonical if set 334*04fd306cSNickeau * otherwise derive it from the id 335*04fd306cSNickeau * by taking the last two parts 336*04fd306cSNickeau * 337*04fd306cSNickeau * @return WikiPath 338*04fd306cSNickeau * @throws ExceptionNotFound 339*04fd306cSNickeau * @deprecated for {@link Canonical::getValueOrDefault()} 340*04fd306cSNickeau */ 341*04fd306cSNickeau public 342*04fd306cSNickeau function getCanonicalOrDefault(): WikiPath 343*04fd306cSNickeau { 344*04fd306cSNickeau return $this->canonical->getValueFromStoreOrDefault(); 345*04fd306cSNickeau 346*04fd306cSNickeau } 347*04fd306cSNickeau 348*04fd306cSNickeau 349*04fd306cSNickeau /** 350*04fd306cSNickeau * Rebuild the page 351*04fd306cSNickeau * (refresh from disk, reset object to null) 352*04fd306cSNickeau * @return $this 353*04fd306cSNickeau */ 354*04fd306cSNickeau public 355*04fd306cSNickeau function rebuild(): MarkupPath 356*04fd306cSNickeau { 357*04fd306cSNickeau $this->readStore = null; 358*04fd306cSNickeau $this->buildPropertiesFromFileSystem(); 359*04fd306cSNickeau return $this; 360*04fd306cSNickeau } 361*04fd306cSNickeau 362*04fd306cSNickeau /** 363*04fd306cSNickeau * 364*04fd306cSNickeau * @return MarkupPath[]|null the internal links or null 365*04fd306cSNickeau */ 366*04fd306cSNickeau public 367*04fd306cSNickeau function getLinkReferences(): ?array 368*04fd306cSNickeau { 369*04fd306cSNickeau $store = $this->getReadStoreOrDefault(); 370*04fd306cSNickeau if (!($store instanceof MetadataDokuWikiStore)) { 371*04fd306cSNickeau return null; 372*04fd306cSNickeau } 373*04fd306cSNickeau $metadata = $store->getCurrentFromName('relation'); 374*04fd306cSNickeau if ($metadata === null) { 375*04fd306cSNickeau /** 376*04fd306cSNickeau * Happens when no rendering has been made 377*04fd306cSNickeau */ 378*04fd306cSNickeau return null; 379*04fd306cSNickeau } 380*04fd306cSNickeau if (!key_exists('references', $metadata)) { 381*04fd306cSNickeau return null; 382*04fd306cSNickeau } 383*04fd306cSNickeau 384*04fd306cSNickeau $pages = []; 385*04fd306cSNickeau foreach (array_keys($metadata['references']) as $referencePageId) { 386*04fd306cSNickeau $pages[$referencePageId] = MarkupPath::createMarkupFromId($referencePageId); 387*04fd306cSNickeau } 388*04fd306cSNickeau return $pages; 389*04fd306cSNickeau 390*04fd306cSNickeau } 391*04fd306cSNickeau 392*04fd306cSNickeau 393*04fd306cSNickeau /** 394*04fd306cSNickeau * 395*04fd306cSNickeau * @throws ExceptionNotExists - if the path does not exists 396*04fd306cSNickeau * @throws ExceptionCast - if the path is not a wiki path which is mandatory for the context 397*04fd306cSNickeau */ 398*04fd306cSNickeau public function createHtmlFetcherWithItselfAsContextPath(): FetcherMarkup 399*04fd306cSNickeau { 400*04fd306cSNickeau $path = $this->getPathObject(); 401*04fd306cSNickeau return FetcherMarkup::createXhtmlMarkupFetcherFromPath($path, $path->toWikiPath()); 402*04fd306cSNickeau } 403*04fd306cSNickeau 404*04fd306cSNickeau /** 405*04fd306cSNickeau * @throws ExceptionCompile 406*04fd306cSNickeau */ 407*04fd306cSNickeau public function getHtmlPath(): LocalPath 408*04fd306cSNickeau { 409*04fd306cSNickeau 410*04fd306cSNickeau $fetcher = $this->createHtmlFetcherWithItselfAsContextPath(); 411*04fd306cSNickeau return $fetcher->processIfNeededAndGetFetchPath(); 412*04fd306cSNickeau 413*04fd306cSNickeau } 414*04fd306cSNickeau 415*04fd306cSNickeau /** 416*04fd306cSNickeau * Set the page quality 417*04fd306cSNickeau * @param boolean $value true if this is a low quality page rank false otherwise 418*04fd306cSNickeau * @throws ExceptionCompile 419*04fd306cSNickeau */ 420*04fd306cSNickeau public 421*04fd306cSNickeau function setCanBeOfLowQuality(bool $value): MarkupPath 422*04fd306cSNickeau { 423*04fd306cSNickeau return $this->setQualityIndicatorAndDeleteCacheIfNeeded($this->canBeOfLowQuality, $value); 424*04fd306cSNickeau } 425*04fd306cSNickeau 426*04fd306cSNickeau /** 427*04fd306cSNickeau * @return MarkupPath[] the backlinks 428*04fd306cSNickeau * Duplicate of related 429*04fd306cSNickeau * 430*04fd306cSNickeau * Same as {@link WikiPath::getReferencedBy()} ? 431*04fd306cSNickeau */ 432*04fd306cSNickeau public 433*04fd306cSNickeau function getBacklinks(): array 434*04fd306cSNickeau { 435*04fd306cSNickeau $backlinks = array(); 436*04fd306cSNickeau /** 437*04fd306cSNickeau * Same as 438*04fd306cSNickeau * idx_get_indexer()->lookupKey('relation_references', $ID); 439*04fd306cSNickeau */ 440*04fd306cSNickeau $ft_backlinks = ft_backlinks($this->getWikiId()); 441*04fd306cSNickeau foreach ($ft_backlinks as $backlinkId) { 442*04fd306cSNickeau $backlinks[$backlinkId] = MarkupPath::createMarkupFromId($backlinkId); 443*04fd306cSNickeau } 444*04fd306cSNickeau return $backlinks; 445*04fd306cSNickeau } 446*04fd306cSNickeau 447*04fd306cSNickeau 448*04fd306cSNickeau /** 449*04fd306cSNickeau * Low page quality 450*04fd306cSNickeau * @return bool true if this is a low quality page 451*04fd306cSNickeau */ 452*04fd306cSNickeau function isLowQualityPage(): bool 453*04fd306cSNickeau { 454*04fd306cSNickeau 455*04fd306cSNickeau 456*04fd306cSNickeau if (!$this->getCanBeOfLowQuality()) { 457*04fd306cSNickeau return false; 458*04fd306cSNickeau } 459*04fd306cSNickeau 460*04fd306cSNickeau if (!Site::isLowQualityProtectionEnable()) { 461*04fd306cSNickeau return false; 462*04fd306cSNickeau } 463*04fd306cSNickeau try { 464*04fd306cSNickeau return $this->getLowQualityIndicatorCalculated(); 465*04fd306cSNickeau } catch (ExceptionNotFound $e) { 466*04fd306cSNickeau // We were returning null but null used in a condition is falsy 467*04fd306cSNickeau // we return false 468*04fd306cSNickeau return false; 469*04fd306cSNickeau } 470*04fd306cSNickeau 471*04fd306cSNickeau } 472*04fd306cSNickeau 473*04fd306cSNickeau 474*04fd306cSNickeau /** 475*04fd306cSNickeau * 476*04fd306cSNickeau */ 477*04fd306cSNickeau public function getCanBeOfLowQuality(): bool 478*04fd306cSNickeau { 479*04fd306cSNickeau 480*04fd306cSNickeau return $this->canBeOfLowQuality->getValueOrDefault(); 481*04fd306cSNickeau 482*04fd306cSNickeau } 483*04fd306cSNickeau 484*04fd306cSNickeau 485*04fd306cSNickeau /** 486*04fd306cSNickeau * Return the Title 487*04fd306cSNickeau * @deprecated for {@link PageTitle::getValue()} 488*04fd306cSNickeau */ 489*04fd306cSNickeau public 490*04fd306cSNickeau function getTitle(): ?string 491*04fd306cSNickeau { 492*04fd306cSNickeau return $this->title->getValueFromStore(); 493*04fd306cSNickeau } 494*04fd306cSNickeau 495*04fd306cSNickeau /** 496*04fd306cSNickeau * If true, the page is quality monitored (a note is shown to the writer) 497*04fd306cSNickeau * @return null|bool 498*04fd306cSNickeau */ 499*04fd306cSNickeau public 500*04fd306cSNickeau function getQualityMonitoringIndicator(): ?bool 501*04fd306cSNickeau { 502*04fd306cSNickeau return $this->qualityMonitoringIndicator->getValueFromStore(); 503*04fd306cSNickeau } 504*04fd306cSNickeau 505*04fd306cSNickeau /** 506*04fd306cSNickeau * @return string the title, or h1 if empty or the id if empty 507*04fd306cSNickeau * Shortcut to {@link PageTitle::getValueOrDefault()} 508*04fd306cSNickeau * 509*04fd306cSNickeau */ 510*04fd306cSNickeau public 511*04fd306cSNickeau function getTitleOrDefault(): string 512*04fd306cSNickeau { 513*04fd306cSNickeau try { 514*04fd306cSNickeau return $this->title->getValueOrDefault(); 515*04fd306cSNickeau } catch (ExceptionNotFound $e) { 516*04fd306cSNickeau LogUtility::internalError("Internal Error: The page ($this) does not have any default title"); 517*04fd306cSNickeau return $this->getPathObject()->getLastNameWithoutExtension(); 518*04fd306cSNickeau } 519*04fd306cSNickeau 520*04fd306cSNickeau } 521*04fd306cSNickeau 522*04fd306cSNickeau 523*04fd306cSNickeau public function getH1OrDefault(): string 524*04fd306cSNickeau { 525*04fd306cSNickeau 526*04fd306cSNickeau return $this->h1->getValueOrDefault(); 527*04fd306cSNickeau 528*04fd306cSNickeau } 529*04fd306cSNickeau 530*04fd306cSNickeau /** 531*04fd306cSNickeau * @return string 532*04fd306cSNickeau * @throws ExceptionNotFound 533*04fd306cSNickeau */ 534*04fd306cSNickeau public 535*04fd306cSNickeau function getDescription(): string 536*04fd306cSNickeau { 537*04fd306cSNickeau return $this->description->getValue(); 538*04fd306cSNickeau } 539*04fd306cSNickeau 540*04fd306cSNickeau 541*04fd306cSNickeau /** 542*04fd306cSNickeau * @return string - the description or the dokuwiki generated description 543*04fd306cSNickeau */ 544*04fd306cSNickeau public 545*04fd306cSNickeau function getDescriptionOrElseDokuWiki(): string 546*04fd306cSNickeau { 547*04fd306cSNickeau return $this->description->getValueOrDefault(); 548*04fd306cSNickeau } 549*04fd306cSNickeau 550*04fd306cSNickeau 551*04fd306cSNickeau /** 552*04fd306cSNickeau * @return string 553*04fd306cSNickeau * The content / markup that should be parsed by the parser 554*04fd306cSNickeau */ 555*04fd306cSNickeau public 556*04fd306cSNickeau function getMarkup(): string 557*04fd306cSNickeau { 558*04fd306cSNickeau 559*04fd306cSNickeau try { 560*04fd306cSNickeau return FileSystems::getContent($this->getPathObject()); 561*04fd306cSNickeau } catch (ExceptionNotFound $e) { 562*04fd306cSNickeau LogUtility::msg("The page ($this) was not found"); 563*04fd306cSNickeau return ""; 564*04fd306cSNickeau } 565*04fd306cSNickeau 566*04fd306cSNickeau } 567*04fd306cSNickeau 568*04fd306cSNickeau 569*04fd306cSNickeau public 570*04fd306cSNickeau function isInIndex(): bool 571*04fd306cSNickeau { 572*04fd306cSNickeau $Indexer = idx_get_indexer(); 573*04fd306cSNickeau $pages = $Indexer->getPages(); 574*04fd306cSNickeau $return = array_search($this->getPathObject()->getWikiId(), $pages, true); 575*04fd306cSNickeau return $return !== false; 576*04fd306cSNickeau } 577*04fd306cSNickeau 578*04fd306cSNickeau 579*04fd306cSNickeau /** 580*04fd306cSNickeau * Save the content with the {@link ChangeLog} 581*04fd306cSNickeau * @param string $content 582*04fd306cSNickeau * @param string $summary 583*04fd306cSNickeau * @return $this 584*04fd306cSNickeau * Use {@link FileSystems::setContent()} if you don't want any log 585*04fd306cSNickeau * This function wraps {@link saveWikiText()} it implements the events system and may have side-effects 586*04fd306cSNickeau */ 587*04fd306cSNickeau public 588*04fd306cSNickeau function setContentWithLog(string $content, string $summary = "Default"): MarkupPath 589*04fd306cSNickeau { 590*04fd306cSNickeau $path = $this->getPathObject(); 591*04fd306cSNickeau if (!($path instanceof WikiPath)) { 592*04fd306cSNickeau throw new ExceptionRuntime("The path of this markup is not a wiki path"); 593*04fd306cSNickeau } 594*04fd306cSNickeau saveWikiText($path->getWikiId(), $content, $summary); 595*04fd306cSNickeau return $this; 596*04fd306cSNickeau } 597*04fd306cSNickeau 598*04fd306cSNickeau public 599*04fd306cSNickeau function addToIndex() 600*04fd306cSNickeau { 601*04fd306cSNickeau /** 602*04fd306cSNickeau * Add to index check the metadata cache 603*04fd306cSNickeau * Because we log the cache at the requested page level, we need to 604*04fd306cSNickeau * set the global ID 605*04fd306cSNickeau */ 606*04fd306cSNickeau global $ID; 607*04fd306cSNickeau $keep = $ID; 608*04fd306cSNickeau global $ACT; 609*04fd306cSNickeau $keepACT = $ACT; 610*04fd306cSNickeau try { 611*04fd306cSNickeau $ACT = "show"; 612*04fd306cSNickeau $ID = $this->getPathObject()->toWikiPath()->getWikiId(); 613*04fd306cSNickeau idx_addPage($ID); 614*04fd306cSNickeau } finally { 615*04fd306cSNickeau $ID = $keep; 616*04fd306cSNickeau $ACT = $keepACT; 617*04fd306cSNickeau } 618*04fd306cSNickeau return $this; 619*04fd306cSNickeau 620*04fd306cSNickeau } 621*04fd306cSNickeau 622*04fd306cSNickeau /** 623*04fd306cSNickeau * @return mixed 624*04fd306cSNickeau */ 625*04fd306cSNickeau public 626*04fd306cSNickeau function getTypeOrDefault() 627*04fd306cSNickeau { 628*04fd306cSNickeau return $this->type->getValueFromStoreOrDefault(); 629*04fd306cSNickeau } 630*04fd306cSNickeau 631*04fd306cSNickeau 632*04fd306cSNickeau /** 633*04fd306cSNickeau * @throws ExceptionNotFound 634*04fd306cSNickeau */ 635*04fd306cSNickeau public 636*04fd306cSNickeau function getFirstImage(): IFetcherLocalImage 637*04fd306cSNickeau { 638*04fd306cSNickeau try { 639*04fd306cSNickeau return IFetcherLocalImage::createImageFetchFromPath(FirstRasterImage::createForPage($this)->getValue()); 640*04fd306cSNickeau } catch (ExceptionBadSyntax|ExceptionBadArgument $e) { 641*04fd306cSNickeau LogUtility::error("First Raster Image error. Error: " . $e->getMessage(), self::CANONICAL_PAGE, $e); 642*04fd306cSNickeau throw new ExceptionNotFound(); 643*04fd306cSNickeau } catch (ExceptionNotExists $e) { 644*04fd306cSNickeau throw new ExceptionNotFound(); 645*04fd306cSNickeau } 646*04fd306cSNickeau 647*04fd306cSNickeau } 648*04fd306cSNickeau 649*04fd306cSNickeau /** 650*04fd306cSNickeau * Return the media stored during parsing 651*04fd306cSNickeau * 652*04fd306cSNickeau * They are saved via the function {@link \Doku_Renderer_metadata::_recordMediaUsage()} 653*04fd306cSNickeau * called by the {@link \Doku_Renderer_metadata::internalmedia()} 654*04fd306cSNickeau * 655*04fd306cSNickeau * 656*04fd306cSNickeau * {@link \Doku_Renderer_metadata::externalmedia()} does not save them 657*04fd306cSNickeau */ 658*04fd306cSNickeau public 659*04fd306cSNickeau function getMediasMetadata(): ?array 660*04fd306cSNickeau { 661*04fd306cSNickeau 662*04fd306cSNickeau $store = $this->getReadStoreOrDefault(); 663*04fd306cSNickeau if (!($store instanceof MetadataDokuWikiStore)) { 664*04fd306cSNickeau return null; 665*04fd306cSNickeau } 666*04fd306cSNickeau $medias = []; 667*04fd306cSNickeau 668*04fd306cSNickeau $relation = $store->getCurrentFromName('relation'); 669*04fd306cSNickeau if (isset($relation['media'])) { 670*04fd306cSNickeau /** 671*04fd306cSNickeau * The relation is 672*04fd306cSNickeau * $this->meta['relation']['media'][$src] = $exists; 673*04fd306cSNickeau * 674*04fd306cSNickeau */ 675*04fd306cSNickeau foreach ($relation['media'] as $src => $exists) { 676*04fd306cSNickeau if ($exists) { 677*04fd306cSNickeau $medias[] = $src; 678*04fd306cSNickeau } 679*04fd306cSNickeau } 680*04fd306cSNickeau } 681*04fd306cSNickeau return $medias; 682*04fd306cSNickeau } 683*04fd306cSNickeau 684*04fd306cSNickeau 685*04fd306cSNickeau /** 686*04fd306cSNickeau * Get author name 687*04fd306cSNickeau * 688*04fd306cSNickeau * @return string 689*04fd306cSNickeau */ 690*04fd306cSNickeau public 691*04fd306cSNickeau function getAuthor(): ?string 692*04fd306cSNickeau { 693*04fd306cSNickeau $store = $this->getReadStoreOrDefault(); 694*04fd306cSNickeau if (!($store instanceof MetadataDokuWikiStore)) { 695*04fd306cSNickeau return null; 696*04fd306cSNickeau } 697*04fd306cSNickeau 698*04fd306cSNickeau return $store->getFromName('creator'); 699*04fd306cSNickeau } 700*04fd306cSNickeau 701*04fd306cSNickeau /** 702*04fd306cSNickeau * Get author ID 703*04fd306cSNickeau * 704*04fd306cSNickeau * @return string 705*04fd306cSNickeau */ 706*04fd306cSNickeau public 707*04fd306cSNickeau function getAuthorID(): ?string 708*04fd306cSNickeau { 709*04fd306cSNickeau 710*04fd306cSNickeau $store = $this->getReadStoreOrDefault(); 711*04fd306cSNickeau if (!($store instanceof MetadataDokuWikiStore)) { 712*04fd306cSNickeau return null; 713*04fd306cSNickeau } 714*04fd306cSNickeau 715*04fd306cSNickeau return $store->getFromName('user'); 716*04fd306cSNickeau 717*04fd306cSNickeau } 718*04fd306cSNickeau 719*04fd306cSNickeau 720*04fd306cSNickeau /** 721*04fd306cSNickeau * Get the create date of page 722*04fd306cSNickeau * 723*04fd306cSNickeau * @return DateTime 724*04fd306cSNickeau * @throws ExceptionNotFound 725*04fd306cSNickeau */ 726*04fd306cSNickeau public 727*04fd306cSNickeau function getCreatedTime(): ?DateTime 728*04fd306cSNickeau { 729*04fd306cSNickeau return $this->creationTime->getValue(); 730*04fd306cSNickeau } 731*04fd306cSNickeau 732*04fd306cSNickeau 733*04fd306cSNickeau /** 734*04fd306cSNickeau * 735*04fd306cSNickeau * @return DateTime 736*04fd306cSNickeau */ 737*04fd306cSNickeau public 738*04fd306cSNickeau function getModifiedTime(): DateTime 739*04fd306cSNickeau { 740*04fd306cSNickeau return $this->modifiedTime->getValueFromStore(); 741*04fd306cSNickeau } 742*04fd306cSNickeau 743*04fd306cSNickeau /** 744*04fd306cSNickeau * @throws ExceptionNotFound 745*04fd306cSNickeau */ 746*04fd306cSNickeau public 747*04fd306cSNickeau function getModifiedTimeOrDefault(): DateTime 748*04fd306cSNickeau { 749*04fd306cSNickeau return $this->modifiedTime->getValueFromStoreOrDefault(); 750*04fd306cSNickeau } 751*04fd306cSNickeau 752*04fd306cSNickeau 753*04fd306cSNickeau /** 754*04fd306cSNickeau * Utility class, refresh the metadata (used only in test) 755*04fd306cSNickeau * @deprecated if possible used {@link FetcherMarkup} instead 756*04fd306cSNickeau */ 757*04fd306cSNickeau public function renderMetadataAndFlush(): MarkupPath 758*04fd306cSNickeau { 759*04fd306cSNickeau 760*04fd306cSNickeau if (!FileSystems::exists($this)) { 761*04fd306cSNickeau if (PluginUtility::isDevOrTest()) { 762*04fd306cSNickeau LogUtility::msg("You can't render the metadata of a markup path that does not exist ($this)"); 763*04fd306cSNickeau } 764*04fd306cSNickeau return $this; 765*04fd306cSNickeau } 766*04fd306cSNickeau 767*04fd306cSNickeau try { 768*04fd306cSNickeau $wikiPath = $this->getPathObject()->toWikiPath(); 769*04fd306cSNickeau FetcherMarkup::confRoot() 770*04fd306cSNickeau ->setRequestedContextPath($wikiPath) 771*04fd306cSNickeau ->setRequestedExecutingPath($wikiPath) 772*04fd306cSNickeau ->setRequestedMimeToMetadata() 773*04fd306cSNickeau ->build() 774*04fd306cSNickeau ->processMetadataIfNotYetDone(); 775*04fd306cSNickeau } catch (ExceptionCast|ExceptionNotExists $e) { 776*04fd306cSNickeau // not a wiki path, no meta 777*04fd306cSNickeau } 778*04fd306cSNickeau 779*04fd306cSNickeau 780*04fd306cSNickeau return $this; 781*04fd306cSNickeau 782*04fd306cSNickeau } 783*04fd306cSNickeau 784*04fd306cSNickeau /** 785*04fd306cSNickeau * @return string|null 786*04fd306cSNickeau * @deprecated for {@link Region} 787*04fd306cSNickeau */ 788*04fd306cSNickeau public 789*04fd306cSNickeau function getLocaleRegion(): ?string 790*04fd306cSNickeau { 791*04fd306cSNickeau return $this->region->getValueFromStore(); 792*04fd306cSNickeau } 793*04fd306cSNickeau 794*04fd306cSNickeau public 795*04fd306cSNickeau function getRegionOrDefault() 796*04fd306cSNickeau { 797*04fd306cSNickeau 798*04fd306cSNickeau return $this->region->getValueFromStoreOrDefault(); 799*04fd306cSNickeau 800*04fd306cSNickeau } 801*04fd306cSNickeau 802*04fd306cSNickeau public 803*04fd306cSNickeau function getLang(): ?string 804*04fd306cSNickeau { 805*04fd306cSNickeau return $this->lang->getValueFromStore(); 806*04fd306cSNickeau } 807*04fd306cSNickeau 808*04fd306cSNickeau public function getLangOrDefault(): string 809*04fd306cSNickeau { 810*04fd306cSNickeau return $this->lang->getValueOrDefault(); 811*04fd306cSNickeau } 812*04fd306cSNickeau 813*04fd306cSNickeau /** 814*04fd306cSNickeau * The home page is an index page 815*04fd306cSNickeau * Adapted from {@link FsWikiUtility::getHomePagePath()} 816*04fd306cSNickeau * @return bool 817*04fd306cSNickeau */ 818*04fd306cSNickeau public function isIndexPage(): bool 819*04fd306cSNickeau { 820*04fd306cSNickeau 821*04fd306cSNickeau $startPageName = Site::getIndexPageName(); 822*04fd306cSNickeau try { 823*04fd306cSNickeau if ($this->getPathObject()->getLastNameWithoutExtension() === $startPageName) { 824*04fd306cSNickeau return true; 825*04fd306cSNickeau } 826*04fd306cSNickeau } catch (ExceptionNotFound $e) { 827*04fd306cSNickeau // ok 828*04fd306cSNickeau } 829*04fd306cSNickeau 830*04fd306cSNickeau try { 831*04fd306cSNickeau /** 832*04fd306cSNickeau * page named like the NS inside the NS 833*04fd306cSNickeau * ie ns:ns 834*04fd306cSNickeau */ 835*04fd306cSNickeau $objectPath = $this->path; 836*04fd306cSNickeau $parentPath = $this->path->getParent(); 837*04fd306cSNickeau if (!($parentPath instanceof WikiPath)) { 838*04fd306cSNickeau return false; 839*04fd306cSNickeau } 840*04fd306cSNickeau if ($parentPath->getLastNameWithoutExtension() === $objectPath->getLastNameWithoutExtension()) { 841*04fd306cSNickeau /** 842*04fd306cSNickeau * If the start page does not exists, this is the index page 843*04fd306cSNickeau */ 844*04fd306cSNickeau $startPage = $parentPath->resolveId($startPageName); 845*04fd306cSNickeau if (!FileSystems::exists($startPage)) { 846*04fd306cSNickeau return true; 847*04fd306cSNickeau } 848*04fd306cSNickeau } 849*04fd306cSNickeau } catch (ExceptionNotFound $e) { 850*04fd306cSNickeau // no parent, no last name, etc 851*04fd306cSNickeau } 852*04fd306cSNickeau 853*04fd306cSNickeau return false; 854*04fd306cSNickeau } 855*04fd306cSNickeau 856*04fd306cSNickeau 857*04fd306cSNickeau /** 858*04fd306cSNickeau * @throws ExceptionNotFound 859*04fd306cSNickeau */ 860*04fd306cSNickeau public 861*04fd306cSNickeau function getPublishedTime(): DateTime 862*04fd306cSNickeau { 863*04fd306cSNickeau return $this->publishedDate->getValueFromStore(); 864*04fd306cSNickeau } 865*04fd306cSNickeau 866*04fd306cSNickeau /** 867*04fd306cSNickeau * @return bool 868*04fd306cSNickeau * @deprecated for {@link FileSystems::exists()} 869*04fd306cSNickeau */ 870*04fd306cSNickeau public function exists(): bool 871*04fd306cSNickeau { 872*04fd306cSNickeau return FileSystems::exists($this); 873*04fd306cSNickeau } 874*04fd306cSNickeau 875*04fd306cSNickeau /** 876*04fd306cSNickeau * @return DateTime 877*04fd306cSNickeau * @throws ExceptionNotFound 878*04fd306cSNickeau */ 879*04fd306cSNickeau public 880*04fd306cSNickeau function getPublishedElseCreationTime(): DateTime 881*04fd306cSNickeau { 882*04fd306cSNickeau return $this->publishedDate->getValueFromStoreOrDefault(); 883*04fd306cSNickeau } 884*04fd306cSNickeau 885*04fd306cSNickeau 886*04fd306cSNickeau public 887*04fd306cSNickeau function isLatePublication(): bool 888*04fd306cSNickeau { 889*04fd306cSNickeau try { 890*04fd306cSNickeau $dateTime = $this->getPublishedElseCreationTime(); 891*04fd306cSNickeau } catch (ExceptionNotFound $e) { 892*04fd306cSNickeau return false; 893*04fd306cSNickeau } 894*04fd306cSNickeau return $dateTime > new DateTime('now'); 895*04fd306cSNickeau } 896*04fd306cSNickeau 897*04fd306cSNickeau /** 898*04fd306cSNickeau * The unique page Url (also known as Canonical URL) used: 899*04fd306cSNickeau * * in the link 900*04fd306cSNickeau * * in the canonical ref 901*04fd306cSNickeau * * in the site map 902*04fd306cSNickeau * @return Url 903*04fd306cSNickeau */ 904*04fd306cSNickeau public 905*04fd306cSNickeau function getCanonicalUrl(): Url 906*04fd306cSNickeau { 907*04fd306cSNickeau 908*04fd306cSNickeau /** 909*04fd306cSNickeau * Dokuwiki Methodology Taken from {@link tpl_metaheaders()} 910*04fd306cSNickeau */ 911*04fd306cSNickeau if ($this->isRootHomePage()) { 912*04fd306cSNickeau return UrlEndpoint::createBaseUrl(); 913*04fd306cSNickeau } 914*04fd306cSNickeau 915*04fd306cSNickeau try { 916*04fd306cSNickeau return UrlEndpoint::createDokuUrl() 917*04fd306cSNickeau ->setQueryParameter(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE, $this->getWikiId()); 918*04fd306cSNickeau } catch (ExceptionBadArgument $e) { 919*04fd306cSNickeau LogUtility::error("This markup path ($this) can not be accessed externaly"); 920*04fd306cSNickeau return UrlEndpoint::createBaseUrl(); 921*04fd306cSNickeau } 922*04fd306cSNickeau 923*04fd306cSNickeau 924*04fd306cSNickeau } 925*04fd306cSNickeau 926*04fd306cSNickeau 927*04fd306cSNickeau 928*04fd306cSNickeau /** 929*04fd306cSNickeau * 930*04fd306cSNickeau * @return string|null - the locale facebook way 931*04fd306cSNickeau * @throws ExceptionNotFound 932*04fd306cSNickeau * @deprecated for {@link Locale} 933*04fd306cSNickeau */ 934*04fd306cSNickeau public 935*04fd306cSNickeau function getLocale($default = null): ?string 936*04fd306cSNickeau { 937*04fd306cSNickeau $value = $this->locale->getValueFromStore(); 938*04fd306cSNickeau if ($value === null) { 939*04fd306cSNickeau return $default; 940*04fd306cSNickeau } 941*04fd306cSNickeau return $value; 942*04fd306cSNickeau } 943*04fd306cSNickeau 944*04fd306cSNickeau 945*04fd306cSNickeau /** 946*04fd306cSNickeau * 947*04fd306cSNickeau * @deprecated use a {@link FetcherMarkup::getFetchString()} instead 948*04fd306cSNickeau */ 949*04fd306cSNickeau public function toXhtml(): string 950*04fd306cSNickeau { 951*04fd306cSNickeau 952*04fd306cSNickeau $fetcherMarkup = $this->createHtmlFetcherWithItselfAsContextPath(); 953*04fd306cSNickeau return $fetcherMarkup->getFetchString(); 954*04fd306cSNickeau 955*04fd306cSNickeau 956*04fd306cSNickeau } 957*04fd306cSNickeau 958*04fd306cSNickeau 959*04fd306cSNickeau public 960*04fd306cSNickeau function getHtmlAnchorLink($logicalTag = null): string 961*04fd306cSNickeau { 962*04fd306cSNickeau $id = $this->getPathObject()->getWikiId(); 963*04fd306cSNickeau try { 964*04fd306cSNickeau return LinkMarkup::createFromPageIdOrPath($id) 965*04fd306cSNickeau ->toAttributes($logicalTag) 966*04fd306cSNickeau ->toHtmlEnterTag("a") 967*04fd306cSNickeau . $this->getNameOrDefault() 968*04fd306cSNickeau . "</a>"; 969*04fd306cSNickeau } catch (ExceptionCompile $e) { 970*04fd306cSNickeau LogUtility::msg("The markup ref returns an error for the creation of the page anchor html link ($this). Error: {$e->getMessage()}"); 971*04fd306cSNickeau return "<a href=\"{$this->getCanonicalUrl()}\" data-wiki-id=\"$id\">{$this->getNameOrDefault()}</a>"; 972*04fd306cSNickeau } 973*04fd306cSNickeau } 974*04fd306cSNickeau 975*04fd306cSNickeau 976*04fd306cSNickeau /** 977*04fd306cSNickeau * Without the `:` at the end 978*04fd306cSNickeau * @return string 979*04fd306cSNickeau * @throws ExceptionNotFound 980*04fd306cSNickeau * @deprecated / shortcut for {@link WikiPath::getParent()} 981*04fd306cSNickeau * Because a page has always a parent, the string is never null. 982*04fd306cSNickeau */ 983*04fd306cSNickeau public function getNamespacePath(): string 984*04fd306cSNickeau { 985*04fd306cSNickeau 986*04fd306cSNickeau return $this->getParent()->toAbsoluteId(); 987*04fd306cSNickeau 988*04fd306cSNickeau } 989*04fd306cSNickeau 990*04fd306cSNickeau 991*04fd306cSNickeau /** 992*04fd306cSNickeau * @return $this 993*04fd306cSNickeau * @deprecated use {@link MetadataDokuWikiStore::deleteAndFlush()} 994*04fd306cSNickeau */ 995*04fd306cSNickeau public 996*04fd306cSNickeau function deleteMetadatasAndFlush(): MarkupPath 997*04fd306cSNickeau { 998*04fd306cSNickeau MetadataDokuWikiStore::getOrCreateFromResource($this) 999*04fd306cSNickeau ->deleteAndFlush(); 1000*04fd306cSNickeau return $this; 1001*04fd306cSNickeau } 1002*04fd306cSNickeau 1003*04fd306cSNickeau /** 1004*04fd306cSNickeau * @throws ExceptionNotFound 1005*04fd306cSNickeau */ 1006*04fd306cSNickeau public 1007*04fd306cSNickeau function getName(): string 1008*04fd306cSNickeau { 1009*04fd306cSNickeau 1010*04fd306cSNickeau return $this->pageName->getValue(); 1011*04fd306cSNickeau 1012*04fd306cSNickeau } 1013*04fd306cSNickeau 1014*04fd306cSNickeau public 1015*04fd306cSNickeau function getNameOrDefault(): string 1016*04fd306cSNickeau { 1017*04fd306cSNickeau 1018*04fd306cSNickeau return ResourceName::createForResource($this)->getValueOrDefault(); 1019*04fd306cSNickeau 1020*04fd306cSNickeau 1021*04fd306cSNickeau } 1022*04fd306cSNickeau 1023*04fd306cSNickeau /** 1024*04fd306cSNickeau * @param $property 1025*04fd306cSNickeau */ 1026*04fd306cSNickeau public 1027*04fd306cSNickeau function unsetMetadata($property) 1028*04fd306cSNickeau { 1029*04fd306cSNickeau $meta = p_read_metadata($this->getPathObject()->getWikiId()); 1030*04fd306cSNickeau if (isset($meta['persistent'][$property])) { 1031*04fd306cSNickeau unset($meta['persistent'][$property]); 1032*04fd306cSNickeau } 1033*04fd306cSNickeau p_save_metadata($this->getPathObject()->getWikiId(), $meta); 1034*04fd306cSNickeau 1035*04fd306cSNickeau } 1036*04fd306cSNickeau 1037*04fd306cSNickeau /** 1038*04fd306cSNickeau * @return array - return the standard / generated metadata 1039*04fd306cSNickeau * used to create a variable environment (context) in rendering 1040*04fd306cSNickeau */ 1041*04fd306cSNickeau public 1042*04fd306cSNickeau function getMetadataForRendering(): array 1043*04fd306cSNickeau { 1044*04fd306cSNickeau 1045*04fd306cSNickeau $metadataNames = [ 1046*04fd306cSNickeau PageH1::PROPERTY_NAME, 1047*04fd306cSNickeau PageTitle::PROPERTY_NAME, 1048*04fd306cSNickeau Lead::PROPERTY_NAME, 1049*04fd306cSNickeau Canonical::PROPERTY_NAME, 1050*04fd306cSNickeau PagePath::PROPERTY_NAME, 1051*04fd306cSNickeau Label::PROPERTY_NAME, 1052*04fd306cSNickeau PageDescription::PROPERTY_NAME, 1053*04fd306cSNickeau ResourceName::PROPERTY_NAME, 1054*04fd306cSNickeau PageType::PROPERTY_NAME, 1055*04fd306cSNickeau Slug::PROPERTY_NAME, 1056*04fd306cSNickeau PageTemplateName::PROPERTY_NAME, 1057*04fd306cSNickeau DokuwikiId::DOKUWIKI_ID_ATTRIBUTE, // Dokuwiki id is deprecated for path 1058*04fd306cSNickeau PageLevel::PROPERTY_NAME, 1059*04fd306cSNickeau PageKeywords::PROPERTY_NAME 1060*04fd306cSNickeau ]; 1061*04fd306cSNickeau 1062*04fd306cSNickeau /** 1063*04fd306cSNickeau * The metadata that works only 1064*04fd306cSNickeau * if the file exists 1065*04fd306cSNickeau */ 1066*04fd306cSNickeau if (FileSystems::exists($this)) { 1067*04fd306cSNickeau $metadataThatNeedsExistingFile = [ 1068*04fd306cSNickeau PageId::PROPERTY_NAME, 1069*04fd306cSNickeau CreationDate::PROPERTY_NAME, 1070*04fd306cSNickeau ModificationDate::PROPERTY_NAME, 1071*04fd306cSNickeau PagePublicationDate::PROPERTY_NAME, 1072*04fd306cSNickeau StartDate::PROPERTY_NAME, 1073*04fd306cSNickeau EndDate::PROPERTY_NAME, 1074*04fd306cSNickeau ]; 1075*04fd306cSNickeau $metadataNames = array_merge($metadataNames, $metadataThatNeedsExistingFile); 1076*04fd306cSNickeau } 1077*04fd306cSNickeau 1078*04fd306cSNickeau 1079*04fd306cSNickeau foreach ($metadataNames as $metadataName) { 1080*04fd306cSNickeau try { 1081*04fd306cSNickeau $metadata = Meta\Api\MetadataSystem::getForName($metadataName); 1082*04fd306cSNickeau } catch (ExceptionNotFound $e) { 1083*04fd306cSNickeau LogUtility::msg("The metadata ($metadataName) should be defined"); 1084*04fd306cSNickeau continue; 1085*04fd306cSNickeau } 1086*04fd306cSNickeau /** 1087*04fd306cSNickeau * The Value or Default is returned 1088*04fd306cSNickeau * 1089*04fd306cSNickeau * Because the title/h1 should never be null 1090*04fd306cSNickeau * otherwise a template link such as [[$path|$title]] will return a link without an description 1091*04fd306cSNickeau * and therefore will be not visible 1092*04fd306cSNickeau * 1093*04fd306cSNickeau * ToStoreValue to get the string format of date/boolean in the {@link PipelineUtility} 1094*04fd306cSNickeau * If we want the native value, we need to change the pipeline 1095*04fd306cSNickeau */ 1096*04fd306cSNickeau $value = $metadata 1097*04fd306cSNickeau ->setResource($this) 1098*04fd306cSNickeau ->setReadStore(MetadataDokuWikiStore::class) 1099*04fd306cSNickeau ->setWriteStore(TemplateStore::class) 1100*04fd306cSNickeau ->buildFromReadStore() 1101*04fd306cSNickeau ->toStoreValueOrDefault(); 1102*04fd306cSNickeau $array[$metadataName] = $value; 1103*04fd306cSNickeau } 1104*04fd306cSNickeau 1105*04fd306cSNickeau $array["url"] = $this->getCanonicalUrl()->toAbsoluteUrl()->toString(); 1106*04fd306cSNickeau $array["now"] = Iso8601Date::createFromNow()->toString(); 1107*04fd306cSNickeau return $array; 1108*04fd306cSNickeau 1109*04fd306cSNickeau } 1110*04fd306cSNickeau 1111*04fd306cSNickeau 1112*04fd306cSNickeau public 1113*04fd306cSNickeau function getPublishedTimeAsString(): ?string 1114*04fd306cSNickeau { 1115*04fd306cSNickeau return $this->getPublishedTime() !== null ? $this->getPublishedTime()->format(Iso8601Date::getFormat()) : null; 1116*04fd306cSNickeau } 1117*04fd306cSNickeau 1118*04fd306cSNickeau 1119*04fd306cSNickeau /** 1120*04fd306cSNickeau * @throws ExceptionNotFound 1121*04fd306cSNickeau */ 1122*04fd306cSNickeau public 1123*04fd306cSNickeau function getEndDate(): DateTime 1124*04fd306cSNickeau { 1125*04fd306cSNickeau return $this->endDate->getValue(); 1126*04fd306cSNickeau } 1127*04fd306cSNickeau 1128*04fd306cSNickeau 1129*04fd306cSNickeau 1130*04fd306cSNickeau /** 1131*04fd306cSNickeau * @throws ExceptionNotFound 1132*04fd306cSNickeau */ 1133*04fd306cSNickeau public 1134*04fd306cSNickeau function getStartDate(): DateTime 1135*04fd306cSNickeau { 1136*04fd306cSNickeau return $this->startDate->getValue(); 1137*04fd306cSNickeau } 1138*04fd306cSNickeau 1139*04fd306cSNickeau /** 1140*04fd306cSNickeau * A page id 1141*04fd306cSNickeau * @return string 1142*04fd306cSNickeau * @throws ExceptionNotFound - when the page does not exist 1143*04fd306cSNickeau */ 1144*04fd306cSNickeau public 1145*04fd306cSNickeau function getPageId(): string 1146*04fd306cSNickeau { 1147*04fd306cSNickeau return PageId::createForPage($this)->getValue(); 1148*04fd306cSNickeau } 1149*04fd306cSNickeau 1150*04fd306cSNickeau 1151*04fd306cSNickeau /** 1152*04fd306cSNickeau * @throws ExceptionNotExists 1153*04fd306cSNickeau */ 1154*04fd306cSNickeau public 1155*04fd306cSNickeau function fetchAnalyticsDocument(): FetcherMarkup 1156*04fd306cSNickeau { 1157*04fd306cSNickeau return renderer_plugin_combo_analytics::createAnalyticsFetcherForPageFragment($this); 1158*04fd306cSNickeau } 1159*04fd306cSNickeau 1160*04fd306cSNickeau /** 1161*04fd306cSNickeau * @throws ExceptionCompile 1162*04fd306cSNickeau * @throws ExceptionNotExists 1163*04fd306cSNickeau */ 1164*04fd306cSNickeau public 1165*04fd306cSNickeau function fetchAnalyticsPath(): Path 1166*04fd306cSNickeau { 1167*04fd306cSNickeau $fetcher = renderer_plugin_combo_analytics::createAnalyticsFetcherForPageFragment($this); 1168*04fd306cSNickeau return $fetcher->processIfNeededAndGetFetchPath(); 1169*04fd306cSNickeau 1170*04fd306cSNickeau } 1171*04fd306cSNickeau 1172*04fd306cSNickeau /** 1173*04fd306cSNickeau */ 1174*04fd306cSNickeau public 1175*04fd306cSNickeau function getDatabasePage(): DatabasePageRow 1176*04fd306cSNickeau { 1177*04fd306cSNickeau 1178*04fd306cSNickeau return DatabasePageRow::getFromPageObject($this); 1179*04fd306cSNickeau 1180*04fd306cSNickeau } 1181*04fd306cSNickeau 1182*04fd306cSNickeau /** 1183*04fd306cSNickeau * @throws ExceptionSqliteNotAvailable 1184*04fd306cSNickeau */ 1185*04fd306cSNickeau public 1186*04fd306cSNickeau function getOrCreateDatabasePage(): DatabasePageRow 1187*04fd306cSNickeau { 1188*04fd306cSNickeau 1189*04fd306cSNickeau return DatabasePageRow::getOrCreateFromPageObject($this); 1190*04fd306cSNickeau 1191*04fd306cSNickeau } 1192*04fd306cSNickeau 1193*04fd306cSNickeau public 1194*04fd306cSNickeau function canBeUpdatedByCurrentUser(): bool 1195*04fd306cSNickeau { 1196*04fd306cSNickeau return Identity::isWriter($this->getWikiId()); 1197*04fd306cSNickeau } 1198*04fd306cSNickeau 1199*04fd306cSNickeau 1200*04fd306cSNickeau public 1201*04fd306cSNickeau function isRootHomePage(): bool 1202*04fd306cSNickeau { 1203*04fd306cSNickeau global $conf; 1204*04fd306cSNickeau $startPageName = $conf['start']; 1205*04fd306cSNickeau return $this->getPathObject()->toAbsoluteId() === ":$startPageName"; 1206*04fd306cSNickeau 1207*04fd306cSNickeau } 1208*04fd306cSNickeau 1209*04fd306cSNickeau 1210*04fd306cSNickeau /** 1211*04fd306cSNickeau * @throws ExceptionNotFound 1212*04fd306cSNickeau */ 1213*04fd306cSNickeau public 1214*04fd306cSNickeau function getPageType(): string 1215*04fd306cSNickeau { 1216*04fd306cSNickeau return $this->type->getValueFromStore(); 1217*04fd306cSNickeau } 1218*04fd306cSNickeau 1219*04fd306cSNickeau /** 1220*04fd306cSNickeau * @throws ExceptionNotFound 1221*04fd306cSNickeau * @deprecated 1222*04fd306cSNickeau */ 1223*04fd306cSNickeau public 1224*04fd306cSNickeau function getCanonical(): WikiPath 1225*04fd306cSNickeau { 1226*04fd306cSNickeau return $this->canonical->getValue(); 1227*04fd306cSNickeau } 1228*04fd306cSNickeau 1229*04fd306cSNickeau /** 1230*04fd306cSNickeau * Create a canonical from the last page path part. 1231*04fd306cSNickeau * 1232*04fd306cSNickeau * @return string|null 1233*04fd306cSNickeau * @throws ExceptionNotFound 1234*04fd306cSNickeau */ 1235*04fd306cSNickeau public 1236*04fd306cSNickeau function getDefaultCanonical(): ?string 1237*04fd306cSNickeau { 1238*04fd306cSNickeau return $this->canonical->getDefaultValue(); 1239*04fd306cSNickeau } 1240*04fd306cSNickeau 1241*04fd306cSNickeau /** 1242*04fd306cSNickeau * @throws ExceptionNotFound 1243*04fd306cSNickeau */ 1244*04fd306cSNickeau public 1245*04fd306cSNickeau function getLayout() 1246*04fd306cSNickeau { 1247*04fd306cSNickeau return $this->layout->getValueFromStore(); 1248*04fd306cSNickeau } 1249*04fd306cSNickeau 1250*04fd306cSNickeau /** 1251*04fd306cSNickeau * @throws ExceptionNotFound 1252*04fd306cSNickeau */ 1253*04fd306cSNickeau public 1254*04fd306cSNickeau function getDefaultPageName(): string 1255*04fd306cSNickeau { 1256*04fd306cSNickeau return $this->pageName->getDefaultValue(); 1257*04fd306cSNickeau } 1258*04fd306cSNickeau 1259*04fd306cSNickeau public 1260*04fd306cSNickeau function getDefaultTitle(): string 1261*04fd306cSNickeau { 1262*04fd306cSNickeau return $this->title->getDefaultValue(); 1263*04fd306cSNickeau } 1264*04fd306cSNickeau 1265*04fd306cSNickeau /** 1266*04fd306cSNickeau * @throws ExceptionNotFound 1267*04fd306cSNickeau */ 1268*04fd306cSNickeau public 1269*04fd306cSNickeau function getDefaultH1() 1270*04fd306cSNickeau { 1271*04fd306cSNickeau return $this->h1->getValueOrDefault(); 1272*04fd306cSNickeau } 1273*04fd306cSNickeau 1274*04fd306cSNickeau public 1275*04fd306cSNickeau function getDefaultType(): string 1276*04fd306cSNickeau { 1277*04fd306cSNickeau return $this->type->getDefaultValue(); 1278*04fd306cSNickeau } 1279*04fd306cSNickeau 1280*04fd306cSNickeau public 1281*04fd306cSNickeau function getDefaultLayout(): string 1282*04fd306cSNickeau { 1283*04fd306cSNickeau return $this->layout->getDefaultValue(); 1284*04fd306cSNickeau } 1285*04fd306cSNickeau 1286*04fd306cSNickeau 1287*04fd306cSNickeau /** 1288*04fd306cSNickeau * 1289*04fd306cSNickeau * @throws ExceptionCompile 1290*04fd306cSNickeau */ 1291*04fd306cSNickeau public 1292*04fd306cSNickeau function setLowQualityIndicatorCalculation($bool): MarkupPath 1293*04fd306cSNickeau { 1294*04fd306cSNickeau return $this->setQualityIndicatorAndDeleteCacheIfNeeded($this->lowQualityIndicatorCalculated, $bool); 1295*04fd306cSNickeau } 1296*04fd306cSNickeau 1297*04fd306cSNickeau 1298*04fd306cSNickeau /** 1299*04fd306cSNickeau * Change the quality indicator 1300*04fd306cSNickeau * and if the quality level has become low 1301*04fd306cSNickeau * and that the protection is on, delete the cache 1302*04fd306cSNickeau * @param MetadataBoolean $lowQualityAttributeName 1303*04fd306cSNickeau * @param bool $value 1304*04fd306cSNickeau * @return MarkupPath 1305*04fd306cSNickeau * @throws ExceptionBadArgument - if the value cannot be persisted 1306*04fd306cSNickeau */ 1307*04fd306cSNickeau private 1308*04fd306cSNickeau function setQualityIndicatorAndDeleteCacheIfNeeded(MetadataBoolean $lowQualityAttributeName, bool $value): MarkupPath 1309*04fd306cSNickeau { 1310*04fd306cSNickeau try { 1311*04fd306cSNickeau $actualValue = $lowQualityAttributeName->getValue(); 1312*04fd306cSNickeau } catch (ExceptionNotFound $e) { 1313*04fd306cSNickeau $actualValue = null; 1314*04fd306cSNickeau } 1315*04fd306cSNickeau if ($value !== $actualValue) { 1316*04fd306cSNickeau $lowQualityAttributeName 1317*04fd306cSNickeau ->setValue($value) 1318*04fd306cSNickeau ->persist(); 1319*04fd306cSNickeau } 1320*04fd306cSNickeau return $this; 1321*04fd306cSNickeau } 1322*04fd306cSNickeau 1323*04fd306cSNickeau 1324*04fd306cSNickeau /** 1325*04fd306cSNickeau * @throws ExceptionNotFound 1326*04fd306cSNickeau */ 1327*04fd306cSNickeau public 1328*04fd306cSNickeau function getLowQualityIndicatorCalculated() 1329*04fd306cSNickeau { 1330*04fd306cSNickeau 1331*04fd306cSNickeau return $this->lowQualityIndicatorCalculated->getValueOrDefault(); 1332*04fd306cSNickeau 1333*04fd306cSNickeau } 1334*04fd306cSNickeau 1335*04fd306cSNickeau /** 1336*04fd306cSNickeau * @return PageImage[] 1337*04fd306cSNickeau * @deprecated 1338*04fd306cSNickeau */ 1339*04fd306cSNickeau public 1340*04fd306cSNickeau function getPageMetadataImages(): array 1341*04fd306cSNickeau { 1342*04fd306cSNickeau return $this->pageImages->getValueAsPageImages(); 1343*04fd306cSNickeau } 1344*04fd306cSNickeau 1345*04fd306cSNickeau 1346*04fd306cSNickeau /** 1347*04fd306cSNickeau * @param array|string $jsonLd 1348*04fd306cSNickeau * @return $this 1349*04fd306cSNickeau * @throws ExceptionCompile 1350*04fd306cSNickeau * @deprecated for {@link LdJson} 1351*04fd306cSNickeau */ 1352*04fd306cSNickeau public 1353*04fd306cSNickeau function setJsonLd($jsonLd): MarkupPath 1354*04fd306cSNickeau { 1355*04fd306cSNickeau $this->ldJson 1356*04fd306cSNickeau ->setValue($jsonLd) 1357*04fd306cSNickeau ->sendToWriteStore(); 1358*04fd306cSNickeau return $this; 1359*04fd306cSNickeau } 1360*04fd306cSNickeau 1361*04fd306cSNickeau /** 1362*04fd306cSNickeau * @throws ExceptionCompile 1363*04fd306cSNickeau */ 1364*04fd306cSNickeau public 1365*04fd306cSNickeau function setPageType(string $value): MarkupPath 1366*04fd306cSNickeau { 1367*04fd306cSNickeau $this->type 1368*04fd306cSNickeau ->setValue($value) 1369*04fd306cSNickeau ->sendToWriteStore(); 1370*04fd306cSNickeau return $this; 1371*04fd306cSNickeau } 1372*04fd306cSNickeau 1373*04fd306cSNickeau 1374*04fd306cSNickeau /** 1375*04fd306cSNickeau * @param $aliasPath 1376*04fd306cSNickeau * @param string $aliasType 1377*04fd306cSNickeau * @return Alias 1378*04fd306cSNickeau * @deprecated for {@link Aliases} 1379*04fd306cSNickeau */ 1380*04fd306cSNickeau public 1381*04fd306cSNickeau function addAndGetAlias($aliasPath, string $aliasType = AliasType::REDIRECT): Alias 1382*04fd306cSNickeau { 1383*04fd306cSNickeau 1384*04fd306cSNickeau return $this->aliases->addAndGetAlias($aliasPath, $aliasType); 1385*04fd306cSNickeau 1386*04fd306cSNickeau } 1387*04fd306cSNickeau 1388*04fd306cSNickeau 1389*04fd306cSNickeau /** 1390*04fd306cSNickeau * @return Alias[] 1391*04fd306cSNickeau * @throws ExceptionNotFound 1392*04fd306cSNickeau */ 1393*04fd306cSNickeau public 1394*04fd306cSNickeau function getAliases(): array 1395*04fd306cSNickeau { 1396*04fd306cSNickeau return $this->aliases->getValueAsAlias(); 1397*04fd306cSNickeau } 1398*04fd306cSNickeau 1399*04fd306cSNickeau /** 1400*04fd306cSNickeau * @return string 1401*04fd306cSNickeau */ 1402*04fd306cSNickeau public 1403*04fd306cSNickeau function getSlugOrDefault(): string 1404*04fd306cSNickeau { 1405*04fd306cSNickeau try { 1406*04fd306cSNickeau return $this->getSlug(); 1407*04fd306cSNickeau } catch (ExceptionNotFound $e) { 1408*04fd306cSNickeau return $this->getDefaultSlug(); 1409*04fd306cSNickeau } 1410*04fd306cSNickeau 1411*04fd306cSNickeau } 1412*04fd306cSNickeau 1413*04fd306cSNickeau /** 1414*04fd306cSNickeau * 1415*04fd306cSNickeau * @return string 1416*04fd306cSNickeau * 1417*04fd306cSNickeau */ 1418*04fd306cSNickeau public 1419*04fd306cSNickeau function getDefaultSlug(): string 1420*04fd306cSNickeau { 1421*04fd306cSNickeau return $this->slug->getDefaultValue(); 1422*04fd306cSNickeau } 1423*04fd306cSNickeau 1424*04fd306cSNickeau /** 1425*04fd306cSNickeau * The parent page is the parent in the page tree directory 1426*04fd306cSNickeau * 1427*04fd306cSNickeau * If the page is at the root, the parent page is the root home 1428*04fd306cSNickeau * Only the root home does not have any parent page and return null. 1429*04fd306cSNickeau * 1430*04fd306cSNickeau * @return MarkupPath 1431*04fd306cSNickeau * @throws ExceptionNotFound 1432*04fd306cSNickeau */ 1433*04fd306cSNickeau public function getParent(): MarkupPath 1434*04fd306cSNickeau { 1435*04fd306cSNickeau 1436*04fd306cSNickeau $names = $this->getNames(); 1437*04fd306cSNickeau if (sizeof($names) == 0) { 1438*04fd306cSNickeau throw new ExceptionNotFound("No parent page"); 1439*04fd306cSNickeau } 1440*04fd306cSNickeau $slice = 1; 1441*04fd306cSNickeau if ($this->isIndexPage()) { 1442*04fd306cSNickeau /** 1443*04fd306cSNickeau * The parent of a home page 1444*04fd306cSNickeau * is in the parent directory 1445*04fd306cSNickeau */ 1446*04fd306cSNickeau $slice = 2; 1447*04fd306cSNickeau } 1448*04fd306cSNickeau /** 1449*04fd306cSNickeau * Delete the last or the two last parts 1450*04fd306cSNickeau */ 1451*04fd306cSNickeau if (sizeof($names) < $slice) { 1452*04fd306cSNickeau throw new ExceptionNotFound("No parent page"); 1453*04fd306cSNickeau } 1454*04fd306cSNickeau /** 1455*04fd306cSNickeau * Get the actual directory for a page 1456*04fd306cSNickeau * or the parent directory for a home page 1457*04fd306cSNickeau */ 1458*04fd306cSNickeau $parentNames = array_slice($names, 0, sizeof($names) - $slice); 1459*04fd306cSNickeau /** 1460*04fd306cSNickeau * Create the parent namespace id 1461*04fd306cSNickeau */ 1462*04fd306cSNickeau $parentNamespaceId = implode(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, $parentNames) . WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT; 1463*04fd306cSNickeau try { 1464*04fd306cSNickeau return self::getIndexPageFromNamespace($parentNamespaceId); 1465*04fd306cSNickeau } catch (ExceptionBadSyntax $e) { 1466*04fd306cSNickeau $message = "Error on getParentPage, null returned - Error: {$e->getMessage()}"; 1467*04fd306cSNickeau LogUtility::internalError($message); 1468*04fd306cSNickeau throw new ExceptionNotFound($message); 1469*04fd306cSNickeau } 1470*04fd306cSNickeau 1471*04fd306cSNickeau } 1472*04fd306cSNickeau 1473*04fd306cSNickeau /** 1474*04fd306cSNickeau * @throws ExceptionCompile 1475*04fd306cSNickeau */ 1476*04fd306cSNickeau public 1477*04fd306cSNickeau function setDescription($description): MarkupPath 1478*04fd306cSNickeau { 1479*04fd306cSNickeau 1480*04fd306cSNickeau $this->description 1481*04fd306cSNickeau ->setValue($description) 1482*04fd306cSNickeau ->sendToWriteStore(); 1483*04fd306cSNickeau return $this; 1484*04fd306cSNickeau } 1485*04fd306cSNickeau 1486*04fd306cSNickeau /** 1487*04fd306cSNickeau * @throws ExceptionCompile 1488*04fd306cSNickeau * @deprecated uses {@link EndDate} instead 1489*04fd306cSNickeau */ 1490*04fd306cSNickeau public 1491*04fd306cSNickeau function setEndDate($value): MarkupPath 1492*04fd306cSNickeau { 1493*04fd306cSNickeau $this->endDate 1494*04fd306cSNickeau ->setFromStoreValue($value) 1495*04fd306cSNickeau ->sendToWriteStore(); 1496*04fd306cSNickeau return $this; 1497*04fd306cSNickeau } 1498*04fd306cSNickeau 1499*04fd306cSNickeau /** 1500*04fd306cSNickeau * @throws ExceptionCompile 1501*04fd306cSNickeau * @deprecated uses {@link StartDate} instead 1502*04fd306cSNickeau */ 1503*04fd306cSNickeau public 1504*04fd306cSNickeau function setStartDate($value): MarkupPath 1505*04fd306cSNickeau { 1506*04fd306cSNickeau $this->startDate 1507*04fd306cSNickeau ->setFromStoreValue($value) 1508*04fd306cSNickeau ->sendToWriteStore(); 1509*04fd306cSNickeau return $this; 1510*04fd306cSNickeau } 1511*04fd306cSNickeau 1512*04fd306cSNickeau /** 1513*04fd306cSNickeau * @throws ExceptionCompile 1514*04fd306cSNickeau */ 1515*04fd306cSNickeau public 1516*04fd306cSNickeau function setPublishedDate($value): MarkupPath 1517*04fd306cSNickeau { 1518*04fd306cSNickeau $this->publishedDate 1519*04fd306cSNickeau ->setFromStoreValue($value) 1520*04fd306cSNickeau ->sendToWriteStore(); 1521*04fd306cSNickeau return $this; 1522*04fd306cSNickeau } 1523*04fd306cSNickeau 1524*04fd306cSNickeau /** 1525*04fd306cSNickeau * Utility to {@link ResourceName::setValue()} 1526*04fd306cSNickeau * Used mostly to create page in test 1527*04fd306cSNickeau * @throws ExceptionCompile 1528*04fd306cSNickeau * @deprecated use not persist 1529*04fd306cSNickeau */ 1530*04fd306cSNickeau public 1531*04fd306cSNickeau function setPageName($value): MarkupPath 1532*04fd306cSNickeau { 1533*04fd306cSNickeau $this->pageName 1534*04fd306cSNickeau ->setValue($value) 1535*04fd306cSNickeau ->sendToWriteStore(); 1536*04fd306cSNickeau return $this; 1537*04fd306cSNickeau } 1538*04fd306cSNickeau 1539*04fd306cSNickeau 1540*04fd306cSNickeau /** 1541*04fd306cSNickeau * @throws ExceptionCompile 1542*04fd306cSNickeau */ 1543*04fd306cSNickeau public 1544*04fd306cSNickeau function setTitle($value): MarkupPath 1545*04fd306cSNickeau { 1546*04fd306cSNickeau $this->title 1547*04fd306cSNickeau ->setValue($value) 1548*04fd306cSNickeau ->sendToWriteStore(); 1549*04fd306cSNickeau return $this; 1550*04fd306cSNickeau } 1551*04fd306cSNickeau 1552*04fd306cSNickeau /** 1553*04fd306cSNickeau * @throws ExceptionCompile 1554*04fd306cSNickeau */ 1555*04fd306cSNickeau public 1556*04fd306cSNickeau function setH1($value): MarkupPath 1557*04fd306cSNickeau { 1558*04fd306cSNickeau $this->h1 1559*04fd306cSNickeau ->setValue($value) 1560*04fd306cSNickeau ->sendToWriteStore(); 1561*04fd306cSNickeau return $this; 1562*04fd306cSNickeau } 1563*04fd306cSNickeau 1564*04fd306cSNickeau /** 1565*04fd306cSNickeau * @throws Exception 1566*04fd306cSNickeau */ 1567*04fd306cSNickeau public 1568*04fd306cSNickeau function setRegion($value): MarkupPath 1569*04fd306cSNickeau { 1570*04fd306cSNickeau $this->region 1571*04fd306cSNickeau ->setFromStoreValue($value) 1572*04fd306cSNickeau ->sendToWriteStore(); 1573*04fd306cSNickeau return $this; 1574*04fd306cSNickeau } 1575*04fd306cSNickeau 1576*04fd306cSNickeau /** 1577*04fd306cSNickeau * @throws ExceptionCompile 1578*04fd306cSNickeau */ 1579*04fd306cSNickeau public 1580*04fd306cSNickeau function setLang($value): MarkupPath 1581*04fd306cSNickeau { 1582*04fd306cSNickeau 1583*04fd306cSNickeau $this->lang 1584*04fd306cSNickeau ->setFromStoreValue($value) 1585*04fd306cSNickeau ->sendToWriteStore(); 1586*04fd306cSNickeau return $this; 1587*04fd306cSNickeau } 1588*04fd306cSNickeau 1589*04fd306cSNickeau /** 1590*04fd306cSNickeau * @throws ExceptionCompile 1591*04fd306cSNickeau */ 1592*04fd306cSNickeau public 1593*04fd306cSNickeau function setLayout($value): MarkupPath 1594*04fd306cSNickeau { 1595*04fd306cSNickeau $this->layout 1596*04fd306cSNickeau ->setValue($value) 1597*04fd306cSNickeau ->sendToWriteStore(); 1598*04fd306cSNickeau return $this; 1599*04fd306cSNickeau } 1600*04fd306cSNickeau 1601*04fd306cSNickeau 1602*04fd306cSNickeau /** 1603*04fd306cSNickeau * 1604*04fd306cSNickeau * We manage the properties by setter and getter 1605*04fd306cSNickeau * 1606*04fd306cSNickeau * Why ? 1607*04fd306cSNickeau * * Because we can capture the updates 1608*04fd306cSNickeau * * Because setter are the entry point to good quality data 1609*04fd306cSNickeau * * Because dokuwiki may cache the metadata (see below) 1610*04fd306cSNickeau * 1611*04fd306cSNickeau * Note all properties have been migrated 1612*04fd306cSNickeau * but they should be initialized below 1613*04fd306cSNickeau * 1614*04fd306cSNickeau * Dokuwiki cache: the data may be cached without our consent 1615*04fd306cSNickeau * The method {@link p_get_metadata()} does it with this logic 1616*04fd306cSNickeau * ``` 1617*04fd306cSNickeau * $cache = ($ID == $id); 1618*04fd306cSNickeau * $meta = p_read_metadata($id, $cache); 1619*04fd306cSNickeau * ``` 1620*04fd306cSNickeau */ 1621*04fd306cSNickeau private 1622*04fd306cSNickeau function buildPropertiesFromFileSystem() 1623*04fd306cSNickeau { 1624*04fd306cSNickeau 1625*04fd306cSNickeau /** 1626*04fd306cSNickeau * New meta system 1627*04fd306cSNickeau * Even if it does not exist, the metadata object should be instantiated 1628*04fd306cSNickeau * otherwise, there is a null exception 1629*04fd306cSNickeau */ 1630*04fd306cSNickeau $this->cacheExpirationDate = CacheExpirationDate::createForPage($this); 1631*04fd306cSNickeau $this->aliases = Aliases::createForPage($this); 1632*04fd306cSNickeau $this->pageImages = PageImages::createForPage($this); 1633*04fd306cSNickeau $this->pageName = ResourceName::createForResource($this); 1634*04fd306cSNickeau $this->cacheExpirationFrequency = CacheExpirationFrequency::createForPage($this); 1635*04fd306cSNickeau $this->ldJson = LdJson::createForPage($this); 1636*04fd306cSNickeau $this->canonical = Canonical::createForPage($this); 1637*04fd306cSNickeau $this->description = PageDescription::createForPage($this); 1638*04fd306cSNickeau $this->h1 = PageH1::createForPage($this); 1639*04fd306cSNickeau $this->type = PageType::createForPage($this); 1640*04fd306cSNickeau $this->creationTime = CreationDate::createForPage($this); 1641*04fd306cSNickeau $this->title = PageTitle::createForMarkup($this); 1642*04fd306cSNickeau $this->keywords = PageKeywords::createForPage($this); 1643*04fd306cSNickeau $this->publishedDate = PagePublicationDate::createFromPage($this); 1644*04fd306cSNickeau $this->startDate = StartDate::createFromPage($this); 1645*04fd306cSNickeau $this->endDate = EndDate::createFromPage($this); 1646*04fd306cSNickeau $this->locale = Locale::createForPage($this); 1647*04fd306cSNickeau $this->lang = Lang::createForMarkup($this); 1648*04fd306cSNickeau $this->region = Region::createForPage($this); 1649*04fd306cSNickeau $this->slug = \ComboStrap\Slug::createForPage($this); 1650*04fd306cSNickeau $this->canBeOfLowQuality = LowQualityPageOverwrite::createForPage($this); 1651*04fd306cSNickeau $this->lowQualityIndicatorCalculated = LowQualityCalculatedIndicator::createFromPage($this); 1652*04fd306cSNickeau $this->qualityMonitoringIndicator = QualityDynamicMonitoringOverwrite::createFromPage($this); 1653*04fd306cSNickeau $this->modifiedTime = ModificationDate::createForPage($this); 1654*04fd306cSNickeau $this->pageUrlPath = PageUrlPath::createForPage($this); 1655*04fd306cSNickeau $this->layout = PageTemplateName::createFromPage($this); 1656*04fd306cSNickeau 1657*04fd306cSNickeau } 1658*04fd306cSNickeau 1659*04fd306cSNickeau 1660*04fd306cSNickeau function getPageIdAbbr() 1661*04fd306cSNickeau { 1662*04fd306cSNickeau 1663*04fd306cSNickeau if ($this->getPageId() === null) return null; 1664*04fd306cSNickeau return PageId::getAbbreviated($this->getPageId()); 1665*04fd306cSNickeau 1666*04fd306cSNickeau } 1667*04fd306cSNickeau 1668*04fd306cSNickeau public 1669*04fd306cSNickeau function setDatabasePage(DatabasePageRow $databasePage): MarkupPath 1670*04fd306cSNickeau { 1671*04fd306cSNickeau $this->databasePage = $databasePage; 1672*04fd306cSNickeau return $this; 1673*04fd306cSNickeau } 1674*04fd306cSNickeau 1675*04fd306cSNickeau 1676*04fd306cSNickeau /** 1677*04fd306cSNickeau * @return string|null 1678*04fd306cSNickeau * 1679*04fd306cSNickeau * @throws ExceptionNotFound 1680*04fd306cSNickeau */ 1681*04fd306cSNickeau public 1682*04fd306cSNickeau function getSlug(): string 1683*04fd306cSNickeau { 1684*04fd306cSNickeau return $this->slug->getValue(); 1685*04fd306cSNickeau } 1686*04fd306cSNickeau 1687*04fd306cSNickeau 1688*04fd306cSNickeau /** 1689*04fd306cSNickeau * @throws ExceptionCompile 1690*04fd306cSNickeau */ 1691*04fd306cSNickeau public 1692*04fd306cSNickeau function setSlug($slug): MarkupPath 1693*04fd306cSNickeau { 1694*04fd306cSNickeau $this->slug 1695*04fd306cSNickeau ->setFromStoreValue($slug) 1696*04fd306cSNickeau ->sendToWriteStore(); 1697*04fd306cSNickeau return $this; 1698*04fd306cSNickeau } 1699*04fd306cSNickeau 1700*04fd306cSNickeau 1701*04fd306cSNickeau /** 1702*04fd306cSNickeau * @return string - the id in the Url 1703*04fd306cSNickeau */ 1704*04fd306cSNickeau public function getUrlId(): string 1705*04fd306cSNickeau { 1706*04fd306cSNickeau return $this->pageUrlPath->getValueOrDefaultAsWikiId(); 1707*04fd306cSNickeau } 1708*04fd306cSNickeau 1709*04fd306cSNickeau 1710*04fd306cSNickeau /** 1711*04fd306cSNickeau * @throws ExceptionCompile 1712*04fd306cSNickeau */ 1713*04fd306cSNickeau public 1714*04fd306cSNickeau function setQualityMonitoringIndicator($boolean): MarkupPath 1715*04fd306cSNickeau { 1716*04fd306cSNickeau $this->qualityMonitoringIndicator 1717*04fd306cSNickeau ->setFromStoreValue($boolean) 1718*04fd306cSNickeau ->sendToWriteStore(); 1719*04fd306cSNickeau return $this; 1720*04fd306cSNickeau } 1721*04fd306cSNickeau 1722*04fd306cSNickeau /** 1723*04fd306cSNickeau * 1724*04fd306cSNickeau * @param $aliasPath - third information - the alias used to build this page 1725*04fd306cSNickeau */ 1726*04fd306cSNickeau public 1727*04fd306cSNickeau function setBuildAliasPath($aliasPath) 1728*04fd306cSNickeau { 1729*04fd306cSNickeau $this->buildAliasPath = $aliasPath; 1730*04fd306cSNickeau } 1731*04fd306cSNickeau 1732*04fd306cSNickeau public 1733*04fd306cSNickeau function getBuildAlias(): ?Alias 1734*04fd306cSNickeau { 1735*04fd306cSNickeau if ($this->buildAliasPath === null) return null; 1736*04fd306cSNickeau try { 1737*04fd306cSNickeau $aliases = $this->getAliases(); 1738*04fd306cSNickeau } catch (ExceptionNotFound $e) { 1739*04fd306cSNickeau // should not 1740*04fd306cSNickeau return null; 1741*04fd306cSNickeau } 1742*04fd306cSNickeau foreach ($aliases as $alias) { 1743*04fd306cSNickeau if ($alias->getPath() === $this->buildAliasPath) { 1744*04fd306cSNickeau return $alias; 1745*04fd306cSNickeau } 1746*04fd306cSNickeau } 1747*04fd306cSNickeau return null; 1748*04fd306cSNickeau } 1749*04fd306cSNickeau 1750*04fd306cSNickeau public 1751*04fd306cSNickeau function isDynamicQualityMonitored(): bool 1752*04fd306cSNickeau { 1753*04fd306cSNickeau if ($this->getQualityMonitoringIndicator() !== null) { 1754*04fd306cSNickeau return $this->getQualityMonitoringIndicator(); 1755*04fd306cSNickeau } 1756*04fd306cSNickeau return $this->getDefaultQualityMonitoring(); 1757*04fd306cSNickeau } 1758*04fd306cSNickeau 1759*04fd306cSNickeau public 1760*04fd306cSNickeau function getDefaultQualityMonitoring(): bool 1761*04fd306cSNickeau { 1762*04fd306cSNickeau if (SiteConfig::getConfValue(QualityMessageHandler::CONF_DISABLE_QUALITY_MONITORING) === 1) { 1763*04fd306cSNickeau return false; 1764*04fd306cSNickeau } else { 1765*04fd306cSNickeau return true; 1766*04fd306cSNickeau } 1767*04fd306cSNickeau } 1768*04fd306cSNickeau 1769*04fd306cSNickeau /** 1770*04fd306cSNickeau * @param MetadataStore|string $store 1771*04fd306cSNickeau * @return $this 1772*04fd306cSNickeau */ 1773*04fd306cSNickeau public 1774*04fd306cSNickeau function setReadStore($store): MarkupPath 1775*04fd306cSNickeau { 1776*04fd306cSNickeau $this->readStore = $store; 1777*04fd306cSNickeau return $this; 1778*04fd306cSNickeau } 1779*04fd306cSNickeau 1780*04fd306cSNickeau 1781*04fd306cSNickeau /** 1782*04fd306cSNickeau * @param array $usages 1783*04fd306cSNickeau * @return IFetcherLocalImage[] 1784*04fd306cSNickeau */ 1785*04fd306cSNickeau public 1786*04fd306cSNickeau function getImagesForTheFollowingUsages(array $usages): array 1787*04fd306cSNickeau { 1788*04fd306cSNickeau $usages = array_merge($usages, [PageImageUsage::ALL]); 1789*04fd306cSNickeau $images = []; 1790*04fd306cSNickeau foreach ($this->getPageMetadataImages() as $pageImage) { 1791*04fd306cSNickeau foreach ($usages as $usage) { 1792*04fd306cSNickeau if (in_array($usage, $pageImage->getUsages())) { 1793*04fd306cSNickeau $path = $pageImage->getImagePath(); 1794*04fd306cSNickeau try { 1795*04fd306cSNickeau $images[] = IFetcherLocalImage::createImageFetchFromPath($path); 1796*04fd306cSNickeau } catch (ExceptionBadArgument $e) { 1797*04fd306cSNickeau LogUtility::error(`The page image $path of the page $this is not an image`); 1798*04fd306cSNickeau } catch (ExceptionBadSyntax $e) { 1799*04fd306cSNickeau LogUtility::error(`The page image $path has a bad syntax`); 1800*04fd306cSNickeau } catch (ExceptionNotExists $e) { 1801*04fd306cSNickeau LogUtility::error(`The page image $path does not exists`); 1802*04fd306cSNickeau } 1803*04fd306cSNickeau continue 2; 1804*04fd306cSNickeau } 1805*04fd306cSNickeau } 1806*04fd306cSNickeau } 1807*04fd306cSNickeau return $images; 1808*04fd306cSNickeau 1809*04fd306cSNickeau } 1810*04fd306cSNickeau 1811*04fd306cSNickeau 1812*04fd306cSNickeau /** 1813*04fd306cSNickeau * @throws ExceptionNotFound 1814*04fd306cSNickeau */ 1815*04fd306cSNickeau public 1816*04fd306cSNickeau function getKeywords(): array 1817*04fd306cSNickeau { 1818*04fd306cSNickeau return $this->keywords->getValue(); 1819*04fd306cSNickeau } 1820*04fd306cSNickeau 1821*04fd306cSNickeau /** 1822*04fd306cSNickeau * @throws ExceptionNotFound 1823*04fd306cSNickeau */ 1824*04fd306cSNickeau public function getKeywordsOrDefault(): array 1825*04fd306cSNickeau { 1826*04fd306cSNickeau return $this->keywords->getValueOrDefaults(); 1827*04fd306cSNickeau } 1828*04fd306cSNickeau 1829*04fd306cSNickeau 1830*04fd306cSNickeau /** 1831*04fd306cSNickeau * @throws ExceptionCompile 1832*04fd306cSNickeau */ 1833*04fd306cSNickeau public 1834*04fd306cSNickeau function setKeywords($value): MarkupPath 1835*04fd306cSNickeau { 1836*04fd306cSNickeau $this->keywords 1837*04fd306cSNickeau ->setFromStoreValue($value) 1838*04fd306cSNickeau ->sendToWriteStore(); 1839*04fd306cSNickeau return $this; 1840*04fd306cSNickeau } 1841*04fd306cSNickeau 1842*04fd306cSNickeau /** 1843*04fd306cSNickeau * @return DateTime|null 1844*04fd306cSNickeau * @throws ExceptionNotFound 1845*04fd306cSNickeau * @deprecated for {@link CacheExpirationDate} 1846*04fd306cSNickeau */ 1847*04fd306cSNickeau public 1848*04fd306cSNickeau function getCacheExpirationDate(): ?DateTime 1849*04fd306cSNickeau { 1850*04fd306cSNickeau return $this->cacheExpirationDate->getValue(); 1851*04fd306cSNickeau } 1852*04fd306cSNickeau 1853*04fd306cSNickeau /** 1854*04fd306cSNickeau * @return DateTime|null 1855*04fd306cSNickeau * @throws ExceptionNotFound 1856*04fd306cSNickeau * @deprecated for {@link CacheExpirationDate} 1857*04fd306cSNickeau */ 1858*04fd306cSNickeau public 1859*04fd306cSNickeau function getDefaultCacheExpirationDate(): ?DateTime 1860*04fd306cSNickeau { 1861*04fd306cSNickeau return $this->cacheExpirationDate->getDefaultValue(); 1862*04fd306cSNickeau } 1863*04fd306cSNickeau 1864*04fd306cSNickeau /** 1865*04fd306cSNickeau * @return string|null 1866*04fd306cSNickeau * @throws ExceptionNotFound 1867*04fd306cSNickeau * @deprecated for {@link CacheExpirationFrequency} 1868*04fd306cSNickeau */ 1869*04fd306cSNickeau public 1870*04fd306cSNickeau function getCacheExpirationFrequency(): string 1871*04fd306cSNickeau { 1872*04fd306cSNickeau return $this->cacheExpirationFrequency->getValue(); 1873*04fd306cSNickeau } 1874*04fd306cSNickeau 1875*04fd306cSNickeau 1876*04fd306cSNickeau /** 1877*04fd306cSNickeau * @param DateTime $cacheExpirationDate 1878*04fd306cSNickeau * @return $this 1879*04fd306cSNickeau * @deprecated for {@link CacheExpirationDate} 1880*04fd306cSNickeau */ 1881*04fd306cSNickeau public 1882*04fd306cSNickeau function setCacheExpirationDate(DateTime $cacheExpirationDate): MarkupPath 1883*04fd306cSNickeau { 1884*04fd306cSNickeau $this->cacheExpirationDate->setValue($cacheExpirationDate); 1885*04fd306cSNickeau return $this; 1886*04fd306cSNickeau } 1887*04fd306cSNickeau 1888*04fd306cSNickeau 1889*04fd306cSNickeau /** 1890*04fd306cSNickeau * Utility class 1891*04fd306cSNickeau * Get the instructions document as if it was the main page. 1892*04fd306cSNickeau * Ie the context path is: 1893*04fd306cSNickeau * * the markup path itself) 1894*04fd306cSNickeau * * or the default context path if the path cannot be transformed as wiki path. 1895*04fd306cSNickeau */ 1896*04fd306cSNickeau public function getInstructionsDocument(): FetcherMarkup 1897*04fd306cSNickeau { 1898*04fd306cSNickeau 1899*04fd306cSNickeau $path = $this->getPathObject(); 1900*04fd306cSNickeau try { 1901*04fd306cSNickeau $contextPath = $path->toWikiPath(); 1902*04fd306cSNickeau } catch (ExceptionCast $e) { 1903*04fd306cSNickeau $contextPath = ExecutionContext::getActualOrCreateFromEnv() 1904*04fd306cSNickeau ->getDefaultContextPath(); 1905*04fd306cSNickeau } 1906*04fd306cSNickeau return FetcherMarkup::confRoot() 1907*04fd306cSNickeau ->setRequestedExecutingPath($path) 1908*04fd306cSNickeau ->setRequestedContextPath($contextPath) 1909*04fd306cSNickeau ->setRequestedMimeToInstructions() 1910*04fd306cSNickeau ->build(); 1911*04fd306cSNickeau 1912*04fd306cSNickeau } 1913*04fd306cSNickeau 1914*04fd306cSNickeau public 1915*04fd306cSNickeau function delete() 1916*04fd306cSNickeau { 1917*04fd306cSNickeau 1918*04fd306cSNickeau Index::getOrCreate()->deletePage($this); 1919*04fd306cSNickeau saveWikiText($this->getWikiId(), "", "Delete"); 1920*04fd306cSNickeau 1921*04fd306cSNickeau } 1922*04fd306cSNickeau 1923*04fd306cSNickeau /** 1924*04fd306cSNickeau * @return Url -the absolute canonical url 1925*04fd306cSNickeau */ 1926*04fd306cSNickeau public 1927*04fd306cSNickeau function getAbsoluteCanonicalUrl(): Url 1928*04fd306cSNickeau { 1929*04fd306cSNickeau return $this->getCanonicalUrl()->toAbsoluteUrl(); 1930*04fd306cSNickeau } 1931*04fd306cSNickeau 1932*04fd306cSNickeau 1933*04fd306cSNickeau public 1934*04fd306cSNickeau function getReadStoreOrDefault(): MetadataStore 1935*04fd306cSNickeau { 1936*04fd306cSNickeau if ($this->readStore === null) { 1937*04fd306cSNickeau /** 1938*04fd306cSNickeau * No cache please if not set 1939*04fd306cSNickeau * Cache should be in the MetadataDokuWikiStore 1940*04fd306cSNickeau * that is page requested scoped and not by slot 1941*04fd306cSNickeau */ 1942*04fd306cSNickeau return MetadataDokuWikiStore::getOrCreateFromResource($this); 1943*04fd306cSNickeau } 1944*04fd306cSNickeau if (!($this->readStore instanceof MetadataStore)) { 1945*04fd306cSNickeau $this->readStore = MetadataStoreAbs::toMetadataStore($this->readStore, $this); 1946*04fd306cSNickeau } 1947*04fd306cSNickeau return $this->readStore; 1948*04fd306cSNickeau } 1949*04fd306cSNickeau 1950*04fd306cSNickeau /** 1951*04fd306cSNickeau * @return Path 1952*04fd306cSNickeau * A markup path wraps a path 1953*04fd306cSNickeau */ 1954*04fd306cSNickeau public function getPathObject(): Path 1955*04fd306cSNickeau { 1956*04fd306cSNickeau return $this->path; 1957*04fd306cSNickeau } 1958*04fd306cSNickeau 1959*04fd306cSNickeau 1960*04fd306cSNickeau /** 1961*04fd306cSNickeau * A shortcut for {@link MarkupPath::getPathObject()::getDokuwikiId()} 1962*04fd306cSNickeau * 1963*04fd306cSNickeau * @throws ExceptionBadArgument - if the markup path is not a {@link WikiPath} 1964*04fd306cSNickeau */ 1965*04fd306cSNickeau public 1966*04fd306cSNickeau function getWikiId(): string 1967*04fd306cSNickeau { 1968*04fd306cSNickeau $path = $this->getPathObject(); 1969*04fd306cSNickeau return WikiPath::createFromPathObject($path)->getWikiId(); 1970*04fd306cSNickeau } 1971*04fd306cSNickeau 1972*04fd306cSNickeau public 1973*04fd306cSNickeau function getUid(): Metadata 1974*04fd306cSNickeau { 1975*04fd306cSNickeau return PageId::createForPage($this); 1976*04fd306cSNickeau } 1977*04fd306cSNickeau 1978*04fd306cSNickeau 1979*04fd306cSNickeau public 1980*04fd306cSNickeau function getAbsolutePath(): string 1981*04fd306cSNickeau { 1982*04fd306cSNickeau return WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT . $this->getWikiId(); 1983*04fd306cSNickeau } 1984*04fd306cSNickeau 1985*04fd306cSNickeau /** 1986*04fd306cSNickeau * Todo, it should be a property of the markup not every markup file are main page markup. 1987*04fd306cSNickeau * @return string 1988*04fd306cSNickeau */ 1989*04fd306cSNickeau function getType(): string 1990*04fd306cSNickeau { 1991*04fd306cSNickeau return self::TYPE; 1992*04fd306cSNickeau } 1993*04fd306cSNickeau 1994*04fd306cSNickeau /** 1995*04fd306cSNickeau * @return PageUrlPath 1996*04fd306cSNickeau * @deprecated use {@link PageUrlPath} instead 1997*04fd306cSNickeau */ 1998*04fd306cSNickeau public 1999*04fd306cSNickeau function getUrlPathObject(): PageUrlPath 2000*04fd306cSNickeau { 2001*04fd306cSNickeau return $this->pageUrlPath; 2002*04fd306cSNickeau } 2003*04fd306cSNickeau 2004*04fd306cSNickeau 2005*04fd306cSNickeau public function getSideSlot(): ?MarkupPath 2006*04fd306cSNickeau { 2007*04fd306cSNickeau 2008*04fd306cSNickeau /** 2009*04fd306cSNickeau * Only primary slot have a side slot 2010*04fd306cSNickeau * Root Home page does not have one either 2011*04fd306cSNickeau */ 2012*04fd306cSNickeau if ($this->isSlot()) { 2013*04fd306cSNickeau return null; 2014*04fd306cSNickeau } 2015*04fd306cSNickeau 2016*04fd306cSNickeau $nearestMainFooter = $this->findNearest(SlotSystem::getSidebarName()); 2017*04fd306cSNickeau if ($nearestMainFooter === false) { 2018*04fd306cSNickeau return null; 2019*04fd306cSNickeau } 2020*04fd306cSNickeau return MarkupPath::createMarkupFromId($nearestMainFooter); 2021*04fd306cSNickeau 2022*04fd306cSNickeau 2023*04fd306cSNickeau } 2024*04fd306cSNickeau 2025*04fd306cSNickeau /** 2026*04fd306cSNickeau * @param $pageName 2027*04fd306cSNickeau * @return false|string 2028*04fd306cSNickeau */ 2029*04fd306cSNickeau private function findNearest($pageName) 2030*04fd306cSNickeau { 2031*04fd306cSNickeau global $ID; 2032*04fd306cSNickeau $keep = $ID; 2033*04fd306cSNickeau try { 2034*04fd306cSNickeau $ID = $this->getWikiId(); 2035*04fd306cSNickeau return page_findnearest($pageName); 2036*04fd306cSNickeau } finally { 2037*04fd306cSNickeau $ID = $keep; 2038*04fd306cSNickeau } 2039*04fd306cSNickeau 2040*04fd306cSNickeau } 2041*04fd306cSNickeau 2042*04fd306cSNickeau /** 2043*04fd306cSNickeau * The slots that are independent from the primary slot 2044*04fd306cSNickeau * 2045*04fd306cSNickeau * @return MarkupPath[] 2046*04fd306cSNickeau * @deprecated should be {@link TemplateForWebPage} based 2047*04fd306cSNickeau */ 2048*04fd306cSNickeau public function getPrimaryIndependentSlots(): array 2049*04fd306cSNickeau { 2050*04fd306cSNickeau $secondarySlots = []; 2051*04fd306cSNickeau $sideSlot = $this->getSideSlot(); 2052*04fd306cSNickeau if ($sideSlot !== null) { 2053*04fd306cSNickeau $secondarySlots[] = $sideSlot; 2054*04fd306cSNickeau } 2055*04fd306cSNickeau return $secondarySlots; 2056*04fd306cSNickeau } 2057*04fd306cSNickeau 2058*04fd306cSNickeau 2059*04fd306cSNickeau public function isHidden(): bool 2060*04fd306cSNickeau { 2061*04fd306cSNickeau return isHiddenPage($this->getWikiId()); 2062*04fd306cSNickeau } 2063*04fd306cSNickeau 2064*04fd306cSNickeau 2065*04fd306cSNickeau public function getPrimaryHeaderPage(): ?MarkupPath 2066*04fd306cSNickeau { 2067*04fd306cSNickeau $nearest = page_findnearest(SlotSystem::getMainHeaderSlotName()); 2068*04fd306cSNickeau if ($nearest === false) { 2069*04fd306cSNickeau return null; 2070*04fd306cSNickeau } 2071*04fd306cSNickeau return MarkupPath::createMarkupFromId($nearest); 2072*04fd306cSNickeau } 2073*04fd306cSNickeau 2074*04fd306cSNickeau public function createPageFetcherHtml(): FetcherPage 2075*04fd306cSNickeau { 2076*04fd306cSNickeau return FetcherPage::createPageFetcherFromMarkupPath($this); 2077*04fd306cSNickeau } 2078*04fd306cSNickeau 2079*04fd306cSNickeau public function getHttpResponse(): HttpResponse 2080*04fd306cSNickeau { 2081*04fd306cSNickeau return HttpRequest::fetchXhtmlPageResponse($this->getWikiId()); 2082*04fd306cSNickeau } 2083*04fd306cSNickeau 2084*04fd306cSNickeau /** 2085*04fd306cSNickeau * @return Outline 2086*04fd306cSNickeau * @deprecated uses {@link FetcherMarkup::getOutline()} instead 2087*04fd306cSNickeau */ 2088*04fd306cSNickeau public function getOutline(): Outline 2089*04fd306cSNickeau { 2090*04fd306cSNickeau 2091*04fd306cSNickeau return $this->getInstructionsDocument()->getOutline(); 2092*04fd306cSNickeau 2093*04fd306cSNickeau } 2094*04fd306cSNickeau 2095*04fd306cSNickeau 2096*04fd306cSNickeau public function persistToDefaultMetaStore(): MarkupPath 2097*04fd306cSNickeau { 2098*04fd306cSNickeau $this->getReadStoreOrDefault()->persist(); 2099*04fd306cSNickeau return $this; 2100*04fd306cSNickeau } 2101*04fd306cSNickeau 2102*04fd306cSNickeau public function getInstructionsPath(): LocalPath 2103*04fd306cSNickeau { 2104*04fd306cSNickeau 2105*04fd306cSNickeau $instructionsDocument = $this->getInstructionsDocument(); 2106*04fd306cSNickeau return $instructionsDocument->getInstructionsPath(); 2107*04fd306cSNickeau 2108*04fd306cSNickeau } 2109*04fd306cSNickeau 2110*04fd306cSNickeau public function setContent(string $textContent): MarkupPath 2111*04fd306cSNickeau { 2112*04fd306cSNickeau FileSystems::setContent($this, $textContent); 2113*04fd306cSNickeau return $this; 2114*04fd306cSNickeau } 2115*04fd306cSNickeau 2116*04fd306cSNickeau /** 2117*04fd306cSNickeau * @throws ExceptionNotExists - if the path does not exist 2118*04fd306cSNickeau */ 2119*04fd306cSNickeau public function createHtmlFetcherWithRequestedPathAsContextPath(): FetcherMarkup 2120*04fd306cSNickeau { 2121*04fd306cSNickeau $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 2122*04fd306cSNickeau $executingPath = $this->getPathObject(); 2123*04fd306cSNickeau $requestedPath = $executionContext->getRequestedPath(); 2124*04fd306cSNickeau $requestedMarkupPath = MarkupPath::createPageFromPathObject($requestedPath); 2125*04fd306cSNickeau 2126*04fd306cSNickeau if ($requestedMarkupPath->isSlot()) { 2127*04fd306cSNickeau try { 2128*04fd306cSNickeau $markupContextPath = SlotSystem::getContextPath(); 2129*04fd306cSNickeau SlotSystem::sendContextPathMessage($markupContextPath); 2130*04fd306cSNickeau $requestedPath = $markupContextPath->toWikiPath(); 2131*04fd306cSNickeau } catch (\Exception $e) { 2132*04fd306cSNickeau // should not 2133*04fd306cSNickeau } 2134*04fd306cSNickeau } 2135*04fd306cSNickeau return FetcherMarkup::confRoot() 2136*04fd306cSNickeau ->setRequestedMimeToXhtml() 2137*04fd306cSNickeau ->setRequestedContextPath($requestedPath) 2138*04fd306cSNickeau ->setRequestedExecutingPath($executingPath) 2139*04fd306cSNickeau ->build(); 2140*04fd306cSNickeau } 2141*04fd306cSNickeau 2142*04fd306cSNickeau public 2143*04fd306cSNickeau function isRootItemPage(): bool 2144*04fd306cSNickeau { 2145*04fd306cSNickeau try { 2146*04fd306cSNickeau if ($this->isIndexPage()) { 2147*04fd306cSNickeau return false; 2148*04fd306cSNickeau } 2149*04fd306cSNickeau $parent = $this->getParent(); 2150*04fd306cSNickeau if ($parent->isRootHomePage()) { 2151*04fd306cSNickeau return true; 2152*04fd306cSNickeau } 2153*04fd306cSNickeau return false; 2154*04fd306cSNickeau } catch (ExceptionNotFound $e) { 2155*04fd306cSNickeau return false; 2156*04fd306cSNickeau } 2157*04fd306cSNickeau } 2158*04fd306cSNickeau 2159*04fd306cSNickeau private 2160*04fd306cSNickeau function getPrimaryFooterPage(): ?MarkupPath 2161*04fd306cSNickeau { 2162*04fd306cSNickeau $nearest = page_findnearest(SlotSystem::getMainFooterSlotName()); 2163*04fd306cSNickeau if ($nearest === false) { 2164*04fd306cSNickeau return null; 2165*04fd306cSNickeau } 2166*04fd306cSNickeau return MarkupPath::createMarkupFromId($nearest); 2167*04fd306cSNickeau } 2168*04fd306cSNickeau 2169*04fd306cSNickeau /** 2170*04fd306cSNickeau * Set the page path to an index page for a directory path 2171*04fd306cSNickeau * @return void 2172*04fd306cSNickeau */ 2173*04fd306cSNickeau private 2174*04fd306cSNickeau function setCorrectPathForDirectoryToIndexPage(): void 2175*04fd306cSNickeau { 2176*04fd306cSNickeau 2177*04fd306cSNickeau 2178*04fd306cSNickeau if (!($this->path instanceof WikiPath)) { 2179*04fd306cSNickeau return; 2180*04fd306cSNickeau } 2181*04fd306cSNickeau /** 2182*04fd306cSNickeau * @var $path WikiPath 2183*04fd306cSNickeau */ 2184*04fd306cSNickeau $path = $this->path; 2185*04fd306cSNickeau 2186*04fd306cSNickeau /** 2187*04fd306cSNickeau * We correct the path 2188*04fd306cSNickeau * We don't return a page because it does not work in a constructor 2189*04fd306cSNickeau */ 2190*04fd306cSNickeau $startPageName = Site::getIndexPageName(); 2191*04fd306cSNickeau $indexPath = $path->resolveId($startPageName); 2192*04fd306cSNickeau if (FileSystems::exists($indexPath)) { 2193*04fd306cSNickeau // start page inside namespace 2194*04fd306cSNickeau $this->path = $indexPath; 2195*04fd306cSNickeau return; 2196*04fd306cSNickeau } 2197*04fd306cSNickeau 2198*04fd306cSNickeau // page named like the NS inside the NS 2199*04fd306cSNickeau try { 2200*04fd306cSNickeau $parentName = $this->getLastNameWithoutExtension(); 2201*04fd306cSNickeau $nsInsideNsIndex = $this->path->resolveId($parentName); 2202*04fd306cSNickeau if (FileSystems::exists($nsInsideNsIndex)) { 2203*04fd306cSNickeau $this->path = $nsInsideNsIndex; 2204*04fd306cSNickeau return; 2205*04fd306cSNickeau } 2206*04fd306cSNickeau } catch (ExceptionNotFound $e) { 2207*04fd306cSNickeau // no last name 2208*04fd306cSNickeau } 2209*04fd306cSNickeau 2210*04fd306cSNickeau // We don't support the child page 2211*04fd306cSNickeau // Does not exist but can be used by hierarchical function 2212*04fd306cSNickeau $this->path = $indexPath; 2213*04fd306cSNickeau } 2214*04fd306cSNickeau 2215*04fd306cSNickeau 2216*04fd306cSNickeau public 2217*04fd306cSNickeau function getUidObject(): Metadata 2218*04fd306cSNickeau { 2219*04fd306cSNickeau if ($this->uidObject === null) { 2220*04fd306cSNickeau try { 2221*04fd306cSNickeau $this->uidObject = Meta\Api\MetadataSystem::toMetadataObject($this->getUid()) 2222*04fd306cSNickeau ->setResource($this); 2223*04fd306cSNickeau } catch (ExceptionBadArgument $e) { 2224*04fd306cSNickeau throw new ExceptionRuntimeInternal("Uid object is a metadata object. It should not happen.", self::CANONICAL_PAGE, 1, $e); 2225*04fd306cSNickeau } 2226*04fd306cSNickeau } 2227*04fd306cSNickeau 2228*04fd306cSNickeau return $this->uidObject; 2229*04fd306cSNickeau } 2230*04fd306cSNickeau 2231*04fd306cSNickeau function getExtension(): string 2232*04fd306cSNickeau { 2233*04fd306cSNickeau return $this->path->getExtension(); 2234*04fd306cSNickeau } 2235*04fd306cSNickeau 2236*04fd306cSNickeau function getLastNameWithoutExtension(): string 2237*04fd306cSNickeau { 2238*04fd306cSNickeau return $this->path->getLastNameWithoutExtension(); 2239*04fd306cSNickeau } 2240*04fd306cSNickeau 2241*04fd306cSNickeau function getScheme(): string 2242*04fd306cSNickeau { 2243*04fd306cSNickeau return MarkupFileSystem::SCHEME; 2244*04fd306cSNickeau } 2245*04fd306cSNickeau 2246*04fd306cSNickeau function getLastName(): string 2247*04fd306cSNickeau { 2248*04fd306cSNickeau return $this->path->getLastName(); 2249*04fd306cSNickeau } 2250*04fd306cSNickeau 2251*04fd306cSNickeau function getNames() 2252*04fd306cSNickeau { 2253*04fd306cSNickeau return $this->path->getNames(); 2254*04fd306cSNickeau } 2255*04fd306cSNickeau 2256*04fd306cSNickeau function toAbsoluteId(): string 2257*04fd306cSNickeau { 2258*04fd306cSNickeau return $this->path->toAbsoluteId(); 2259*04fd306cSNickeau } 2260*04fd306cSNickeau 2261*04fd306cSNickeau function toUriString(): string 2262*04fd306cSNickeau { 2263*04fd306cSNickeau return $this->path->toUriString(); 2264*04fd306cSNickeau } 2265*04fd306cSNickeau 2266*04fd306cSNickeau function toAbsolutePath(): Path 2267*04fd306cSNickeau { 2268*04fd306cSNickeau return $this->path->toAbsolutePath(); 2269*04fd306cSNickeau } 2270*04fd306cSNickeau 2271*04fd306cSNickeau 2272*04fd306cSNickeau function resolve(string $name): Path 2273*04fd306cSNickeau { 2274*04fd306cSNickeau return $this->path->resolve($name); 2275*04fd306cSNickeau } 2276*04fd306cSNickeau 2277*04fd306cSNickeau 2278*04fd306cSNickeau function getUrl(): Url 2279*04fd306cSNickeau { 2280*04fd306cSNickeau return FetcherPage::createPageFetcherFromMarkupPath($this) 2281*04fd306cSNickeau ->getFetchUrl(); 2282*04fd306cSNickeau } 2283*04fd306cSNickeau 2284*04fd306cSNickeau function getHost(): string 2285*04fd306cSNickeau { 2286*04fd306cSNickeau return $this->path->getHost(); 2287*04fd306cSNickeau } 2288*04fd306cSNickeau 2289*04fd306cSNickeau public 2290*04fd306cSNickeau function __toString(): string 2291*04fd306cSNickeau { 2292*04fd306cSNickeau return $this->path->__toString(); 2293*04fd306cSNickeau } 2294*04fd306cSNickeau 2295*04fd306cSNickeau /** 2296*04fd306cSNickeau * @throws ExceptionBadSyntax 2297*04fd306cSNickeau * @throws ExceptionBadArgument 2298*04fd306cSNickeau */ 2299*04fd306cSNickeau public 2300*04fd306cSNickeau static function createFromUri(string $uri): MarkupPath 2301*04fd306cSNickeau { 2302*04fd306cSNickeau $path = FileSystems::createPathFromUri($uri); 2303*04fd306cSNickeau return new MarkupPath($path); 2304*04fd306cSNickeau } 2305*04fd306cSNickeau 2306*04fd306cSNickeau 2307*04fd306cSNickeau} 2308