ich hatte Peter ja letzte Woche schon angekündigt, dass ich versuchen möchte, mich mit dem ein oder anderen Modul oder Addon einzubringen. Bis ich da etwas veröffentlichungsfähiges habe, wird es wohl noch etwas dauern, allerdings habe ich hier etwas anderes, das ich gerne vorstellen möchte und zu dem mich Eure Meinungen oder Tipps interessieren:
Neben Redaxo arbeite ich auch viel mit Drupal. Dabei habe ich das Theming-System von Drupal zu schätzen gelernt. Der HTML-Teil eines Addons wird in einer eigenen Datei ausgelagert. Speichert man in einem vorgesehen Verzeichnis eine bearbeitete Kopie der HTML-Daten ab, wird diese vom Modul automatisch bei der Ausgabe herangezogen.
Das erleichtert ein optisches Update enorm und nachdem ich beim Erneuern der ersten meiner in die Jahre gekommenen Redaxo-Projekte öfter festgestellt habe, dass so ein System einiges erleichtern würde, habe ich eine Klasse geschrieben, die angelehnt an die Art, wie Templates und Module im Addon-Template in der Datenbank bearbeitet werden, das Theming Konzept auf Redaxo überträgt.
Code: Alles auswählen
<?php
/**
* Klasse zum rendern von Theme-Daten
*
* Die Dateien werden entweder aus der Datenbank, dem 'developer_files'-Ordner oder
* dem Addon-Ordner gelesen.
* Dem Theme wird ein Array mit Werten übergeben, Übergabe entweder als
* Variable => Wert
* oder als
* {Platzhalter} => Wert
*
* @version 0.2
* @author Daniel Weitenauer
*/
class ahoi_Theme
{
// Flag für PHP Parser, TRUE = ein
const PARSE_PHP = TRUE;
protected $param = array(); // Die Variablen, die ans Theme übergeben werden
protected $file; // Dateiname
protected $addon; // Addon, falls vorhanden
protected $themeData; // die eingelesenen Daten
public function __construct(array $param, $file, $addon = NULL)
{
$this->setParam($param);
$this->file = $file;
$this->addon = $addon;
// Daten holen
$this->themeData = $this->getTheme();
}
/**
* Variablen setzen
*
* ein Array mit dem Format array( 'Variable' => Wert, '{Platzhalter}' => Wert );
*
* @param array $param Variablendaten
*/
public function setParam(array $param)
{
$this->param = $param;
}
/**
* Theme-Datei holen
*
* @param string $file Dateiname
* @param string $addon Addon-Ordner
* @param string $source Datenquelle bei Addon ('system', 'files', 'addon')
* @return string
*/
protected function getTheme($file = NULL, $addon = NULL, $source = NULL)
{
// Voreinstellungen
if(!$file) $file = $this->file;
if(!$addon) $addon = $this->addon;
$themeData = NULL;
// Daten holen
// Template
if ((!$source && $themeData=='') || $source=='system')
{
$content = self::getTemplate($file, $addon);
if ($content) $themeData = $content;
}
// Developer-Files
if ((!$source && $themeData=='') || $source=='files')
{
$themeData = self::getFile($file, $addon, TRUE);
}
// Addon-Ordner
if ((!$source && $themeData=='') || $source=='addon')
{
$themeData = self::getFile($file, $addon, FALSE);
}
// Hinweis ausgeben
if (!$themeData) echo('File '.($addon? '["'.$addon.'"] "'.$pathInc : '"'.$pathFiles).$file.'" not found.<br/>');
return "?>\n".$themeData;
}
/**
* Datei öffnen und parsen.
*
* @param array $param Parameter
* @param string $file Dateiname
* @param string $addon Addon-Ordner
* @return string geparste Datei
*/
public function parseTheme($param = NULL)
{
if (!is_array($param))
{
$param += $this->$param;
}
$output = $this->themeData;
// Parsen
ob_start();
// Ersetzen von Tags
foreach($param as $key => $value)
{
if(preg_match('%\{.*\}%', $key)) $output = str_replace($key, $value, $output);
}
// PHP parsen
if (PARSE_PHP)
{
$replace = extract($param); // Variablen in aktuellen Namespace übernehmen
eval($output); // PHP ausführen
}
$output = ob_get_contents()."\n";
ob_end_clean();
return $output;
}
/**
* Templates in Datenbank schreiben
*
* Templates müssen mit ###ID:[Addon-Name#]Template-Name### ausgezeichnet werden
*
* @param string $addon Addon-Name
* @param array $modules Template-Namen
* @param bool $branding true, wenn der Addon-Name eingefügt werden soll
* @return TRUE bei Erfolg
*/
public static function writeTemplate($file, $addon = NULL, $developer=FALSE)
{
global $REX;
// Datei holen
$content = self::getFile($file, $addon, $developer);
if (!$content) return FALSE;
// vorhandene Templates auslesen
$itId = $itName = NULL;
$it = new rex_sql;
$it->setQuery('SELECT * FROM rex_template WHERE content LIKE "%###ID:'.($addon? $addon.'#' : '').$file.'###%"');
foreach($it->getArray() as $i)
{
$itId = $i["id"];
$itName = $i["name"];
}
$sql = new rex_sql;
$sql->setTable('rex_template');
$sql->setValue('content', addslashes($content));
// Modul aktualisieren
if($itId!=NULL && $itName!=NULL)
{
$sql->setWhere('id="'.$itId.'"');
if($sql->update())
{
echo rex_info('"'.$itName.'" updated.');
}
else
{
$REX['ADDON']['installmsg'][$addon] = 'Could not update "'.$itName.'".';
return FALSE;
}
}
// Modul installieren
else
{
$sql->setValue('name',addslashes(($addon? $addon.' - ' : '').$file));
if($sql->insert())
{
echo rex_info('"'.($addon? $addon.' - ' : '').$file.'" installed.');
}
else
{
$REX['ADDON']['installmsg'][$addon] = 'Could not install "'.($addon? $addon.' - ' : '').$file.'".';
return FALSE;
}
}
return TRUE;
}
/**
* Template aus Datenbank holen
*
* Templates müssen mit ###ID:[Addon#]Template-Name### ausgezeichnet werden
*
* @param string $addon
* @param string $template
* @return string Template-Inhalt
*/
protected static function getTemplate($template, $addon = NULL)
{
$content = NULL;
$sql = new rex_sql;
$sql->setQuery('SELECT * FROM rex_template WHERE content LIKE "%###ID:'.($addon? $addon.'#' : '').$template.'###%"');
foreach($sql->getArray() as $i)
{
$content = $i["content"];
}
return $content;
}
/**
* Datei einlesen
* @param string $file Dateiname
* @param string $addon Addon-Ordner
* @return string
*/
protected static function getFile($file, $addon = NULL, $developer = FALSE)
{
global $REX;
$themeData = NULL;
$path = $addon? $REX['INCLUDE_PATH'].'/addons/'.$addon.'/theme' : ''; // Addon-Ordner
if ($developer) $path = $REX['INCLUDE_PATH'].'/developer_files/theme'.($addon? '/'.$addon : ''); // der default-Ordner des Addons 'developer'
if (file_exists($path.'/'.$file.'.tpl.php'))
{
$themeData = file_get_contents($path.'/'.$file.'.tpl.php');
}
else
{
$themeData = '';
}
return $themeData;
}
}
?>
Manches ist noch nicht ganz fertig bearbeitet, etwa der Vorgang, wenn kein Addon mit angegeben wurde.
Was denkt Ihr?
Daniel
Edit 12.11.: die ursprünglich gepostete Version enthielt Fehler im Quelltext, die sind nun korrigiert...