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

ContentLion Updater

Für den 200sten ContentLion Beitrag musste ich mir etwas besonderes ausdenken. Die meisten von euch werden ContentLion nur einmal installiert haben. Ich werde aber in Kürze damit beginnen erste Projekte mit ContentLion anzufangen. Dort brauche ich mehrere Installationen, wo es aufwändig wäre jede Änderung von Hand zu übertragen. Dafür gibt es ab jetzt einen Updater!

Ihr sollt natürlich am ebsten noch alle Änderungen nachvollziehen, könnt aber ab jetzt auch gerne zusätzlich den Updater nutzen. Dieser ist als Plugin angelegt und in diesem Artikel werde ich die grundsätzliche Funktionsweise (des Clients) erklären.

Für den Updater werden einige Komponenten von ContentLion als Pakete eingeteilt. So ist zum Beispiel ein Paket der Contentlion-Core. Andere Packete sind Plugins oder Skins. Diese Pakete werden mit der aktuellen Version in der neuen Tabelle cl_packages gespeichert:

CREATE TABLE `cl_packages` (
  `name` varchar(50) NOT NULL,
  `version` int(11) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Derzeit haben wir bereits einige Pakete. Diese werden so registriert:

INSERT INTO `cl_packages` (`name`, `version`) VALUES
('contentlion-core', 1),
('plugin_lookaround', 1),
('plugin_updater', 1),
('plugin_filelistwidget', 1),
('plugin_menulistwidget', 1),
('plugin_pagelistwidget', 1),
('skin_default', 1),
('skin_backaenddefault', 1);

Für Plugins möchte ich gerne die Präfix plugin_ und für Skins skin_ verwenden. Die Paketnamen werden später bei der Installation von Plugins und Co eingebaut.

Die einzelnen Pakete werden über einen Get-Parameter mit der Version an die Adresse http://connect.contentlion.org/update.php?format=xml übergeben. Zurück kommt eine XML-Datei mit den einzelnen Update-Paketen. Diese Update-Pakete haben den gleichen Namen wie das normale Paket und eine Url über welcher die einzelnen Update-Befehle heruntergeladen werden können.

Befehle

Die einzelnen Änderungen werden pro Paket über eine Datei übergeben. Die Datei ist eine einfache Text-Datei, welche pro Zeile einen Befehl enthält. Am Anfang steht immer der Name des Befehls, danach ein Doppelpunkt und dann die Parameter in einem freien Format.

Für die ersten Tests habe ich 2 Befehle erstellt:

  • FileTransfer – lädt eine Datei herunter
  • SqlCommand – Führt einen Sql-Query aus.

In Kürze werden wahrscheinlich die folgenden Befehle folgen:

  • Delete – Löscht eine Datei
  • Include – Included eine PHP-Datei
  • AddLanguageToken – Fügt eine neue Übersetzung hinzu

weitere Vorschläge könnt ihr gerne einreichen.

Oberfläche

Der Updater ist erstmal ein Widget. Später könnten wir noch weitere Anzeigemöglichkeiten hinzufügen. Bei jedem öffnen des Widgets wird nach neuen Updates gesucht. Sollten Updates vorhanden sein, werden Paket-Name und Install-Link angezeigt.

Die Datei /system/plugins/updater/widget.php hat folgenden Code:

<?PHP
  class Updater extends WidgetBase{
    public function load(){
	  $this->headline = "Updater";
      include('interfaces/iupdateimporter.php');
      include('interfaces/iupdatecommand.php');
      $installedPackages = Plugin_Updater_Package::readFromDB();
      $path = "http://connect.contentlion.org/update.php?format=xml";
      $i = 0;
      foreach($installedPackages as $package){
        $path .= "&".$package->getUpdateToken($i);
        $i++;
      }
      $importer = new Plugin_Updater_UpdateXmlImporter();
      $importer->importPath($path);
      if($importer->areUpdatesAvailible()){
        $host = getSetting("global","global","host");
        foreach($importer->getUpdates() as $update){
          if(isset($_GET['update']) && $_GET['update'] == $update->getName()){
            $this->content .= "<br />Installiere ".$update->getName()."...";
            $update->runUpdate();
            $this->content .="<br />Installation abgeschlossen";
          }
          else{
            $this->content .= "<br />".$update->getName()." - <a href='".$host."admin/home.html?update=".$update->getName()."'>Installieren</a>";
          }
        }
      }
      else{
        $this->content =  "Keine Updates vorhanden!";
      }
	}
  }
?>

Wie ihr vielleicht erkennen können, habe ich hier unser Plugin-Klassenformat benutzt. So können die Klassen zum Updater unter /system/plugins/updater/classes abgelegt werden. Neben den Klassen gibt es auch einige Interfaces, welcher hier liegen: /system/plugins/updater/interfaces.

Zu guter letzt noch der SQL-Code, der das Widget aktiviert:

INSERT INTO `cl_dashboards` VALUES ('admin/home', 1, 2, 'updater/widget.php');
INSERT INTO `cl_widgets` VALUES ('updater/widget.php', 'Updater', 'Updater');
INSERT INTO `cl_activated_plugins` VALUES ('updater');

Update Import

Ich möchte euch jetzt nochmal kurz die Klasse Plugin_Updater_UpdateXmlImporter vorstellen. Das ist die Klasse, die prüft, ob Updates vorhanden sind. Diese implementiert das Interface IUpdateImporter. Ich habe ein Interface benutzt, damit man später das Format zum Beispiel auf CSV o.Ä. umstellen könnte.

Das XML lese ich über XPath aus. Einzelne Updates werden der Eigenschaft $updates hinzugefügt. Mit areUpdatesAvailible kann geprüft werden, ob Updates vorhanden sind. /system/plugins/classes/updatexmlimporter.php:

<?PHP
  class Plugin_Updater_UpdateXmlImporter implements IUpdateImporter{
    protected $updates = array();

    public function getUpdates(){
      return $this->updates;
    }

    public function importPath($path){
      $source=fopen($path,"r");
      while ($a=fread($source,1024)){
        $text .= $a;
      }
      fclose($source);
      return $this->importCode($text);
    }

    public function importCode($code){
      $xml = new SimpleXMLElement($code);
      foreach($xml->xpath('/contentlionupdates/update') as $update){
        $package = Plugin_Updater_UpdatePackage::get($update->path);
        $package->setName($update->name);
        $this->updates[] = $package;
      }
      return $this;
    }

    public function areUpdatesAvailible(){
      return sizeof($this->updates) > 0;
    }
  }
?>

Weitere Änderungen stehen selbstverständlich wieder bei Google: Revision 19.

Um das Ganze einmal zu testen, habe ich euch bereits ein kleines Update zur Verfügung gestellt. Dieses lädt einfach eine Testdatei herunter. Viel Spaß damit!

Kommentare

Daniel schrieb am 29.07.2010:

Nabend Stefan. Da ich morgen einen Tag frei habe, werde ich den Updater mal intensivst testen.

Daniel schrieb am 29.07.2010:

Ich hoffe Du bist mir nicht böse wenn ich auf http://www.buschimnetz.de/contentlion-news die Entwicklungsfortschritte von CL mit dokumentiere indem ich die Tutorialschritte verlinke? Wenn das der Fall sein sollte sage es einfach und die Seite fliegt wieder raus. MfG Daniel