Custom Theme Generator

Hallo liebe Entwickler,

generell ist das Template Override Verfahren von Oxid sehr praktisch um Updates problemlos einspielen zu können. Jedoch ist es beim Entwickeln eines Templates meistens leichter direkt in einer vollständigen Kopie eines Templates zu arbeiten. Deshalb haben wir ein Script entwickelt dass nachdem die Template arbeiten abgeschlossen sind automatisch die geänderten Dateien aus einem Template extrahiert und in einem Extra Ordner ablegt - dieser kann dann als sCustomTheme gesetzt werden.

Die Verwendung ist einfach, geändertes und original Template wählen (es muss eine unveränderte Version des Templates auf dem Server liegen), Zielordner eingeben und Start drücken.

Das Script steht unter der WTFPL (http://sam.zoy.org/wtfpl/COPYING) - also “Do what the fuck you want to” :wink:

Folgenden Code in eine Datei namens tploverride.php in Shop Hauptverzeichnis ablegen und aufrufen, es erscheint dann das Interface. [B]Nach der Verwendung unbedingt wieder vom Server löschen![/B]


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
 <head>
  <title>Template Override generieren</title>
  <link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap-1.1.1.min.css">
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 </head>
<?php

	function makeAll($dir, $mode = 0777, $recursive = true) {
		if( is_null($dir) || $dir === "" ){
			return FALSE;
		}
		
		if( is_dir($dir) || $dir === "/" ){
			return TRUE;
		}
		if( makeAll(dirname($dir), $mode, $recursive) ){
			return mkdir($dir, $mode);
		}
		return FALSE;
	}
	
	function smartCopy($source, $dest, $options=array('folderPermission'=>0755,'filePermission'=>0755))
	{
		$result=false;
		
		//For Cross Platform Compatibility
		if (!isset($options['noTheFirstRun'])) {
			$source=str_replace('\\','/',$source);
			$dest=str_replace('\\','/',$dest);
			$options['noTheFirstRun']=true;
		}
		
		if (is_file($source)) {
			if ($dest[strlen($dest)-1]=='/') {
				if (!file_exists($dest)) {
					makeAll($dest,$options['folderPermission'],true);
				}
				$__dest=$dest."/".basename($source);
			} else {
				$__dest=$dest;
			}
			if (!file_exists($__dest)) {
				$result=copy($source, $__dest);
				chmod($__dest,$options['filePermission']);
			}
		} elseif(is_dir($source)) {
			if ($dest[strlen($dest)-1]=='/') {
				if ($source[strlen($source)-1]=='/') {
					//Copy only contents
				} else {
					//Change parent itself and its contents
					$dest=$dest.basename($source);
					@mkdir($dest);
					chmod($dest,$options['filePermission']);
				}
			} else {
				if ($source[strlen($source)-1]=='/') {
					//Copy parent directory with new name and all its content
					@mkdir($dest,$options['folderPermission']);
					chmod($dest,$options['filePermission']);
				} else {
					//Copy parent directory with new name and all its content
					@mkdir($dest,$options['folderPermission']);
					chmod($dest,$options['filePermission']);
				}
			}
	
			$dirHandle=opendir($source);
			while($file=readdir($dirHandle))
			{
				if($file!="." && $file!="..")
				{
					$__dest=$dest."/".$file;
					$__source=$source."/".$file;
					//echo "$__source ||| $__dest<br />";
					if ($__source!=$dest) {
						$result=smartCopy($__source, $__dest, $options);
					}
				}
			}
			closedir($dirHandle);
			
		} else {
			$result=false;
		}
		return $result;
	}

	function compareDirectories( $path = '.', $changePath = '.', $level = 0 ){
		
		$ignore = array( 'cgi-bin', '.', '..' );
		$dh = @opendir( $path );
		
		while( false !== ( $file = readdir( $dh ) ) ){ // Loop through the directory
			if( !in_array( $file, $ignore ) ){
				if( is_dir( "$path/$file" ) ){
					// Its a directory, so we need to keep reading down…
					compareDirectories( "$path/$file", "$changePath/$file", ($level+1),$time );
				} else {
					compareFiles("$path/$file", "$changePath/$file");
				}//elseif
			}//if in array
		}//while
		
		closedir( $dh );
		
	}
	
	function compareFiles( $path = '.', $changePath = '.' ){
		$vanilla_path = $path;
		$branch_path = $changePath;
		
		if( !file_exists($branch_path) || strcmp(file_get_contents($vanilla_path),file_get_contents($branch_path)) ){
			if($_REQUEST["displayonly"] == 1){
				echo "$vanilla_path >> $branch_path<br/>";
			}else{
				$tPath = str_replace($_REQUEST['modifiedtpl']."/",'',$vanilla_path);
			
				makeAll(dirname("out/".$_REQUEST['targetfolder']."/$tPath"));
				smartCopy($vanilla_path, "out/".$_REQUEST['targetfolder']."/$tPath");
			}
		}	
		return true;
	}
	
	

	
	$aTemplates = array();
	foreach ( glob("out/**",GLOB_ONLYDIR) as $tplfolder ) {
		if(file_exists($tplfolder."/theme.php")){
			$aTemplates[] = $tplfolder;
		}
	}
	
	if($_REQUEST['fnc'] == 'create'){
		
		compareDirectories( $_REQUEST['modifiedtpl'], $_REQUEST['originaltpl']);
		
		$blCopied = true;
		
	}
	
?>
 
<body style="padding-top: 60px">

 <div class="topbar-wrapper noprint" style="z-index: 5">
  <div class="topbar">
 	<div class="fill">
 		<div class="container">
 			<h3><a href="#">Aggrosoft Override Generator</a></h3>
 		</div>
 	</div>
 </div>
 </div>

<div class="container">

	    <div class="alert-message success">
		<p><strong>Kopiervorgang erfolgreich!</strong> Sie finden das neue Template jetzt im Ziel Ordner.</p>
		</div>

  <form action="tploverride.php" method="post">
  	<input type="hidden" name="fnc" value="create">
	<fieldset>
	  <legend>Custom Theme generieren</legend>
	  <div class="clearfix">
		<label for="username">Geändertes Template</label>
		<div class="input">
		  <select name="modifiedtpl">
		  	<?php foreach ($aTemplates as $sTemplate) : ?>
		  	<option value="<?php echo $sTemplate; ?>"><?php echo $sTemplate; ?></option>
		  	<?php endforeach; ?>
		  </select>
		</div>
	  </div><!-- /clearfix -->
	  <div class="clearfix">
		<label for="username">Original Template</label>
		<div class="input">
		  <select name="originaltpl">
		  	<?php foreach ($aTemplates as $sTemplate) : ?>
		  	<option value="<?php echo $sTemplate; ?>"><?php echo $sTemplate; ?></option>
		  	<?php endforeach; ?>
		  </select>
		</div>
	  </div><!-- /clearfix -->
	  <div class="clearfix">
		<label for="username">Ziel Ordner (in out)</label>
		<div class="input">
		  <input type="text" size="30" name="targetfolder" class="xlarge">
		</div>
	  </div><!-- /clearfix -->
	  <div class="clearfix">
		<label for="username">Simulieren</label>
		<div class="input">
			<div class="input-prepend">
		  		<label class="add-on"><input type="checkbox" name="displayonly" value="1"></label>
		  		<input class="small" readonly="readonly" value="Nur anzeigen" type="text">
		  	</div>
		</div>
	  </div><!-- /clearfix -->	  	  
	  <div class="actions">
		<button class="btn primary" type="submit">Start</button> <button class="btn" type="reset">Cancel</button>
	  </div>
	</fieldset>
  </form>

	</div>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
  <script type="text/javascript" src="http://autobahn.tablesorter.com/jquery.tablesorter.min.js"></script>
  <script type="text/javascript">
  	$(function(){
  		$("table").tablesorter({ sortList: [[1,1]] });
  	});
  </script>
 </body>
</html>

Schick - danke!

Kann man die tploverride.php selbst benamsen, oder muss der vorgegebene Name verwendet werden?

Kann ich das ins Wiki aufnehmen?

Sehr interessant, danke!

[QUOTE=Hebsacker;70369]Schick - danke!

Kann man die tploverride.php selbst benamsen, oder muss der vorgegebene Name verwendet werden?

Kann ich das ins Wiki aufnehmen?[/QUOTE]

Naja, theoretisch ja - nur die HTML Form hat als action Attribut halt den Script Namen drin. Mit ein bisschen Anpassung geht das sicher auch (Action leer lassen eventuell).

Ja kannst du in’s wiki einstellen, ist ja WTFPL :smiley:

war nur die Frage aus Sicherheitsgründen, damit man nicht so auf gut Glück versuchen kann die Datei irgendwo aufzurufen…

Aufgenommen ins Wiki: http://wiki.oxidforge.org/Tutorials/Theme_Management_im_OXID_eShop_ab_4.5.0#Script_zum_Kopieren_ausschliesslich_ver.C3.A4nderter_Template-Dateien

Coole Sache!
Das Kopieren nur geänderter Templates erschien mir zuerst überflüssig, da ich selbst immer nur das Template in den Custom-Theme-Ordner kopiere, was ich wirklich ändere.

Aber: Aggrosofts Script vergleicht darüber hinaus ja auch die Sprachdateien und nicht zuletzt auch die Bilder! Das ist ziemlich sinnvoll… und das Ganze auch noch als WTFPL - Daumen hoch :smiley:

Moin,

Nach Änderungen im tmpTemplate habe ich einen Ordner (in /out) angelegt, ihm die Rechte 777 gegeben und diesen im Interface als Ziel Ordner angegeben. Mit out/Azure als original Template und tmpTemplate als geändertes Template. Die Eingaben verschwinden wieder aus den Eingabefeldern und im grünen Balken steht: “Kopiervorgang erfolgreich! Sie finden das neue Template jetzt im Ziel Ordner.”

Aber der Zielordner ist leer! Ich sehe im Backend das neue Template (welches genau so heist wie das geänderte Template) und kann es auch aktivieren doch dann hab ich natürlich bloß noch eine weisse Seite im Frontend :eek:

In diesem neuen Template im Backend steht dann unter dem Reiter Einstell.: “Datei nicht gefunden (bitte EXCEPTION_LOG.txt für Details prüfen)” Dort finde ich den Inhalt des Sreenies ->

Was hab ich falsch gemacht?

Gruß RalfB

Hier der Anhang:

Hier der Anhang :wink:

Was habe ich denn falsch gemacht, wenn ich nach dem erfolgreichen Aufruf der Datei, der Auswahl der Templates und und dem Start folgende Fehlermeldung bekomme:

„Die angeforderte Seite ‘tploverride/’ konnte nicht gefunden werden.“

Viele Grüße

Mario

Du hast vermutlich den Code aus dem Wiki genommen. Dort steht:
<form action=“tploverride” method=“post”>

Das führte bei mit auch zu der Fehlermeldung.

Hier in Post #1 steht aber:
<form action=“tploverride.php” method=“post”>

Damit funktioniert es bei mir auf jeden Fall.

Jaaaa, so funktioniert es! :wink: Vielen Dank für Deine Hilfe!

Viele Grüße

Mario

das ist übrigens ein Wiki - was sich ja unter anderem dadurch auszeichnet, dass es von jedem befüllt / korrigiert werden kann

(habs schon korrigiert…)

Wenn ich das erzeugte Thema aktiviere, klappt der Zugriff auf nicht geänderte Bilder nicht mehr. Diese werden alle …/out/custom_azure gesucht, nicht in /out/azure.

File does not exist: /kunden/213460_32760/shop1/out/custom_azure/theme.jpg
File does not exist: /…/shop1/out/custom_azure/img/arrow-down.png

Da ich nicht so recht erkennen kann, was das Skript genau macht, ist jetzt meine Frage, ob das Skript fehlerhaft durchgelaufen ist oder ob ich noch irgendetwas ändern müsste, damit auch die Bilder aus /out/azure gelesen werden?

Das ist immer so wenn man die oxid.css ändert: https://bugs.oxid-esales.com/view.php?id=4249
Entweder man legt eine eigene “custom.css” an, in der sich nur die Änderungen befinden, und bindet diese in base.tpl ein, oder man kopiert den Inhalt von /img und /src/bg in das custom theme. Die Datei /theme.jpg sollte ein verkleinerter Screenshot des neuen Themes sein.

Funktioniert das Script auch noch mit der 4.5.12? Ich bekomme zwar die Meldung “Kopiervorgang erfolgreich! Sie finden das neue Template jetzt im Ziel Ordner.”, aber im entsprechenden Ordner ist gar nichts.

Hast du auch mal F5 gedrückt? Oft erscheinen dann neue Dinge auf dem FTP-Server wie durch Zauberhand :slight_smile:

Auch nach “durchdrücken” der F5 ist das Template noch nicht im angegebenen Ordner.

Normal drücken sollte genügen.
Aber um deine ursprüngliche Frage zu beantworten:
Ja, es funktioniert auch in 4.5.x, 4.6.x und 4.7.x. Es ist praktisch Versionsunabhängig.

Fumktioniert nun. Kann jedoch nicht sagen warum. Hab die Datei nochmals neu hochgeladen, das Verzeichnis neu erstellung und nochmals neu ausgeführt.