Frage zu Chains und Hooks

Alles rund um Module und Plugins in CONTENIDO 4.9.
xmurrix
Beiträge: 2928
Registriert: Do 21. Okt 2004, 11:08
Wohnort: Augsburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 14:03

Hallo Viktor,
homtata hat geschrieben:
Fr 23. Okt 2020, 13:24
...der vorgeschlagene Weg mit CREATE_SUCCESS funktioniert nicht. Offensichtlich bekomme ich zwar die (zukünftige) idartlang zurück damit, ABER der Artikel ist zum Zeitpunkt, wo der Callback abgearbeitet wird, noch gar nicht in der Datenbank angelegt..
ich habe mir nochmal die Stelle genauer angesehen. Die Callback-Funktion für CREATE_SUCCESS geht leider nicht, da es an der Art und Weise liegt, wie Datensätze in CONTENIDO per GenericDB angelegt werden.

Wenn man mit den cApi* Klassen einen neuen Datensatz anlegt, erstellt die GenericDB Klasse zuerst einen leeren Datensatz in der Datenbank. Da gibt es nur die ID, sonst keine weiteren Werte für die anderen Felder des Datensatzes, außer Default-Werte. Danach aktualisiert die GenericDB Klasse die Felder und speichert den Datensatz erneut.
Was also funktionieren würde, ist die Verwendung der Callback-Funktion für STORE_SUCCESS:

Code: Alles auswählen

cGenericDb::register(cGenericDb::STORE_SUCCESS, 'myNewArticleLanguageSucessCallback', 'cApiArticleLanguage');
Einen Nachteil gibt es. Die Callback-Funktion für STORE_SUCCESS wird halt immer ausgeführt, wenn der Datensatz gespeichert wird. Aber hier kannst du prüfen, ob das Feld 'created', also $artLang->get('created') sehr nah oder identisch mit der aktuellen Zeit ist. So weißt du, dass der Datensatz aktualisiert wurde, kurz nach dem es erstellt wurde.

Eigentlich sollte man in CONTENIDO das Verhalten beim Erstellen von Datensätzen umstellen. Die jetzige Vorgehensweise hat vermutlich historische Gründe und ist nicht mehr zeitgemäß. Aber das ist ein anderes Thema...
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:02

xmurrix hat geschrieben:
Fr 23. Okt 2020, 11:47
Faar hat geschrieben:
Fr 23. Okt 2020, 11:39
wäre der Hook "Contenido.Article.AfterCreation" hier nicht genau der richtige?
Gibt es denn in CONTENIDO eine Chain mit dem Namen "Contenido.Article.AfterCreation"?
Ok, hab mich verschrieben, so heißt sie: Contenido.Content.AfterStore
https://docs.contenido.org/display/CONDEVE/Chain

Nun frage ich mich, müssen diese Parameter angegeben werden oder kann man die dort abholen?
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:03

homtata hat geschrieben:
Fr 23. Okt 2020, 13:25
den Hook "Contenido.Article.AfterCreation" gibts nicht.
Aber den: Contenido.Content.AfterStore
https://docs.contenido.org/display/CONDEVE/Chain
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 15:19

Faar hat geschrieben:
Fr 23. Okt 2020, 15:02
Nun frage ich mich, müssen diese Parameter angegeben werden oder kann man die dort abholen?
Mit der Chain 'Contenido.Content.AfterStore' sollte es auch gehen. Callback-Funktionen bekommen mehrere Parameter, siehe Ende der Funktion conMakeArticleIndex() in contenido/includes/functions.con.php.
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:33

xmurrix hat geschrieben:
Fr 23. Okt 2020, 15:19
Callback-Funktionen bekommen mehrere Parameter, siehe Ende der Funktion conMakeArticleIndex() in contenido/includes/functions.con.php.
Da verstehe ich die Logik nicht.
Diese Funktion benötigt als Parameter eben genau diese $idartlang, die ja gesucht wird.
So wie ich Viktor verstanden habe, sucht er ja genau diese Parameter und in die Funktion müsste man die doch schon mit übergeben?
Er schrieb, dass ein Artikel gespeichert wurde und er nun die Parameter des Artikels benötigt.
Da braucht es eine Funktion, die sucht, welcher Artikel wurde zuletzt gespeichert und sich davon die Parameter holt.

Was genau macht die Contenido.Content.AfterStore ?
Muss ich da die Parameter eingeben oder bekomme ich die?
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:44

Ist es sowas, was Viktor sucht?

Code: Alles auswählen

    protected function _getIdArtLang($idart, $idlang) {
        global $cfg;

        $sql = 'SELECT idartlang FROM `%s` WHERE idart = %d AND idlang = %d';
        $this->db->query($sql, $cfg['tab']['art_lang'], $idart, $idlang);
        $this->db->nextRecord();

        return $this->db->f('idartlang');
    }
Das ist leider eine protected Function in der Class.articlelanguage.php aber man kann die Datenbankabfrage vielleicht auch ins Plugin einbauen.
Man muss hier nur noch Artikel-ID und die Sprach-ID wissen.
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 15:45

Faar hat geschrieben:
Fr 23. Okt 2020, 15:33
xmurrix hat geschrieben:
Fr 23. Okt 2020, 15:19
Callback-Funktionen bekommen mehrere Parameter, siehe Ende der Funktion conMakeArticleIndex() in contenido/includes/functions.con.php.
Da verstehe ich die Logik nicht.
Diese Funktion benötigt als Parameter eben genau diese $idartlang, die ja gesucht wird.
So wie ich Viktor verstanden habe, sucht er ja genau diese Parameter und in die Funktion müsste man die doch schon mit übergeben?
Er schrieb, dass ein Artikel gespeichert wurde und er nun die Parameter des Artikels benötigt.
Da braucht es eine Funktion, die sucht, welcher Artikel wurde zuletzt gespeichert und sich davon die Parameter holt.

Was genau macht die Contenido.Content.AfterStore ?
Muss ich da die Parameter eingeben oder bekomme ich die?
Ich habe es falsch ausgedrückt, die Callback-Funktionen bekommen immer die Parameter, die übergeben werden. Im Fall von 'Contenido.Content.AfterStore' ist es ein Array, siehe den Code:

Code: Alles auswählen

    // build data structure expected by handlers of Contenido.Content.AfterStore
    $articleIds = array(
        'idclient' => $idclient,
        'idlang' => $idlang,
        'idcat' => $idcat,
        'idcatlang' => $idcatlang,
        'idart' => $idart,
        'idartlang' => $idartlang
    );

    // iterate chain Contenido.Content.AfterStore
    $iterator = cRegistry::getCecRegistry()->getIterator('Contenido.Content.AfterStore');
    while (false !== $chainEntry = $iterator->next()) {
        $chainEntry->execute($articleIds); // <- Hier wird der Parameter an die Callback-Funktion übergeben, ein assoziatives Array.
    }
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 15:46

Faar hat geschrieben:
Fr 23. Okt 2020, 15:44
Ist es sowas, was Viktor sucht?

Code: Alles auswählen

    protected function _getIdArtLang($idart, $idlang) {
        global $cfg;

        $sql = 'SELECT idartlang FROM `%s` WHERE idart = %d AND idlang = %d';
        $this->db->query($sql, $cfg['tab']['art_lang'], $idart, $idlang);
        $this->db->nextRecord();

        return $this->db->f('idartlang');
    }
Das ist leider eine protected Function in der Class.articlelanguage.php aber man kann die Datenbankabfrage vielleicht auch ins Plugin einbauen.
Man muss hier nur noch Artikel-ID und die Sprach-ID wissen.
Nein, das ist ganz was anderes.
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:56

xmurrix hat geschrieben:
Do 22. Okt 2020, 20:56
Immer, wenn ein neuer Artikel erstellt wird, wird auch die registrierte Callback-Funktion ausgeführt. Dieses Feature gibt es schon ziemlich lange (seit CONTENIDO 4.9), es ist aber nicht bekannt.
Mit den Generic DB Callbacks kann man so ziemlich auf alle Änderungen in der Datenbank reagieren, sofern diese Änderungen durch die Verwendung der cApi* Klassen stattfinden.
Ist das nicht dokumentiert?
Es klingt sehr interressant und nützlich.
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

Faar
Beiträge: 1652
Registriert: Sa 8. Sep 2007, 16:23
Wohnort: Brandenburg
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von Faar » Fr 23. Okt 2020, 15:58

xmurrix hat geschrieben:
Fr 23. Okt 2020, 15:46
Nein, das ist ganz was anderes.
Mir scheint, dass es noch gar keine Funktion gibt, die einem die Daten des zuletzt erzeugten Artikels gibt?
Wenn ich die Artikel ID weiß, kann ich ja mit bestehenden cAPI Funktionen den Rest holen.
Aber ohne die ID komme ich nicht so einfach an den zuletzt eingetragenen Artikel dran, stimmts?
Fliegt der Bauer übers Dach, ist der Wind weißgott nicht schwach.

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 16:22

Faar hat geschrieben:
Fr 23. Okt 2020, 15:56
Ist das nicht dokumentiert?
Es klingt sehr interressant und nützlich.
Die einzige Doku ist folgende:
https://docs.contenido.org/display/COND ... +callbacks
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 16:28

Faar hat geschrieben:
Fr 23. Okt 2020, 15:58
Mir scheint, dass es noch gar keine Funktion gibt, die einem die Daten des zuletzt erzeugten Artikels gibt?
Wenn ich die Artikel ID weiß, kann ich ja mit bestehenden cAPI Funktionen den Rest holen.
Aber ohne die ID komme ich nicht so einfach an den zuletzt eingetragenen Artikel dran, stimmts?
Es gibt keine Funktion, die die Daten des zuletzt erzeugten Artikels liefert.
  • Die Chain 'Contenido.Content.AfterStore' übergibt eine assoziative Liste mit ein paar Werten, da kann man den Rest mit der cApi* Klasse holen
  • Der GenericDB Callback CREATE_SUCCESS übergibt die Id, aber alle anderen Werte des Datensatzes sind noch nicht gesetzt, daher hilft hier auch nicht die cApi* Klasse
  • Der GenericDB Callback STORE_SUCCESS liefert die Id, den Rest kann man dann mit der cApi* Klasse holen
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

homtata
Beiträge: 1094
Registriert: Mi 14. Jan 2004, 14:41
Kontaktdaten:

Re: Frage zu Chains und Hooks

Beitrag von homtata » Fr 23. Okt 2020, 20:05

Also, ich versuchs mal laienhaft auszudrücken: die Hooks übergeben schon immer ein Array an die Callbackfunktion, aber halt nie das gleiche - das hab ich anfangs nicht verstanden. Der Hook Contenido.Content.AfterStore übergibt sogar unterschiedliche Arrays, je nachdem ob ein Content-Container gespeichert wurde oder ob der Artikel bei "Eigenschaften" gespeichert wurde. Die CallbackFunktion wird ja ohne Parameter aufgerufen, die Übergabe findet automatisch statt - dennoch muss natürlich bei der erwartenden Funktion ein Parameter definiert sein.

Beispiel: die Chain wird so gebaut, dass die Funktion im Callbackteil ohne Funktionsklammern oder Übergabewert aufgerufen wird:

Code: Alles auswählen

$_cecRegistry->addChainFunction('Contenido.Article.ConMakeOnline', 'FullsearchCollection::handleStoringOfContentEntry');
Dennoch übergibt Contenido.Article.ConMakeOnline einen Wert, in unserem Fall ein Array. Auf der Gegenstelle gibt es daher besagte Funktion, die einen Parameter erwarten muss, also:

Code: Alles auswählen

public function handleStoringofContentEntry ( $uebergabewert) { }
So. Und nun habe ich mir einfach bei jeder Aktion diesen Übergabewert per var_dump zeigen lassen, bis ich kapiert hatte, dass ich jedesmal etwas anderes kriege und die Funktion so schreiben muss, dass aus den Dingern, die da kommen, ich mir immer meine 6 gleichen Werte berechne, die ich dann benötige, um den Artikel in meiner Vollsuche korrekt anzulegen.

Und als ich das verstanden hatte, ging mit AfterStore natürlich viel - ich musste nur ständig das Übergabearray auf die für mich nötigen Werte umbiegen.

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

Re: Frage zu Chains und Hooks

Beitrag von xmurrix » Fr 23. Okt 2020, 22:13

homtata hat geschrieben:
Fr 23. Okt 2020, 20:05
...die Hooks übergeben schon immer ein Array an die Callbackfunktion, aber halt nie das gleiche...
Der Aufruf der CEC Hooks übergibt nicht immer eine Liste an die Callback-Funktionen.

Früher gab es in CONTENIDO eine config.chains.php, in der alle vorhandenen Chains registriert und dokumentiert waren, so konnte man an einer Stelle sehen, welche Parameter die Callback-Funktionen bekommen. Irgendwann in CONTENIDO 4.9 ist die Datei config.chains.php als veraltet markiert, es wird nicht mehr verwendet.

Um herauszufinden, welche Parameter an die Callback-Funktionen übergeben werden, sollte man die Chain Doku-Seite dazu ansehen, sicherheitshalber die Stelle im Sourcecode, in die CEC Hook ausgeführt wird, da die Doku-Seite vielleicht nicht auf dem neuesten Stand ist.

Hier einige Beispiele:

Aufruf von 'Contenido.Frontend.AfterLoadPlugins', übergibt keine Parameter

Code: Alles auswählen

cApiCecHook::execute('Contenido.Frontend.AfterLoadPlugins');

// Callback-Funktion kann so implementiert werden
function myAfterLoadPluginsCallback() {
    // ...
}
Aufruf von 'Contenido.Frontend.AllowEdit', übergibt vier Parameter

Code: Alles auswählen

$allow = cApiCecHook::executeWhileBreakCondition('Contenido.Frontend.AllowEdit', $lang, $idcat, $idart, $auth->auth['uid']);

// Callback-Funktion kann so implementiert werden
function myAllowEditCallback($lang, $idcat, $idart, $authUid) {
    // ...
}
Aufruf von 'Contenido.Article.ConMakeOnline', übergibt einen Parameter (assoziative Liste)

Code: Alles auswählen

cApiCecHook::execute('Contenido.Article.ConMakeOnline', array(
    'idart' => $idart,
    'idlang' => $lang,
    'state' => $online
));

// Callback-Funktion kann so implementiert werden
function myConMakeOnlineCallback(array $data) {
    // ...
}
homtata hat geschrieben:
Fr 23. Okt 2020, 20:05
...Der Hook Contenido.Content.AfterStore übergibt sogar unterschiedliche Arrays, je nachdem ob ein Content-Container gespeichert wurde oder ob der Artikel bei "Eigenschaften" gespeichert wurde...
Die Hook für 'Contenido.Content.AfterStore' wird in CONTENIDO an einer einzigen Stele ausgeführt und da sieht der Code so aus:

Code: Alles auswählen

    $articleIds = array(
        'idclient' => $idclient,
        'idlang' => $idlang,
        'idcat' => $idcat,
        'idcatlang' => $idcatlang,
        'idart' => $idart,
        'idartlang' => $idartlang
    );

    // iterate chain Contenido.Content.AfterStore
    $iterator = cRegistry::getCecRegistry()->getIterator('Contenido.Content.AfterStore');
    while (false !== $chainEntry = $iterator->next()) {
        $chainEntry->execute($articleIds);
    }
Die Callback-Funktionen bekommen hier also immer eine assoziative Liste, die Werte darin können mit denen im globalen Kontext übereinstimmen, das müssen sie aber nicht.
CONTENIDO downloads: CONTENIDO 4.10.1
CONTENIDO links: Documentation, API documentation
CONTENIDO @ Github: CONTENIDO 4.10

Antworten