xref: /plugin/combo/ComboStrap/BreadcrumbTag.php (revision dff3a8c8e9d5229502eb360aee88a665b7d1c2dc)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeaunamespace ComboStrap;
404fd306cSNickeau
504fd306cSNickeau
604fd306cSNickeau/**
704fd306cSNickeau * Utility class for breadcrumb
804fd306cSNickeau *
904fd306cSNickeau *
1004fd306cSNickeau *
1104fd306cSNickeau * https://en.wikipedia.org/wiki/Breadcrumb_navigation#Websites
1204fd306cSNickeau */
1304fd306cSNickeauclass BreadcrumbTag
1404fd306cSNickeau{
1504fd306cSNickeau    /**
1604fd306cSNickeau     * The type of breadcrumb
1704fd306cSNickeau     *
1804fd306cSNickeau     * Navigation is a markup that should be present
1904fd306cSNickeau     * only once in a page
2004fd306cSNickeau     */
2104fd306cSNickeau    public const NAVIGATION_TYPE = "nav";
2204fd306cSNickeau    /**
2304fd306cSNickeau     * Typography is when a breadcrumb is used in a iterator
2404fd306cSNickeau     * for instance as sub-title
2504fd306cSNickeau     */
2604fd306cSNickeau    public const TYPOGRAPHY_TYPE = "typo";
2704fd306cSNickeau    public const MARKUP_BLOCK = "breadcrumb";
2804fd306cSNickeau    public const LOGICAL_TAG = "breadcrumb";
2904fd306cSNickeau    public const CANONICAL_HIERARCHICAL = "breadcrumb-hierarchical";
3004fd306cSNickeau    public const DEPTH_ATTRIBUTE = "depth";
3104fd306cSNickeau    const TYPES = [self::TYPOGRAPHY_TYPE, self::NAVIGATION_TYPE];
3204fd306cSNickeau
3304fd306cSNickeau    /**
3404fd306cSNickeau     * Hierarchical breadcrumbs (you are here)
3504fd306cSNickeau     *
3604fd306cSNickeau     * This will return the Hierarchical breadcrumbs.
3704fd306cSNickeau     *
3804fd306cSNickeau     * Config:
3904fd306cSNickeau     *    - $conf['youarehere'] must be true
4004fd306cSNickeau     *    - add $lang['youarehere'] if $printPrefix is true
4104fd306cSNickeau     *
4204fd306cSNickeau     * Metadata comes from here
4304fd306cSNickeau     * https://developers.google.com/search/docs/data-types/breadcrumb
4404fd306cSNickeau     *
4504fd306cSNickeau     * @param TagAttributes|null $tagAttributes
4604fd306cSNickeau     * @return string
4704fd306cSNickeau     */
4804fd306cSNickeau    public static function toBreadCrumbHtml(TagAttributes $tagAttributes = null): string
4904fd306cSNickeau    {
5004fd306cSNickeau
5104fd306cSNickeau        if ($tagAttributes === null) {
5204fd306cSNickeau            $tagAttributes = TagAttributes::createEmpty(self::MARKUP_BLOCK);
5304fd306cSNickeau        }
5404fd306cSNickeau
5504fd306cSNickeau
5604fd306cSNickeau        /**
5704fd306cSNickeau         * Get the page
5804fd306cSNickeau         */
5904fd306cSNickeau        $path = \syntax_plugin_combo_iterator::getContextPathForComponentThatMayBeInFragment($tagAttributes);
6004fd306cSNickeau        $actualPath = MarkupPath::createPageFromPathObject($path);
6104fd306cSNickeau
6204fd306cSNickeau        $type = $tagAttributes->getType();
6304fd306cSNickeau
6404fd306cSNickeau
6504fd306cSNickeau        /**
6604fd306cSNickeau         * Print in function of the depth
6704fd306cSNickeau         */
6804fd306cSNickeau        switch ($type) {
6904fd306cSNickeau            case self::NAVIGATION_TYPE:
7004fd306cSNickeau                /**
7104fd306cSNickeau                 * https://www.w3.org/TR/wai-aria-practices/examples/breadcrumb/index.html
7204fd306cSNickeau                 * Arial-label Provides a label that describes the type of navigation provided in the nav element.
7304fd306cSNickeau                 */
7404fd306cSNickeau                $tagAttributes->addOutputAttributeValue("aria-label", "Hierarchical breadcrumb");
7504fd306cSNickeau                $htmlOutput = $tagAttributes->toHtmlEnterTag("nav");
7604fd306cSNickeau                $htmlOutput .= '<ol class="breadcrumb">';
7704fd306cSNickeau
7804fd306cSNickeau                $lisHtmlOutput = self::getLiHtmlOutput($actualPath, true);
7904fd306cSNickeau                while (true) {
8004fd306cSNickeau                    try {
8104fd306cSNickeau                        $actualPath = $actualPath->getParent();
8204fd306cSNickeau                    } catch (ExceptionNotFound $e) {
8304fd306cSNickeau                        break;
8404fd306cSNickeau                    }
8504fd306cSNickeau                    $liHtmlOutput = self::getLiHtmlOutput($actualPath);
8604fd306cSNickeau                    $lisHtmlOutput = $liHtmlOutput . $lisHtmlOutput;
8704fd306cSNickeau                }
8804fd306cSNickeau                $htmlOutput .= $lisHtmlOutput;
8904fd306cSNickeau                // close the breadcrumb
9004fd306cSNickeau                $htmlOutput .= '</ol>';
9104fd306cSNickeau                $htmlOutput .= '</nav>';
9204fd306cSNickeau                return $htmlOutput;
9304fd306cSNickeau            case self::TYPOGRAPHY_TYPE:
9404fd306cSNickeau
9504fd306cSNickeau                try {
9604fd306cSNickeau                    $requiredDepth = DataType::toInteger($tagAttributes->getValueAndRemoveIfPresent(self::DEPTH_ATTRIBUTE));
9704fd306cSNickeau                } catch (ExceptionBadArgument $e) {
98*dff3a8c8SNico                    LogUtility::error("We were unable to determine the depth attribute. The depth was set to 1. Error: {$e->getMessage()}",self::LOGICAL_TAG);
9904fd306cSNickeau                    $requiredDepth = 1;
10004fd306cSNickeau                }
10104fd306cSNickeau                if ($requiredDepth > 1) {
10204fd306cSNickeau                    SnippetSystem::getFromContext()->attachCssInternalStyleSheet("breadcrumb-$type");
10304fd306cSNickeau                }
10404fd306cSNickeau                $htmlOutput = $tagAttributes->toHtmlEnterTag("span");
10504fd306cSNickeau                $lisHtmlOutput = "";
10604fd306cSNickeau                $actualDepth = 0;
10704fd306cSNickeau                while (true) {
10804fd306cSNickeau                    try {
10904fd306cSNickeau                        $actualPath = $actualPath->getParent();
11004fd306cSNickeau                    } catch (ExceptionNotFound $e) {
11104fd306cSNickeau                        break;
11204fd306cSNickeau                    }
11304fd306cSNickeau                    $actualDepth = $actualDepth + 1;
11404fd306cSNickeau                    $nameOrDefault = $actualPath->getNameOrDefault();
11504fd306cSNickeau                    $liHtmlOutput = "<span class=\"breadcrumb-$type-item\">$nameOrDefault</span>";
11604fd306cSNickeau                    $lisHtmlOutput = $liHtmlOutput . $lisHtmlOutput;
11704fd306cSNickeau                    if ($actualDepth >= $requiredDepth) {
11804fd306cSNickeau                        break;
11904fd306cSNickeau                    }
12004fd306cSNickeau                }
12104fd306cSNickeau                $htmlOutput .= $lisHtmlOutput;
12204fd306cSNickeau                $htmlOutput .= '</span>';
12304fd306cSNickeau                return $htmlOutput;
12404fd306cSNickeau            default:
12504fd306cSNickeau                // internal error
12604fd306cSNickeau                LogUtility::error("The breadcrumb type ($type) is unknown");
12704fd306cSNickeau                return "";
12804fd306cSNickeau
12904fd306cSNickeau        }
13004fd306cSNickeau
13104fd306cSNickeau
13204fd306cSNickeau    }
13304fd306cSNickeau
13404fd306cSNickeau    /**
13504fd306cSNickeau     * @param MarkupPath $page
13604fd306cSNickeau     * @param bool $current
13704fd306cSNickeau     * @param bool $link
13804fd306cSNickeau     * @return string - the list item for the page
13904fd306cSNickeau     */
14004fd306cSNickeau    public static function getLiHtmlOutput(MarkupPath $page, bool $current = false, bool $link = true): string
14104fd306cSNickeau    {
14204fd306cSNickeau        $liClass = "";
14304fd306cSNickeau        $liArial = "";
14404fd306cSNickeau        if ($current) {
14504fd306cSNickeau            $liClass = " active";
14604fd306cSNickeau            /**
14704fd306cSNickeau             * https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/
14804fd306cSNickeau             * Applied to a link in the breadcrumb set to indicate that it represents the current page.
14904fd306cSNickeau             */
15004fd306cSNickeau            $liArial = " aria-current=\"page\"";
15104fd306cSNickeau        }
15204fd306cSNickeau        $liHtmlOutput = "<li class=\"breadcrumb-item$liClass\"$liArial>";
15304fd306cSNickeau
15404fd306cSNickeau        if (FileSystems::exists($page->getPathObject()) && $current === false) {
15504fd306cSNickeau            if ($link) {
15604fd306cSNickeau                $liHtmlOutput .= $page->getHtmlAnchorLink(self::CANONICAL_HIERARCHICAL);
15704fd306cSNickeau            } else {
15804fd306cSNickeau                $liHtmlOutput .= $page->getNameOrDefault();
15904fd306cSNickeau            }
16004fd306cSNickeau        } else {
16104fd306cSNickeau            $liHtmlOutput .= $page->getNameOrDefault();
16204fd306cSNickeau        }
16304fd306cSNickeau        $liHtmlOutput .= '</li>';
16404fd306cSNickeau        return $liHtmlOutput;
16504fd306cSNickeau    }
16604fd306cSNickeau
16704fd306cSNickeau    /**
16804fd306cSNickeau     * Same rendering for typographic or navigational breadcrumb
16904fd306cSNickeau     * @param TagAttributes $tagAttributes
17004fd306cSNickeau     * @return string
17104fd306cSNickeau     */
17204fd306cSNickeau    public static function render(TagAttributes $tagAttributes): string
17304fd306cSNickeau    {
17404fd306cSNickeau
17504fd306cSNickeau        try {
17604fd306cSNickeau            ExecutionContext::getActualOrCreateFromEnv()
17704fd306cSNickeau                ->getExecutingMarkupHandler()
17804fd306cSNickeau                ->getOutputCacheDependencies()
17904fd306cSNickeau                // the output has the data from the requested page
18004fd306cSNickeau                ->addDependency(MarkupCacheDependencies::REQUESTED_PAGE_DEPENDENCY)
18104fd306cSNickeau                // the data from the requested page is dependent on the name, title or description of the page
18204fd306cSNickeau                ->addDependency(MarkupCacheDependencies::PAGE_PRIMARY_META_DEPENDENCY);
18304fd306cSNickeau        } catch (ExceptionNotFound $e) {
18404fd306cSNickeau            // not a fetcher markup run
18504fd306cSNickeau        }
18604fd306cSNickeau
18704fd306cSNickeau        return BreadcrumbTag::toBreadCrumbHtml($tagAttributes);
18804fd306cSNickeau
18904fd306cSNickeau    }
19004fd306cSNickeau
19104fd306cSNickeau    public static function getDefaultBlockAttributes(): array
19204fd306cSNickeau    {
19304fd306cSNickeau        return [TagAttributes::TYPE_KEY => BreadcrumbTag::NAVIGATION_TYPE];
19404fd306cSNickeau    }
19504fd306cSNickeau
19604fd306cSNickeau    public static function handleEnter(TagAttributes $tagAttributes): array
19704fd306cSNickeau    {
19804fd306cSNickeau        if ($tagAttributes->getType() === self::TYPOGRAPHY_TYPE) {
19904fd306cSNickeau            return [PluginUtility::DISPLAY => Call::INLINE_DISPLAY];
20004fd306cSNickeau        } else {
20104fd306cSNickeau            return [PluginUtility::DISPLAY => Call::BlOCK_DISPLAY];
20204fd306cSNickeau        }
20304fd306cSNickeau    }
20404fd306cSNickeau
20504fd306cSNickeau}
206