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