dedlfix: Verwirrende verschachtelungen eines Menüs

Beitrag lesen

echo $begrüßung;

Es soll eine Menüstruktur mittels einer Textdatei erfasst werden. Jede Zeile der Datei stellt einen Menüpunkt dar. Das Menü darf unendlich tief verschachtelt werden.
Ich komme an dem Punkt der Verschachtelungen nicht weiter. Immer fehlt irgendwo irgendwas, entweder was geöffnet wird oder was geschlossen wird und ich bekomme keine Übersicht rein. Ich mache es dann im Endeffekt in PHP, aber eigentlich würde es mir ausreichen, wenn mir jemand mal die Logik dahinter erklären würde, wie ich so ein Menü mit sich selbst aufrufenden schleifen oder Funktionen automatisch unendlich tief bauen kann?

Meine Lösung sieht so aus: Aus dem Menü-String wird ein verschachteltes Array erstellt (Funktion einlesen()). In einem zweiten Schritt wird daraus das <ul><li>-Konstrukt erzeugt (Funktion ulli()).

Das "ulli" lässt sich aus dem Array heraus besser erzeugen. Man muss dann auch die großen Level-Sprünge, wie von cacc nach d nicht mehr berücksichtigen, da durch das rekursive Hinab- und wieder Hinaufsteigen jedes Level mitgenommen wird.

Und auch beim Einlesen verwende ich die Funktion rekursiv.

Seht selbst: (-:

  
/**  
 * einlesen() - Einlesen eines Jeena-Menü-Strings in ein Array  
 *  
 * @param array $menuarray Referenz auf das Ergebnis-Array  
 * @param string/array $menu ein Jeena-Menu als String oder zeilenweise als Array  
 * @param integer $i interner Wert, nicht verwenden  
 * @param integer $level interner Wert, nicht verwenden  
 */  
function einlesen(&$menuarray, $menu, $i = 0, $level = 1) {  
 if (is_string($menu)) {  
  $menu = strtr($menu, array("\r\n" => "\n", "\r" => "\n"));  
  $menu = explode("\n", $menu);  
 }  
  
 while ($i < count($menu)) {  
  list($itemlevel, $item) = explode(' ', $menu[$i], 2);  
  $itemlevel = strlen($itemlevel);  
  
  // eine/mehrere Ebene(n) zurück  
  if ($level > $itemlevel)  
   break;  
  // weiter "nach unten"  
  if ($level < $itemlevel) {  
   if ($level + 1 < $itemlevel)  
    die('Verschachtlungsfehler an Position '. $menu[$i]);  
   $i = einlesen($menuarray[] = array(), $menu, $i, $level + 1);  
  }  
  // gleiches Level  
  else  
   $menuarray[] = trim($item);  
  
  $i++;  
 } //while $i < $menu  
  
 // Rückgabewert bei Verschachtlungen: Index des nächsten zu lesenden $menu-Eintrag  
 return --$i;  
}  
  
/**  
 * ulli() - Umwandeln eines Jeena-Menü-Arrays in einen HTML-ul-li-String  
 *  
 * @param array $menuarray ein Jeena-Menü-Array  
 * @param string $class ul-Klassenname  
 * @param integer $level (optional) Einrücktiefe  
 * @return string HTML-String eines Jeena-Menüs  
 */  
function ulli($menuarray, $class='level', $level = 0) {  
 $ulli = '';  
 foreach ($menuarray as $item) {  
  if (is_scalar($item)) {  
   // vorhergehendes Item schließen, wenn vorhanden  
   if (strlen($ulli))  
    $ulli .= "</li>\n";  
   // nächstes Item eingerückt anfangen  
   $ulli .= str_repeat('  ', $level + 1) . '<li>' . htmlspecialchars($item);  
  }  
  if (is_array($item)) {  
   $ulli .= ulli($item, $level + 1);  
  }  
 } //foreach $menuarray  
 return sprintf("<ul class='%s%s'>\n%s</li>\n%s</ul>",  
  $class, $level, $ulli, str_repeat('  ', $level));  
}  
  
  
$menu = <<<MENU  
- a  
- b  
-- ba  
-- bb  
-- bc  
- c  
-- ca  
--- caa  
--- cab  
--- cac  
---- caca  
---- cacb  
---- cacc  
- d  
-- da  
- e  
- f  
-- fa  
--- faa  
MENU;  
  
$menuarray = null;  
einlesen($menuarray, $menu);  
  
// Kontrollausgabe  
print_r($menuarray);  
  
$ulli = ulli($menuarray);  
echo '<pre>' . htmlspecialchars($ulli) . '</pre>';  
echo $ulli;  

echo "$verabschiedung $name";