xref: /plugin/combo/ComboStrap/Meta/Field/PageTemplateName.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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