Creates the navigation list html. Why this and not a template? My attempts at trying to get a recursive template
working failed.

@param  \stdClass $tree Full tree to create navigation out of.
@return string navigation html.
188555
protected function create_navigation(\stdClass $tree) {
        if ($this->firstelement) {
            $html = \html_writer::start_tag('ul', ['class' => 'treeview parent block_tree list', 'id' => 'my-tree']);
            $this->firstelement = false;
        } else {
            $html = \html_writer::start_tag('ul', ['class' => 'parent', 'role' => 'group']);
        }
        foreach ($tree->children as $child) {
            if (isset($child->children)) {
                $html .= \html_writer::start_tag('li', ['class' => 'menu-item', 'role' => 'treeitem', 'aria-expanded' => 'false']);
                $html .= $child->name;
                $html .= $this->create_navigation($child);
            } else {
                $html .= \html_writer::start_tag('li', ['class' => 'item', 'role' => 'treeitem', 'aria-expanded' => 'false']);
                // Normal display.
                if (isset($child->datavar)) {
                    $html .= \html_writer::link('#', $child->name, ['data-var' => $child->datavar]);
                } else {
                    $html .= \html_writer::link($child->url, $child->name, ['target' => '_blank']);
                }
            }
            $html .= \html_writer::end_tag('li');
        }
        $html .= \html_writer::end_tag('ul');
        return $html;
    }
786071
protected function navigation_node(navigation_node $node, $attrs=array(), $depth = 1) {
        $items = $node->children;

        // exit if empty, we don't want an empty ul element
        if ($items->count()==0) {
            return '';
        }

        // array of nested li elements
        $lis = array();
        $number = 0;
        foreach ($items as $item) {
            $number++;
            if (!$item->display) {
                continue;
            }

            $isbranch = ($item->children->count()>0  || $item->nodetype==navigation_node::NODETYPE_BRANCH);

            if ($isbranch) {
                $item->hideicon = true;
            }

            $content = $this->output->render($item);
            $id = $item->id ? $item->id : html_writer::random_id();
            $ulattr = ['id' => $id . '_group', 'role' => 'group'];
            $liattr = ['class' => [$item->get_css_type(), 'depth_'.$depth], 'tabindex' => '-1'];
            $pattr = ['class' => ['tree_item'], 'role' => 'treeitem'];
            $pattr += !empty($item->id) ? ['id' => $item->id] : [];
            $hasicon = (!$isbranch && $item->icon instanceof renderable);

            if ($isbranch) {
                $liattr['class'][] = 'contains_branch';
                if (!$item->forceopen || (!$item->forceopen && $item->collapse) || ($item->children->count() == 0
                        && $item->nodetype == navigation_node::NODETYPE_BRANCH)) {
                    $pattr += ['aria-expanded' => 'false'];
                } else {
                    $pattr += ['aria-expanded' => 'true'];
                }
                if ($item->requiresajaxloading) {
                    $pattr['data-requires-ajax'] = 'true';
                    $pattr['data-loaded'] = 'false';
                } else {
                    $pattr += ['aria-owns' => $id . '_group'];
                }
            } else if ($hasicon) {
                $liattr['class'][] = 'item_with_icon';
                $pattr['class'][] = 'hasicon';
            }
            if ($item->isactive === true) {
                $liattr['class'][] = 'current_branch';
            }
            if (!empty($item->classes) && count($item->classes) > 0) {
                $pattr['class'] = array_merge($pattr['class'], $item->classes);
            }
            $nodetextid = 'label_' . $depth . '_' . $number;

            // class attribute on the div item which only contains the item content
            $pattr['class'][] = 'tree_item';
            if ($isbranch) {
                $pattr['class'][] = 'branch';
            } else {
                $pattr['class'][] = 'leaf';
            }

            $liattr['class'] = join(' ', $liattr['class']);
            $pattr['class'] = join(' ', $pattr['class']);

            if (isset($pattr['aria-expanded']) && $pattr['aria-expanded'] === 'false') {
                $ulattr += ['aria-hidden' => 'true'];
            }

            $content = html_writer::tag('p', $content, $pattr) . $this->navigation_node($item, $ulattr, $depth + 1);
            if (!empty($item->preceedwithhr) && $item->preceedwithhr===true) {
                $content = html_writer::empty_tag('hr') . $content;
            }
            $liattr['aria-labelledby'] = $nodetextid;
            $content = html_writer::tag('li', $content, $liattr);
            $lis[] = $content;
        }

        if (count($lis)) {
            if (empty($attrs['role'])) {
                $attrs['role'] = 'group';
            }
            return html_writer::tag('ul', implode("\n", $lis), $attrs);
        } else {
            return '';
        }
    }
1094447
public function getBlock(Tree $tree, int $block_id, string $ctype = '', array $cfg = []): string
    {
        $menu = app(ModuleThemeInterface::class)->menuThemes();

        if ($menu) {
            $content = '<ul class="nav text-justify">' . $menu->bootstrap4() . '</ul>';

            if ($ctype !== '') {
                return view('modules/block-template', [
                    'block'      => Str::kebab($this->name()),
                    'id'         => $block_id,
                    'config_url' => '',
                    'title'      => $this->title(),
                    'content'    => $content,
                ]);
            }

            return $content;
        }

        return '';
    }
34482
protected Content getNavLinkTree() {
        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, treeLabel);
        return li;
    }
543667
public function getMenu(Tree $tree, $reference = null) {
        $tree_url = $tree ? $tree->getNameUrl() : '';
        return new Menu($this->getTitle(), 'module.php?mod=' . $this->getName() . '&mod_action=Certificate@listAll&ged=' . $tree_url, 'menu-maj-list-certificate', array('rel' => 'nofollow'));
    }
829902
protected function htmllize_tree($tree, $dir) {
        global $CFG;

        if (empty($dir['subdirs']) and empty($dir['files'])) {
            return '';
        }
        $result = '<ul>';
        foreach ($dir['subdirs'] as $subdir) {
            $image = $this->output->pix_icon(file_folder_icon(24), $subdir['dirname'], 'moodle');
            $filename = html_writer::tag('span', $image, array('class' => 'fp-icon')).
                    html_writer::tag('span', s($subdir['dirname']), array('class' => 'fp-filename'));
            $filename = html_writer::tag('div', $filename, array('class' => 'fp-filename-icon'));
            $result .= html_writer::tag('li', $filename. $this->htmllize_tree($tree, $subdir));
        }
        foreach ($dir['files'] as $file) {
            $filename = $file->get_filename();
            $url = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(),
                    $file->get_filearea(), $file->get_itemid(), $file->get_filepath(), $filename, false);
            $filenamedisplay = clean_filename($filename);
            if (file_extension_in_typegroup($filename, 'web_image')) {
                $image = $url->out(false, array('preview' => 'tinyicon', 'oid' => $file->get_timemodified()));
                $image = html_writer::empty_tag('img', array('src' => $image));
            } else {
                $image = $this->output->pix_icon(file_file_icon($file, 24), $filenamedisplay, 'moodle');
            }
            $filename = html_writer::tag('span', $image, array('class' => 'fp-icon')).
                    html_writer::tag('span', $filenamedisplay, array('class' => 'fp-filename'));
            $filename = html_writer::tag('span',
                    html_writer::link($url->out(false, array('forcedownload' => 1)), $filename),
                    array('class' => 'fp-filename-icon'));
            $result .= html_writer::tag('li', $filename);
        }
        $result .= '</ul>';

        return $result;
    }
494839
protected function menuSearchPhonetic(Tree $tree): Menu
    {
        /* I18N: search using “sounds like”, rather than exact spelling */
        return new Menu(I18N::translate('Phonetic search'), route('search-phonetic', ['ged' => $tree->name(), 'action' => 'soundex']), 'menu-search-soundex', ['rel' => 'nofollow']);
    }
532291
public function menuMyPage(Tree $tree): Menu
    {
        return new Menu(I18N::translate('My page'), route('user-page', ['ged' => $tree->name()]), 'menu-mypage');
    }
774382
public function getMenu(Tree $tree): ?Menu
    {
        if ($this->faqsExist($tree, WT_LOCALE)) {
            return new Menu($this->title(), route('module', [
                'module' => $this->name(),
                'action' => 'Show',
                'ged'    => $tree->name(),
            ]), 'menu-help');
        }

        return null;
    }
1214592
public function __async_tree($currentMainNavID = null)
    {
        /** @var CMSNav $currentMainNav */
        $currentMainNav = null;
        if (dbQuery('\samson\cms\web\navigation\CMSNav')->StructureID($currentMainNavID)->first($currentMainNav)) {
            $currentMainNav->currentNavID = $currentMainNavID;
        } else {
            $currentMainNav = CMSNav::fullTree();
        }

        $tree = new \samson\treeview\SamsonTree('tree/tree-template', 0, 'structure/addchildren');

        $sub_menu = $this->view('sub_menu')->parentnav_id($currentMainNavID)->nav_id($currentMainNavID)->output();

        // return Ajax response
        return array(
            'status' => 1,
            'tree' => $tree->htmlTree($currentMainNav),
            'sub_menu' => $sub_menu
        );
    }
772201
public function getMenu(Tree $tree): ?Menu
    {
        $request    = app(ServerRequestInterface::class);
        $xref       = $request->getQueryParams()['xref'] ?? '';
        $individual = Individual::getInstance($xref, $tree) ?? $tree->significantIndividual(Auth::user());
        $submenus   = $this->module_service->findByComponent(ModuleReportInterface::class, $tree, Auth::user())
            ->map(static function (ModuleReportInterface $module) use ($individual): Menu {
                return $module->getReportMenu($individual);
            });

        if ($submenus->isEmpty()) {
            return null;
        }

        return new Menu(I18N::translate('Reports'), '#', 'menu-report', ['rel' => 'nofollow'], $submenus->all());
    }
1023562
public function renderCategoryTree(
        \Twig_Environment $environment,
        $tree,
        $selectedCategory = null,
        $currentCategory = null,
        $template = null
    ) {
        if (count($tree)) {
            if ($template === null) {
                $template = $this->getTemplate();
            }

            return $environment->render(
                $template,
                [
                    'categories' => $tree,
                    'selected_category' => $selectedCategory,
                    'current_category' => $currentCategory,
                ]
            );
        }

        return null;
    }
1246958
public function render(SuffixTree $tree): string
    {
        $node_map = [];

        $nodes = [];
        foreach ($this->collectNodes($tree->getRoot(), []) as $node_id => $node) {
            $nodes[] = $this->renderNode($node, $node_id);
            $node_map[$node_id] = $node;
        }

        $edges = [];
        foreach ($node_map as $node) {
            foreach ($node->getChildren() as $child) {
                $edges[] = $this->renderEdge($node, $child, $node_map, $tree->getS());
            }
            if ($node->getSuffixLink() !== null && $node->getSuffixLink() !== $tree->getRoot()) {
                $edges[] = $this->renderSuffixLink($node, $node_map);
            }
        }

        return sprintf(self::GRAPH_TPL, implode("\n\t", $nodes), implode("\n\t", $edges));
    }
658058
function _buildTree(&$tree, &$element) {
        $tree[$element->name()] = $element;
        if ($element->superclass()) {
            $rootDoc = & $this->_doclet->rootDoc();
            $superclass = & $rootDoc->classNamed($element->superclass());
            if ($superclass) {
                $this->_buildTree($tree, $superclass);
            }
        }
    }
638480
public function menuMyIndividualRecord(Tree $tree): ?Menu
    {
        $record = Individual::getInstance($tree->getUserPreference(Auth::user(), 'gedcomid'), $tree);

        if ($record) {
            return new Menu(I18N::translate('My individual record'), $record->url(), 'menu-myrecord');
        }

        return null;
    }
922217
public function actionTree()
    {
        foreach (CmsTree::find()->each(10) as $cmsTree) {
            $this->stdout('Tree id: ' . $cmsTree->id . " - ");
            
            $redirect = CmsTreeRedirect::find()->where([
                'cms_tree_id' => $cmsTree->id
            ])->andWhere(['slug' => $cmsTree->code])->one();
            
            if ($redirect) {
                $this->stdout("exist \n", Console::FG_YELLOW);
            } else {
                $redirect = new CmsTreeRedirect();
                $redirect->cms_tree_id = $cmsTree->id;
                $redirect->slug = $cmsTree->code;

                if (!$redirect->save()) {
                    $this->stdout("Not saved redirect: {$redirect->slug} for id={$cmsTree->id}. " . print_r($redirect->errors, true) . "\n", Console::FG_RED);
                } else {
                    $this->stdout("created \n", Console::FG_GREEN);
                }
            }
        }
    }
245354
protected function parseRecursive( $root, $tree )
	{
		$nodes = array();
		if( $child = $root->firstChild )
		{
			while( $child )
			{
				$attributes	= $child->hasAttributes()? $child->attributes : array();
				switch( $child->nodeType )
				{
					case XML_ELEMENT_NODE:
						$node = new XML_DOM_Node( $child->nodeName );
						if( !$this->parseRecursive( $child, $node ) )
						{
	#						$node->setContent( utf8_decode( $child->textContent ) );
							$node->setContent( $child->textContent );
						}
						foreach( $attributes as $attribute)
							$node->setAttribute( $attribute->nodeName, stripslashes( $attribute->nodeValue ) );
						$tree->addChild( $node );
						break;
					case XML_TEXT_NODE:
						if( strlen( trim( $content = $child->textContent ) ) )
						{
							return false;
						}
						else if( isset( $attributes['type'] ) && preg_match( "/.*ml/i", $attributes['type'] ) )
						{
							return false;
						}
						break;
					case XML_CDATA_SECTION_NODE:
						$tree->setContent( stripslashes( $child->textContent ) );
						break;
					default:
						break;
				}
				$child = $child->nextSibling;
			}
		}
		return true;
	}