0251 / 590 837 15
info@a-coding-project.de
;

Submenüs Teil 2 (CMS)

In unseren Submenüs im CMS geht es heute um das Anlegen / Bearbeiten von Menüeinträgen. Außerdem gibt es die Auflösung der Aufgabe die ich euch vorgestern aufgegeben hab 😉

Fangen wir an mit einer kleinen Umstrukturierung der Menü-Architektur. Es gibt nun die neue Klasse /system/classes/menuentry.php. Sie steht für genau einen Menüeintrag und übernimmt die Funktion des Anzeigen Speichern und Speichern.

Ich finde die Aufteilung etwas gelungener, da es mit den neuen Typen etwas unübersichtlich werden würde. Hier ist der Code:

<?PHP
  class MenuEntry{
    public $id    = -1;
    public $type  = 0;
    public $href  = '';
    public $menu  = '';
    
    public function display($globalstart,$globalend, $elementstart,$elementend,$class,$index){
        echo $elementstart."<a href="".$this->href."" title="".$this->title."" 
             class="".$class." menue-".$id."-".$index."">".$this->title."</a>".$elementend;
    }
    
    public function displayEditAble(){
        ?>
          <input name="<?PHP echo $this->id; ?>_title" value="<?PHP echo $this->title; ?>" />
          <select name="<?PHP echo $this->id; ?>_type" onChange="typeSelected()">
            <option value="0"<?PHP if($this->type == 0) echo " selected="1""; ?>>Seite Intern</option>
            <option value="1"<?PHP if($this->type == 1) echo " selected="1""; ?>>Seite Extern</option>
            <option value="2"<?PHP if($this->type == 2) echo " selected="1""; ?>>Men&uuml;</option>
          </select> 
          <?PHP
            if($this->type == 0){
              $selector = new PageSelector();
              $selector->name  = $this->id.'_href';
              $selector->value = $this->href;
              $selector->display();
            }
            else if($this->type == 1){
          ?>
            <input name="<?PHP echo $this->id; ?>_href" value="<?PHP echo $this->href; ?>" />
          <?PHP
            }
            else if($this->type == 2){
              $selector = new MenueSelector();
              $selector->name  = $this->id.'_href';
              $selector->value = $this->href;
              $selector->display();
            }
          ?>
          <input type="submit" name="<?PHP echo $this->id; ?>_delete" value="X" /><br />
        <?PHP
    }
    
    public function save(){
      if($this->id == -1){
        return $this->insert();
      }
      else{
        return $this->update();
      }
    }
    
    private function insert(){
      $menu  = $GLOBALS['db']->EscapeString($this->menu);
      $title = $GLOBALS['db']->EscapeString($this->title);
      $href  = $GLOBALS['db']->EscapeString($this->href);
      $type  = $GLOBALS['db']->EscapeString($this->type);
      $maxID = $GLOBALS['db']->ReadField("SELECT MAX(id) FROM {'dbprefix'}menu 
                                          WHERE menuID = '".$menu."'");
      $id = $maxID + 1;
      $res = $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}menu (id,menuID,title,href,type)
                                      VALUES('".$id."','".$menu."',
                                      '".$title."','".$href."','".$type."')");
      if($res){
        $args['menu']  = $menu;
        $args['title'] = $title;
        $args['href']  = $href;
        EventManager::raiseEvent("menu_entry_added","../",$args);
      }
      return $res;
    }
    
    private function update(){
      $id    = $GLOBALS['db']->EscapeString($this->id);
      $menu  = $GLOBALS['db']->EscapeString($this->menu);
      $title = $GLOBALS['db']->EscapeString($this->title);
      $href  = $GLOBALS['db']->EscapeString($this->href);
      $type  = $GLOBALS['db']->EscapeString($this->type);
      $res =  $GLOBALS['db']->Execute("UPDATE {'dbprefix'}menu SET 
                                       href = '".$href."', 
                                         title = '".$title."', 
                                         type = '".$type."' 
                                       WHERE id = '".$id."' 
                                       AND menuID = '".$menu."'");
    if($res){
      $args['menu']  = $menu;
      $args['title'] = $title;
      $args['href']  = $href;
      $args['id']    = $id;
      EventManager::raiseEvent("menu_entry_edit","../",$args);
    }
    return $res;
    }
  }

?>

Dementsprechen müssen wir die Datei /system/classes/menu.php anpassen. Diese hat zusätzlich die Methode getEntries, welche alle Einträge mit der neuen Klasse liefert:

<?PHP
class Menu{
  function display($id, $globalstart,$globalend, $elementstart,$elementend,$class){
    $entries = self::getEntries($id);
    echo $globalstart;
    $i = 1;
    if($entries){
      foreach($entries as $entry){ 
          $entry->display($globalstart,$globalend, $elementstart,$elementend,$class,$index);
        $i++;
      }
    }
    echo $globalend;
  }
  
  function getIdByName($name){
    $name = $GLOBALS['db']->EscapeString(strtolower(trim($name)));
    return $GLOBALS['db']->ReadField("SELECT id FROM {'dbprefix'}menu_names WHERE lower(trim(name)) = '".$name."' LIMIT 0,1");;
  }

  function displayEditable($id){
    $entries = self::getEntries($id);
    if($entries){
      foreach($entries as $entry){ 
        $entry->displayEditable();
      }
    }
  }

  function addEntry($menu,$title,$href){
    $maxID = $GLOBALS['db']->ReadField("SELECT MAX(id) FROM {'dbprefix'}menu 
                                        WHERE menuID = '".$menu."'");
    $id = $maxID + 1;
    $res = $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}menu (id,menuID,title,href)
                                    VALUES('".$id."','".$menu."',
                                    '".$title."','".$href."')");
    if($res){
      $args['menu']  = $menu;
      $args['title'] = $title;
      $args['href']  = $href;
      EventManager::raiseEvent("menu_entry_added","../",$args);
    }
    return $res;
  }

  function editEntry($menu,$id,$title,$href){
    $res =  $GLOBALS['db']->Execute("UPDATE {'dbprefix'}menu SET 
                                     href = '".$href."', 
                                     title = '".$title."' 
                                     WHERE id = '".$id."' 
                                     AND menuID = '".$menu."'");
    if($res){
      $args['menu']  = $menu;
      $args['title'] = $title;
      $args['href']  = $href;
      $args['id']    = $href;
      EventManager::raiseEvent("menu_entry_edit","../",$args);
    }
    return $res;
  }

  function deleteEntry($menu,$id){
    $res = $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}menu WHERE menuID = '".$menu."' AND id = '".$id."'");
    if($res){
      $res = $GLOBALS['db']->Execute("UPDATE {'dbprefix'}menu SET id = id - 1 WHERE id > '".$id."'");
      if($res){
        $args['menu']  = $menu;
        $args['id'] = $id;
        EventManager::raiseEvent("menu_entry_deleted","../",$args);
      }
    }
    return $res;
  }

  function create($name){
    $res = $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}menu_names (name) VALUES ('".$name."')");
    if($res){
      $args['name']  = $name;
      EventManager::raiseEvent("menu_created","../",$args);
    }
    return $GLOBALS['db']->InsertID();
  }

  function delete($id){
    $res = $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}menu_names WHERE id = '".$id."'");
    if($res){
      $res = $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}menu WHERE menuID = '".$id."'");
      if($res){
        $args['id']  = $id;
        EventManager::raiseEvent("menu_deleted","../",$args);
      }
    }
    return $res;
  }
  
  function getEntries($id){
    $rows = $GLOBALS['db']->ReadRows("SELECT * FROM {'dbprefix'}menu WHERE menuID = '".$id."' ORDER BY id");
    if($rows){
      foreach($rows as $row){
        $entry = new MenuEntry();
        $entry->id    = $row->id;
        $entry->type  = $row->type;
        $entry->href  = $row->href;
        $entry->title = $row->title;
        $entry->menu  = $id;
        $res[] = $entry;
      }
    }
    return $res;
  }
}
?>

Kommen wir jetzt zur Datei /admin/includes/menu-edit.php und damit auch zu eurer Hausaufgabe. Diese Datei wurde zum einen auf das neue Menüsystem umgestellt und das Problem mit den Abständen wurde (von mir).

Der Trick ist ganz einfach: Ich schiebe die Combo- & TextBoxen alle aufeinander und ändere den Text des Labels. So sieht die Datei aus:

<?PHP
  if($_POST['add']){
    if(trim($_POST['newtitle']) != ""){
      if(trim($_POST['newurl']) != ""){
        $entry        = new MenuEntry();
        $entry->menu  = $_GET['menu'];
        $entry->title = $_POST['newtitle'];
        $entry->type  = $_POST['type'];
        if($entry->type == 0){
          $entry->href  = $_POST['newPage'];
        }
        else if($entry->type == 1){
          $entry->href  = $_POST['newurl'];
        }
        else{
          $entry->href  = $_POST['newMenu'];
        }
        $res = $entry->save();
        if($res){
          echo "<p>Eintrag hinzugef&uuml;gt!</p>";
        }
        else{
          echo "<p>Eintrag nicht hinzugef&uuml;gt!</p>";
        }
      }
      else{
         echo "<p>Bitte geben Sie ein Link-Ziel ein</p>";
      }
    }
    else{
       echo "<p>Bitte geben Sie einen Link-Titel ein</p>";
    }
  }
  else if($_POST['save']){
    foreach($_POST as $param=>$value){
      if(strlen($param) >= 6){
        if(substr($param,-5,5) == "_href"){
          $entries[substr($param,0,-5)][href] = $value;
        }
        else if(strlen($param) >= 7 && substr($param,-6,6) == "_title"){
          $entries[substr($param,0,-6)][title] = $value;
        }
        else if(substr($param,-5,5) == "_type"){
          $entries[substr($param,0,-5)][type] = $value;
        }
      }
    }
    foreach($entries as $id=>$params){
      $entry        = new MenuEntry();
      $entry->id    = $id;
      $entry->menu  = $_GET['menu'];
      $entry->title = $params['title'];
      $entry->href  = $params['href'];
      $entry->type  = $params['type'];
      $entry->save();
    }
  }
  else{
    foreach($_POST as $param=>$value){
      if(strlen($param) >= 8){
        if(substr($param,-7,7) == "_delete"){
          Menu::deleteEntry($GLOBALS['db']->EscapeString($_GET['menu']),
                            $GLOBALS['db']->EscapeString(substr($param,0,-7)));
        }
      }
    }
  }
?>
<h1>Men&uuml; bearbeiten</h1>
<form action="index.php?page=menu-edit&menu=<?PHP echo $_GET['menu']; ?>" method="POST">
  <h2>Eintr&auml;ge Bearbeiten</h2>
  <?PHP
    Menu::displayEditable($GLOBALS['db']->EscapeString($_GET['menu']));
  ?>
  <input name="save" type="submit" value="Speichern"/>

  <h2>Neuen Eintrag hinzuf&uuml;gen</h2>
  <table>
    <tr>
      <td style="width:100px;">Text:</td>
      <td><input name="newtitle" style="width:200px;" /></td>
    </tr>
    <tr>
      <td>Typ:</td>
      <td>
        <script language="javascript">
          function typeSelected(){
            document.getElementsByName('newPage')[0].style.visibility ='hidden';
            document.getElementsByName('newurl')[0].style.visibility ='hidden';
            document.getElementsByName('newMenu')[0].style.visibility  ='hidden';
            if(document.getElementById('type').selectedIndex == 0){
              document.getElementsByName('newPage').style.visibility ='visible';
              document.getElementById('newLabel').innerHTML = 'Seite';
            }
            else if(document.getElementById('type').selectedIndex == 1){
              document.getElementsByName('newurl')[0].style.visibility  ='visible';
              document.getElementById('newLabel').innerHTML = 'Url';
            }
            else{
              document.getElementsByName('newMenu')[0].style.visibility ='visible';
              document.getElementById('newLabel').innerHTML = 'Menü';
            }
          }
        </script>
        <select id="type" name="type" onChange="typeSelected()" style="width:200px;">
          <option value="0">Seite Intern</option>
          <option value="1">Seite Extern</option>
          <option value="2">Men&uuml;</option>
        </select>
      </td>
      </tr>
      <tr>
        <td><span id="newLabel">Seite</a>:</td>
        <td>
          <input name="newurl" value="http://" style="width:200px;visibility:hidden" />
          <?PHP
            $selector = new MenueSelector();
            $selector->name  = 'newMenu';
            $selector->value = -1;
            $selector->style = 'width:200px;position:relative;left:-210px;visibility:hidden';
            $selector->display();
          ?>
          <?PHP
            $selector = new PageSelector();
            $selector->name  = 'newPage';
            $selector->value = -1;
            $selector->style = 'width:200px;position:relative;left:-415px;';
            $selector->display();
          ?>
        </td>
      </tr>
  </table>
  <input name="add" type="submit" value="Hinzuf&uuml;gen"/>
</form>

Die beiden klassen Page- & Menüselector haben das Attribut style bekommen:

/system/classes/pageselector.php:

<?PHP
  class pageselector extends Control{ 
    public $style = '';

    public function display(){
      echo "<select name="".$this->name."" style="".$this->style."">";
      $pages = $GLOBALS['db']->ReadRows("SELECT * FROM {'dbprefix'}pages ORDER BY title");
      if($pages){
        foreach($pages as $page){
          if($page->id == $this->value){
            echo "<option value="".$page->id."" selected="1">".$page->title."</option>";
          }
          else{
            echo "<option value="".$page->id."">".$page->title."</option>";
          }
        }
        echo "</select>";
      }
    }

  }
?>

/system/classes/menueselector.php:

<?PHP
  class menueselector extends Control{
    public $style = '';
    
    public function display(){
      echo "<select name="".$this->name."" style="".$this->style."">";
      foreach(sys::getMenues() as $menue){
        if($menue->id == $this->value){
            echo "<option value="".$menue->id."" selected="1">".$menue->name."</option>";
        }
        else{
            echo "<option value="".$menue->id."">".$menue->name."</option>";
        }
      }
      echo "</select>";
    }

  }
?>

Kommentare

Elvis67 schrieb am 07.01.2012:

Ich verstehe die Sache mit dem Editieren der Menus noch nicht ganz. Ich habe zunächst in der DB alle Links des Adminmenus {admin} auf type 1 gesetzt. Ich bekomme aber jedes mal beim Betätigen der Selectbox für den type eines Menueintrages die Javascript Fehlermeldung document.getElementsByName("newPage").style is undefined und die zu Begin geladene Selectbox für die Seitenauswahl im Bereich "Neuen Eintrag hinzufügen" verschwindet. Was genau soll hier eigentlich passieren? Sollen die Menueinträge über das Formular für einen neuen Menueintrag editiert werden? Wie gesagt, ich verstehe nur Bahnhof. An dieser Stelle noch ein dickes Lob für diese Serie. Ich bin bis hierhin am Ball geblieben und habe für mich eine Menge über OOP und die Funktionsweise eines CMS lernen können.

Stefan Wienströer schrieb am 07.01.2012:

kannst du mal im Browser-Quelltext nachschauen, ob es das select mit den Namen newPage gibt?