1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeau 4*04fd306cSNickeaunamespace ComboStrap\Meta\Field; 5*04fd306cSNickeau 6*04fd306cSNickeau 7*04fd306cSNickeauuse ComboStrap\ExceptionNotFound; 8*04fd306cSNickeauuse ComboStrap\ExecutionContext; 9*04fd306cSNickeauuse ComboStrap\FileSystems; 10*04fd306cSNickeauuse ComboStrap\LogUtility; 11*04fd306cSNickeauuse ComboStrap\MarkupPath; 12*04fd306cSNickeauuse ComboStrap\Meta\Api\Metadata; 13*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataText; 14*04fd306cSNickeauuse ComboStrap\MetaManagerForm; 15*04fd306cSNickeauuse ComboStrap\TemplateEngine; 16*04fd306cSNickeauuse ComboStrap\Site; 17*04fd306cSNickeauuse ComboStrap\SlotSystem; 18*04fd306cSNickeauuse ComboStrap\Tag\BarTag; 19*04fd306cSNickeau 20*04fd306cSNickeauclass PageTemplateName extends MetadataText 21*04fd306cSNickeau{ 22*04fd306cSNickeau 23*04fd306cSNickeau 24*04fd306cSNickeau public const PROPERTY_NAME = "template"; 25*04fd306cSNickeau public const PROPERTY_NAME_OLD = "layout"; 26*04fd306cSNickeau public const HOLY_TEMPLATE_VALUE = "holy"; 27*04fd306cSNickeau public const MEDIUM_TEMPLATE_VALUE = "medium"; 28*04fd306cSNickeau public const LANDING_TEMPLATE_VALUE = "landing"; 29*04fd306cSNickeau public const INDEX_TEMPLATE_VALUE = "index"; 30*04fd306cSNickeau public const HAMBURGER_TEMPLATE_VALUE = "hamburger"; 31*04fd306cSNickeau public const BLANK_TEMPLATE_VALUE = "blank"; 32*04fd306cSNickeau 33*04fd306cSNickeau /** 34*04fd306cSNickeau * Not public, used in test to overwrite it to {@link PageTemplateName::BLANK_TEMPLATE_VALUE} 35*04fd306cSNickeau * to speed up test 36*04fd306cSNickeau */ 37*04fd306cSNickeau const CONF_DEFAULT_NAME = "defaultLayoutName"; 38*04fd306cSNickeau 39*04fd306cSNickeau 40*04fd306cSNickeau /** 41*04fd306cSNickeau * App page 42*04fd306cSNickeau */ 43*04fd306cSNickeau const APP_PREFIX = "app-"; 44*04fd306cSNickeau const APP_EDIT = self::APP_PREFIX . ExecutionContext::EDIT_ACTION; 45*04fd306cSNickeau const APP_LOGIN = self::APP_PREFIX . ExecutionContext::LOGIN_ACTION; 46*04fd306cSNickeau const APP_SEARCH = self::APP_PREFIX . ExecutionContext::SEARCH_ACTION; 47*04fd306cSNickeau const APP_REGISTER = self::APP_PREFIX . ExecutionContext::REGISTER_ACTION; 48*04fd306cSNickeau const APP_RESEND_PWD = self::APP_PREFIX . ExecutionContext::RESEND_PWD_ACTION; 49*04fd306cSNickeau const APP_REVISIONS = self::APP_PREFIX . ExecutionContext::REVISIONS_ACTION; 50*04fd306cSNickeau const APP_DIFF = self::APP_PREFIX . ExecutionContext::DIFF_ACTION; 51*04fd306cSNickeau const APP_INDEX = self::APP_PREFIX . ExecutionContext::INDEX_ACTION; 52*04fd306cSNickeau const APP_PROFILE = self::APP_PREFIX . ExecutionContext::PROFILE_ACTION; 53*04fd306cSNickeau 54*04fd306cSNickeau /** 55*04fd306cSNickeau * @deprecated for {@link self::MEDIUM_TEMPLATE_VALUE} 56*04fd306cSNickeau * changed to medium (median has too much mathematics connotation) 57*04fd306cSNickeau * medium: halfway between two extremes 58*04fd306cSNickeau */ 59*04fd306cSNickeau const MEDIAN_OLD_TEMPLATE = "median"; 60*04fd306cSNickeau const HOLY_MEDIUM_LAYOUT = "holy-medium"; 61*04fd306cSNickeau const INDEX_MEDIUM_LAYOUT = "index-medium"; 62*04fd306cSNickeau 63*04fd306cSNickeau 64*04fd306cSNickeau public static function createFromPage(MarkupPath $page): PageTemplateName 65*04fd306cSNickeau { 66*04fd306cSNickeau return (new PageTemplateName()) 67*04fd306cSNickeau ->setResource($page); 68*04fd306cSNickeau } 69*04fd306cSNickeau 70*04fd306cSNickeau static public function getTab(): string 71*04fd306cSNickeau { 72*04fd306cSNickeau return MetaManagerForm::TAB_PAGE_VALUE; 73*04fd306cSNickeau } 74*04fd306cSNickeau 75*04fd306cSNickeau static public function getDescription(): string 76*04fd306cSNickeau { 77*04fd306cSNickeau return "A template applies a layout on your page"; 78*04fd306cSNickeau } 79*04fd306cSNickeau 80*04fd306cSNickeau static public function getLabel(): string 81*04fd306cSNickeau { 82*04fd306cSNickeau return "Template"; 83*04fd306cSNickeau } 84*04fd306cSNickeau 85*04fd306cSNickeau public function getPossibleValues(): ?array 86*04fd306cSNickeau { 87*04fd306cSNickeau try { 88*04fd306cSNickeau $templateNames = []; 89*04fd306cSNickeau $directories = TemplateEngine::createFromContext() 90*04fd306cSNickeau ->getTemplateSearchDirectories(); 91*04fd306cSNickeau foreach ($directories as $directory) { 92*04fd306cSNickeau $files = FileSystems::getChildrenLeaf($directory); 93*04fd306cSNickeau foreach ($files as $file) { 94*04fd306cSNickeau $lastNameWithoutExtension = $file->getLastNameWithoutExtension(); 95*04fd306cSNickeau if (strpos($lastNameWithoutExtension, self::APP_PREFIX) === 0) { 96*04fd306cSNickeau continue; 97*04fd306cSNickeau } 98*04fd306cSNickeau if ($file->getExtension() === TemplateEngine::EXTENSION_HBS) { 99*04fd306cSNickeau 100*04fd306cSNickeau $templateNames[] = $lastNameWithoutExtension; 101*04fd306cSNickeau } 102*04fd306cSNickeau } 103*04fd306cSNickeau } 104*04fd306cSNickeau sort($templateNames); 105*04fd306cSNickeau return $templateNames; 106*04fd306cSNickeau } catch (ExceptionNotFound $e) { 107*04fd306cSNickeau LogUtility::error("No template could be found", self::CANONICAL, $e); 108*04fd306cSNickeau return []; 109*04fd306cSNickeau } 110*04fd306cSNickeau } 111*04fd306cSNickeau 112*04fd306cSNickeau 113*04fd306cSNickeau static public function getName(): string 114*04fd306cSNickeau { 115*04fd306cSNickeau return self::PROPERTY_NAME; 116*04fd306cSNickeau } 117*04fd306cSNickeau 118*04fd306cSNickeau static public function getPersistenceType(): string 119*04fd306cSNickeau { 120*04fd306cSNickeau return Metadata::PERSISTENT_METADATA; 121*04fd306cSNickeau } 122*04fd306cSNickeau 123*04fd306cSNickeau static public function isMutable(): bool 124*04fd306cSNickeau { 125*04fd306cSNickeau return true; 126*04fd306cSNickeau } 127*04fd306cSNickeau 128*04fd306cSNickeau /** 129*04fd306cSNickeau * @return string 130*04fd306cSNickeau */ 131*04fd306cSNickeau public function getDefaultValue(): string 132*04fd306cSNickeau { 133*04fd306cSNickeau /** 134*04fd306cSNickeau * @var MarkupPath $page 135*04fd306cSNickeau */ 136*04fd306cSNickeau $page = $this->getResource(); 137*04fd306cSNickeau 138*04fd306cSNickeau /** 139*04fd306cSNickeau * Slot first 140*04fd306cSNickeau * because they are also root item page 141*04fd306cSNickeau */ 142*04fd306cSNickeau try { 143*04fd306cSNickeau switch ($page->getPathObject()->getLastNameWithoutExtension()) { 144*04fd306cSNickeau case SlotSystem::getSidebarName(): 145*04fd306cSNickeau case SlotSystem::getMainHeaderSlotName(): 146*04fd306cSNickeau case SlotSystem::getMainFooterSlotName(): 147*04fd306cSNickeau case SlotSystem::getMainSideSlotName(): 148*04fd306cSNickeau return self::INDEX_MEDIUM_LAYOUT; 149*04fd306cSNickeau case SlotSystem::getPageHeaderSlotName(): 150*04fd306cSNickeau case SlotSystem::getPageFooterSlotName(): 151*04fd306cSNickeau /** 152*04fd306cSNickeau * Header and footer contains bar 153*04fd306cSNickeau * {@link \syntax_plugin_combo_menubar menubar} or 154*04fd306cSNickeau * {@link \syntax_plugin_combo_bar} 155*04fd306cSNickeau * They therefore should not be constrained 156*04fd306cSNickeau * Landing page is perfect 157*04fd306cSNickeau */ 158*04fd306cSNickeau return self::LANDING_TEMPLATE_VALUE; 159*04fd306cSNickeau } 160*04fd306cSNickeau } catch (ExceptionNotFound $e) { 161*04fd306cSNickeau // No last name not installed 162*04fd306cSNickeau } 163*04fd306cSNickeau 164*04fd306cSNickeau 165*04fd306cSNickeau if ($page->isRootHomePage()) { 166*04fd306cSNickeau /** 167*04fd306cSNickeau * Ultimattely a {@link self::LANDING_TEMPLATE_VALUE} 168*04fd306cSNickeau * but for that the user needs to add {@link BarTag} 169*04fd306cSNickeau * 170*04fd306cSNickeau */ 171*04fd306cSNickeau return self::HAMBURGER_TEMPLATE_VALUE; 172*04fd306cSNickeau } 173*04fd306cSNickeau if ($page->isRootItemPage()) { 174*04fd306cSNickeau /** 175*04fd306cSNickeau * Home/Root item does not really belongs to the same 176*04fd306cSNickeau * namespace, we don't show therefore a sidebar 177*04fd306cSNickeau */ 178*04fd306cSNickeau return self::INDEX_MEDIUM_LAYOUT; 179*04fd306cSNickeau } 180*04fd306cSNickeau 181*04fd306cSNickeau 182*04fd306cSNickeau /** 183*04fd306cSNickeau * Default by namespace 184*04fd306cSNickeau * 185*04fd306cSNickeau * Calculate the possible template 186*04fd306cSNickeau * prefix in order 187*04fd306cSNickeau */ 188*04fd306cSNickeau try { 189*04fd306cSNickeau $parentNames = $page->getPathObject()->getParent()->getNames(); 190*04fd306cSNickeau $templatePrefixes = []; 191*04fd306cSNickeau $hierarchicalName = ''; 192*04fd306cSNickeau foreach ($parentNames as $name) { 193*04fd306cSNickeau if (empty($hierarchicalName)) { 194*04fd306cSNickeau $hierarchicalName .= $name; 195*04fd306cSNickeau } else { 196*04fd306cSNickeau $hierarchicalName .= "-$name"; 197*04fd306cSNickeau } 198*04fd306cSNickeau $templatePrefixes[] = $name; 199*04fd306cSNickeau if ($hierarchicalName !== $name) { 200*04fd306cSNickeau $templatePrefixes[] = $hierarchicalName; 201*04fd306cSNickeau } 202*04fd306cSNickeau } 203*04fd306cSNickeau $templatePrefixes = array_reverse($templatePrefixes); 204*04fd306cSNickeau } catch (ExceptionNotFound $e) { 205*04fd306cSNickeau // no parent, root 206*04fd306cSNickeau $templatePrefixes = []; 207*04fd306cSNickeau } 208*04fd306cSNickeau 209*04fd306cSNickeau $pageTemplateEngine = TemplateEngine::createFromContext(); 210*04fd306cSNickeau 211*04fd306cSNickeau 212*04fd306cSNickeau /** 213*04fd306cSNickeau * Index pages 214*04fd306cSNickeau */ 215*04fd306cSNickeau if ($page->isIndexPage()) { 216*04fd306cSNickeau foreach ($templatePrefixes as $templatePrefix) { 217*04fd306cSNickeau $templateName = "$templatePrefix-index"; 218*04fd306cSNickeau if ($pageTemplateEngine->templateExists($templateName)) { 219*04fd306cSNickeau return $templateName; 220*04fd306cSNickeau } 221*04fd306cSNickeau } 222*04fd306cSNickeau return self::INDEX_TEMPLATE_VALUE; 223*04fd306cSNickeau } 224*04fd306cSNickeau 225*04fd306cSNickeau /** 226*04fd306cSNickeau * Item page 227*04fd306cSNickeau */ 228*04fd306cSNickeau foreach ($templatePrefixes as $templatePrefix) { 229*04fd306cSNickeau $templateName = "$templatePrefix-item"; 230*04fd306cSNickeau if ($pageTemplateEngine->templateExists($templateName)) { 231*04fd306cSNickeau return $templateName; 232*04fd306cSNickeau } 233*04fd306cSNickeau } 234*04fd306cSNickeau 235*04fd306cSNickeau return ExecutionContext::getActualOrCreateFromEnv()->getConfig()->getDefaultLayoutName(); 236*04fd306cSNickeau 237*04fd306cSNickeau 238*04fd306cSNickeau } 239*04fd306cSNickeau 240*04fd306cSNickeau static public function getCanonical(): string 241*04fd306cSNickeau { 242*04fd306cSNickeau return self::PROPERTY_NAME; 243*04fd306cSNickeau } 244*04fd306cSNickeau 245*04fd306cSNickeau 246*04fd306cSNickeau /** 247*04fd306cSNickeau * @return string 248*04fd306cSNickeau */ 249*04fd306cSNickeau public function getValueOrDefault(): string 250*04fd306cSNickeau { 251*04fd306cSNickeau 252*04fd306cSNickeau try { 253*04fd306cSNickeau $value = $this->getValue(); 254*04fd306cSNickeau if ($value === "") { 255*04fd306cSNickeau return $this->getDefaultValue(); 256*04fd306cSNickeau } 257*04fd306cSNickeau return $value; 258*04fd306cSNickeau } catch (ExceptionNotFound $e) { 259*04fd306cSNickeau return $this->getDefaultValue(); 260*04fd306cSNickeau } 261*04fd306cSNickeau 262*04fd306cSNickeau 263*04fd306cSNickeau } 264*04fd306cSNickeau 265*04fd306cSNickeau /** @noinspection PhpMissingReturnTypeInspection */ 266*04fd306cSNickeau public function buildFromReadStore() 267*04fd306cSNickeau { 268*04fd306cSNickeau 269*04fd306cSNickeau $metaDataStore = $this->getReadStore(); 270*04fd306cSNickeau $value = $metaDataStore->getFromName(self::PROPERTY_NAME); 271*04fd306cSNickeau if ($value === null) { 272*04fd306cSNickeau $value = $metaDataStore->getFromName(self::PROPERTY_NAME_OLD); 273*04fd306cSNickeau } 274*04fd306cSNickeau if ($value === self::MEDIAN_OLD_TEMPLATE) { 275*04fd306cSNickeau $value = self::MEDIUM_TEMPLATE_VALUE; 276*04fd306cSNickeau } 277*04fd306cSNickeau parent::setFromStoreValueWithoutException($value); 278*04fd306cSNickeau return $this; 279*04fd306cSNickeau } 280*04fd306cSNickeau 281*04fd306cSNickeau public function sendToWriteStore(): Metadata 282*04fd306cSNickeau { 283*04fd306cSNickeau 284*04fd306cSNickeau parent::sendToWriteStore(); 285*04fd306cSNickeau $writeStore = $this->getWriteStore(); 286*04fd306cSNickeau $value = $writeStore->getFromName(self::PROPERTY_NAME_OLD); 287*04fd306cSNickeau if ($value !== null) { 288*04fd306cSNickeau // delete the old value 289*04fd306cSNickeau $writeStore->setFromPersistentName(self::PROPERTY_NAME_OLD, null); 290*04fd306cSNickeau } 291*04fd306cSNickeau 292*04fd306cSNickeau return $this; 293*04fd306cSNickeau } 294*04fd306cSNickeau 295*04fd306cSNickeau public static function getOldPersistentNames(): array 296*04fd306cSNickeau { 297*04fd306cSNickeau return [self::PROPERTY_NAME_OLD]; 298*04fd306cSNickeau } 299*04fd306cSNickeau 300*04fd306cSNickeau 301*04fd306cSNickeau static public function isOnForm(): bool 302*04fd306cSNickeau { 303*04fd306cSNickeau return true; 304*04fd306cSNickeau } 305*04fd306cSNickeau} 306