Contao-Summit 2026
Ergebnis 1 bis 15 von 15

Thema: Contao via SSH mit KI-Agenten steuern — contao-ai-cli + contao-ai-core-bundle

  1. #1
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    HTML Contao via SSH mit KI-Agenten steuern — contao-ai-cli + contao-ai-core-bundle

    Ich habe zwei Pakete veröffentlicht, die Contao 5 für KI-Agenten (z.B. Claude Code) zugänglich machen:

    contao-ai-core-bundle — ein Contao-Bundle das CMS-Operationen als Symfony-Console-Commands bereitstellt: CRUD für Seiten, Artikel, Content-Elemente, News, Events, FAQs, Member, User, Files, Templates und Versionsverwaltung.
    https://github.com/webwerkwien/contao-ai-core-bundle

    contao-ai-cli — ein Python-CLI das sich per SSH mit der Contao-Installation verbindet und diese Commands für KI-Agenten zugänglich macht. Daneben auch direkt im Terminal nutzbar. Es kann alleine genutzt werden, hat aber mit dem obigen Paket weit mehr Funktionen.
    https://github.com/webwerkwien/contao-ai-cli

    Beide (KI-generierte) Pakete sind noch früh in der Entwicklung — produktiv eingesetzt habe ich sie bisher kaum, Feedback aus der Praxis ist daher sehr willkommen. Bisherige Tests haben sich vorwiegend auf Sicherheit und Code-Qualität beschränkt. Nicht in aktiven Websites nutzen. Die Anwendung ist nicht für Redakteure gedacht, für solche wird es ein Backend-Modul geben.

    Ich freue mich über Erfahrungsberichte und natürlich Issues auf GitHub.

  2. #2
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard Update: contao-ai-backend-bundle ist da + neue Macro-Engine im Core

    Kurzes Update zu der Pakete-Familie:

    contao-ai-backend-bundle ist jetzt veröffentlicht (v0.1.0, public): https://github.com/webwerkwien/contao-ai-backend-bundle

    Das ist das Backend-Modul, das ich oben angekündigt hatte — KI-Agent direkt im Contao-Backend, ohne SSH und ohne CLI. Editoren chatten im Browser mit Claude (oder GPT), der Agent kann lesen und schreiben mit denselben Permission-Checks wie ein normaler Backend-User. Jeder Backend-User trägt seinen eigenen API-Key (Anthropic oder OpenAI) ein, das Bundle bringt keinen mit.
    Code:
    composer require webwerkwien/contao-ai-backend-bundle
    contao-ai-core-bundle ist auf v0.2.0 gewachsen — neue Macro-Commands für Bulk-Operationen:

    contao:record:clone — News-Archive, Calendar, FAQ-Kategorie oder ganzen Seitenbaum mit allen Kindern in einer DB-Transaktion klonen
    contao:record:list — tabellenagnostisches Listing mit Filtern, Pagination, sauberen Default-Spalten
    contao-ai-cli ist auf v0.3.2 — neue bridge- und health-Befehle:

    contao-ai-cli bridge rewrite --table tl_news_archive --id 5 --recursive --instructions "..." ruft die Macros direkt im Backend-Bundle über HTTPS auf, der LLM-Loop läuft serverseitig. Praktisch für „alle 50 News auf Englisch" ohne Browser-Wechsel.
    contao-ai-cli health zeigt CLI-, Core- und Bridge-Stand auf einen Blick.
    Auth für die Bridge läuft über einen separaten Token, den jeder Backend-User in seinem Profil generieren kann (Hash-Storage, einmaliger Klartext-Anzeige). Editoren bleiben damit im Browser-Chat, Admins/Devs bleiben im Terminal.

    Status weiterhin Beta — in Produktivumgebungen weiter mit Vorsicht nutzen. Über Praxis-Feedback und GitHub-Issues freue ich mich.

  3. #3
    Contao-Urgestein Avatar von jan.theofel
    Registriert seit
    23.06.2009.
    Ort
    Berlin
    Beiträge
    1.857

    Standard

    Hi!

    Danke für die Extension!

    Ich versuche damit gerade für eine Migration zu nutzen. Abner ich scheitere bei den Bildern. Wenn ich ein Bild mittels contao:file:write einspiele und mittels contao:filesync n och synchronisiere. Woher bekomme ich dann die UUID um das Bild auch als Content-Element einfügen zu können?

    Danke
    Jan
    Jan Theofel
    Barcamp-Moderator für Corporate-Barcamps und öffentliche Barcamps

  4. #4
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Servus! Das ist jetzt mit v0.2.1 (gerade veröffentlicht) gelöst — composer update webwerkwien/contao-ai-core-bundle (bzw. über die contao-ai-cli), dann:

    1. contao:file:write gibt jetzt die UUID zurück und synchronisiert die Datei direkt in die DBAFS — ein separates contao:filesync brauchst du dafür nicht mehr:

    Code:
    {"status":"ok","path":"files/dein/bild.jpg","bytes":12345,"version":false,"uuid":"c8045c91-8865-11f1-ba75-525400338fcc"}
    2. Diese UUID kannst du direkt in singleSRC setzen — content:create/content:update wandeln String-UUIDs jetzt automatisch in Contaos binäre Speicherform um (gilt für alle fileTree-Felder, also auch multiSRC):

    Code:
    contao:content:create --type=image --pid=<artikel-id> --set="singleSRC=c8045c91-8865-11f1-ba75-525400338fcc"
    Das Bild-Element referenziert die Datei danach korrekt — identisch zu einem im Backend angelegten Element.

    Nebenbei steckte in content:create noch ein Bug: invisible wurde als leerer String gesetzt, was unter striktem SQL-Modus (MariaDB) jedes Anlegen abbrechen ließ — ebenfalls in v0.2.1 behoben.

    Danke fürs Melden — hat direkt zwei Verbesserungen ausgelöst! Liebe Grüße!

  5. #5
    Contao-Urgestein Avatar von jan.theofel
    Registriert seit
    23.06.2009.
    Ort
    Berlin
    Beiträge
    1.857

    Standard

    Zitat Zitat von Creasign Beitrag anzeigen
    Servus! Das ist jetzt mit v0.2.1 (gerade veröffentlicht) gelöst

    Danke! Für diese Migration habe ich einen Workaround geschaffen und alle Bilder importiert und dan die UUID aus der Datenbank ausgelesen. Für die nächste Runde hilft das aber auf jeden Fall!
    Jan Theofel
    Barcamp-Moderator für Corporate-Barcamps und öffentliche Barcamps

  6. #6
    Contao-Urgestein Avatar von jan.theofel
    Registriert seit
    23.06.2009.
    Ort
    Berlin
    Beiträge
    1.857

    Standard

    Ich habe noch eine andere Stelle, die ich nicht in den Griff bekomme und auch keinen Workaroudn finde:
    Wie setze ich bei Content-Elementen neben der Überschrift set='headline=Foobar' auch die Überschriftenordnung h1-h6?
    Da das so ein kombiniertes Feld ist, finde ich da noch keinen Weg für.
    Jan Theofel
    Barcamp-Moderator für Corporate-Barcamps und öffentliche Barcamps

  7. #7
    Wandelndes Contao-Lexikon Avatar von zonky
    Registriert seit
    19.03.2010.
    Ort
    Berlin, Rdf
    Beiträge
    10.586
    User beschenken
    Wunschliste

    Standard

    guck dir mal einen Original-Datensatz an - serialisiertes Feld

  8. #8
    Contao-Urgestein Avatar von jan.theofel
    Registriert seit
    23.06.2009.
    Ort
    Berlin
    Beiträge
    1.857

    Standard

    Zitat Zitat von zonky Beitrag anzeigen
    guck dir mal einen Original-Datensatz an - serialisiertes Feld
    Habe ich. Aber das kann ich dem Feld nicht also solches über die CLI übergeben.

    PHP-Code:
    php bin/console contao:content:create   --pid=177   --type=text   --operator=serialize   --set='headline={"unit":"h1","value":"Test"}'   --set='text=<p>Testinhalt</p>'   --set='published=1'   --set='invisible=0' 
    führt nur dazu, dass in dem Überschriftenfeld
    {"unit":"h1","value":"Test"}
    drin steht...
    Jan Theofel
    Barcamp-Moderator für Corporate-Barcamps und öffentliche Barcamps

  9. #9
    Contao-Urgestein Avatar von jan.theofel
    Registriert seit
    23.06.2009.
    Ort
    Berlin
    Beiträge
    1.857

    Standard

    Zitat Zitat von Creasign Beitrag anzeigen
    Kurzes Update zu der Pakete-Familie:
    Vorschlag für das nächste Update:
    In vendor/webwerkwien/contao-ai-core-bundle/src/Command/ContentCreateCommand.php folgende Anpassung ab Zeile 46:

    PHP-Code:
            // if (\array_key_exists('headline', $fields) && \is_string($fields['headline'])) {
            //    $fields['headline'] = serialize(['unit' => 'h2', 'value' => $fields['headline']]);
            //}
            
    if (\array_key_exists('headline'$fields) && \is_string($fields['headline'])) {
              
    $unit $fields['headline_unit'] ?? 'h2';
              unset(
    $fields['headline_unit']);
              
    $fields['headline'] = serialize(['unit' => $unit'value' => $fields['headline']]);
            } 
    Dann geht das per CLI mittels:

    Code:
    php bin/console contao:content:create \
      --pid=177 \
      --type=text \
      --set="headline=Testüberschrift mit H1" \
      --set="headline_unit=h1" \
      --set="text=<p>Testinhalt</p>" \
      --set="published=1" \
      --set="invisible=0"
    Oder ein allgemeiner Weg um serialisierte Inhalte angeben zu können. Das ist ja nicht die einzige Stelle, die davon betroffen ist.
    Jan Theofel
    Barcamp-Moderator für Corporate-Barcamps und öffentliche Barcamps

  10. #10
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Servus Jan! Umgesetzt in v0.2.3. Deine Idee mit dem Begleitfeld wurde aufgegriffen und gleich generisch für alle inputUnit-Felder gebaut (also auch News).

    Code:
    php bin/console contao:content:create \
      --pid=177 --type=text \
      --set="headline=Testüberschrift mit H1" \
      --set="headline_unit=h1" \
      --set="text=<p>Testinhalt</p>" \
      --set="published=1" --set="invisible=0"
    Das <feld>_unit-Begleitfeld steuert die Ordnung (validiert gegen h1–h6; ohne Angabe Default h2 bei Content, h1 bei News). Alternativ geht der Wert auch direkt als JSON:

    Code:
    --set='headline={"unit":"h1","value":"Testüberschrift"}'
    Beides gilt für content:create/content:update und news:*; bei einem Update bleibt eine vorhandene Unit erhalten, wenn du nur den Text änderst. news:create hat zusätzlich eine --unit-Option.

    Info zu #8: --operator ist der Audit-/Benutzer-Kontext fürs Versioning, keine Serialisierungs-Option. Die brauchst du hier nicht.

    Danke für den konkreten Vorschlag, das hat die Umsetzung beschleunigt!

  11. #11
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Hallo!

    Ich muss meine Antwort aus Beitrag #10 korrigieren — für News war sie leider falsch.

    tl_news.headline ist kein inputUnit-Feld, sondern ein reines Textfeld — es ist der
    News-Titel. Contaos DCA im news-bundle:

    Code:
    'headline' => array(
        'inputType' => 'text',
        'eval'      => array('mandatory'=>true, 'maxlength'=>255, ...),
        'sql'       => "varchar(255) NOT NULL default ''"
    ),
    Contao liest den Wert unverändert (NewsFeedListener, InsertTag news_title). Ein
    serialisiertes {value,unit} landet dort also 1:1 als Titel — im Backend-Listing, im
    Feed und im Frontend steht dann a:2:{s:5:"value";...}.

    Betroffen ist alles, was mit contao:news:create bis v0.2.3 angelegt wurde,
    inklusive der --unit-Option aus #10.

    Behoben in v0.2.4:
    - news:create schreibt Klartext, --unit ist entfallen
    - news:read gibt den Wert roh zurück (die Deserialisierung hatte den Fehler maskiert)
    - neuer Reparatur-Command für Altbestände:

    Code:
    composer update webwerkwien/contao-ai-core-bundle
    php bin/console contao:news:repair-headlines --dry-run
    php bin/console contao:news:repair-headlines
    Der Command entpackt serialisierte Headlines zum reinen Titel, ist idempotent und
    lässt alles unangetastet, was kein {value,unit}-Payload ist. --dry-run zeigt vorab,
    was sich ändern würde.

    Für Content-Elemente bleibt alles wie in #10 beschrieben — tl_content.headline
    ist tatsächlich ein inputUnit-Feld:

    Code:
    php bin/console contao:content:create \
      --pid=177 --type=text \
      --set="headline=Testüberschrift mit H1" \
      --set="headline_unit=h1" \
      --set="text=<p>Testinhalt</p>" \
      --set="published=1" --set="invisible=0"

    Liebe Grüße!

  12. #12
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard Update zur Paketfamilie

    Servus! Kurzes Update zur Paketfamilie — die vergangene Woche hat einiges gebracht.


    contao-ai-core-bundle — v0.2.7 -> v0.2.16

    • record:clone hat jeden tinyint-Wert auf 1 gekappt (v0.2.15). Alle vier Cloner betroffen, also auch News, Events und FAQ — und das bei status: ok. Dazu unten mehr.
    • Löschen kaskadiert jetzt und landet als ein Eintrag im Papierkorb (v0.2.8/v0.2.9). Vorher blieben Kinddatensätze als Waisen zurück.
    • unpublish schrieb '' in eine tinyint-Spalte und flog auf Servern mit striktem SQL-Modus (v0.2.10).
    • Schreibzugriffe tauchten nie im Systemlog auf (v0.2.11–v0.2.13). Jetzt eine Zeile je Vorgang unter System ? Systemlog, Herkunft "Kommandozeile" (v0.2.14).
    • --operator wirkt auch bei version:restore und template:write, damit die Zuordnung stimmt (v0.2.14).
    • Datei-Referenzen (fileTree) kamen beim Lesen als Zeichensalat statt als UUID zurück (v0.2.15).
    • Neu: --ids für Massenänderungen; published und hide sind beim Klonen überschreibbar (v0.2.15).


    Wer schon geklont hat, sollte nachzählen — sinngemäß für eigene Zahlenfelder:

    Code:
    SELECT COUNT(*) FROM tl_page WHERE mein_zahlenfeld > 1;
    Steht dort 0, obwohl es größere Werte geben müsste, sind sie gekappt. Die Versionshistorie der Quelldatensätze hat sie noch.

    Der Merksatz dahinter: tinyint ist in Contao der Ja/Nein-Typ — Doctrine mappt es auf boolean, unabhängig von der Längenangabe. Für Zahlen also smallint(5) unsigned nehmen, so macht es die Core-DCA auch.


    contao-ai-cli — v0.4.1 -> v0.6.0

    • 15 fehlende Schreibbefehle ergänzt (v0.5.0): update und delete für Seiten, Artikel, Inhalte, News, Events und FAQ, dazu page publish.
    • --ids und --ids-from-file auf allen Update-Befehlen (v0.6.0). Ein Feld auf 174 Seiten zu setzen dauerte vorher rund vier Minuten — 1,4 s je Datensatz, davon 0,67 s reiner Verbindungsaufbau. Jetzt eine Verbindung, aber weiterhin eine eigene Version je Datensatz.
    • connect nutzt auf Managed Editions den Composer-Passthrough des Contao Managers, statt allow-plugins in die Projekt-composer.json zu schreiben (v0.4.2).
    • Das Selbstupdate meldete Erfolg, ohne je etwas zu tun (v0.4.3).
    • Der REPL startete nur auf einer Konsole in UTF-8 (v0.4.4). Und jeder Befehl stürzte ab, sobald ein Datensatz ein Zeichen außerhalb von cp1252 enthielt (v0.6.0).
    • health unterscheidet jetzt "Bundle fehlt" von "nicht konfiguriert" (v0.5.1), schlägt keine Downgrades mehr vor (v0.5.2) und nennt die Contao-Version des Ziels (v0.6.0).


    Für --ids braucht es core-bundle v0.2.15 auf dem Ziel.


    contao-ai-backend-bundle — v0.1.3 -> v0.1.5

    • Der Systemlog-Eintrag eines Tool-Aufrufs sagte nicht, welches Tool lief — drei fast gleiche Zeilen je Chat-Runde (v0.1.4).
    • Die Beschreibung des record_clone-Tools behauptete, nicht erlaubte Felder würden stillschweigend verworfen (v0.1.5). Seit v0.2.15 kommen sie als ignored_modifications zurück — und eine Tool-Beschreibung ist das, woraus das Modell seine Schlüsse zieht.



    Update wie gewohnt:

    Code:
    composer update webwerkwien/contao-ai-core-bundle
    composer update webwerkwien/contao-ai-backend-bundle
    pipx install --force git+https://github.com/webwerkwien/contao-ai-cli.git@v0.6.0
    Liebe Grüße!

  13. #13
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Servus! Größeres Update — das Backend-Menü ist jetzt durchgehend schreibbar.
    core-bundle v0.2.16 -> v0.2.27, CLI v0.6.0 -> v0.8.7.

    Bisher konnte die Paketfamilie Seiten, Artikel, Inhalte, News, Events und FAQ
    bearbeiten. Alles andere im Backend war lesbar, aber nicht änderbar — Theme-Ebene,
    Rechte, Einstellungen, Papierkorb, die Elterntabellen, Formulargenerator und
    Newsletter. Das ist jetzt geschlossen.

    Dazu record list und record schema für jede Tabelle mit einer DCA, auch aus
    Erweiterungen. Tabelle, Spalten, Filter und Sortierung werden serverseitig
    geprüft — einen Spaltennamen zu raten ist also gefahrlos, es scheitert laut
    statt still.

    Zwei Dinge zum Nachsehen

    1. contao:dca:schema gab bei Auswahlfeldern die falschen Werte zurück
    (behoben in v0.2.21). Statt der Optionswerte kamen die Array-Indizes:

    Code:
    tl_page.sitemap  ->  [0, 1, 2]
    deklariert ist    ->  map_default, map_always, map_never
    Betroffen waren 63 von 66 Optionslisten im Kern. Wer sich auf dca:schema verlassen hat, um gültige Werte zu ermitteln, sollte
    die betroffenen Stellen einmal nachsehen.

    2. Ein --set mit einem Feldnamen, den es nicht gibt, wird jetzt abgewiesen
    (v0.2.27). Vorher kam:

    Code:
    --set gibtesnicht=1  ->  {"status":"ok","updated":["gibtesnicht"]}
    Geschrieben wurde nichts. Contao verwirft beim Speichern, was keine Spalte ist —
    gemeldet wurde trotzdem Erfolg. Ein Tippfehler im Feldnamen las sich damit als
    erfolgreiche Änderung.

    Der Newsletter verschickt nicht — mit Absicht

    newsletter send gibt es als Befehl, und er lehnt immer ab. Zwei Gründe:

    Contaos Versand ist an den Browser gebunden. Jeder Zyklus endet mit einem
    JavaScript-Timer, der das nächste Paket nachlädt — das Handbuch sagt
    ausdrücklich, man dürfe das Fenster nicht schließen. Es gibt also nichts, was
    sich an eine Konsole durchreichen ließe. Und eine verschickte Mail holt kein
    Backup zurück.

    Wichtig für alle, die auf die Idee kommen könnten, das über die Datenbank
    abzukürzen: tl_newsletter.sent auf 1 zu setzen verschickt nichts. Es
    markiert den Newsletter als versendet und veröffentlicht ihn im Frontend-Archiv,
    weil der Reader genau auf dieses Feld filtert. Das Bundle weist Schreibzugriffe
    auf sent und date deshalb ab.

    Anlegen, Ändern und Löschen von Kanälen, Newslettern und Empfängern geht
    vollständig. Empfänger folgen dabei den Regeln von Contaos eigenem CSV-Import:
    gültige Adresse, keine Dublette im Kanal, und nicht auf der Sperrliste des
    Kanals. Wer über die CLI anlegt, muss das Aktivieren ausdrücklich angeben —
    Double Opt-in schützt die Selbstanmeldung im Frontend, nicht die Tabelle, und
    die Einwilligung liegt damit beim Betreiber.

    Dazu eine Reihe weiterer Bugfixes in beiden Paketen — Details in den CHANGELOGs.

    Update wie gewohnt

    Code:
    composer update webwerkwien/contao-ai-core-bundle
    pipx install --force git+https://github.com/webwerkwien/contao-ai-cli.git@v0.8.7
    Die CLI setzt für die neuen Gruppen core-bundle v0.2.27 auf dem Ziel voraus.
    contao-ai-backend-bundle ist unverändert bei v0.1.5.

    Liebe Grüße!

  14. #14
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Update: core-bundle v0.2.37, contao-ai-cli v0.13.3

    Geändert

    • Die Listenbefehle antworten mit JSON vom Server statt mit einer geparsten ASCII-Tabelle. Werte behalten ihren Typ (3 statt "3", NULL unterscheidbar), Zeilen liegen unter "results", und count gegen total sagt, ob gekürzt wurde. Ab CLI v0.9.0 braucht jede Liste das core-bundle auf dem Ziel — vorher lief das über doctrine:query:sql und damit auf nacktem Contao.
    • eval.rgxp wird beim Schreiben durchgesetzt, eval.unique jetzt auch beim Update. date/time/datim sind ausgenommen: deren rgxp beschreibt die Widget-Eingabe im Anzeigeformat, nicht die Speicherform.
    • Fehlt einer Tabelle die DCA, weil das zugehörige Bundle nicht installiert ist, wird das Paket beim Namen genannt statt nur "DCA not found".


    Neu

    • Seitenbaum — ebenenweise statt alles auf einmal, zwei Ebenen als Vorgabe, --root zum Absteigen, --depth für mehr. Ein Feld "truncated" sagt, ob darunter noch etwas liegt.
    • ext-Gruppe — Console-Commands erreichen, die die CLI nicht wrappt.
    • Vertrag am eigenen Command — siehe unten.


    Code:
    contao:page:tree                       Seitenbaum, ebenenweise
    
    contao-ai-cli ext list                 was die Installation kann und die CLI nicht wrappt
    contao-ai-cli ext describe shop:x:y    Argumente, Optionen, Hilfe — vom Server gelesen
    contao-ai-cli ext run shop:x:y         ausführen, mit Warnung und tl_log-Eintrag vorab
    Ein ungewrappter Command läuft ohne die Zusagen der gewrappten: keine Feldkonvertierung,
    keine DCA-Prüfung, keine Zusicherung über Version, Undo oder Logeintrag. Die Warnung sagt
    das, und der Protokolleintrag entsteht vor dem Start — ein nachträglicher hielte nur fest,
    was gutgegangen ist.

    Eigenes Plugin einbinden

    Attribut an die Command-Klasse, fertig:

    Code:
    #[AsCommand(name: 'shop:order:confirm', description: 'Bestellung bestätigen')]
    #[\Webwerkwien\ContaoAiCoreBundle\Attribute\AiContract(
        writes: true,
        tables: ['tl_shop_order', 'tl_shop_voucher'],
        trace: ['tl_log'],
        traceWhen: 'before',                // oder 'on-success'
        irreversible: 'verschickt eine Bestätigungsmail an den Kunden',
        repeatable: false,
        answerShape: ['status', 'id'],
        genericPathUnsuitable: ['tl_shop_order' => 'Übergänge hängen an save_callbacks'],
    )]
    class ConfirmOrderCommand extends Command { /* … */ }
    Vier Dinge, die man dazu wissen muss:

    • Kein composer require. PHP löst eine Attributklasse erst bei newInstance() auf; gelesen werden die Rohwerte über getArguments(), instanziiert wird nie. Der voll qualifizierte Name genügt, kein use — und auf einer Installation ohne das lesende Bundle passiert schlicht nichts.
    • Der Präfix bleibt eurer. Die Deklaration macht den Command erreichbar, nicht sein Name. Symfony empfiehlt einen eigenen Präfix, veröffentlichte Contao-Erweiterungen halten es genauso. Ohne Deklaration bleibt nur der Contao-Namensraum erreichbar.
    • Die Aufbewahrungsfrist nicht angeben. Sie wird aus der Installation gelesen (logPeriod, undoPeriod, versionPeriod). tl_log und tl_version sind im Standard 7 gegen 90 Tage — das sind keine austauschbaren Zusagen.
    • Keine Geschäftsregeln. Vorlauffristen, Saisonhinweise und Ähnliches gehören in die Beschreibung des Commands, nicht in eine maschinenlesbare Zusicherung.


    Die Ausgabe trennt, was prüfbar ist — die genannten Tabellen gegen die DCA — von dem, was
    nur behauptet werden kann: ob etwas außerhalb der Datenbank passiert, das sich nicht
    zurücknehmen lässt, und ob der Command wiederholbar ist. Das steht getrennt und wird auch
    so bezeichnet. Dazu der Hinweis, dass ein Vertrag einen Console-Command beschreibt und
    nicht alle Schreibwege einer Erweiterung: DCA-Callbacks, Frontend-Controller und Cronjobs
    kann er nicht abdecken.

    Feldliste und Beschreibung der Ausgabe:
    https://github.com/webwerkwien/conta...ur-own-command

    Rückmeldung willkommen — besonders, ob ein Feld fehlt oder eines Ballast ist.

  15. #15
    Contao-Nutzer
    Registriert seit
    06.10.2011.
    Ort
    Wien
    Beiträge
    99

    Standard

    Hallo. Zweite Sicherheits- und Korrekturrunde über alle drei Pakete. Zwei Punkte betreffen jeden, der sie schon einsetzt — die stelle ich voran.

    Bitte nachsehen, wenn ihr Archive oder Kalender geklont habt

    contao:record:clone hat bei News-Archiven und Kalendern alle Inhaltselemente zurückgelassen und trotzdem ok gemeldet. Gezählt wurden nur die News beziehungsweise Termine. Bei Seiten war es korrekt, dort kam der Inhaltsbaum mit.

    Der Beleg stand im eigenen Quelltext: der Kaskaden-Sammler fürs Löschen weiß seit jeher, dass tl_content unter Artikeln, News und Terminen hängt. Das Löschen nahm die Inhalte mit, das Klonen nicht. Eine Hälfte wusste es, die andere nicht.

    Im selben Zug: geklonte Aliasse wurden erzeugt, aber nie auf Eindeutigkeit geprüft. Model::save() führt den DCA-save_callback nicht aus, Contaos eigene Prüfung lief also nie — und tl_news, tl_calendar_events und tl_faq deklarieren alle drei unique und doNotCopy. Auf unserer Testinstallation teilten sich am Ende sechs News denselben Alias; welche davon ein Alias-Aufruf erreicht, entscheidet die Zeilenreihenfolge.

    Behoben in core-bundle v0.4.0. Wer geklont hat, sollte die Klone auf fehlende Inhaltselemente und doppelte Aliasse ansehen.

    Und wenn ihr Redakteure ohne Admin-Rechte habt

    Kalender- und FAQ-Rechte haben jeden Nicht-Admin abgewiesen, auch bei korrekt gesetzten Rechten:

    Code:
    BackendUser::hasAccess($feld, $array)   // liest $this->$array
    
    tl_news_archive   userRoot = news        wir fragten 'news'       richtig
    tl_calendar       userRoot = calendars   wir fragten 'calendar'   falsch
    tl_faq_category   userRoot = faqs        wir fragten 'faq'        falsch
    $this->calendar gibt es nicht, die Prüfung fiel durch und verweigerte. Es scheiterte geschlossen — es ist nichts abgeflossen —, aber Kalender und FAQs waren für Redakteure unbenutzbar. Als Admin merkt man nichts davon, weil vorher ein früher Rücksprung greift.

    Behoben in backend-bundle v0.6.0, jetzt über die contao_user.*-Voter statt hasAccess(). Das ist ohnehin der haltbarere Weg: hasAccess() ist seit Contao 5.2 deprecated und meldet selbst, es werde in Contao 6 nicht mehr funktionieren.

    Passwörter nicht mehr auf der Kommandozeile

    Die CLI setzte den Passwort-Befehl von Contao mit --password=… zusammen. shlex.quote schützt davor, dass die Shell den Wert interpretiert — mit Sichtbarkeit hatte das nie etwas zu tun. Die Zeichenkette ist Argument des lokalen ssh-Prozesses und des entfernten php-Prozesses, und /proc/<pid>/cmdline ist für jeden Benutzer der Maschine lesbar. Auf beiden Seiten.

    Contao sagt es in der eigenen Hilfe:

    Code:
    contao:user:password --help
      -p, --password=PASSWORD  The new password (using this option is not
                               recommended for security reasons)
    Die CLI nutzt jetzt die interaktive Abfrage und schickt das Passwort über stdin. Neu dazu --password-stdin an user create, user password und security hash-password, damit es auch nicht in der Kommandozeile der CLI steht:

    Code:
    printf '%s\n' "$PW" | contao-ai-cli user password --username alice --password-stdin
    --password funktioniert weiter, ist aber nicht mehr die empfohlene Form.

    Neu: CRUD für Termine und FAQs im Backend-Chat

    event_create, event_update, event_delete, event_read und dieselben vier für faq_*. Damit haben Kalender und FAQ dieselbe Abdeckung wie News, Seiten, Artikel und Inhaltselemente.

    Der Zuschnitt vorher war gewachsen, nicht entschieden: die CRUD-Werkzeuge kamen mit der ersten Version, Kalender und FAQ erst später über Kloner und Rewriter. Der Agent konnte einen Kalender klonen und einen Termin umschreiben, aber keinen anlegen.

    Beim Aktualisieren

    Code:
    webwerkwien/contao-ai-core-bundle     v0.4.1
    webwerkwien/contao-ai-backend-bundle  v0.6.0   benötigt core >= 0.4.0
    contao-ai-cli                         v0.15.0
    Die Bedingung des Backend-Bundles ist bewusst angehoben: record_clone nutzt den Kloner des core-bundle direkt. Mit einem älteren core verliert das Werkzeug weiterhin die Inhaltselemente — still, und mit ok als Antwort.

    Vollständige Changelogs in den Repos:
    https://github.com/webwerkwien/conta...undle/releases
    https://github.com/webwerkwien/conta...undle/releases
    https://github.com/webwerkwien/contao-ai-cli/releases

    Rückmeldung willkommen — besonders, wenn euch beim Klonen etwas aufgefallen ist, das ihr euch nicht erklären konntet. LG

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 3 (Registrierte Benutzer: 0, Gäste: 3)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •