SineCosine
SineCosine

Reputation: 387

Constructing Multidimensional Tree From Array

I am trying to create a tree from an array like this:

array('admin/home', 'admin/home/page', 'admin/test', 'team/tree/template', 'site');

Or more visually seen as:

admin/home

admin/home/page

admin/test

team/tree/template

site

However, I also need the last nested string of each array to become bolded to signify that it is a webpage itself.

The final product should look like:

    admin
        home
            page
        test
    team
        tree
            template
    site

I have used a few different solutions from this site but I have not been able to get the right outcome.

Any ideas or examples on where I should start would be greatly appreciated, thanks.

Upvotes: 0

Views: 245

Answers (1)

ralphje
ralphje

Reputation: 995

You are probably looking for something like this:

<?php

$items = array('admin/home', 'admin/home/page', 'admin/test', 'site', 'team/tree/template');
sort($items);

$previous = array();
foreach ($items as $item) {
    $path = explode('/', $item);

    // $i is common nesting level of the previous item
    // e.g. 0 is nothing in common, 1 is one level in common, etc.
    for ($i = 0; $i < min(count($path), count($previous)) && ($path[$i] == $previous[$i]); $i++) { }

    // close <ul> from previous nesting levels:
    // that is, we close the amount of levels that the previous and this one have NOT in common
    for ($k = 0; $k < count($previous)-$i-1; $k++) { echo "</ul>"; }
    // $j is the current nesting level
    // we start at the common nesting level
    for ($j = $i; $j < count($path); $j++) {
        // open <ul> for new nesting levels:
        // i.e., we open a level for every level deeper than the previous level
        if ($j >= count($previous))
            echo "<ul>";
        echo "<li>";
        // make the path bold if the end of the current path is reached
        if (count($path)-1 == $j)
            echo "<b>" . $path[$j] . "</b>";
        else
            echo $path[$j];
        echo "</li>";
    }
    $previous = $path;
}
// close remaining <ul>
for ($k = 0; $k < count($previous); $k++) { echo "</ul>"; }
?>

Note that I order the array to make sure that all nested items come next to each other.

It might have some bugs, but I guess you can work them out yourself. Note that I close the list items before opening a nested <ul>. This is not really how it should; I guess you actually should open the nested <ul> in the final <li> at that level, but you can figure that out yourself.

Update I updated the code to properly close the <ul>'s in some cases.

Upvotes: 1

Related Questions