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

ordner- und seitenspezifische Einstellungen (CMS)

Heute beginnen wir im CMS mit einem Punkt der mir relativ wichtig ist. Ich möchte nämlich eine Contentlion Installation für all meine Websites nutzen. So hab ich eine zentrale Verwaltung und muss mich nicht immer von Backend zu Backend durchschlagen.

Die Basis der Einstellungen liegt, wie du sicher weißt, auf der Settings-Klasse. Genau diese Klasse bekommt heute wieder viele Änderungen. Zunächst einmal möchte ich das Konzept von den ordner- und seitenspezifischen Einstellungen vorstellen.

In der settings-Tabelle gibt es die neue Spalte dir. In ihr kann eine globale Einstellung überschrieben werden können. Ein kleines Beispiel:

dir = global, property = title, value = CMS

dir = global/admin, property = title, value = Backend

dir = global/admin/home§page, property = title, value = Backend-Home

Hier wird der Titel des CMS (nicht nur der Seite) für bestimmte Bereiche gesetzt. Mit dem globalen ‚dir‘ wird der Titel standardmäßig auf ‚CMS‘ gesetzt. Ist man im Ordner settings wird es zu ‚Backend‘. Landet man auf der Seite admin/home, ist es Backend-Home. Sollte die Einstellung für home nun nicht existieren, müssten wir uns zunächst die vom admin ziehen. Ist diese auch nicht vorhanden, muss die globale Einstellung genommen werden.

Es kann natürlich auch mehrere Ordner, weshalb dich das nochprüfen des übergeordneten Settings etwas schwierig ist. Hierbei musste ich zur Rekrusion greifen.

Derzeit haben wir in der Klasse /system/classes/settings.php ein zweidimensionales Array für area und areatype. Jetzt setzen wir noch eine dritte Dimion darauf: Das Verzeichnis. Die wichtigste der neuen Funktionen ist die dir-Funktion. Sie setzt das Verzeichnis und splittet es anhand der / auf:

<?PHP
  class Settings{

    protected $area              = "global";
    protected $areaType          = "global";
    protected $dir               = "global";
    protected $parent            = null;
    protected $properties        = array();
    protected static $instances  = array();
    protected static $default    = null;

    public function get($property){
      $res = null;
      if(isset($this->properties[$property])){
        $res = $this->properties[$property];
      }
      else{
        $res = $this->getFromDB($property);
        if(!$res && $this->parent != null){
          $res = $this->parent->get($property);
        }
        $this->properties[$property] = $res;
      }

      return $res;
    }

    protected function getFromDB($property){
      $area     = $GLOBALS['db']->EscapeString($this->area);
      $areaType = $GLOBALS['db']->EscapeString($this->areaType);
      $dir      = $GLOBALS['db']->EscapeString($this->dir);
      $property = $GLOBALS['db']->EscapeString($property);
      $sql      = "";
      if(isset($_SESSION['user'])){
       $sql = "SELECT value FROM {'dbprefix'}settings WHERE role = '".$_SESSION['user']->role->ID."' AND area = '".$area."' AND areaType = '".$areaType."' AND dir = '".$dir."' AND property = '".$property."' UNION ";
      }
      $sql .= "SELECT value FROM {'dbprefix'}settings WHERE role = '3' AND area = '".$area."' AND areaType = '".$areaType."' AND dir = '".$dir."' AND property = '".$property."'";
      return $GLOBALS['db']->ReadField($sql);
    }

    public function set($property,$value,$role){
      $area     = $GLOBALS['db']->EscapeString($this->area);
      $areaType = $GLOBALS['db']->EscapeString($this->areaType);
      $property = $GLOBALS['db']->EscapeString($property);
      $value    = $GLOBALS['db']->EscapeString($value);
      $role     = $GLOBALS['db']->EscapeString($role);
      $allUserData = $GLOBALS['db']->ReadRow("SELECT * FROM  {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '3'");
      if($GLOBALS['db']->EscapeString($allUserData->value) != $value or $role == 3){
        $exists = $GLOBALS['db']->ReadField("SELECT COUNT(*) FROM {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."'") > 0;
        if($exists){
          $res = $GLOBALS['db']->Execute("UPDATE {'dbprefix'}settings SET value = '".$value."' WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."'");
        }
        else{
          $res = $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}settings (value,area,areaType,property,role,description,type) VALUES ('".$value."', '".$area."', '".$areaType."', '".$property."', '".$role."','".$allUserData->description."','".$allUserData->type."')");
        }
      }
      else{
        $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."'") ;
      }
      return $res;
    }

    protected function setArea($area){
      $this->area = $area;
    }

    protected function setAreaType($area){
      $this->areaType = $area;
    }

    protected function setDir($dir){
      $this->dir = $dir;
    }

    public static function getInstance(){
      if(!isset(self::$default)){
        if(!isset(self::$instances["global"]["global"]["global"])){
          $res = new Settings();
          self::$instances["global"]["global"]["global"] = $res;
        }
        else{
          $res = self::$instances["global"]["global"]["global"];
        }
      }
      else{
        $res = self::$default;
      }
      return $res;
    }

    public static function setDefaultInstance(Settings $settings){
      self::$default = $settings;
    }

    public function specify($areaType = "global",$area = "global"){
      if(!isset($this->$instances[$areaType][$area][$this->dir])){
        $res = new Settings();
        $res->parent = $this;
        $res->setAreaType($areaType);
        $res->setArea($area);
        $this->instances[$areaType][$area][$this->dir] = $res;
      }
      else{
        $res = $this->instances[$areaType][$area][$this->dir];
      }
      return $res;
    }

    public function dir($dir,$settings = null){
      if($settings == null){
        $settings = $this;
      }
      if(substr($dir,0,1) == "/"){
        $dir = substr($dir,1);
      }
      if(!isset($this->$instances[$this->areaType][$this->area][$this->dir."/".$dir])){
        $localdir = $dir;
        if(strpos($dir,"/") > -1){
          $localdir = split("/",$dir);
          $localdir = $localdir[0];
        }
        $res = new Settings();
        $res->parent = $this;
        $res->setAreaType($this->areaType);
        $res->setArea($this->area);
        $res->setDir($this->dir."/".$localdir);
        $this->instances[$areaType][$area][$this->dir."/".$dir] = $res;
        if(strpos($dir,"/") > -1){
          $res = $res->dir(substr($dir,strlen($localdir)));
        }
      }
      else{
        $res = $this->instances[$areaType][$area][$this->dir."/".$dir];
      }
      return $res;
    }

  }
?>

In der Funktion wird immer zum ersten Teil vor dem / ein neues Settings-Objekt gebildet. Im diesem wird dann wieder die gleiche Funktion mit dem Rest des Pfades aufgerufen. Was noch fehlt, ist das setzen des Verzeichnisses. Dies wird in der /index.php bzw. /content/index.txt erledigt:

  GetParamParser::parse();
  $db = new MySQL('system/dbsettings.php');
  $db->Connect();
  Settings::setDefaultInstance(Settings::getInstance()->dir($_GET['include']."§page"));
  $language = new Language();

Damit wird die Default-Instanz auf dem zur Zeit ausgewählten Ordner gesetzt.

Die ganze Settings-Sachen hat jedoch noch einen Nachteil: Sie ist total langsam! Wir müssen für jedes auslesen eines neuen Settings immer alle Verzeichnisse durchforsten. Aus diesem Grund wird es auch im nächsten Beitrag um caching gehen, so dass wir nicht immer auf die Datenbank zugreifen müssen.

Außer dieser Änderung hab ich noch zwei weitere Sachen gemacht: Es gibt ein noch nicht funktionierendes Settings-Widget, mit welchem wir in Kürze zunächst die ordnerspezifischen Einstellungen speichern können (wir müssen aber zuvor das Caching einbauen, da es etwas schwierig ist, ihr werdet es merken).

Außerdem habe ich an dem Updater herumgeschraubt, denn eigentlich wollte ich euch alle Änderungen als Update zur Verfügung stellen. Doch leider benutzt der Updater noch nicht die neue Settings-Klasse, er greift immer noch auf die alten Funktionen zurück. Es gibt im Updater jetzt den mkdir-Command, der Verzeichnisse erstellt und Updates für den Updater selbst müssen immer zuerst installiert werden. Aber bei der nächsten Änderung können wir dann wieder den Updater nutzen!

Alle Änderungen in Revision r67, r68 und r69.