Wie erstelle ich einen Customizer?

Support für das kostenlose Rechnungsprogramm (open3A)
Gesperrt
Support
Administrator
Beiträge: 3093
Registriert: 24.Okt.2007, 23:59

Wie erstelle ich einen Customizer?

Beitrag von Support » 19.Jan.2012, 11:12

Bitte erstellen Sie bei Fragen zur Customizer-Erstellung einen Beitrag im open3A-Forum.

Klassenaufbau
MrFloppy hat geschrieben:Was als erstes schon mal hilfreich wäre, ist eine Klassen-Übersicht bzw. fürs erste die Klasse für das Auftrags-Plugin (zu der der Schalter Brutto/Netto hinzugefügt werden soll).
Die Klassen sind immer in den Verzeichnissen der Plugins enthalten.

Das bedeutet, die Klasse für die Aufträge der open3A-Anwendung befindet sich im Verzeichnis /open3A/Auftraege.
Die Klassen, die jeweils für die Erstellung der GUI zuständig sind, tragen die Erweiterung "GUI".

Davon gibt es in der Regel zwei Stück:
AuftragGUI.class.php für die linke Seite
AuftraegeGUI.class.php für die rechte Seite (in den neueren Plugins wird nicht der Plural verwendet, sondern ein "m" vor den Klassennamen gesetzt, also z.B. mArtikel.class.php)

Da ein Auftrag mehrere Belege enthalten kann, hat ein Beleg die eigene Klasse GRLBM mit seiner eigenen GUI-Klasse.
MrFloppy hat geschrieben:Gibt es vielleicht ein einfaches, zugrundeliegendes Konzept, aus dem man sich solche Sachen logisch herleiten kann? (Wobei eine Dokumentation immer besser wäre ;)
Wenn es eine Tabelle Namens "Auftrag" gibt, habe ich immer ein Objekt "Auftrag", das von "PersistentObject" erbt.
Für die rechte Tabelle ist dann (außer bei den ganz alten Plugins wie den Aufträgen) die Klasse mit dem "m" davor und dem "GUI" dahinter zuständig. Also zum Beispiel "Artikel" und "mArtikelGUI".
Die linke Seite macht immer die einfache Klasse mit dem "GUI" dahinter, also "ArtikelGUI".
MrFloppy hat geschrieben:Das zweite wäre: Wie kann ich aus dem Customizer die Vorlagen-Klasse ansprechen? (Also praktisch das $this in der Klasse Vorlage_xy, bei dem ich showBruttoPreise setzen will); zugegeben ich bin hier zu faul um mir das selbst zu suchen ;)
Die Customizer sind hauptsächlich für die GUI vorgesehen, da sich die Vorlagen gut selbst erweitern lassen, indem einfach eine neue Kind-Klasse erstellt wird, wie es ja auch zum Beispiel der Vorlageneditor macht.
Konkret für die Umschaltung zwischen Brutto- und Nettopreis auf der Vorlage würde ich daher keinen Customizer verwenden, sondern die Vorlage selbst anpassen.

Tabellenupdates
MrFloppy hat geschrieben:Beschreibung für tableUpdateXML bzw. die Daten. Nicht das ich hier mit anderen Customizern kollidiere oder gar die Tabellen zerschieße.
Das XML für die Datenbankupdates ist recht simpel aufgebaut:

Code: Alles auswählen

<phynx>
	<collectionOf>Patch</collectionOf>
	<entry>

		<id>6</id>
		<attribute name="PatchID"><![CDATA[6]]></attribute>
		<attribute name="PatchType"><![CDATA[mysql]]></attribute>
		<attribute name="PatchDescription"><![CDATA[Rabatt]]></attribute>
		<attribute name="PatchValue"><![CDATA[ALTER TABLE `Posten` ADD `rabatt` DECIMAL( 6,3 ) NOT NULL DEFAULT \'0.000\' COMMENT \'CustomizerColumn\']]></attribute>
		<attribute name="PatchExecuted"><![CDATA[0]]></attribute>
		<attribute name="PatchDate"><![CDATA[1242253670]]></attribute>
		<attribute name="PatchApplication"><![CDATA[open3A]]></attribute>

		<attribute name="PatchNummer"><![CDATA[1000010]]></attribute>
		
	</entry>
	
</phynx>
Interessant sind dabei die Einträge innerhalb von <entry>:
  • <id> und "PatchID" werden in diesem Fall nicht beachtet
  • "PatchType" ist eigentlich immer mysql
  • "PatchDescription" enthält eine kurze Beschreibung
  • "PatchValue" enthält pro Zeile eine SQL-Anweisung, die bei der Aktivierung des Customizers ausgeführt werden
  • "PatchExecuted" sollte 0 sein
  • "PatchDate" enthält den Timestamp der letzten Aktualisierung des SQL-Statements. So weiß open3A, dass sich etwas geändert hat
  • "PatchApplication" ist selbsterklärend
  • "PatchNummer" enthält eine eindeutige Customizer-Nummer mit maximal 10 Stellen. Wenn Sie etwas über 2000000 angeben, sollten Kollisionen unwahrscheinlich werden.
Symbole
MrFloppy hat geschrieben:Sind die Icons wirklich als CDATA direkt in der Customizer-Klasse gespeichert? In welcher Klasse finde ich dann die Schaltfläche?
Ja, das mache ich, um Icons zusammen mit dem Customizer auszuliefern.
Sie können die Datei aber auch zum Beispiel im specifics-Verzeichnis ablegen.

Die Verwendung des Bildes aus dem Customizer funktioniert über die Hilfsklasse DBImage:

Code: Alles auswählen

DBImageGUI::imageLink("CustomizerBelegAuftrag", "", "image")
Dabei wird aus der Klasse CustomizerBelegAuftrag der Wert des Attributs "image" als Bild interpretiert.

Die Customizer-Klasse braucht dann die weiteren Methoden "loadMe" und "A":

Code: Alles auswählen

	public function loadMe(){
		$this->A = new stdClass();

		$this->A->image = "image/png:::1863:::iVBORw0KGgpcMFww...";
	}

	public function A($val){
		return $this->A->$val;
	}
Das Bild selbst muss Base64-Codiert mit dem mimetype voran in dem Attribut abgelegt werden.
Folgendes Skript konvertiert das Symbol "calendar_view_month.png":

Code: Alles auswählen

<?php
$file = "calendar_view_month.png";
echo filesize($file).":::".base64_encode(addslashes(file_get_contents($file)));
?>
Eingabefelder
Eine $checkbox erstellen Sie mit new HTMLInput("BruttoNetto", "checkbox", $value);
Der $value muss dabei 0 oder 1 sein, je nachdem ob ein Häkchen gesetzt ist oder nicht.
An den aktuellen Wert kommen Sie in der customizeGUI($class, $GUI)-Methode mit $class->A("BruttoNetto").

Da das Aufträge-Formular keinen Speichern-Knopf hat, müssen Sie bei jedem Klick auf das Häkchen den neuen Wert speichern (ansonsten würde es automatisch mitgespeichert).
Dafür hat die HTMLInput-Klasse die Methode activateMultiEdit:

activateMultiEdit($targetClass, $targetClassID) erwartet die beiden Parameter $targetClass und $targetClassID.
$targetClass ist dabei "Auftrag", und an die ID kommen Sie über $class->getID();

Code: Alles auswählen

 new HTMLInput("bruttoKunde", "checkbox", $class->A("bruttoKunde"));
$I->activateMultiEdit("Auftrag", $class->getID());
$class->newDisplayedFields(array("Brutto?" => $I));
Datenbankzugriff
MrFloppy hat geschrieben:Wie kann ich am einfachsten auf die Datenbank-Tabelle zugreifen (ich habe hier eine neue Spalte "BruttoNetto" in der Tabelle "Auftrag" eingefügt). Geht da was mit $Auftrag->A?
An eine bestimmte Zeile in der Tabelle Auftrag mit der ID "5" kommen Sie mit $Auftrag = new Auftrag(5);
An die Spalte BruttoNetto kommen Sie mit $Auftrag->A("BruttoNetto");

Vorlagenanpassungen
MrFloppy hat geschrieben:Wie kann ich das Ganze dann am besten in die Vorlage einbauen bzw. an diese weitergeben? (Eigentlich muß ich ja nur die Variable showBruttoPreise entsprechend setzen).
In der Vorlage müssen Sie eine Methode erweitern, nachdem das Attribut VarsGRLBM gesetzt ist. Da das in printGRLBM(GRLBM $GRLBM) passiert, wäre mein Vorschlag:

Code: Alles auswählen

function printGRLBM(GRLBM $GRLBM) {
	parent::printGRLBM($GRLBM);

	$Auftrag = new Auftrag($GRLBM->A("AuftragID"));
	#...
}
Das sollte auch noch reichen, um showBruttoPreise zu setzen.

Aspekte
MrFloppy hat geschrieben:Nun noch eine Frage zur Variable showBruttoPreise: Gibt es eine Möglichkeit, einer Vorlage die Variable einfach so mitzugeben? Dann wäre der Customizer universeller und würde mit jeder Vorlage funktionieren.
Leider lassen sich keine Variablen mitgeben, aber ich habe noch eine andere Möglichkeit, die Klasse anzupassen. Im Konstruktor wäre ebenfalls zu früh, da die Vorlage den Auftrag noch nicht kennt.

Um im Customizer einen joinPoint anzusprechen, erweitern Sie dessen Konstruktormethode:

Code: Alles auswählen

function __construct(){
	Aspect::registerPointCut("before", "PDFBrief::printGRLBM", "CustomizerTestGUI::advicePDFBrief");
	//Hier sagen Sie dem System, welchen joinPoint Sie meinen (PDFBrief::printGRLBM) und welche Methode aufgerufen wird (CustomizerTestGUI::advicePDFBrief)
	//CustomizerTestGUI müssen Sie natürlich noch anpassen
}

//Dies ist die Callback-Methode (CustomizerTestGUI::advicePDFBrief), die aufgerufen wird.
//In $args stecken dabei die Parameter der Methode printGRLBM, an erster Stelle also $GRLBM
public static function advicePDFBrief($class, $args){
	$fpdf = $class;
	$Auftrag = new Auftrag($args[0]->A("AuftragID"));

	$fpdf->showBruttoPreise = $Auftrag->A("AuftragNetto");
}

Gesperrt

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste