controlPage = $controlPage; } /** * @inheritdoc * @todo theoretically it should be possible to also take the recursionDecision into account, even though * we don't recurse here. Passing the depth would be easy, but actually aborting going deeper is difficult. */ public function generate(): void { $this->top = new Top(); $instructions = p_cached_instructions(wikiFN($this->controlPage)); if (!$instructions) { throw new \RuntimeException('No instructions for control page found'); } $parents = [ 0 => $this->top ]; $level = 0; $resolver = new PageResolver($this->controlPage); foreach ($instructions as $instruction) { switch ($instruction[0]) { case 'listu_open': $level++; // new list level break; case 'listu_close': // if we had a node on this level, remove it from the parents if(isset($parents[$level])) { unset($parents[$level]); } $level--; // close list level break; case 'internallink': case 'externallink': if ($instruction[0] == 'internallink') { if ($this->flags & self::FLAG_NOINTERNAL) break; $newpage = new WikiPage( $resolver->resolveId($instruction[1][0]), $instruction[1][1] ); } else { if ($this->flags & self::FLAG_NOEXTERNAL) break; $newpage = new ExternalLink( $instruction[1][0], $instruction[1][1] ); } if($level) { // remember this page as the parent for this level $parents[$level] = $newpage; // parent is the last page on the previous level // levels may not be evenly distributed, so we need to check the count $parent = $parents[count($parents) - 2]; } else { // not in a list, so parent is always the top $parent = $this->top; } $newpage->setParent($parent); $newpage = $this->applyNodeProcessor($newpage); if($newpage instanceof AbstractNode) { $parent->addChild($newpage); } break; } } $this->generated = true; } }