Archiv der Kategorie: Kategorien

Custom Post Type Kochbuch: das Feintuning, mit Custom Taxonomies

Verwendung des Excerpts/Auszugs

Zuallererst möchte ich einstellen, dass man bei den Kochbüchern in der Blog View nicht den ganzen Inhalt angezeigt bekommt, der ist nämlich im Zweifelsfall recht lang, und ausserdem mit mehreren großformatigen Bildern versehen. Dafür gibt es in WordPress die Funktion des Auszugs (Engl. Excerpt), damit kann man einen kurzen Einführungstext erstellen, der dann z.B. in der Liste der Suchergebnisse statt dem ganzen Beitrag angezeigt wird. Den Auszug hatten wir in unserer Post-Type-Definition aus dem vorigen Beitrag noch nicht mit drin, das ist aber schnell nachgeholt. Wir ergänzen in der functions.php unseres Childthemes die Post-Type-Definition wie folgt:

function post_type_kochbuch() {
    register_post_type(
                'kochbuch',
                array(
                    'label' => __('Kochbuch'),
                    'public' => true,
                    'show_ui' => true,
                    'supports' => array(
                    'title',
                    'editor',
                    'excerpt',
                    'post-thumbnails',
                    'custom-fields',
                    'revisions')
                )
        );
    
     
}

Damit wird im Beitragseditor unter dem Content-Feld jetzt das Feld Auszug mit angezeigt, und wir können einen Kurztext eingeben. Wie und wo überall der angezeigt wird ist vom Theme abhängig, ich arbeite hier mit einem Child von Twenty Twelve, da geht man es so an:

Dafür klemmt man sich die content.php und legt eine Kopie ins ChildTheme-Verzeichnis. Dann macht man sich auf die Suche nach der Codezeile:

<?php if ( is_search() ) : // Only display Excerpts for Search ?>

Die ändert man wie folgt:

<?php if ( is_search() || is_home() ) : // Display Excerpts for Search and Homepage ?>

Und schon tauchen auf der Kochbücher-Seite nur noch die Titel und die Auszüge auf. Kleiner Pferdefuß: das gilt jetzt auch für die Rezepte-Blogseite, auch dort werden nur noch Titel und Excerpts(falls vorhanden) angezeigt – ist mir aber ganz recht so, ich finde das wesentlich übersichtlicher. Ich schau aber mal, ob ich da noch eine genauere Steuerungsmöglichkeit finde.

Kategorien und Schlagwörter für die Kochbücher

Dafür legen wir uns zwei Custom Taxonomies an, die nur für den Post Type Kochbuch gelten. Das ist nicht weiter kompliziert, hier der Eintrag für die functions.php:

function kochbuch_create_my_taxonomy() {

    register_taxonomy(
        'land',
        'kochbuch',
        array(
            'label' => __( 'Land' ),
            'rewrite' => array( 'slug' => 'land' ),
            'query_var' => 'land',
            'show_ui' => true,
            'hierarchical' => true,
        )
    );
      register_taxonomy( 
      'kochbuch-stichwort', 
      'kochbuch',
        array(
             'hierarchical' => false,
             'label' => __('Kochbuch-Stichwort'),
             'query_var' => 'kochbuch-stichwort',
             'show_ui' => true,
             'rewrite' => array('slug' => 'kochbuch-stichwort' )
        )
    );
}
add_action( 'init', 'kochbuch_create_my_taxonomy' );

Rot markiert sind die Einträge für die Benennungen und die Slugs der jeweiligen Taxonomie. Die grün markierte Option ‚kochbuch‚ am oberen Ende der Taxonomie-Definition sorgt dafür, daß die Taxonomie auch nur für den Post Type Kochbuch herangezogen wird. Der einzige Unterschied zwischen den beiden Taxonomien ist, dass ich für die Land-Taxonomie ‚hierarchical’=>true eingestellt habe, das erlaubt eine Schachtelung der Länder. Für die Kochbuch-Stichworte steht hierarchical => false, das ergibt eine Ebene wie man es von den Stichworten in Worpress gewohnt ist.

Das sollte schon genügen, um unsere Custom Taxonomies funktional zu machen:

custom_taxonomies

custom_taxonomies

Ich hatte übrigens beim Testen am Anfang das Problem, dass neue Taxonomie-Einträge sich nicht abspeichern liessen. Die Ursache war ein Plugin-Konflikt! Ich hatte auf der Testumgebung noch einen Haufen experimentelle Plugins am Laufen, die hab ich deaktiviert, dann hat es ganz normal funktioniert. Die Wurzel des Problems war anscheinend eine Schlamperei meinerseits, ich hatte in einigen Plugins vor dem öffnenden <?php-Tag Whitespaces drin, das mag WordPress gar nicht, da gibt es die bekannte Meldung „Das Plugin verursachte X Zeichen unerwartete Ausgabe…“

Wie man die neuen Taxonomien ins Template einfügt

Das hängt wieder ziemlich vom Theme ab, da muss man ein bisschen rumprobieren. Die Taxonomie Land bekommt man mit folgender Codezeile:

<div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?>
            
        </div>

Ich hab da gleich mal die div class= „entry meta“ mitgenommen, damit die Formatierung wie bei den WordPress-Standardkategorien ausfällt. Die Codezeile kommt in die content.php ins Child-Theme, und zwar zwischen dem Block für den entry-content und dem footer:

</div><!-- .entry-content -->
        <?php endif; ?>
        <div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?>
            
        </div>
        <footer class="entry-meta">

In der Blogansicht sieht das dann so aus:

land_anzeige

land_anzeige

Und so sieht es aus, wenn man auch noch die Stichworte an der selben Position ausgibt:

<div class="entry-meta">
            <?php echo get_the_term_list( $post->ID, 'land', 'Rezepte aus aller Welt: ', ', ', '' ); ?><br>
            <?php echo get_the_term_list( $post->ID, 'kocbuch-stichwort', 'Stichworte: ', ', ', '' ); ?>
            
        </div>

(im kocbuch-Stichwort ist ein Schreibfehler, bitte ignorieren)

Nicht vergessen: Permalinks updaten!

Sonst kriegt man die 404-Meldung, wenn man auf einen der Taxonomy-Einträge klickt. Unser Endergebnis sieht jetzt in der Blog-Ansicht so aus:

blogview_kochbuch

blogview_kochbuch

Wir haben: den Titel, den Excerpt, die Länder und die Stichworte. Paßt!

Jetzt möchte ich noch gern meinen neuen Post Type Kochbuch in einem Widget „Die neuesten Kochbücher“ ausgeben, und die Kochbuch-Länder ebenfalls, aber dazu gibt es einen neuen Beitrag.

WordPress Custom Post Types – die Ehrenrettung als CMS?

Was in anderen CMS längst zur Standardausrüstung gehört, nämlich eine Logik zur Verwaltung und Präsentation unterschiedlicher Beitragstypen, ist in WordPress „out of the box“ erstmal nicht machbar, man hat Blog-Beiträge und statische Seiten, und das wars erstmal. In Joomla habe ich dafür die Kategorien mit einem ausgefeilten Verwaltungssystem, in Drupal die Inhaltstypen mit nicht minder komfortabler Steuerung über die Benutzeroberfläche.

Wozu braucht man überhaupt diese Unterscheidung nach unterschiedlichen Inhaltstypen?

Das ist für einen einfachen Quasselblog erstmal noch nicht notwendig, man kann ja seine Beiträge über die WordPress-Kategorien sehr feinkörnig und sogar hierarchisch logisch gruppieren. Das Kategoriensystem von WordPress ist sogar besonders ausgefeilt und komfortabel in der Bedienung, da haben sich die Core-Programmierer wirklich was einfallen lassen.

Es stellt sich aber bei den meisten Blogs mit der Zeit heraus, dass der ursprünglich vorgesehene Rahmen nach einiger Laufzeit zum zu engen Korsett wird. Einfaches Beispiel: dieser Blog hier, der vor anderthalb Jahren als reiner WordPress-Plauderblog angefangen hat. Mit der Zeit kamen dann noch andere Themen dazu, reine PHP- oder MySQL-Topics zum Beispiel, oder auch vor ein paar Monaten die Beitragsserie über Joomla. Wenn ich da gleich sauber gearbeitet hätte, hätte ich mir gleich einen neuen Beitragstyp für jedes neue Thema angelegt, da hab ich geschlampert und versucht, das über den Kategorienbaum zu steuern. Hat jetzt nicht gerade zur Übersichtlichkeit beigetragen, ich gebs ja zu. Ob ich das jetzt nachträglich noch umbauen möchte weiss ich noch nicht, aber schöner wärs schon man hätte für jedes Haupthema eine eigene Blogseite, und auch eine eigene Kategorisierung oder auch Stichwort-Verwaltung.

Wieso – ist denn WordPress MultiBlog-fähig?

Ein definitives „Im Prinzip ja“. Es geht halt nicht so ohne weiteres über die Benutzeroberfläche, man kommt nicht darum herum in die functions.php einzugreifen oder sich ein Plugin zu schreiben. Aber gehen tuts – mit Custom Post Types. Es ist noch nicht einmal besonders schwierig, und Tante Google liefert auch jede Menge Artikel zu dem Thema. Besonders informativ fand ich diesen Beitrag bei Elmastudio,  und auch der Beitrag hier von drweb bringt ordentlich Licht in die Sache. Mit den Custom Post Types in einem Atemzug werden häufig die Custom Taxonomies angesprochen, das klingt erstmal kompliziert, ist aber eigentlich auch nicht weiter schwierig. Man kann sich damit eigene Kategorie- und Stichwort-Logiken für die neuen Post Types anlegen, das ist sehr nützlich und absolut praxistauglich.

Wir gehens hier aber mal langsam und der Reihe nach an. Ich nehme als Beispiel wieder mein Inselfisch-Kochbuch, da haben wir gleich einen praktischen Einsatz.

Wozu jetzt einen neuen Beitragstyp?

Im Inselfisch-Kochbuch sind die Beiträge meine Rezepte, und das ist gut eingefahren und funktioniert auch prächtig. Die Anwender finden sich gut zurecht, das Kategoriensystem ist in der Praxis bewährt und sowohl übersichtlich als auch informativ. Welche Inhalte also habe ich, die einen neuen Beitragstyp sinnvoll machen würden? Na, die Kochbücher! Die habe ich auf statische Seiten gelegt, und das ist weder besonders übersichtlich für die Anwender (ellenlanges Aufklappmenü) noch für mich komfortabel zu pflegen. Ich hätte ja noch eine ganze Latte Kochbücher, die ich auch gern einstellen würde, aber da jedesmal das Menü wieder umzustricken ist mir echt zu aufwendig. Da wäre es doch viel schöner, ich könnte im Blog-Stil meine Kochbücher der Reihe nach reinklopfen und immer wieder dynamisch welche dazuschreiben… ja, auf gehts!

Wie soll der neue Post Type Kochbuch aussehen?

Eigentlich auch nicht anders als jeder andere WordPress-Beitrag. Titel, Beschreibung, gegebenenfalls ein Bild. Dazu noch Autor und Verlag, gegebenenfalls der Preis und  die Seitenzahl – aber das muss jetzt nicht in eine strikte Logik gepackt werden, das hat alles im Inhalt Platz. Interessanter ist es dann schon, die Kochbücher nach Herkunftsland (Bayern, USA, Asien…) zu gruppieren, dafür werde ich eine eigene Logik basteln. Und dann nehmen wir noch eine Stichwortverwaltung mit rein, in der könnte sowas stehen wie: Nachschlagewerk, Lesefutter, Grundrezepte, Spezialitäten, Für Anfänger, für Profis… das kommt dann beim Eintragen der Kochbücher, da wird sich noch einiges finden. Für die Herkunftsländer macht eine hierarchische Kategorien-Logik Sinn (Asien/Thailand, Asien/China…), für die Stichwörter (irgendwie logisch) die Stichwörter. Das legen wir uns jetzt mal der Reihe nach an.

Definition des neuen Post Types Kochbuch in der functions.php

Da können wir so gut wie alle WordPress-Beitragseigenschaften übernehmen, deswegen wird die Definition relativ kurz und knackig:

function post_type_kochbuch() {
    register_post_type(
                'kochbuch',
                array(
                    'label' => __('Kochbuch'),
                    'public' => true,
                    'show_ui' => true,
                    'supports' => array(
                    'title',
                    'editor',
                    'post-thumbnails',
                    'custom-fields',
                    'revisions')
                )
        );
}
add_action('init', 'post_type_kochbuch');

Damit ist der neue Post-Type auch schon angelegt und taucht bereits im Admin-Menü auf:

kochbuch_admin

kochbuch_admin

Man kann auch schon mal testweise einen neuen Eintrag vom Typ Kochbuch anlegen, aber wenn man ihn anschauen will, kommt wahrscheinlich die 404-Fehlermeldung. Wir machen auch erst mal noch was anderes:

Ein Template für den neuen Post Type anlegen

Dafür klemmt man sich die archive.php aus dem Parent-Theme und macht eine Kopie mit dem Namen archive-kochbuch, die legt man ins ChildTheme-Verzeichnis. Zuerst ändert man den Templatenamen:

/**
 * Template Name: Kochbuch Archive pages
 *
 */

Dann ergänzt man den Code unmittelbar vor dem Loop um eine Zeile, so daß WordPress auch den richtigen Post Type anzieht:

<?php query_posts(array('post_type'=>'kochbuch')); ?>
            <?php
            /* Start the Loop */
            while ( have_posts() ) : the_post();

Jetzt noch im Dashboard unter Einstellungen/Permalinks einmal die Permalink-Einstellungen speichern. Jetzt sollte man sich den eben erstellten ersten Kochbuch-Beitrag auch angucken können.

Eine eigene Seite für die Kochbücher erstellen

Neue Seite erstellen, ich nenn sie mal einfach Kochbücher. Wenn alles geklappt hat, kann man jetzt bei den Templates das soeben erstellte Kochbuch-Template anwählen:

kochbuch_template

kochbuch_template

Damit werden auf dieser Seite automatisch alle Beiträge vom neuen Post Type Kochbuch angezeigt. Diese Seite fügt man sich jetzt noch in sein Menü ein, und schon kann man loslegen.

Jetzt fehlt noch ein bisschen Feintuning, zum Beispiel möchte ich noch die Herkunftsländer und die Stichworte haben, aber dafür gibt es einen neuen Beitrag.

 

Von Joomla nach WordPress umziehen – der Vollständigkeit halber

Ich habe drüben im Drupal-Blog ausführlich beschrieben, wie man Inhalte aus Drupal in WordPress-Beiträge überführt, nachzulesen hier. Das selbe machen wir jetzt noch mit Joomla, und zwar möchte ich die Beiträge aus einer bestimmten Kategorie nach WordPress exportieren. Meine ausgewählte Kategorie sind natürlich die Rezepte, mit der Kategorie-ID 8 (im Zweifelsfall nachschlagen in der Tabelle #__categories).

Wie kommen wir an Titel und Inhalt der Rezepte?

Aus der Tabelle #__content. Die holen wir uns nach Access rüber und schauen sie mal näher an.

content

content

Die id und den title nehmen wir mit, den alias lassen wir aus. Dann brauchen wir noch den introtext und den fulltext (beide!), weil Joomla den Beitragstext in diese beiden Felder aufteilt, sobald man einen Weiterlesen-Tag eingefügt hat. Das sieht man hier im Screenshot oben bei den ids 4 bis 8, so sieht das dann aus.

Den state müssen wir filtern, -2 bedeutet „marked for deletion“, 1 ist veröffentlicht, wir nehmen nur die 1er. Und die catid filtern wir auch, auf die 8 für Rezepte. (Bei mir ist noch ein Haufen Schrott vom Testen mit drin, ich nehm mal noch die Datensätze 9-47 raus). Übrig bleibt die folgende Tabelle:

content_gefiltert

content_gefiltert

Die specken wir noch ab, die Felder introtext und fulltext werden zu einem Feld namens bodytext zusammengefügt, die catid und der state fliegen raus.

Jetzt fehlen noch die Tags für die Kategorien

Kleine Erinnerung: ich hatte die Rezeptkategorien aus WordPress auf Joomla-Tags ohne Schachtelung abgebildet. Die holen wir uns jetzt wieder zurück, und zwar aus der Tabelle #__tags.

tags

tags

Der erste Eintrag für root fliegt raus, vom Rest übernehmen wir id und title. Parent_id ist überall leer, weil nicht geschachtelt, published = 1 passt auch. Um jetzt die Tags den Rezepten (hier in der Tabelle id_title_bodytext) zuzuordnen, verknüpfen wir über die Tabelle contentitem_tag_map. Beim Importieren nach Access darauf achten, dass content_item_id und tag_id als Integer rüberkommen! Das sieht dann so aus:

tags_beziehungen

tags_beziehungen

Darüber basteln wir uns eine Abfrage, in der zunächst mal jedes Rezept so oft vorkommt, wie es Tags zugeordnet hat:

abfrage_tags

abfrage_tags

Kurzer Blick über die Tabelle: ich habe zu keinem Rezept mehr als 2 Tags zugeordnet, aber das passt schon, ist korrekt.

Zuordnen der Tags zu WordPress-Kategorien

Dafür zieht man sich alle gültigen Tags aus der #–tags ab und importiert sie als Kategorien nach WordPress, wie das geht habe ich in diesem Artikel unter Schritt 1: Anlegen der Kategorien in WordPress im Drupal-Blog ausführlich beschrieben.

Dann habe ich mir die entstandene Tabelle wp_terms nach Access rübergeholt:

wp_terms

wp_terms

Hier kann ich jetzt über den name des Terms auf den title des tags verknüpfen, weil die Schreibweise identisch ist:

join_term_name

join_term_name

Damit bekomme ich die WordPress-Kategorie-IDs zu den Rezepten.

term_id

term_id

Das hatten wir so ähnlich schonmal, jedes Rezept taucht jetzt so oft auf, wie es Kategorien/Tags hat. Jetzt Gruppieren wir noch, und nehmen den ersten und letzten Wert der Term-ID. Diese sind bei den Datensätzen gleich, die nur eine Kategorie zugeordnet haben, das ist schon richtig so.

ersterwert_letzterwert

ersterwert_letzterwert

So, das wars. Diese Tabelle kann man nach WordPress importieren, und zwar genau so wie ich es in diesem Artikel beschrieben habe:

DRUPAL NACH WORDPRESS: BEITRÄGE MIT KATEGORIEN ERZEUGEN

Dabei muss man wahrscheinlich noch eine kleine Abfrage einbauen, was passieren soll wenn erster und letzte Wert der term_id gleich sind, aber prinzipiell funktioniert die Sache so einwandfrei, die Beiträge werden in WordPress angelegt und mit Kategorien versehen.

Nachtrag: mehr als 2 Kategorien in der Export-Datei

Ich hab ja ganz lässig behauptet, wenn man mehr als zwei Kategorien pro Rezept  in die Export-Datei schreiben will, braucht man in Access eine Kreuztabelle. Jetzt bin ich gefragt worden, wie man das anstellt, und ich muss zugeben die ist sehr, sehr haarig zu konfigurieren. Ich hab da mal den „kleinen Dienstweg“ über ein Excel-Makro genommen, funktioniert auch und ist wesentlich leichter nachzuvollziehen.

Die Ausgangsbasis

Wir schubsen unsere Ausgangstabelle in Excel rein, die dürfte ja inzwischen bekannt sein. Jeder Datensatz taucht so oft auf, wie er Kategorien hat, und wir haben die Joomla-ID dazugemappt:

excel_startdaten

excel_startdaten

Post_id, post_title, term_id und name kommen aus WordPress, das was hier joomla_map.id heißt ist die Joomla-Tag-ID aus unserer mapping-Tabelle.

So soll es dann aussehen

Das Arbeitsblatt mit den Ausgangsdaten habe ich „start“ genannt, das Output-Arbeitsblatt heisst „ziel“ und sieht in leerem Zustand so aus:

excel_ziel_leer

excel_ziel_leer

Wir übernehmen nur die id und den titel, und verteilen die Tags auf die entsprechenden Felder tag1…tagn. Der Clou dabei ist, dass man unbegrenzt viele Tags pro Datensatz übernehmen und einsortieren kann. Den Content hab ich mir hier gespart, kann man sich später über die id wieder dazumappen.

So wirds gemacht

Der VBA-Code dazu sieht so aus:

Sheets("start").Select
        
    i = 2
    j = 2
    k = 0
    akt_id = Cells(2, 1).Value
        
    While akt_id <> ""
        
                Sheets("start").Select
                akt_id = Cells(i, 1).Value
                akt_titel = Cells(i, 2).Value
                akt_kat = Cells(i, 4).Value
                akt_tag = Cells(i, 5).Value
                    
                    
                Sheets("ziel").Select
                Cells(j, 1).Value = akt_id
                Cells(j, 2).Value = akt_titel
                Cells(j, 3 + k).Value = akt_tag
                
                
                i = i + 1
                If Worksheets("start").Cells(i, 1) <> akt_id Then
                    j = j + 1
                    k = 0
                Else
                k = k + 1
                End If
        Wend

Was hab ich gemacht? Ich steppe mit dem i durch die start-Tabelle und schreibe so lange in die selbe Zeile j der ziel-Tabelle, wie ich in start auf die selbe id treffe. Das k zählt die Spalte für das tag1..n hoch. Treffe ich auf eine neue id in der Zieltabelle, wird j um 1 erhöht und k wieder auf 0 gesetzt, und das ganze so lange bis ich auf das erste leere Feld id in der start-Tabelle treffe.

Das Ergebnis sieht dann so aus:

excel_zieldaten

excel_zieldaten

In der Praxis wird man sicher die Anzahl der zu importierenden tags auf ein handliches Mass  beschränken, das muss sich jeder selber überlegen, was da bei seinen Bestandsdaten Sinn macht. Aber so bekommt man alle Kategorien aus WordPress auf Joomla-Tags gemappt, mit dieser Export-Tabelle kann man weiterarbeiten.

Rezepte mit 2 Tags importieren, so gehts

Ich hab mir mal eine kleine Export-Tabelle mit 11 Datensätzen gebaut, die sieht so aus:

11_export

11_export

id, titel und content kommen wie gehabt aus WordPress, kat_1 und kat_2 sind die passenden Schlagwort-IDs aus Joomla, die wir im letzten Beitrag via Access zugeordnet haben. Jetzt wird noch das Import-Skript umgebaut, da kommt die Logik für die Tag-Zuordnung innerhalb der Foreach-Schleife nach dem Erzeugen des neuen Artikelobjekts mit rein. Das Ganze sieht dann so aus:

//**************Tags zuordnen
           $roh1 = $zeile->kat_1;
           $roh2 = $zeile->kat_2; 
           
            $tag1 =strval($roh1);
            $tag2 =strval($roh2);
            $neue_id= $article->id;
            
            // Das ist einen Versuch wert!
                $basePath = JPATH_ADMINISTRATOR.'/components/com_content';
                require_once $basePath.'/models/article.php';
                $articlemodel = new ContentModelArticle(array('table_path' => $basePath . '/tables'));

                $params = array(
                    'id' => $neue_id,                // Article being tagged 
                    'tags' => array($tag1, $tag2)   // Tag IDs from #__tags to tag article with
                );
                
                if($articlemodel->save($params)){
                    echo 'Success!';
                }
                    
                    
                    
                    
                    
                    //**************Ende Tags zuordnen

Der Import der Rezepte bleibt genau wie gehabt, nur findet jetzt noch die Tag-Zuordnung statt. Damit erhalten wir nach dem Import eine wohlgefüllte Tagliste:

tagliste_screenshot

tagliste_screenshot

Was, wenn ich mehr als 2 Kategorien übernehmen will?

Dann muss das Tagmapping in Access aufgebohrt werden, wo ich jetzt mit erster Wert/letzter Wert operiert habe, muss eine Kreuztabelle rein, damit sollten auch beliebig viele Kategorien pro Rezept abgebildet werden können. Die Export-Tabelle wird dann halt ziemlich breit, und das Script braucht eine Logik, mit der alle Tag-Felder (kat_1.. kat_n) berücksichtigt werden. Aber das führt mir jetzt entschieden zu weit, da darf jeder selber experimentieren. Ich mach hier einen Break, und eine Denkpause für den nächsten Beitrag.

Tagmapping: da brauchts ein bisschen Vorarbeit

Die grundlegende Mechanik zum programmatischen Einfügen von Tags

Dank eines guten Tipps aus dem deutschen Joomla-Forum habe ich folgendes Codesnippet zum Laufen gekriegt. Es ordnet dem Artikel mit der ID 80 zwei Tags mit den IDs 7 und 9 zu. Der Knackpunkt war, dass man die IDs der zuzuordnenden Tags als Strings übergeben muss – da musste auch erstmal draufkommen!

    $roh1 = 7;
    $roh2 = 13;
    $tag1 =strval($roh1);
    $tag2 =strval($roh2);
    
        $basePath = JPATH_ADMINISTRATOR.'/components/com_content';
        require_once $basePath.'/models/article.php';
        $articlemodel = new ContentModelArticle(array('table_path' => $basePath . '/tables'));

        $params = array(
            'id' => 80,                // Article being tagged 
            'tags' => array($tag1, $tag2)   // Tag IDs from #__tags to tag article with
        );
        
        if($articlemodel->save($params)){
            echo 'Success!';
        }

Jedenfalls, das ist schonmal eine gute Ausgangsbasis. Soweit ich das bislang beim Testen gesehen habe, werden die Tags immer neu zugeordnet, evtl. vorher zum Artikel schon angelegte Tags werden rausgeschmissen. Macht aber nix, wir arbeiten ja auf einer niegelnagelneuen Joomla-Installation, da sind jetzt erstmal noch keine Tags zugeordnet. Bevor wir diese Mechanik aber in unseren Artikelimport aus WordPress einbauen können, ist noch etwas Freiturnen auf der Datenbank angesagt. Ich geh da mal wieder den Weg über Access, weil das doch etwas handlicher ist als MySQL.

Die Ausgangsbasis

Ich hab nochmal eine Einschränkung beschlossen, zu jedem Beitrag aus WordPress werden maximal zwei Kategorien exportiert, sonst ist mir das jetzt zu aufwendig.

Erste Voraussetzung ist schonmal, dass wir alle Kategorien aus WordPress abgefasst und erfolgreich als Schlagwörter nach Joomla importiert haben. Davon ziehe ich mir die #__tags-Tabelle nach Access ab und bastle mir eine Abfrage auf meine Tabelle mit den WordPress-Kategorien, der Join geht hier über den Namen der Kategorie in WordPress auf den Titel des Tags in Joomla. Das funktioniert, weil die Schreibweisen identisch sind. Das Tagmapping sieht dann so aus:

tagmap_screenshot

tagmap_screenshot

Die term_id und der name kommen aus WordPress, title und id aus Joomla, das ist die Basis für unser Mapping.

Zuordnung der Kategorien zu den WordPress-Posts

Man braucht vier Tabellen, um die Zuordnung der Kategorien zu den einzelnen Beiträgen in WordPress abzubilden, das sieht so aus:

wordpress_kat_post

wordpress_kat_post

Meine Tabelle published_posts ist ein schlanker Auszug aus der wp_posts und enthält nur ID, Titel und Content der veröffentlichten Rezepte. So kriege ich erstmal eine Liste aller Rezepte mit den zugeordneten Kategorien, wobei jedes Rezept so oft auftaucht wie es Kategorien hat:

alleposts_allekat

alleposts_allekat

Um das ganze jetzt auf zwei Kategorien pro Rezept einzuschränken, setze ich hierauf noch einmal eine Abfrage, in der jeweils nur der erste und der letzte Wert der Kategorien zu einem Rezept angezeigt wird :

ersterwert_letzterwert

ersterwert_letzterwert

Den PostContent hab ich mal weggelassen, sonst wirds so unübersichtlich. Jetzt kann man noch den ersten und letzten Wert der term_id einblenden:

ersterletzterwert_termid

ersterletzterwert_termid

Hierzu Joine ich mir dann noch meine Mapping-Tabelle von oben und ziehe mir daraus die Joomla-Tag-IDs:

tagmapping_ausfuehrlich

tagmapping_ausfuehrlich

Das sieht soweit ganz gut aus, jetzt können wir die überflüssigen Felder ausblenden, so dass nur der post_title, der post_content und die beiden Joomla-Tag-IDs übrigbleiben. So, das wars. Damit erstelle ich mir meine neue Import-Tabelle. Ach so, den post_content hab ich unterwegs verloren, den holen wir uns jetzt wieder dazu, aber dann ist jetzt wirklich Finish.

mapping_endprodukt

mapping_endprodukt

Mit Access macht sowas richtig Spaß! Für die Import-Mechanik nach Joomla gibts jetzt aber einen neuen Beitrag, der hier ist lang genug.

Schlagworte/Tags nach Joomla importieren: ohne Gewährleistung

Mit diesem Codebeispiel von der Stackexchange ging es jetzt doch relativ flott, ich habe mir eine Mechanik gebastelt, mit der ich tatsächlich Schlagwörter nach Joomla importieren kann. Ich zeig hier erst mal nur den funktionalen Code für ein Schlagwort, die Schleife über eine Liste (im Zweifelsfall eine Import-Tabelle) kann sich jeder selber dazu denken. Die ganze Sache sieht so aus:

$data = "Joschis Cocktailbar";
 $date = new JDate();
 include_once JPATH_BASE . '/administrator/components/com_tags/tables/tag.php';
 $table = new TagsTableTag(JFactory::getDbo());

 $table->title = $data;
 $table->note = '';
 $table->description = '';
 $table->published = 1;
 $table->checked_out = 0;
 $table->checked_out_time = '0000-00-00 00:00:00';
 $table->created_user_id = 839;
 $table->created_time = $date->toSql();
 $table->modified_user_id = 0;
 $table->modified_time = '0000-00-00 00:00:00';
 $table->hits = 0;
 $table->language = '*';
 //$table->parent_id = 1; (hat keine Auswirkung)
 //$table->level = 1; (hat keine Auswirkung)
 $table->path = JFilterOutput::stringURLSafe($data);
 
 $table->check();

 $table->store();

Warum sich die parent_id und der level nicht setzen lassen ist mit ehrlich gesagt völlig schleierhaft, aber es scheint weiter keine Auswirkungen zu haben, der Tag „Joschis Cocktailbar“ wird mit diesem Code erzeugt und scheint auch regulär zu funktionieren. Jetzt noch die Daten aus einer Importtabelle laden und mit einem Foreach durchsteppen, das ist der nächste Schritt, das mach ich später noch.

Was, wenn ein Schlagwort schon vorhanden ist?

Soweit ich das nachvollziehen konnte, wird es dann nicht neu angelegt, und auch nicht überschrieben, sondern der Datensatz wird dann nicht neu erzeugt.

Und woher nehm ich die Kategorienliste aus WordPress?

Das habe ich in diesem Beitrag zu den WordPress-Kategorien ausführlich beschrieben, das sollte jeder nachvollziehen können. Wir nehmen da einen kleinen Umweg über mein Leib-und Magendatenbankerl Access, das ist etwas handlicher als MySQL.

Warum ohne Gewährleistung?

Weil die programmatisch neu erzeugten Schlagwort-Datensätze nicht ganz logisch identisch mit den manuell angelegten sind, so bleiben z.B. die parent_id und der level beide = 0. Was das im Ernstfall für Auswirkungen hat kann ich nicht sagen, dafür ist mir die Logik der #__tags-Tabelle zu undurchsichtig. Die schliesst nämlich die Möglichkeit zum Schachteln von Tags in einer Baumstruktur ein, das hab ich bisher unterschlagen dass das in Joomla geht. Ich verwende es aber auch nicht, deswegen sei mir die Auslassung erlaubt. Wer sich dran versuchen möchte, geschachtelte WordPress-Kategorien nach geschachtelten Joomla-Tags abzubilden, bittesehr, aber ich mach hier mal einen Punkt. Die Schlagwörter sollten sich so importieren lassen, und das ohne Handarbeit des Praktikanten. Ist doch mal ein ganz guter Anfang. Jetzt müssten wir sie nur noch unseren zu importierenden Rezepte zuordnen können, aber dazu gibts eine Denkpause und einen neuen Beitrag.

Kleiner Nachtrag

Ich hab den Import jetzt mal durchgezogen, hat klaglos funktioniert, alle 28 Datensätze sind einwandfrei in Joomla als neue Tags importiert worden. Jetzt gehts dann aber ans Eingemachte, das mit dem Mapping wird ne harte Nuss!

WordPress-Kategorien auf Joomla-Tags abbilden? Vorüberlegungen

Etwas vereinfachte Voraussetzungen

OK, meine Ausgangsbasis ist relativ simpel, ich habe (bis auf eine Ausnahme) im Original-Inselfisch-Kochbuch keine geschachtelten Kategorien verwendet, das spielt sich alles auf einer Ebene ab. Deswegen kann ich es mir erlauben, die Kategorien in Joomla als Schlagwörter (Tags) abzubilden. Ich habe mir auch die Einschränkung erlaubt, dass ich Schlagwörter in Joomla nur für die Rezepte verwende, für meine einzige andere „echte“ Joomla-Kategorie, die Kochbücher, werden keine Tags verwendet, und auch sonst nirgendwo. Mit dieser Mechanik kann ich bisher manuell meine Schlagwörter der Reihe nach erfassen und jedem Rezept zuordnen. Jetzt wärs natürlich schick, wenn man beim Datenimport irgendwie die Kategorien aus WordPress mitgeben und diese als Schlagwörter in Joomla automatisch zuordnen könnte. Aber ich fürchte, das wird ein langer Weg… na ja, auch der fängt mit dem ersten Schritt an.

Kann man Schlagwörter überhaupt importieren?

Geht bestimmt, die Frage ist nur: wie aufwendig? Und: wann macht man das? Ich denke, wir sollten hier von einer jungfräulichen Joomla-Installation ausgehen, in die noch keine Rezeptdaten (ich bleibe beim Inselfisch-Kochbuch) importiert worden sind, und in der auch noch keine Schlagwörter per Hand angelegt worden sind. Dann könnte man es mal versuchen, ich hab auf Stack Exchange einen Artikel gefunden: Adding tags to Joomla programmatically. Der sollte eigentlich genau das machen, was wir brauchen, aber ehrlich gesagt, das muss ich mir nochmal in aller Ruhe anschauen.

Und dann hätte ich noch Plan B: es sind nur ca. 30 Kategorien. Die können wir schlimmstenfalls auch zu Fuß einhacken, das macht der Praktikant. Aber jetzt gesetzt mal den Fall, wir schaffen es die Tags zu importieren, was dann?

Zuordnung der Joomla-Tags zu den WordPress-Kategorien

Da wird in irgendeiner Form ein Mapping stattfinden müssen. Das könnte ein bisserl kompliziert werden, weil ich in WordPress theoretisch beliebig viele Kategorien zu einem Beitrag zuordnen kann. Ich mach hier mal einen rigorosen Cut und sage: drei Kategorien pro Beitrag, das muss reichen.

Zuordnung der gemappten Schlagwörter zu den importierten Beiträgen

Sagen wir mal, ich schaffe es die WordPress-Kategorien den Joomla-Tag-ids zuzuordnen und beim Import mitzugeben. Weitergehen könnte es dann so in der Art wie in diesem Codeschnipsel:

$basePath = JPATH_ADMINISTRATOR.'/components/com_content';
require_once $basePath.'/models/article.php';
$articlemodel = new ContentModelArticle(array('table_path' => $basePath . '/tables'));

$params = array(
    'id' => 123,                // Article being tagged
    'tags' => array(7,8,9,14)   // Tag IDs from #__tags to tag article with
);
if($articlemodel->save($params)){
    echo 'Success!';
}

Wie gesagt, das Mapping auf die jetzt in Joomla schon vorhandenen Schlagwörter muss irgendwie hinhauen. Das ist jetzt erstmal ein Haufen Holz, ich geh mir jetzt wieder mal mein Denkmützerl aufsetzen und schaue, wie weit ich komme. Wenn ich was rausgefunden habe, gibts einen neuen Beitrag.