1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeaunamespace ComboStrap; 4*04fd306cSNickeau 5*04fd306cSNickeau 6*04fd306cSNickeauuse ComboStrap\TagAttribute\StyleAttribute; 7*04fd306cSNickeauuse Doku_Handler; 8*04fd306cSNickeau 9*04fd306cSNickeau 10*04fd306cSNickeauclass PageExplorerTag 11*04fd306cSNickeau{ 12*04fd306cSNickeau public const PAGE_TYPE = "page"; 13*04fd306cSNickeau public const FOLDER_ICON = "images:page-explorer-folder"; 14*04fd306cSNickeau /** 15*04fd306cSNickeau * Page canonical and tag pattern 16*04fd306cSNickeau */ 17*04fd306cSNickeau public const CANONICAL = "page-explorer"; 18*04fd306cSNickeau public const HOME_TYPE = "home"; 19*04fd306cSNickeau public const PAGE_ATTRIBUTES = "page-attributes"; 20*04fd306cSNickeau public const INDEX_INSTRUCTIONS = "index-instructions"; 21*04fd306cSNickeau public const NAMESPACE_ATTRIBUTES = "namespace-attributes"; 22*04fd306cSNickeau public const TYPE_TREE = "tree"; 23*04fd306cSNickeau public const PAGE_INSTRUCTIONS = "page-instructions"; 24*04fd306cSNickeau public const PARENT_ATTRIBUTES = "parent-attributes"; 25*04fd306cSNickeau public const INDEX_ATTRIBUTES = "index-attributes"; 26*04fd306cSNickeau public const NAMESPACE_INSTRUCTIONS = "namespace-instructions"; 27*04fd306cSNickeau /** 28*04fd306cSNickeau * Tag in Dokuwiki cannot have a `-` 29*04fd306cSNickeau * This is the last part of the class 30*04fd306cSNickeau */ 31*04fd306cSNickeau public const LOGICAL_TAG = self::PAGE_EXPLORER_MARKUP; 32*04fd306cSNickeau /** 33*04fd306cSNickeau * Namespace attribute 34*04fd306cSNickeau * that contains the namespace information 35*04fd306cSNickeau * (ie 36*04fd306cSNickeau * * a namespace path 37*04fd306cSNickeau * * or current, for the namespace of the current requested page 38*04fd306cSNickeau */ 39*04fd306cSNickeau public const ATTR_NAMESPACE = "ns"; 40*04fd306cSNickeau public const LEVEL_UP_ICON = "images:page-explorer-icons8-level-up"; 41*04fd306cSNickeau 42*04fd306cSNickeau public const NTOC_MARKUP = "ntoc"; 43*04fd306cSNickeau public const PAGE_EXPLORER_MARKUP = "page-explorer"; 44*04fd306cSNickeau 45*04fd306cSNickeau public const PARENT_INSTRUCTIONS = "parent-instructions"; 46*04fd306cSNickeau /** 47*04fd306cSNickeau * Attributes on the home node 48*04fd306cSNickeau */ 49*04fd306cSNickeau public const LIST_TYPE = "list"; 50*04fd306cSNickeau public const INDEX_TAG = "index"; 51*04fd306cSNickeau /** 52*04fd306cSNickeau * The pattern 53*04fd306cSNickeau */ 54*04fd306cSNickeau public const INDEX_HOME_TAG = "home"; 55*04fd306cSNickeau /** 56*04fd306cSNickeau * Tag in Dokuwiki cannot have a `-` 57*04fd306cSNickeau * This is the last part of the class 58*04fd306cSNickeau */ 59*04fd306cSNickeau public const LOGICAL_INDEX_TAG = "pageexplorerhome"; 60*04fd306cSNickeau public const INDEXES_TAG = [PageExplorerTag::INDEX_HOME_TAG, PageExplorerTag::INDEX_TAG]; 61*04fd306cSNickeau /** 62*04fd306cSNickeau * Implementation of the namespace 63*04fd306cSNickeau * * ie the button (in a collapsible menu) http://localhost:63342/bootstrap-5.0.1-examples/sidebars/index.html 64*04fd306cSNickeau * * or the directory in a list menu 65*04fd306cSNickeau * 66*04fd306cSNickeau * This syntax is not a classic syntax plugin 67*04fd306cSNickeau * The instructions are captured at the {@link DOKU_LEXER_END} 68*04fd306cSNickeau * state of {@link syntax_plugin_combo_pageexplorer::handle()} 69*04fd306cSNickeau * to create/generate the namespaces 70*04fd306cSNickeau * 71*04fd306cSNickeau */ 72*04fd306cSNickeau public const NAMESPACE_LOGICAL_TAG = "pageexplorernamespace"; 73*04fd306cSNickeau public const NAMESPACE_SHORT_TAG = "ns"; 74*04fd306cSNickeau public const NAMESPACE_ITEM_TAG = "ns-item"; 75*04fd306cSNickeau public const NAMESPACE_LONG_TAG = "namespace"; 76*04fd306cSNickeau /** 77*04fd306cSNickeau * Tag in Dokuwiki cannot have a `-` 78*04fd306cSNickeau * This is the last part of the class 79*04fd306cSNickeau */ 80*04fd306cSNickeau public const PAGE_LOGICAL_TAG = self::PAGE_TAG; 81*04fd306cSNickeau /** 82*04fd306cSNickeau * The pattern 83*04fd306cSNickeau */ 84*04fd306cSNickeau public const PAGE_TAG = "page"; 85*04fd306cSNickeau public const PAGE_ITEM_TAG = "page-item"; 86*04fd306cSNickeau const PARENT_TAG = "parent"; 87*04fd306cSNickeau 88*04fd306cSNickeau 89*04fd306cSNickeau /** 90*04fd306cSNickeau * @param string $html 91*04fd306cSNickeau * @param MarkupPath $page 92*04fd306cSNickeau * @param array $data - the data array from the handler 93*04fd306cSNickeau * @param string $type 94*04fd306cSNickeau */ 95*04fd306cSNickeau public static function treeProcessLeaf(string &$html, MarkupPath $page, array $data, string $type) 96*04fd306cSNickeau { 97*04fd306cSNickeau /** 98*04fd306cSNickeau * In callstack instructions 99*04fd306cSNickeau * <li> 100*04fd306cSNickeau * $instructions 101*04fd306cSNickeau * </li> 102*04fd306cSNickeau */ 103*04fd306cSNickeau $pageAttributes = $data[self::PAGE_ATTRIBUTES]; 104*04fd306cSNickeau $pageInstructions = $data[self::PAGE_INSTRUCTIONS]; 105*04fd306cSNickeau if ($pageInstructions === null && $pageAttributes !== null) { 106*04fd306cSNickeau return; 107*04fd306cSNickeau } 108*04fd306cSNickeau if (!FileSystems::exists($page->getPathObject())) { 109*04fd306cSNickeau LogUtility::error("The given leaf page ($page) does not exist and was not added to the page-explorer tree", self::CANONICAL); 110*04fd306cSNickeau return; 111*04fd306cSNickeau } 112*04fd306cSNickeau if ($page->isHidden()) { 113*04fd306cSNickeau return; 114*04fd306cSNickeau } 115*04fd306cSNickeau 116*04fd306cSNickeau $listItemEnterTag = TagAttributes::createEmpty() 117*04fd306cSNickeau ->setLogicalTag(self::CANONICAL . "-tree-$type") 118*04fd306cSNickeau ->toHtmlEnterTag("li"); 119*04fd306cSNickeau 120*04fd306cSNickeau $listItemContent = ""; 121*04fd306cSNickeau if ($pageInstructions !== null) { 122*04fd306cSNickeau try { 123*04fd306cSNickeau $listItemContent = MarkupRenderUtility::renderInstructionsToXhtml($pageInstructions, $page->getMetadataForRendering()); 124*04fd306cSNickeau } catch (ExceptionCompile $e) { 125*04fd306cSNickeau LogUtility::error("Error while rendering the leaf. Error: {$e->getMessage()}", self::CANONICAL); 126*04fd306cSNickeau return; 127*04fd306cSNickeau } 128*04fd306cSNickeau } else { 129*04fd306cSNickeau try { 130*04fd306cSNickeau $listItemContent = LinkMarkup::createFromPageIdOrPath($page->getWikiId()) 131*04fd306cSNickeau ->toAttributes() 132*04fd306cSNickeau ->toHtmlEnterTag("a"); 133*04fd306cSNickeau $listItemContent .= "{$page->getNameOrDefault()}</a>"; 134*04fd306cSNickeau } catch (ExceptionCompile $e) { 135*04fd306cSNickeau LogUtility::error("Error while rendering the default tree page. Error: {$e->getMessage()}", self::CANONICAL); 136*04fd306cSNickeau } 137*04fd306cSNickeau } 138*04fd306cSNickeau /** @noinspection PhpUnnecessaryCurlyVarSyntaxInspection */ 139*04fd306cSNickeau $html .= "{$listItemEnterTag}{$listItemContent}</li>"; 140*04fd306cSNickeau 141*04fd306cSNickeau } 142*04fd306cSNickeau 143*04fd306cSNickeau /** 144*04fd306cSNickeau * @param WikiPath $namespacePath 145*04fd306cSNickeau * @return string the last part with a uppercase letter and where underscore became a space 146*04fd306cSNickeau */ 147*04fd306cSNickeau public static function toNamespaceName(WikiPath $namespacePath): string 148*04fd306cSNickeau { 149*04fd306cSNickeau try { 150*04fd306cSNickeau return ucfirst(trim(str_replace("_", " ", $namespacePath->getLastNameWithoutExtension()))); 151*04fd306cSNickeau } catch (ExceptionNotFound $e) { 152*04fd306cSNickeau // root 153*04fd306cSNickeau return ""; 154*04fd306cSNickeau } 155*04fd306cSNickeau } 156*04fd306cSNickeau 157*04fd306cSNickeau /** 158*04fd306cSNickeau * A class prefix added in elements 159*04fd306cSNickeau * @param string $type 160*04fd306cSNickeau * @return string 161*04fd306cSNickeau */ 162*04fd306cSNickeau public static function getClassPrefix(string $type): string 163*04fd306cSNickeau { 164*04fd306cSNickeau return self::CANONICAL . "-$type"; 165*04fd306cSNickeau } 166*04fd306cSNickeau 167*04fd306cSNickeau public static function handleExit(Doku_Handler $handler) 168*04fd306cSNickeau { 169*04fd306cSNickeau $callStack = CallStack::createFromHandler($handler); 170*04fd306cSNickeau 171*04fd306cSNickeau /** 172*04fd306cSNickeau * Capture the instructions for 173*04fd306cSNickeau * {@link syntax_plugin_combo_pageexplorerpage} 174*04fd306cSNickeau * {@link syntax_plugin_combo_pageexplorernamespace} 175*04fd306cSNickeau * {@link syntax_plugin_combo_pageexplorernamehome} 176*04fd306cSNickeau */ 177*04fd306cSNickeau $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall(); 178*04fd306cSNickeau /** 179*04fd306cSNickeau * @var Call[] $namespaceInstructions 180*04fd306cSNickeau * @var array $namespaceAttributes 181*04fd306cSNickeau */ 182*04fd306cSNickeau $namespaceInstructions = null; 183*04fd306cSNickeau $namespaceAttributes = null; 184*04fd306cSNickeau /** 185*04fd306cSNickeau * @var Call[] $templatePageInstructions 186*04fd306cSNickeau * @var array $pageAttributes 187*04fd306cSNickeau */ 188*04fd306cSNickeau $templatePageInstructions = null; 189*04fd306cSNickeau $pageAttributes = null; 190*04fd306cSNickeau /** 191*04fd306cSNickeau * @var Call[] $templateHomeInstructions 192*04fd306cSNickeau * @var array $homeAttributes 193*04fd306cSNickeau */ 194*04fd306cSNickeau $templateHomeInstructions = null; 195*04fd306cSNickeau $homeAttributes = null; 196*04fd306cSNickeau /** 197*04fd306cSNickeau * The instructions for the parent item in a page explorer list 198*04fd306cSNickeau * if any 199*04fd306cSNickeau * @var Call[] $parentInstructions 200*04fd306cSNickeau * @var array $parentAttributes 201*04fd306cSNickeau */ 202*04fd306cSNickeau $parentInstructions = null; 203*04fd306cSNickeau $parentAttributes = null; 204*04fd306cSNickeau /** 205*04fd306cSNickeau * @var Call[] $actualInstructionsStack 206*04fd306cSNickeau */ 207*04fd306cSNickeau $actualInstructionsStack = []; 208*04fd306cSNickeau while ($callStack->next()) { 209*04fd306cSNickeau $actualCall = $callStack->getActualCall(); 210*04fd306cSNickeau $tagName = $actualCall->getTagName(); 211*04fd306cSNickeau switch ($actualCall->getState()) { 212*04fd306cSNickeau case DOKU_LEXER_ENTER: 213*04fd306cSNickeau switch ($tagName) { 214*04fd306cSNickeau case self::PAGE_LOGICAL_TAG: 215*04fd306cSNickeau $pageAttributes = $actualCall->getAttributes(); 216*04fd306cSNickeau continue 3; 217*04fd306cSNickeau case self::NAMESPACE_LOGICAL_TAG: 218*04fd306cSNickeau $namespaceAttributes = $actualCall->getAttributes(); 219*04fd306cSNickeau continue 3; 220*04fd306cSNickeau case self::LOGICAL_INDEX_TAG: 221*04fd306cSNickeau $homeAttributes = $actualCall->getAttributes(); 222*04fd306cSNickeau continue 3; 223*04fd306cSNickeau case self::PARENT_TAG: 224*04fd306cSNickeau $parentAttributes = $actualCall->getAttributes(); 225*04fd306cSNickeau continue 3; 226*04fd306cSNickeau default: 227*04fd306cSNickeau $actualInstructionsStack[] = $actualCall->toCallArray(); 228*04fd306cSNickeau continue 3; 229*04fd306cSNickeau } 230*04fd306cSNickeau case DOKU_LEXER_EXIT: 231*04fd306cSNickeau switch ($tagName) { 232*04fd306cSNickeau case self::PAGE_LOGICAL_TAG: 233*04fd306cSNickeau $templatePageInstructions = $actualInstructionsStack; 234*04fd306cSNickeau $actualInstructionsStack = []; 235*04fd306cSNickeau continue 3; 236*04fd306cSNickeau case self::NAMESPACE_LOGICAL_TAG: 237*04fd306cSNickeau $namespaceInstructions = $actualInstructionsStack; 238*04fd306cSNickeau $actualInstructionsStack = []; 239*04fd306cSNickeau continue 3; 240*04fd306cSNickeau case self::LOGICAL_INDEX_TAG: 241*04fd306cSNickeau $templateHomeInstructions = $actualInstructionsStack; 242*04fd306cSNickeau $actualInstructionsStack = []; 243*04fd306cSNickeau continue 3; 244*04fd306cSNickeau case PageExplorerTag::PARENT_TAG: 245*04fd306cSNickeau $parentInstructions = $actualInstructionsStack; 246*04fd306cSNickeau $actualInstructionsStack = []; 247*04fd306cSNickeau continue 3; 248*04fd306cSNickeau default: 249*04fd306cSNickeau $actualInstructionsStack[] = $actualCall->toCallArray(); 250*04fd306cSNickeau continue 3; 251*04fd306cSNickeau 252*04fd306cSNickeau } 253*04fd306cSNickeau default: 254*04fd306cSNickeau $actualInstructionsStack[] = $actualCall->toCallArray(); 255*04fd306cSNickeau break; 256*04fd306cSNickeau 257*04fd306cSNickeau } 258*04fd306cSNickeau } 259*04fd306cSNickeau /** 260*04fd306cSNickeau * Remove all callstack from the opening tag 261*04fd306cSNickeau */ 262*04fd306cSNickeau $callStack->deleteAllCallsAfter($openingTag); 263*04fd306cSNickeau 264*04fd306cSNickeau /** 265*04fd306cSNickeau * The container/block should have at minimum an enter tag 266*04fd306cSNickeau * to be able to set the {@link action_plugin_combo_sideslotpostprocessing} auto collapsible 267*04fd306cSNickeau * parameter 268*04fd306cSNickeau */ 269*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::NAMESPACE_INSTRUCTIONS, $namespaceInstructions); 270*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::NAMESPACE_ATTRIBUTES, $namespaceAttributes); 271*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::PAGE_INSTRUCTIONS, $templatePageInstructions); 272*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::PAGE_ATTRIBUTES, $pageAttributes); 273*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::INDEX_INSTRUCTIONS, $templateHomeInstructions); 274*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::INDEX_ATTRIBUTES, $homeAttributes); 275*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::PARENT_INSTRUCTIONS, $parentInstructions); 276*04fd306cSNickeau $openingTag->setPluginData(PageExplorerTag::PARENT_ATTRIBUTES, $parentAttributes); 277*04fd306cSNickeau } 278*04fd306cSNickeau 279*04fd306cSNickeau public static function renderEnterTag(TagAttributes $pageExplorerTagAttributes, array $data) 280*04fd306cSNickeau { 281*04fd306cSNickeau 282*04fd306cSNickeau $returnedXhtml = ""; 283*04fd306cSNickeau /** 284*04fd306cSNickeau * Id (id is mandatory for toggle) 285*04fd306cSNickeau */ 286*04fd306cSNickeau $id = $pageExplorerTagAttributes->getValue(TagAttributes::ID_KEY); 287*04fd306cSNickeau if ($id === null) { 288*04fd306cSNickeau $id = IdManager::getOrCreate()->generateNewHtmlIdForComponent(PageExplorerTag::CANONICAL); 289*04fd306cSNickeau $pageExplorerTagAttributes->setComponentAttributeValue(TagAttributes::ID_KEY, $id); 290*04fd306cSNickeau } 291*04fd306cSNickeau 292*04fd306cSNickeau $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 293*04fd306cSNickeau 294*04fd306cSNickeau 295*04fd306cSNickeau try { 296*04fd306cSNickeau 297*04fd306cSNickeau /** 298*04fd306cSNickeau * {@link MarkupCacheDependencies::PAGE_PRIMARY_META_DEPENDENCY} 299*04fd306cSNickeau * The cache output is composed of primary metadata 300*04fd306cSNickeau * (If it changes, the content change) 301*04fd306cSNickeau * 302*04fd306cSNickeau * {@link MarkupCacheDependencies::PAGE_SYSTEM_DEPENDENCY} 303*04fd306cSNickeau * The content depend on the file system tree 304*04fd306cSNickeau * (if a file is added or deleted, the content will change) 305*04fd306cSNickeau */ 306*04fd306cSNickeau $executionContext 307*04fd306cSNickeau ->getExecutingMarkupHandler() 308*04fd306cSNickeau ->getOutputCacheDependencies() 309*04fd306cSNickeau ->addDependency(MarkupCacheDependencies::PAGE_PRIMARY_META_DEPENDENCY) 310*04fd306cSNickeau ->addDependency(MarkupCacheDependencies::PAGE_SYSTEM_DEPENDENCY); 311*04fd306cSNickeau } catch (ExceptionNotFound $e) { 312*04fd306cSNickeau // no fetcher markup running 313*04fd306cSNickeau // ie markup 314*04fd306cSNickeau } 315*04fd306cSNickeau 316*04fd306cSNickeau /** 317*04fd306cSNickeau * Context 318*04fd306cSNickeau */ 319*04fd306cSNickeau $requestedContextPath = $executionContext->getContextPath(); 320*04fd306cSNickeau 321*04fd306cSNickeau /** 322*04fd306cSNickeau * NameSpacePath determination 323*04fd306cSNickeau */ 324*04fd306cSNickeau $pageExplorerType = $pageExplorerTagAttributes->getType(); 325*04fd306cSNickeau $namespaceAttribute = $pageExplorerTagAttributes->getValueAndRemove(PageExplorerTag::ATTR_NAMESPACE); 326*04fd306cSNickeau if ($namespaceAttribute !== null) { 327*04fd306cSNickeau WikiPath::addNamespaceEndSeparatorIfNotPresent($namespaceAttribute); 328*04fd306cSNickeau $namespacePath = WikiPath::createMarkupPathFromPath($namespaceAttribute); 329*04fd306cSNickeau } else { 330*04fd306cSNickeau try { 331*04fd306cSNickeau $namespacePath = $requestedContextPath->getParent(); 332*04fd306cSNickeau } catch (ExceptionNotFound $e) { 333*04fd306cSNickeau $namespacePath = WikiPath::createRootNamespacePathOnMarkupDrive(); 334*04fd306cSNickeau } 335*04fd306cSNickeau try { 336*04fd306cSNickeau $executionContext 337*04fd306cSNickeau ->getExecutingMarkupHandler() 338*04fd306cSNickeau ->getOutputCacheDependencies() 339*04fd306cSNickeau ->addDependency(MarkupCacheDependencies::REQUESTED_NAMESPACE_DEPENDENCY); 340*04fd306cSNickeau } catch (ExceptionNotFound $e) { 341*04fd306cSNickeau // ok 342*04fd306cSNickeau } 343*04fd306cSNickeau } 344*04fd306cSNickeau 345*04fd306cSNickeau 346*04fd306cSNickeau /** 347*04fd306cSNickeau * Class Prefix 348*04fd306cSNickeau */ 349*04fd306cSNickeau $componentClassPrefix = PageExplorerTag::getClassPrefix($pageExplorerType); 350*04fd306cSNickeau 351*04fd306cSNickeau 352*04fd306cSNickeau /** 353*04fd306cSNickeau * Rendering 354*04fd306cSNickeau */ 355*04fd306cSNickeau switch ($pageExplorerType) { 356*04fd306cSNickeau default: 357*04fd306cSNickeau case PageExplorerTag::LIST_TYPE: 358*04fd306cSNickeau 359*04fd306cSNickeau /** 360*04fd306cSNickeau * Class 361*04fd306cSNickeau */ 362*04fd306cSNickeau $classContainer = "list-group"; 363*04fd306cSNickeau $classItem = "list-group-item"; 364*04fd306cSNickeau 365*04fd306cSNickeau /** 366*04fd306cSNickeau * Css 367*04fd306cSNickeau */ 368*04fd306cSNickeau $executionContext 369*04fd306cSNickeau ->getSnippetSystem() 370*04fd306cSNickeau ->attachCssInternalStyleSheet($componentClassPrefix); 371*04fd306cSNickeau 372*04fd306cSNickeau /** 373*04fd306cSNickeau * Create the enter content list tag 374*04fd306cSNickeau */ 375*04fd306cSNickeau $returnedXhtml .= $pageExplorerTagAttributes 376*04fd306cSNickeau ->addClassName($classContainer) 377*04fd306cSNickeau ->removeAttributeIfPresent(TagAttributes::WIKI_ID) 378*04fd306cSNickeau ->setLogicalTag(PageExplorerTag::CANONICAL) 379*04fd306cSNickeau ->toHtmlEnterTag("ul"); 380*04fd306cSNickeau 381*04fd306cSNickeau 382*04fd306cSNickeau /** 383*04fd306cSNickeau * Home 384*04fd306cSNickeau */ 385*04fd306cSNickeau $indexInstructions = $data[PageExplorerTag::INDEX_INSTRUCTIONS]; 386*04fd306cSNickeau $indexAttributes = $data[PageExplorerTag::INDEX_ATTRIBUTES]; 387*04fd306cSNickeau $currentIndexPage = MarkupPath::createPageFromPathObject($namespacePath); 388*04fd306cSNickeau if (!($indexInstructions === null && $indexAttributes !== null)) { 389*04fd306cSNickeau 390*04fd306cSNickeau if (FileSystems::exists($currentIndexPage)) { 391*04fd306cSNickeau 392*04fd306cSNickeau 393*04fd306cSNickeau $indexTagAttributes = TagAttributes::createFromCallStackArray($indexAttributes); 394*04fd306cSNickeau 395*04fd306cSNickeau 396*04fd306cSNickeau /** 397*04fd306cSNickeau * Enter home tag 398*04fd306cSNickeau */ 399*04fd306cSNickeau $indexPageType = "index"; 400*04fd306cSNickeau $returnedXhtml .= $indexTagAttributes 401*04fd306cSNickeau ->addClassName($classItem) 402*04fd306cSNickeau ->setLogicalTag(PageExplorerTag::CANONICAL . "-{$pageExplorerType}-{$indexPageType}") 403*04fd306cSNickeau ->toHtmlEnterTag("li"); 404*04fd306cSNickeau /** 405*04fd306cSNickeau * Content 406*04fd306cSNickeau */ 407*04fd306cSNickeau if ($indexInstructions !== null) { 408*04fd306cSNickeau try { 409*04fd306cSNickeau $returnedXhtml .= MarkupRenderUtility::renderInstructionsToXhtml($indexInstructions, $currentIndexPage->getMetadataForRendering()); 410*04fd306cSNickeau } catch (ExceptionCompile $e) { 411*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the home. Error: {$e->getMessage()}"); 412*04fd306cSNickeau } 413*04fd306cSNickeau } else { 414*04fd306cSNickeau try { 415*04fd306cSNickeau $returnedXhtml .= LinkMarkup::createFromPageIdOrPath($currentIndexPage->getWikiId()) 416*04fd306cSNickeau ->toAttributes() 417*04fd306cSNickeau ->toHtmlEnterTag("a"); 418*04fd306cSNickeau $returnedXhtml .= "{$currentIndexPage->getNameOrDefault()}</a>"; 419*04fd306cSNickeau } catch (ExceptionCompile $e) { 420*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the default home. Error: {$e->getMessage()}"); 421*04fd306cSNickeau } 422*04fd306cSNickeau } 423*04fd306cSNickeau /** 424*04fd306cSNickeau * End home tag 425*04fd306cSNickeau */ 426*04fd306cSNickeau $returnedXhtml .= "</li>"; 427*04fd306cSNickeau } 428*04fd306cSNickeau 429*04fd306cSNickeau } 430*04fd306cSNickeau 431*04fd306cSNickeau /** 432*04fd306cSNickeau * Parent ? 433*04fd306cSNickeau */ 434*04fd306cSNickeau $parentInstructions = $data[PageExplorerTag::PARENT_INSTRUCTIONS]; 435*04fd306cSNickeau $parentAttributes = $data[PageExplorerTag::PARENT_ATTRIBUTES]; 436*04fd306cSNickeau if (!($parentInstructions === null && $indexAttributes !== null)) { 437*04fd306cSNickeau try { 438*04fd306cSNickeau $parentPage = $currentIndexPage->getParent(); 439*04fd306cSNickeau if ($parentPage->exists()) { 440*04fd306cSNickeau 441*04fd306cSNickeau $parentTagAttributes = TagAttributes::createFromCallStackArray($parentAttributes); 442*04fd306cSNickeau /** 443*04fd306cSNickeau * Enter parent tag 444*04fd306cSNickeau */ 445*04fd306cSNickeau $pageType = "parent"; 446*04fd306cSNickeau $returnedXhtml .= $parentTagAttributes 447*04fd306cSNickeau ->addClassName($classItem) 448*04fd306cSNickeau ->setLogicalTag(PageExplorerTag::CANONICAL . "-{$pageExplorerType}-{$pageType}") 449*04fd306cSNickeau ->toHtmlEnterTag("li"); 450*04fd306cSNickeau /** 451*04fd306cSNickeau * Content 452*04fd306cSNickeau */ 453*04fd306cSNickeau if ($parentInstructions !== null) { 454*04fd306cSNickeau try { 455*04fd306cSNickeau $returnedXhtml .= MarkupRenderUtility::renderInstructionsToXhtml($parentInstructions, $parentPage->getMetadataForRendering()); 456*04fd306cSNickeau } catch (ExceptionCompile $e) { 457*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the parent instructions. Error: {$e->getMessage()}"); 458*04fd306cSNickeau } 459*04fd306cSNickeau } else { 460*04fd306cSNickeau try { 461*04fd306cSNickeau $parentWikiId = $parentPage->getPathObject()->getWikiId(); 462*04fd306cSNickeau $returnedXhtml .= LinkMarkup::createFromPageIdOrPath($parentWikiId) 463*04fd306cSNickeau ->toAttributes() 464*04fd306cSNickeau ->toHtmlEnterTag("a"); 465*04fd306cSNickeau $returnedXhtml .= Icon::createFromComboResource(PageExplorerTag::LEVEL_UP_ICON) 466*04fd306cSNickeau ->toHtml(); 467*04fd306cSNickeau $returnedXhtml .= " {$parentPage->getNameOrDefault()}</a>"; 468*04fd306cSNickeau } catch (ExceptionCompile $e) { 469*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the default parent. Error: {$e->getMessage()}"); 470*04fd306cSNickeau } 471*04fd306cSNickeau } 472*04fd306cSNickeau /** 473*04fd306cSNickeau * End parent tag 474*04fd306cSNickeau */ 475*04fd306cSNickeau $returnedXhtml .= "</li>"; 476*04fd306cSNickeau } 477*04fd306cSNickeau } catch (ExceptionNotFound $e) { 478*04fd306cSNickeau // no parent page 479*04fd306cSNickeau } 480*04fd306cSNickeau 481*04fd306cSNickeau } 482*04fd306cSNickeau 483*04fd306cSNickeau /** 484*04fd306cSNickeau * Children (Namespaces/Pages) 485*04fd306cSNickeau */ 486*04fd306cSNickeau 487*04fd306cSNickeau $namespaceEnterTag = TagAttributes::createFromCallStackArray($data[PageExplorerTag::NAMESPACE_ATTRIBUTES]) 488*04fd306cSNickeau ->addClassName($classItem) 489*04fd306cSNickeau ->setLogicalTag(PageExplorerTag::CANONICAL . "-{$pageExplorerType}-namespace") 490*04fd306cSNickeau ->toHtmlEnterTag("li"); 491*04fd306cSNickeau $pageEnterTag = TagAttributes::createFromCallStackArray($data[PageExplorerTag::PAGE_ATTRIBUTES]) 492*04fd306cSNickeau ->addClassName($classItem) 493*04fd306cSNickeau ->setLogicalTag(PageExplorerTag::CANONICAL . "-{$pageExplorerType}-page") 494*04fd306cSNickeau ->toHtmlEnterTag("li"); 495*04fd306cSNickeau 496*04fd306cSNickeau 497*04fd306cSNickeau $pageInstructions = $data[PageExplorerTag::PAGE_INSTRUCTIONS]; 498*04fd306cSNickeau $pageAttributes = $data[PageExplorerTag::PAGE_ATTRIBUTES]; 499*04fd306cSNickeau $namespaceInstructions = $data[PageExplorerTag::NAMESPACE_INSTRUCTIONS]; 500*04fd306cSNickeau $namespaceAttributes = $data[PageExplorerTag::NAMESPACE_ATTRIBUTES]; 501*04fd306cSNickeau 502*04fd306cSNickeau $pageNum = 0; 503*04fd306cSNickeau foreach (FileSystems::getChildrenContainer($namespacePath) as $subNamespacePath) { 504*04fd306cSNickeau 505*04fd306cSNickeau // Namespace 506*04fd306cSNickeau if (!($namespaceInstructions === null && $namespaceAttributes !== null)) { 507*04fd306cSNickeau try { 508*04fd306cSNickeau $subNamespacePage = MarkupPath::getIndexPageFromNamespace($subNamespacePath->toAbsoluteId()); 509*04fd306cSNickeau } catch (ExceptionBadSyntax $e) { 510*04fd306cSNickeau LogUtility::msg("Bad syntax for the namespace $namespacePath. Error: {$e->getMessage()}", LogUtility::LVL_MSG_ERROR, PageExplorerTag::CANONICAL); 511*04fd306cSNickeau return false; 512*04fd306cSNickeau } 513*04fd306cSNickeau if ($subNamespacePage->isHidden()) { 514*04fd306cSNickeau continue; 515*04fd306cSNickeau } 516*04fd306cSNickeau if ($subNamespacePage->exists()) { 517*04fd306cSNickeau /** 518*04fd306cSNickeau * SubNamespace Enter tag 519*04fd306cSNickeau */ 520*04fd306cSNickeau $returnedXhtml .= $namespaceEnterTag; 521*04fd306cSNickeau 522*04fd306cSNickeau /** 523*04fd306cSNickeau * SubNamespace Content 524*04fd306cSNickeau */ 525*04fd306cSNickeau if ($namespaceInstructions !== null) { 526*04fd306cSNickeau try { 527*04fd306cSNickeau $returnedXhtml .= MarkupRenderUtility::renderInstructionsToXhtml($namespaceInstructions, $subNamespacePage->getMetadataForRendering()); 528*04fd306cSNickeau } catch (ExceptionCompile $e) { 529*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the sub-namespace. Error: {$e->getMessage()}"); 530*04fd306cSNickeau } 531*04fd306cSNickeau } else { 532*04fd306cSNickeau try { 533*04fd306cSNickeau $returnedXhtml .= LinkMarkup::createFromPageIdOrPath($subNamespacePage->getWikiId()) 534*04fd306cSNickeau ->toAttributes() 535*04fd306cSNickeau ->toHtmlEnterTag("a"); 536*04fd306cSNickeau $returnedXhtml .= Icon::createFromComboResource(PageExplorerTag::FOLDER_ICON) 537*04fd306cSNickeau ->toHtml(); 538*04fd306cSNickeau $returnedXhtml .= " {$subNamespacePage->getNameOrDefault()}</a>"; 539*04fd306cSNickeau } catch (ExceptionCompile $e) { 540*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the default namespace. Error: {$e->getMessage()}"); 541*04fd306cSNickeau } 542*04fd306cSNickeau 543*04fd306cSNickeau } 544*04fd306cSNickeau /** 545*04fd306cSNickeau * SubNamespace Exit tag 546*04fd306cSNickeau */ 547*04fd306cSNickeau $returnedXhtml .= "</li>"; 548*04fd306cSNickeau } 549*04fd306cSNickeau 550*04fd306cSNickeau } 551*04fd306cSNickeau 552*04fd306cSNickeau } 553*04fd306cSNickeau 554*04fd306cSNickeau $childrenLeaf = FileSystems::getChildrenLeaf($namespacePath); 555*04fd306cSNickeau foreach ($childrenLeaf as $childPagePath) { 556*04fd306cSNickeau $childPage = MarkupPath::createPageFromPathObject($childPagePath); 557*04fd306cSNickeau if ($childPage->isHidden()) { 558*04fd306cSNickeau continue; 559*04fd306cSNickeau } 560*04fd306cSNickeau if (!($pageInstructions === null && $pageAttributes !== null)) { 561*04fd306cSNickeau $pageNum++; 562*04fd306cSNickeau if ($currentIndexPage !== null 563*04fd306cSNickeau && $childPagePath->getWikiId() !== $currentIndexPage->getWikiId() 564*04fd306cSNickeau && FileSystems::exists($childPagePath) 565*04fd306cSNickeau ) { 566*04fd306cSNickeau /** 567*04fd306cSNickeau * Page Enter tag 568*04fd306cSNickeau */ 569*04fd306cSNickeau $returnedXhtml .= $pageEnterTag; 570*04fd306cSNickeau /** 571*04fd306cSNickeau * Page Content 572*04fd306cSNickeau */ 573*04fd306cSNickeau if ($pageInstructions !== null) { 574*04fd306cSNickeau 575*04fd306cSNickeau try { 576*04fd306cSNickeau $returnedXhtml .= MarkupRenderUtility::renderInstructionsToXhtmlFromPage($pageInstructions, $childPage); 577*04fd306cSNickeau } catch (ExceptionCompile $e) { 578*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the page. Error: {$e->getMessage()}"); 579*04fd306cSNickeau } 580*04fd306cSNickeau } else { 581*04fd306cSNickeau try { 582*04fd306cSNickeau $returnedXhtml .= LinkMarkup::createFromPageIdOrPath($childPagePath->getWikiId()) 583*04fd306cSNickeau ->toAttributes() 584*04fd306cSNickeau ->toHtmlEnterTag("a"); 585*04fd306cSNickeau $returnedXhtml .= "{$childPage->getNameOrDefault()}</a>"; 586*04fd306cSNickeau } catch (ExceptionCompile $e) { 587*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the default page. Error: {$e->getMessage()}"); 588*04fd306cSNickeau } 589*04fd306cSNickeau } 590*04fd306cSNickeau /** 591*04fd306cSNickeau * Page Exit tag 592*04fd306cSNickeau */ 593*04fd306cSNickeau $returnedXhtml .= "</li>"; 594*04fd306cSNickeau } 595*04fd306cSNickeau } 596*04fd306cSNickeau } 597*04fd306cSNickeau 598*04fd306cSNickeau 599*04fd306cSNickeau /** 600*04fd306cSNickeau * End container tag 601*04fd306cSNickeau */ 602*04fd306cSNickeau $returnedXhtml .= "</ul>"; 603*04fd306cSNickeau return $returnedXhtml; 604*04fd306cSNickeau 605*04fd306cSNickeau case PageExplorerTag::TYPE_TREE: 606*04fd306cSNickeau 607*04fd306cSNickeau /** 608*04fd306cSNickeau * Printing the tree 609*04fd306cSNickeau * 610*04fd306cSNickeau * data-wiki-id, needed for the 611*04fd306cSNickeau * javascript that open the tree 612*04fd306cSNickeau * to the actual page 613*04fd306cSNickeau */ 614*04fd306cSNickeau $namespaceId = $namespacePath->getWikiId(); 615*04fd306cSNickeau if (!blank($namespaceId)) { 616*04fd306cSNickeau $pageExplorerTagAttributes->addOutputAttributeValue("data-" . TagAttributes::WIKI_ID, $namespaceId); 617*04fd306cSNickeau } else { 618*04fd306cSNickeau $pageExplorerTagAttributes->addBooleanOutputAttributeValue("data-" . TagAttributes::WIKI_ID); 619*04fd306cSNickeau } 620*04fd306cSNickeau 621*04fd306cSNickeau 622*04fd306cSNickeau $snippetId = PageExplorerTag::CANONICAL . "-" . $pageExplorerType; 623*04fd306cSNickeau /** 624*04fd306cSNickeau * Open the tree until the current page 625*04fd306cSNickeau * and make it active 626*04fd306cSNickeau */ 627*04fd306cSNickeau PluginUtility::getSnippetManager()->attachJavascriptFromComponentId($snippetId); 628*04fd306cSNickeau /** 629*04fd306cSNickeau * Styling 630*04fd306cSNickeau */ 631*04fd306cSNickeau PluginUtility::getSnippetManager()->attachCssInternalStyleSheet($snippetId); 632*04fd306cSNickeau $returnedXhtml .= $pageExplorerTagAttributes->toHtmlEnterTag("nav") . DOKU_LF; 633*04fd306cSNickeau $returnedXhtml .= "<ul>" . DOKU_LF; 634*04fd306cSNickeau 635*04fd306cSNickeau try { 636*04fd306cSNickeau $tree = PathTreeNode::buildTreeViaFileSystemChildren($namespacePath); 637*04fd306cSNickeau self::treeProcessTree($returnedXhtml, $tree, $data); 638*04fd306cSNickeau } catch (ExceptionBadSyntax $e) { 639*04fd306cSNickeau $returnedXhtml .= LogUtility::wrapInRedForHtml("Error while rendering the tree sub-namespace. Error: {$e->getMessage()}"); 640*04fd306cSNickeau } 641*04fd306cSNickeau 642*04fd306cSNickeau $returnedXhtml .= "</ul>"; 643*04fd306cSNickeau $returnedXhtml .= "</nav>"; 644*04fd306cSNickeau return $returnedXhtml; 645*04fd306cSNickeau 646*04fd306cSNickeau } 647*04fd306cSNickeau } 648*04fd306cSNickeau 649*04fd306cSNickeau /** 650*04fd306cSNickeau * Process the 651*04fd306cSNickeau * @param string $html - the callstack 652*04fd306cSNickeau * @param PathTreeNode $pathTreeNode 653*04fd306cSNickeau * @param array $data - the data array from the handler 654*04fd306cSNickeau * @throws ExceptionBadSyntax 655*04fd306cSNickeau */ 656*04fd306cSNickeau public static 657*04fd306cSNickeau function treeProcessTree(string &$html, PathTreeNode $pathTreeNode, array $data) 658*04fd306cSNickeau { 659*04fd306cSNickeau 660*04fd306cSNickeau /** 661*04fd306cSNickeau * Home Page first 662*04fd306cSNickeau * @var MarkupPath $homePage 663*04fd306cSNickeau */ 664*04fd306cSNickeau $homePage = null; 665*04fd306cSNickeau /** 666*04fd306cSNickeau * @var TreeNode[] $containerTreeNodes 667*04fd306cSNickeau */ 668*04fd306cSNickeau $containerTreeNodes = []; 669*04fd306cSNickeau /** 670*04fd306cSNickeau * @var MarkupPath[] $nonHomePages 671*04fd306cSNickeau */ 672*04fd306cSNickeau $nonHomePages = []; 673*04fd306cSNickeau 674*04fd306cSNickeau /** 675*04fd306cSNickeau * Scanning the tree node to 676*04fd306cSNickeau * categorize the children as home, page or namespace (container) 677*04fd306cSNickeau * @var PathTreeNode[] $children 678*04fd306cSNickeau */ 679*04fd306cSNickeau $children = $pathTreeNode->getChildren(); 680*04fd306cSNickeau foreach ($children as $child) { 681*04fd306cSNickeau 682*04fd306cSNickeau /** 683*04fd306cSNickeau * Namespace 684*04fd306cSNickeau */ 685*04fd306cSNickeau if ($child->hasChildren()) { 686*04fd306cSNickeau 687*04fd306cSNickeau $containerTreeNodes[] = $child; 688*04fd306cSNickeau 689*04fd306cSNickeau } else { 690*04fd306cSNickeau /** 691*04fd306cSNickeau * Page 692*04fd306cSNickeau */ 693*04fd306cSNickeau $page = MarkupPath::createPageFromPathObject($child->getPath()); 694*04fd306cSNickeau if ($page->isIndexPage()) { 695*04fd306cSNickeau $homePage = $page; 696*04fd306cSNickeau } else { 697*04fd306cSNickeau $nonHomePages[] = $page; 698*04fd306cSNickeau } 699*04fd306cSNickeau 700*04fd306cSNickeau } 701*04fd306cSNickeau 702*04fd306cSNickeau } 703*04fd306cSNickeau 704*04fd306cSNickeau /** 705*04fd306cSNickeau * First the home page 706*04fd306cSNickeau */ 707*04fd306cSNickeau if ($homePage !== null) { 708*04fd306cSNickeau PageExplorerTag::treeProcessLeaf($html, $homePage, $data, PageExplorerTag::HOME_TYPE); 709*04fd306cSNickeau } 710*04fd306cSNickeau 711*04fd306cSNickeau /** 712*04fd306cSNickeau * The subdirectories 713*04fd306cSNickeau */ 714*04fd306cSNickeau $namespaceInstructions = $data[PageExplorerTag::NAMESPACE_INSTRUCTIONS]; 715*04fd306cSNickeau foreach ($containerTreeNodes as $containerTreeNode) { 716*04fd306cSNickeau 717*04fd306cSNickeau /** 718*04fd306cSNickeau * @var WikiPath $containerPath 719*04fd306cSNickeau */ 720*04fd306cSNickeau $containerPath = $containerTreeNode->getPath(); 721*04fd306cSNickeau 722*04fd306cSNickeau /** 723*04fd306cSNickeau * Entering: Creating in instructions form 724*04fd306cSNickeau * the same as in markup form 725*04fd306cSNickeau * 726*04fd306cSNickeau * <li> 727*04fd306cSNickeau * <button data-bs-target="#id" data-bs-collapse="collapse"> 728*04fd306cSNickeau * Label 729*04fd306cSNickeau * </button> 730*04fd306cSNickeau * <div id="id"> 731*04fd306cSNickeau * <ul> 732*04fd306cSNickeau * <li></li> 733*04fd306cSNickeau * <li></li> 734*04fd306cSNickeau * .... 735*04fd306cSNickeau * </div> 736*04fd306cSNickeau * ... 737*04fd306cSNickeau */ 738*04fd306cSNickeau $html .= "<li>"; 739*04fd306cSNickeau 740*04fd306cSNickeau 741*04fd306cSNickeau /** 742*04fd306cSNickeau * Keep the id unique on the page in order to be able to collapse 743*04fd306cSNickeau * the good HTML node 744*04fd306cSNickeau */ 745*04fd306cSNickeau $namespaceId = ExecutionContext::getActualOrCreateFromEnv()->getIdManager()->generateNewHtmlIdForComponent("page-explorer-{$containerPath->getWikiId()}"); 746*04fd306cSNickeau $id = StyleAttribute::addComboStrapSuffix($namespaceId); 747*04fd306cSNickeau $html .= TagAttributes::createEmpty() 748*04fd306cSNickeau ->addOutputAttributeValue("data-bs-target", "#$id") 749*04fd306cSNickeau ->addOutputAttributeValue("data-" . TagAttributes::WIKI_ID, $containerPath->getWikiId()) 750*04fd306cSNickeau ->addOutputAttributeValue("data-bs-toggle", "collapse") 751*04fd306cSNickeau ->addOutputAttributeValue("aria-expanded", "false") 752*04fd306cSNickeau ->addClassName("btn") 753*04fd306cSNickeau ->addClassName("align-items-center") 754*04fd306cSNickeau ->addClassName("rounded") 755*04fd306cSNickeau ->toHtmlEnterTag("button"); 756*04fd306cSNickeau 757*04fd306cSNickeau // Button label 758*04fd306cSNickeau 759*04fd306cSNickeau $subHomePage = MarkupPath::getIndexPageFromNamespace($containerPath->toAbsoluteId()); 760*04fd306cSNickeau if ($subHomePage->exists()) { 761*04fd306cSNickeau if ($namespaceInstructions !== null) { 762*04fd306cSNickeau try { 763*04fd306cSNickeau $html .= MarkupRenderUtility::renderInstructionsToXhtml($namespaceInstructions, $subHomePage->getMetadataForRendering()); 764*04fd306cSNickeau } catch (ExceptionCompile $e) { 765*04fd306cSNickeau $html .= LogUtility::wrapInRedForHtml("Error while rendering the child directory. Error: {$e->getMessage()}"); 766*04fd306cSNickeau } 767*04fd306cSNickeau } else { 768*04fd306cSNickeau $html .= $subHomePage->getNameOrDefault(); 769*04fd306cSNickeau } 770*04fd306cSNickeau } else { 771*04fd306cSNickeau $namespaceName = PageExplorerTag::toNamespaceName($containerPath); 772*04fd306cSNickeau $html .= $namespaceName; 773*04fd306cSNickeau } 774*04fd306cSNickeau // End button 775*04fd306cSNickeau $html .= "</button>"; 776*04fd306cSNickeau 777*04fd306cSNickeau /** 778*04fd306cSNickeau * Sub and Recursion 779*04fd306cSNickeau */ 780*04fd306cSNickeau $html .= TagAttributes::createEmpty() 781*04fd306cSNickeau ->addClassName("collapse") 782*04fd306cSNickeau ->addOutputAttributeValue(TagAttributes::ID_KEY, "$id") 783*04fd306cSNickeau ->toHtmlEnterTag("div"); 784*04fd306cSNickeau $html .= "<ul>"; 785*04fd306cSNickeau self::treeProcessTree($html, $containerTreeNode, $data); 786*04fd306cSNickeau $html .= "</ul>"; 787*04fd306cSNickeau $html .= "</div>"; 788*04fd306cSNickeau 789*04fd306cSNickeau /** 790*04fd306cSNickeau * Closing: Creating in instructions form 791*04fd306cSNickeau * the same as in markup form 792*04fd306cSNickeau * 793*04fd306cSNickeau * </$pageExplorerTreeListTag> 794*04fd306cSNickeau * </$pageExplorerTreeTag> 795*04fd306cSNickeau */ 796*04fd306cSNickeau $html .= "</li>"; 797*04fd306cSNickeau 798*04fd306cSNickeau } 799*04fd306cSNickeau 800*04fd306cSNickeau /** 801*04fd306cSNickeau * Then the other pages 802*04fd306cSNickeau */ 803*04fd306cSNickeau foreach ($nonHomePages as $page) { 804*04fd306cSNickeau PageExplorerTag::treeProcessLeaf($html, $page, $data, PageExplorerTag::PAGE_TYPE); 805*04fd306cSNickeau } 806*04fd306cSNickeau 807*04fd306cSNickeau 808*04fd306cSNickeau } 809*04fd306cSNickeau} 810*04fd306cSNickeau 811