Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Gesperrt
xmurrix
Beiträge: 3147
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Kontaktdaten:

Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von xmurrix » Fr 12. Sep 2008, 12:48

Contenido bietet mit dem CEC die Möglichkeit, um in bestimmte Prozesse einzugreifen und den eigenen Code auszuführen. Die Funktionsweise des CEC ist im InstallationPackage unter "/docs/techref/plugins/Contenido Extension Chainer.pdf" beschrieben.

Verfügbare Chains für Contenido sind der Chain-Konfigurationsdatei "/contenido/includes/config.chains.php" definiert. Jede Chain hat normalerweise einen eindeutigen Namen, aus der man ableiten kann, wo es eingesetzt wird.
Beispiel:

Code: Alles auswählen

/* Chain Contenido.Content.SaveContentEntry
 * This chain is called everytime when content is saved
 *
 * Parameters & order:
 * int      idartlang      idartlang (Article ID)
 * string   type           type (e.g. CMS_HTML)
 * int      typeid         typeid (e.g. CMS_HTML[1])
 * string   value          value for that type
 *
 * Returns:
 * string    The processed value
 */
$_cecRegistry->registerChain("Contenido.Content.SaveContentEntry", "int", "int", "int", "string");
Die Chain "Contenido.Content.SaveContentEntry" (gibt es seit Contenido 4.6.x) wird also im Contenido Backend ausgeführt, wenn ein Content Inhalt (CMS_HTML, CMS_IMG, usw.) gespeichert wird. Die an die Chainfunktionen übergebenen Parameter und die Rückgabe der Funktionen sind beschrieben.
In diesem Fall sollte eine eigene hinzugefüge Chainfunktion 4 Parameter annehmen und den letzten zurückliefern.

Such man in den Sourcen nach der Chain "Contenido.Content.SaveContentEntry", wird man in der Datei "/contenido/includes/functions.con.php" fündig - genauer in der Funktion conSaveContentEntry(), darin wird die Chain abgearbeitet.

Da fällt mir z. B. folgende Einsatzmöglichkeit ein. Das Inlinediting von Contenido ist zwar eine wunderbare Sache, generiert aber unter IE leider HTML-Code, der nicht valide ist. Das könnte man doch sehr gut mit Tidy wieder geradebiegen, Voraussetzung ist natürlich, dass Tidy HTML als PHP-Modul verfügbar und geladen ist (Das ist aber nicht bei jedem Provider der Fall).


Erstellen eines Plugins
Erstellen wir dazu z. B. ein Plugin, legen also einen Ordner "tidy_html" in "/contenido/plugins/" sowie unter "tidy_html" noch einen Ordner "includes" an.

Code: Alles auswählen

/contenido
    /plugins
        /tidy_html
            /includes
Im Ordner "includes" erstellen wir eine Datei "config.plugin.php", diese Datei wird eingebunden und initialisiert somit das "tidy_html" Plugin. Darin erstellen wir unsere Funktion, um Inhalte von CMS_HTML mit Tidy zu bereinigen.

Code: Alles auswählen

/**
 * Userdefined function, which will be added to Chain "Contenido.Content.SaveContentEntry", 
 * processes contents of Contenido CMS_HTML types.
 *
 * @param   int     $idartlang  idartlang (con_art_lang.idartlang)
 * @param   string  $type       CMS Typ (con_type.type)
 * @param   int     $typeid     Position of CMS-Type, e. g. 5 for CMS_HTML[5]
 * @param   string  $value      The value (HTML-Code)
 * @return  string  Processed value
 */
function myCmsHtmlCleanup($idartlang, $type, $typeid, $value) {
    if ($type !== 'CMS_HTML') {
        // type is not CMS_HTML, return value
        return $value;
    } elseif (trim($value) == '') {
        // empty value should not cleaned by tidy, return value
        return $value;
    }

    // some tidy options, like indentation and xhtml output
    $options = array('indent'=>true, 'output-xhtml'=>true);
    
    // do cleanup using tidy
    $value = tidy_parse_string($value, $options);
    tidy_clean_repair($value);

    // result is a full XHTML page, but we need only the content extract it...
    if (preg_match('~<body(.*)>(.*)<\/body>~Uis', $value, $match)) {
        $value = preg_replace(array('~(<body(.*)>)~Uis', '~(<\/body>)~Uis'), '', $match[0]);
        $value = trim($value);
    }
    
    // decorate value with comments to see the result
    return "\n<!-- tidy -->\n" . $value . "\n<!-- /tidy -->\n";
}
Die Funktion ist erstellt, nun müssen wird noch die Funktion der Chain "Contenido.Content.SaveContentEntry" hinzufügen. Das geht mit folgenden Zeilen in der "config.plugin.php":

Code: Alles auswählen

// get cec registry instance
$_cecRegistry = cApiCECRegistry::getInstance();

// add a function to Contenido Extension Chainer
$_cecRegistry->addChainFunction('Contenido.Content.SaveContentEntry', 'myCmsHtmlCleanup');
Somit wurde unsere Funktion der Chain hinzugefügt und kann seine Arbeit aufnehmen. Die Funktion muss bevor es der Chain hinzugefügt wird, vorher definiert werden. Sonst wird eine Warnung ausgegeben und es passiert nichts weiter. Normalerweise ist die Datei "config.plugin.php" dafür gedacht, um ein Plugin zu initialisieren, also die Konfiguration zu setzen und benötigte Sourcen einzubinden. Zusätzliche Funktionen gehören eigentlich in eine separate Datei, die am Anfang der Pluginkonfiguration eingebunden werden kann. In diesem Beispiel ist alles es der Einfachhalthalber in der Pluginkonfiguration enthalten.

Zu guter letzt sollte das nun getestet werden, dafür am besten einen Artikel im inline Editingmodus bearbeiten und speichern. Das Ergebnis im Frontend sollte ein XHML-Valider sauberer Code sein.

Die war nur ein Beispiel darüber, wie einfach eine Contenidoinstallation über Contenido Extension Chainer um eigene Features erweitert werden kann.


Das Beispiel Plugin downloaden.

Grüße
xmurrix
Zuletzt geändert von xmurrix am So 14. Sep 2008, 11:20, insgesamt 1-mal geändert.

josh
Beiträge: 156
Registriert: Do 24. Jun 2004, 09:25
Wohnort: Ahlen
Kontaktdaten:

Beitrag von josh » Sa 13. Sep 2008, 02:46

Hallo xmurrix,

eine gute Idee, ich habe tidy immer in die front_content.php eingebaut.

Ich wollte dir schon vorschlagen die Aktivierung von tidy in das mod_rewrite Plugin mit reinzunehmen. Valider Code hat ja auch was mit Suchmaschinenoptimierung zu tun.

Ich teste das mal.

Viele Grüße

josh

OliverL
Beiträge: 870
Registriert: Do 28. Jun 2007, 09:28
Kontaktdaten:

Beitrag von OliverL » Sa 13. Sep 2008, 14:38

Wieder ein schöner Beitrag für Tips & Tricks.
Da die CEC ab 4.8.6 jetzt immer mehr ergänzt werden bitte noch oberhalb die Version ergänzen ab wann die CECs dafür vorhanden sind.
Danke für den Beitrag. OliverL

nonano
Beiträge: 43
Registriert: Do 13. Apr 2006, 17:45
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von nonano » Fr 21. Mai 2010, 07:31

Hi, danke für dieses sehr schöne Plugin!

Genau das hat mir gefehlt.

Eine Frage dazu, die vllt eher die Verwendung des Extension Chainer betrifft: kann man es auch so einrichten, dass Tidy grundsätzlich beim Speichern ausgeführt wird, und nicht nur bei inline-editing?

Und noch eine Anmerkung: man kann sich das nachträgliche herausparsen des bodys auch sparen, wenn man in den Optionen angibt:

Code: Alles auswählen

        'show-body-only' => true

xmurrix
Beiträge: 3147
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von xmurrix » Fr 21. Mai 2010, 21:28

Hallo nonano,

auch im inline-editing Modus werden die eingegebenen Werte gespeichert. Falls ich mich nicht irre, behandelt das Backend beide Editiermodi gleichermaßen. Trotzdem könnte man irgendwie herausfinden, ob man sich im inline-editing Modus befindet oder nicht, und entsprechend darauf reagieren, z. B. indem man in der CEC-Funktion die Variable ohne zu ändern wieder zurückgibt.

Übrigens, danke für den Tipp mit 'show-body-only'.

Gruß
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.

nonano
Beiträge: 43
Registriert: Do 13. Apr 2006, 17:45
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von nonano » So 23. Mai 2010, 20:05

frohe Pfingsten zusammen! :)
xmurrix hat geschrieben:Falls ich mich nicht irre, behandelt das Backend beide Editiermodi gleichermaßen.
Mag sein dass meine Contenido-Instalation schon zu stark modifiziert ist, aber im Grunde denke ich schon dass Du Dich hier irrst. Zur Präzisierung meines "Problems" – oder auch als Bugreport, je nachdem:

In der functions.con.php, innerhalb der function conSaveContentEntry($idartlang, $type, $typeid, $value, $bForce = false) :

vorher:

Code: Alles auswählen

	while ($chainEntry = $iterator->next())
	{
		$value =  $chainEntry->execute($idartlang, $type, $typeid, $value);
	}
Nachher:

Code: Alles auswählen

	header("content-type: text/plain"); #TEST
	echo 'printing iterators -- $_cecRegistry->getIterator("Contenido.Content.SaveContentEntry")' ."\n\n";
	while ($chainEntry = $iterator->next())
	{
		$value =  $chainEntry->execute($idartlang, $type, $typeid, $value);
		print_r($iterator); #TEST
	}
	echo "\n\ndone";
	exit; #TEST
Das erzeugt, wenn ich im Backend unter Artikel -> Editor einen Artikeltext-Element bearbeite, indem ich einfach in den Text klicke und im daraufhin inline erscheinenden WYSIWYG-Editor Änderungen vornehme, und dann das Disketten-Symbol klicke:

Code: Alles auswählen

printing iterators -- $_cecRegistry->getIterator("Contenido.Content.SaveContentEntry")

cIterator Object
(
    [_aIteratorItems] => Array
        (
            [0] => pApiCECChainItem Object
                (
                    [_sChainName] => Contenido.Content.SaveContentEntry
                    [_sFunctionName] => myCmsHtmlCleanup
                    [_aParameters] => Array
                        (
                            [0] => Contenido.Content.SaveContentEntry
                            [1] => int
                            [2] => int
                            [3] => int
                            [4] => string
                        )

                )

        )

)


done
Also, der inline-edit Modus ist nicht das Problem.

Wähle ich aber den anderen Weg, auch im Backend, und zwar über das Blau/Weisse Bearbeiten-Stift-Icon, dann wiederum im Tiny bearbeiten und auf das grüne Häckchensymbol klicken, so erhalte ich als Ausgabe nur fogendes, ungekürzt:

Code: Alles auswählen

printing iterators -- $_cecRegistry->getIterator("Contenido.Content.SaveContentEntry")



done
also das was eh über echo ausgegeben wird.

Ich denke, da sollte dann auch der Array wie oben ausgegeben werden, oder nicht?

xmurrix
Beiträge: 3147
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von xmurrix » So 23. Mai 2010, 21:10

Hallo nonano,

vermutlich handelt es sich bei dir um das folgende Problem:
http://forum.contenido.org/viewtopic.ph ... 6&p=144582

Gruß
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.

nonano
Beiträge: 43
Registriert: Do 13. Apr 2006, 17:45
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von nonano » Mi 26. Mai 2010, 17:10

viewtopic.php?f=66&t=30326&p=144582
Hmm, ich muss gestehen, den Thread verstehe ich nicht :roll:
Naja egal, ich habe mein Zeug halt in functions.con.php mit reingehackt. Funktioniert wunschgemäß.

Mario_m
Beiträge: 90
Registriert: Sa 24. Okt 2009, 22:57
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von Mario_m » Di 27. Jul 2010, 22:25

Hab hier das Gleiche Problem. Egal wo ich die chain einbinde. Beim Speichern über TinyMCE wird die chain nicht ausgeführt. Beim Speichern über inline wird sie zwar ausgeführt aber der content nicht gespeichert. Hat jemand eine Idee?

xmurrix
Beiträge: 3147
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von xmurrix » Di 27. Jul 2010, 22:34

Öffne die Datei "contenido/includes/include.backendedit.php" und erweitere ab Zeile 73 die Zeilen

Code: Alles auswählen

i18nInit($cfg["path"]["contenido"].$cfg["path"]["locale"], $belang);
cInclude ("includes", 'cfg_language_de.inc.php');
um

Code: Alles auswählen

i18nInit($cfg["path"]["contenido"].$cfg["path"]["locale"], $belang);
cInclude ("includes", 'cfg_language_de.inc.php');
require_once $cfg['path']['contenido'] . $cfg['path']['includes'] . 'functions.includePluginConf.php';
Danach sollten beide Varianten funktionieren.

Gruß
xmurrix
CONTENIDO Downloads: CONTENIDO 4.10.1
CONTENIDO Links: Dokumentationsportal, FAQ, API-Dokumentation
CONTENIDO @ Github: CONTENIDO 4.10 - Mit einem Entwicklungszweig (develop-branch), das viele Verbesserungen/Optimierungen erhalten hat und auf Stabilität und Kompatibilität mit PHP 8.0 bis 8.2 getrimmt wurde.

Mario_m
Beiträge: 90
Registriert: Sa 24. Okt 2009, 22:57
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von Mario_m » Mi 28. Jul 2010, 23:11

Hallo xmurrix,

Hab die Zeilen in der Datei geändert, hat sich nichts geändert.

Oldperl
Beiträge: 4254
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von Oldperl » Do 29. Jul 2010, 08:56

Hallo Mario_m,

welche Contenido Version nutzt du?

Gruß aus Franken

Ortwin
ConLite 2.1, alternatives und stabiles Update von Contenido 4.8.x unter PHP 7.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog

Mario_m
Beiträge: 90
Registriert: Sa 24. Okt 2009, 22:57
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von Mario_m » Do 29. Jul 2010, 22:44

Hallo Ortwin,

ich nutze die Version 4.8.12

Gruss

Mario

Mario_m
Beiträge: 90
Registriert: Sa 24. Okt 2009, 22:57
Kontaktdaten:

Re: Contenido Extension Chainer Beispiel - Plugin Tidy HTML

Beitrag von Mario_m » So 1. Aug 2010, 22:50

Eigentlich ist das bei mir so wie von nonano beschrieben, nur mit der Ergänzung, dass die include.backendedit.php auch bereits beim Öffnen von Tiny durchlaufen wird, was beim inline Editing nicht der Fall ist, dort wird sie offensichtlich garnicht durchlaufen. Die Testausgabe in der Datei liefert zumindest im inline Mode nichts zurück. Dafür wird aber auch der Inhalt nicht gespeichert, im Tiny schon.

Gesperrt