xref: /template/strap/ComboStrap/TemplateSlot.php (revision ad54dffd2a785f08006601bf247e440e47fc7b18)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeau
404fd306cSNickeaunamespace ComboStrap;
504fd306cSNickeau
604fd306cSNickeau
704fd306cSNickeau/**
804fd306cSNickeau * This class represents a page layout slots
904fd306cSNickeau */
1004fd306cSNickeauclass TemplateSlot
1104fd306cSNickeau{
1204fd306cSNickeau    public const SLOT_IDS = [
1304fd306cSNickeau        self::PAGE_SIDE_ID,
1404fd306cSNickeau        self::PAGE_HEADER_ID,
1504fd306cSNickeau        self::PAGE_MAIN_ID,
1604fd306cSNickeau        self::PAGE_FOOTER_ID,
1704fd306cSNickeau        self::MAIN_HEADER_ID,
1804fd306cSNickeau        self::MAIN_CONTENT_ID,
1904fd306cSNickeau        self::MAIN_SIDE_ID,
2004fd306cSNickeau        self::MAIN_FOOTER_ID
2104fd306cSNickeau    ];
2204fd306cSNickeau    public const PAGE_HEADER_ID = "page-header";
2304fd306cSNickeau    public const PAGE_FOOTER_ID = "page-footer";
2404fd306cSNickeau    public const MAIN_SIDE_ID = "main-side";
2504fd306cSNickeau    public const PAGE_SIDE_ID = "page-side";
2604fd306cSNickeau    public const MAIN_CONTENT_ID = "main-content";
2704fd306cSNickeau    public const MAIN_FOOTER_ID = "main-footer";
2804fd306cSNickeau    public const MAIN_HEADER_ID = "main-header";
2904fd306cSNickeau    public const PAGE_MAIN_ID = "page-main";
3004fd306cSNickeau    public const CONF_PAGE_MAIN_SIDEKICK_NAME_DEFAULT = Site::SLOT_MAIN_SIDE_NAME;
31*ad54dffdSgerardnico    public const CONF_PAGE_HEADER_NAME = "combo-conf-008";
32*ad54dffdSgerardnico    public const CONF_PAGE_FOOTER_NAME = "combo-conf-009";
3304fd306cSNickeau    public const CONF_PAGE_HEADER_NAME_DEFAULT = "slot_header";
3404fd306cSNickeau    public const CONF_PAGE_FOOTER_NAME_DEFAULT = "slot_footer";
3504fd306cSNickeau    public const CONF_PAGE_MAIN_SIDEKICK_NAME = "sidekickSlotPageName";
3604fd306cSNickeau    const MAIN_TOC_ID = "main-toc";
3704fd306cSNickeau    const SLOT_MAIN_HEADER_PATH_NAME = "slot_main_header";
3804fd306cSNickeau    const SLOT_MAIN_FOOTER_PATH_NAME = "slot_main_footer";
3904fd306cSNickeau
4004fd306cSNickeau
4104fd306cSNickeau    /**
4204fd306cSNickeau     * @var WikiPath - the context path of this slot
4304fd306cSNickeau     */
4404fd306cSNickeau    private WikiPath $contextPath;
4504fd306cSNickeau    /**
4604fd306cSNickeau     * @var FetcherMarkup - the fetcher if this is a slot and has a page fragment source
4704fd306cSNickeau     */
4804fd306cSNickeau    private FetcherMarkup $fetcherFragment;
4904fd306cSNickeau    private string $elementId;
5004fd306cSNickeau
5104fd306cSNickeau
5204fd306cSNickeau    public function __construct(string $elementId, WikiPath $contextPath)
5304fd306cSNickeau    {
5404fd306cSNickeau
5504fd306cSNickeau        $this->elementId = $elementId;
5604fd306cSNickeau        if (!in_array($elementId, self::SLOT_IDS)) {
5704fd306cSNickeau            throw new ExceptionRuntimeInternal("$elementId is not a valid slot id. Valid ids are (" . ArrayUtility::formatAsString(self::SLOT_IDS) . ").");
5804fd306cSNickeau        }
5904fd306cSNickeau        $this->contextPath = $contextPath;
6004fd306cSNickeau
6104fd306cSNickeau
6204fd306cSNickeau    }
6304fd306cSNickeau
6404fd306cSNickeau    public static function createFromElementId(string $elementId, WikiPath $contextPath = null): TemplateSlot
6504fd306cSNickeau    {
6604fd306cSNickeau
6704fd306cSNickeau        if ($contextPath === null) {
6804fd306cSNickeau            $contextPath = ExecutionContext::getActualOrCreateFromEnv()
6904fd306cSNickeau                ->getConfig()
7004fd306cSNickeau                ->getDefaultContextPath();
7104fd306cSNickeau        }
7204fd306cSNickeau        return new TemplateSlot($elementId, $contextPath);
7304fd306cSNickeau
7404fd306cSNickeau    }
7504fd306cSNickeau
7604fd306cSNickeau    public static function createFromPathName($pathNameWithoutExtension): TemplateSlot
7704fd306cSNickeau    {
7804fd306cSNickeau        return self::createFromElementId(self::getElementIdFromPathName($pathNameWithoutExtension));
7904fd306cSNickeau    }
8004fd306cSNickeau
8104fd306cSNickeau    private static function getElementIdFromPathName($pathNameWithoutExtension): string
8204fd306cSNickeau    {
8304fd306cSNickeau        if ($pathNameWithoutExtension === SlotSystem::getPageHeaderSlotName()) {
8404fd306cSNickeau            return self::PAGE_HEADER_ID;
8504fd306cSNickeau        }
8604fd306cSNickeau
8704fd306cSNickeau        if ($pathNameWithoutExtension === SlotSystem::getPageFooterSlotName()) {
8804fd306cSNickeau            return self::PAGE_FOOTER_ID;
8904fd306cSNickeau        }
9004fd306cSNickeau        if ($pathNameWithoutExtension === SlotSystem::getSidebarName()) {
9104fd306cSNickeau            return self::PAGE_SIDE_ID;
9204fd306cSNickeau        }
9304fd306cSNickeau
9404fd306cSNickeau        if ($pathNameWithoutExtension === SlotSystem::getMainSideSlotName()) {
9504fd306cSNickeau            return self::MAIN_SIDE_ID;
9604fd306cSNickeau        }
9704fd306cSNickeau        if ($pathNameWithoutExtension === self::SLOT_MAIN_HEADER_PATH_NAME) {
9804fd306cSNickeau            return self::MAIN_HEADER_ID;
9904fd306cSNickeau        }
10004fd306cSNickeau        if ($pathNameWithoutExtension === self::SLOT_MAIN_FOOTER_PATH_NAME) {
10104fd306cSNickeau            return self::MAIN_FOOTER_ID;
10204fd306cSNickeau        }
10304fd306cSNickeau        throw new ExceptionRuntimeInternal("Internal: The markup name ($pathNameWithoutExtension) was unexpected, it's not a slot");
10404fd306cSNickeau
10504fd306cSNickeau    }
10604fd306cSNickeau
10704fd306cSNickeau
10804fd306cSNickeau    public
10904fd306cSNickeau    static function getPathNameFromElementId($elementId)
11004fd306cSNickeau    {
11104fd306cSNickeau        switch ($elementId) {
11204fd306cSNickeau            case self::PAGE_HEADER_ID:
11304fd306cSNickeau                return SlotSystem::getPageHeaderSlotName();
11404fd306cSNickeau            case self::PAGE_FOOTER_ID:
11504fd306cSNickeau                return SlotSystem::getPageFooterSlotName();
11604fd306cSNickeau            case self::MAIN_CONTENT_ID:
11704fd306cSNickeau                throw new ExceptionRuntimeInternal("Main content area is not a slot and does not have any last slot name");
11804fd306cSNickeau            case self::PAGE_SIDE_ID:
11904fd306cSNickeau                return SlotSystem::getSidebarName();
12004fd306cSNickeau            case self::MAIN_SIDE_ID:
12104fd306cSNickeau                return SlotSystem::getMainSideSlotName();
12204fd306cSNickeau            case self::MAIN_HEADER_ID:
12304fd306cSNickeau                return self::SLOT_MAIN_HEADER_PATH_NAME;
12404fd306cSNickeau            case self::MAIN_FOOTER_ID:
12504fd306cSNickeau                return self::SLOT_MAIN_FOOTER_PATH_NAME;
12604fd306cSNickeau            default:
12704fd306cSNickeau                throw new ExceptionRuntimeInternal("Internal: The element ($elementId) was unexpected, it's not a slot");
12804fd306cSNickeau        }
12904fd306cSNickeau
13004fd306cSNickeau    }
13104fd306cSNickeau
13204fd306cSNickeau    /**
13304fd306cSNickeau     *
13404fd306cSNickeau     * @return WikiPath
13504fd306cSNickeau     */
13604fd306cSNickeau    public
13704fd306cSNickeau     function getDefaultSlotContentPath(): WikiPath
13804fd306cSNickeau    {
13904fd306cSNickeau        return WikiPath::createComboResource(":slot:{$this->getElementId()}.md");
14004fd306cSNickeau    }
14104fd306cSNickeau
14204fd306cSNickeau
14304fd306cSNickeau    /**
14404fd306cSNickeau     */
14504fd306cSNickeau    public
14604fd306cSNickeau    function getLastFileNameForFragment()
14704fd306cSNickeau    {
14804fd306cSNickeau        $elementId = $this->getElementId();
14904fd306cSNickeau        return self::getPathNameFromElementId($elementId);
15004fd306cSNickeau    }
15104fd306cSNickeau
15204fd306cSNickeau
15304fd306cSNickeau    public
15404fd306cSNickeau    function __toString()
15504fd306cSNickeau    {
15604fd306cSNickeau        return "Slot {$this->getElementId()} for {$this->contextPath}";
15704fd306cSNickeau    }
15804fd306cSNickeau
15904fd306cSNickeau
16004fd306cSNickeau    /**
16104fd306cSNickeau     * @throws ExceptionNotFound - if the area is not a slot or there is no path found
16204fd306cSNickeau     */
16304fd306cSNickeau    private
16404fd306cSNickeau    function getFragmentPath()
16504fd306cSNickeau    {
16604fd306cSNickeau
16704fd306cSNickeau        // Main content
16804fd306cSNickeau        $requestedPath = $this->contextPath;
16904fd306cSNickeau        if ($this->getElementId() === self::MAIN_CONTENT_ID) {
17004fd306cSNickeau            return $requestedPath;
17104fd306cSNickeau        }
17204fd306cSNickeau        // Slot
17304fd306cSNickeau        $contextExtension = $requestedPath->getExtension();
17404fd306cSNickeau        try {
17504fd306cSNickeau            return FileSystems::closest($requestedPath, $this->getLastFileNameForFragment() . '.' . $contextExtension);
17604fd306cSNickeau        } catch (ExceptionNotFound $e) {
17704fd306cSNickeau            foreach (WikiPath::ALL_MARKUP_EXTENSIONS as $markupExtension) {
17804fd306cSNickeau                if ($markupExtension == $contextExtension) {
17904fd306cSNickeau                    continue;
18004fd306cSNickeau                }
18104fd306cSNickeau                try {
18204fd306cSNickeau                    return FileSystems::closest($requestedPath, $this->getLastFileNameForFragment() . '.' . $contextExtension);
18304fd306cSNickeau                } catch (ExceptionNotFound $e) {
18404fd306cSNickeau                    // not found, we let it go to the default if needed
18504fd306cSNickeau                }
18604fd306cSNickeau            }
18704fd306cSNickeau        }
18804fd306cSNickeau
18904fd306cSNickeau
19004fd306cSNickeau        return $this->getDefaultSlotContentPath();
19104fd306cSNickeau
19204fd306cSNickeau
19304fd306cSNickeau
19404fd306cSNickeau    }
19504fd306cSNickeau
19604fd306cSNickeau
19704fd306cSNickeau    /**
19804fd306cSNickeau     * @throws ExceptionNotFound if the page/markup fragment was not found (a container element does not have any also)
19904fd306cSNickeau     */
20004fd306cSNickeau    public
20104fd306cSNickeau    function getMarkupFetcher(): FetcherMarkup
20204fd306cSNickeau    {
20304fd306cSNickeau        if (isset($this->fetcherFragment)) {
20404fd306cSNickeau            return $this->fetcherFragment;
20504fd306cSNickeau        }
20604fd306cSNickeau        /**
20704fd306cSNickeau         * Rebuild the fragment if any
20804fd306cSNickeau         */
20904fd306cSNickeau        $fragmentPath = $this->getFragmentPath();
21004fd306cSNickeau        $contextPath = $this->contextPath;
21104fd306cSNickeau        try {
21204fd306cSNickeau            $this->fetcherFragment = FetcherMarkup::createXhtmlMarkupFetcherFromPath($fragmentPath, $contextPath);
21304fd306cSNickeau        } catch (ExceptionNotExists $e) {
21404fd306cSNickeau            throw new ExceptionNotFound("The fragment path ($fragmentPath) was no found");
21504fd306cSNickeau        }
21604fd306cSNickeau        return $this->fetcherFragment;
21704fd306cSNickeau    }
21804fd306cSNickeau
21904fd306cSNickeau    public
22004fd306cSNickeau    function getElementId(): string
22104fd306cSNickeau    {
22204fd306cSNickeau        return $this->elementId;
22304fd306cSNickeau    }
22404fd306cSNickeau
22504fd306cSNickeau    public function getPathName()
22604fd306cSNickeau    {
22704fd306cSNickeau        return self::getPathNameFromElementId($this->getElementId());
22804fd306cSNickeau    }
22904fd306cSNickeau
23004fd306cSNickeau
23104fd306cSNickeau}
232