Archiv der Kategorie: WordPress

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.

Jetzt gilt’s: Rezepte aus WordPress importieren

Ich hab mir meine Tabelle mit den Rohdaten mal mit so etwa 30 Rezepten geladen, die sieht jetzt so aus:

rohdaten_screenshot

rohdaten_screenshot

Eigentlich brauchen wir nur die Felder titel und content, den URLsafe name können wir auch mit einer eingebauten Joomla-Funktion aus dem titel erzeugen:

$akt_name =JFilterOutput::stringURLSafe($akt_titel);

Aber das ist reine Geschmackssache. Jedenfalls wird die Foreach-Schleife jetzt ordentlich aufgebohrt, da kommt erstmal die Logik für die Belegung des JTable-Objekts rein. Meine drei Felder hab ich mir vorher natürlich auf Variable gelegt, ist übersichtlicher.

JTable-Objekt erzeugen, füllen und mit Insert wegschreiben

$article = JTable::getInstance(‚content‘);

$article->title            = $akt_titel;
        $article->alias            = $akt_name;
        $article->introtext        = $text;
        $article->catid            = 8;
        $article->created          = JFactory::getDate()->toSQL();
        //$article->created_by_alias = ‚Super User‘;
        $article->created_by = 839;
        $article->state            = 1;
        $article->access           = 1;
        $article->metadata         = ‚{„robots“:““,“author“:““,“rights“:““,“xreference“:““}‘;
        $article->language         = ‚*‘;

Dann fehlt nur noch die Logik zum Wegschreiben des befüllten Objekts, die hab ich aus dem Codebeispiel hier übernommen:

https://stackoverflow.com/questions/12643725/create-a-joomla-article-programatically?lq=1

Das sieht dann recht übersichtlich so aus:

// Check to make sure our data is valid, raise notice if it’s not.

        if (!$article->check()) {
            JError::raiseNotice(500, $article->getError());

            return FALSE;
        }

        // Now store the article, raise notice if it doesn’t get stored.

        if (!$article->store(TRUE)) {
            JError::raiseNotice(500, $article->getError());

            return FALSE;
        }

Das war schon die ganze Mechanik! Jetzt müssen wir nur noch die where-Klausel aus dem Select rausnehmen, die liest sich dann ganz einfach so:

$query = „SELECT * FROM 00_rohdaten;“;

Damit steppt unsere Foreach-Schleife brav durch alle Zeilen der Tabelle rohdaten durch und legt die neuen Artikel an. Kurzer Blick in die Beitragsübersicht:

neue_rezepte_screenshot

neue_rezepte_screenshot

Na bitte, da sind sie ja alle!  Auch im Modul „Die neuesten Rezepte“:

die_neuesten_rezepte

die_neuesten_rezepte

Die haben jetzt natürlich alle dasselbe Datum, nämlich heute, aber das anzupassen wäre jetzt schon Feinarbeit. Man könnte natürlich versuchen, das Erstellungsdatum aus WordPress zu übernehmen, das geht sicher auch, aber ich lass es jetzt mal gut sein. Noch ein kurzer Blick auf das alphabetische Inhaltsverzeichnis:

ivz_screenshot

ivz_screenshot

Alles OK, wir haben alles.

Fazit und Ausblick

So schlimm war das doch jetzt gar nicht, oder? Ich gebe zu, mit den Rohdaten aus dem Inselfischkochbuch war die Bereinigungsaktion vor dem Import recht einfach, einfach weil die Rezepte in den meisten Fällen aus sehr straightem HTML-Code bestehen, und den kann man mit wenig Modifikationen nach Joomla übernehmen.

Was mich aber noch ein bisschen fuchst: meine schönen Kategorien aus WordPress sind natürlich futsch, und ich hab eigentlich keine Lust, bei über 300 Rezepten die Kategorien nachträglich als Tags (Schlagworte) manuell einzufügen. Erinnern sie sich, ich hatte in diesem Beitrag meine WordPress-Kategorien als Schlagwortliste nach Joomla abgebildet. Das hatte soweit funktioniert, weil ich in WordPress keine verschachtelten Kategorien benutzt habe, keine ideale Lösung, aber besser als nix. Mal schauen, ob mir dazu noch was einfällt. Aber wir machen hier jetzt erstmal eine wohlverdiente Pause!

Beiträge aus WordPress holen: einige Vorüberlegungen

Nochmal kurz als Gedächtnisstütze: wir brauchen eigentlich nur drei Felder, und zwar:

$article->title            = 'This is my super cool title!';
$article->alias            = JFilterOutput::stringURLSafe('This is my super cool title!');
$article->introtext        = '<p>This is my super cool article!</p>';

Den title können wir straight aus der wp_contents übernehmen, das ist der post_title. Für den alias bietet sich das Feld post_name an, der wäre auch schon URLsafe. Und der introtext kommt aus dem Feld post_content. Sieht doch schon mal ganz gut aus.

Was nicht gehen wird

So leid es mir tut, aber Bilder und Links können wir leider nicht übernehmen, die müssen wir vor dem Import rausputzen. Warum? Ganz einfach, weil sich beide auf eine spezifische URL beziehen, die wir in Joomla nicht nachstellen können. Nochmal kurz zur Erinnerung, ein im Beitragseditor eingefügtes Bild sieht im Quelltext so aus:

caption_screenshot

caption_screenshot

Mit dem caption-Shortcode kann Joomla natürlich auch nix anfangen, der muss raus. Mit dem Link gehts uns nicht viel anders, wenn der so aussieht:

ahref_screenshot

ahref_screenshot

…muss eigentlich der ganze Tag weg bis auf den Text „Haferflockenmüsli a la Oma“, mal sehen ob wir das hinkriegen.

Was drinbleiben kann

Ich geh mal nur vom Inselfisch-Kochbuch aus, da muss jeder sehen, wie das bei ihm selber aussieht und die Ersetzungen ggf. anpassen. Ich hab nicht so sehr viele Formatierungen verwendet, das sind eigentlich nur die Überschriften h1…maximal h4, ab und zu mal eine nummerierte oder unnummerierte Liste, und gelegentlich ein <strong>, das kann alles drinbleiben. Shortcodes oder auch Gallerys oder sowas hab ich gar nicht verwendet, da muss nix passieren. Downloadlinks haben wir gar keine, und auch keine Gimmicks wie Slider oder sowas, das habe ich im Zuge der barrierefreien Restrukturierung alles eliminiert – gute Sache! Jetzt ist nämlich nur noch relativ sauberer HTML-Code im post_content übrig, den man in den meisten Fällen übernehmen können wird.

Zuerst mal: Export aus WordPress

Ich zieh mir  nur die oben genannten drei Felder post_title, post_content und post_name ab, Kriterien post_type = post und post_status = publish. Nachgedanke: die ID nehmen wir auch noch mit, die ist ja unique und macht uns im phpmyadmin das Leben leichter. Davon nehm ich mal nur eine Handvoll Datensätze zum Testen, nicht gleich alle über 300. Die schiebe ich in eine neue MySQL-Tabelle  und dann frisch ans Werk!

Nicht konvertierbare Tags rausschmeissen

Den caption-Shortcode mitsamt dem img-Tag werden wir so los:

replace_caption

replace_caption

Sorry, das gibts nur als Screenshot weil WordPress den Sourcecode verhunzt hat! Das ist übrigens nicht auf meinem Mist gewachsen, das hat Tante Google hergegeben – sehr praktisch.

Ebenso können wir dank fleissigen googlens die alt-Tags entfernen, aber den Linktext stehen lassen:

$text = preg_replace('#<a.*?>(.*?)</a>#i', '\1', $text);

Das wars aber auch schon mit den Bereinigungen! Die ganzen <hx> und so weiter können stehenbleiben, wir wollen ja die Überschriftsformatierungen und all das mitnehmen.

Testausgabe mit der PHP Bridge

Ich hab mir ein Miniformular gebastelt, das nur aus einem „absenden“ Button besteht, und zum Testen in die if (isset($_POST[‚absenden‘])){…} Bedingung  folgenden Code gepackt:

$db = JFactory::getDBO();

$query = „SELECT * FROM 00_rohdaten where id = 224;“;
$db->setQuery($query);

$result = $db->query();
$results = $db->loadObjectList();

foreach ($results as $zeile) :
echo $zeile->id;
echo $zeile->titel;
$text = $zeile->content;

//caption-shortcode mitsamt img-tag weg
$text = preg_replace(‚/\\.*\\[.caption\\]/‘, “, $text);

//a href weg, Linktext stehen lassen
$text = preg_replace(‚#<a.*?>(.*?)</a>#i‘, ‚\1‘, $text);

//bereinigten text ausgeben
echo $text;
//echo $zeile->content;
echo „<br>“;
endforeach;
In den Select muss natürlich der richtige Tabellenname rein, und die ID des Datensatzes, den man zum Testen ausgeben möchte. In der Foreach-Schleife werden dann die Ersetzungen für den Content ausgeführt und das Endergebnis ausgegeben, so hat man eine ganz gute Kontrolle darüber, wie der importierte Datensatz in Joomla aussehen wird.

Und wie gehts jetzt weiter?

Ich tendiere dazu, mir die bereinigten Rohdaten in eine separate Tabelle schreiben zu lassen, und aus dieser dann die Import-Logik zu füttern. Aber darüber muss ich noch ein wenig nachdenken, und dann gibts einen neuen Beitrag.

So schnell geb ich nicht auf: Joomla-Artikel importieren, eine heisse Spur

Ich sitze ja hier immer noch auf über 300 Rezepten aus dem Inselfisch-Kochbuch und habe keine Lust, die per Copy&Paste nach Joomla reinzuschubsen, mehr zu dem Thema habe ich bereits in diesem Artikel erzählt. Jetzt bin ich bei Stackexchange auf einen vielversprechenden Ansatz gestossen, wie man einen Joomla-Artikel programmatisch erzeugen kann, mehr Infos hier:

https://stackoverflow.com/questions/12643725/create-a-joomla-article-programatically?lq=1

Im letzten Beitrag des Threads (Support Joomla 2.5 and Joomla 3.0) findet sich ein Sourcecode, der ohne weitere Modifikationen funktioniert. Ich zitier den mal hier rein:

if (version_compare(JVERSION, '3.0', 'lt')) {
    JTable::addIncludePath(JPATH_PLATFORM . 'joomla/database/table');        
}   
$article = JTable::getInstance('content');
$article->title            = 'This is my super cool title!';
$article->alias            = JFilterOutput::stringURLSafe('This is my super cool title!');
$article->introtext        = '<p>This is my super cool article!</p>';
$article->catid            = 9;
$article->created          = JFactory::getDate()->toSQL();
$article->created_by_alias = 'Super User';
$article->state            = 1;
$article->access           = 1;
$article->metadata         = '{"page_title":"","author":"","robots":""}';
$article->language         = '*';

// Check to make sure our data is valid, raise notice if it's not.

if (!$article->check()) {
    JError::raiseNotice(500, $article->getError());

    return FALSE;
}

// Now store the article, raise notice if it doesn't get stored.

if (!$article->store(TRUE)) {
    JError::raiseNotice(500, $article->getError());

    return FALSE;
}

(Quelle: https://stackoverflow.com/questions/12643725/create-a-joomla-article-programatically?lq=1)

Das sieht soweit gut aus, fehlt höchstens noch ein Eintrag für das Feld created_by (bei mir 839), und die metadata sehen bei mir in der Datenbank auch einen Hauch anders aus, aber das ist Kleinkram. Die catid wäre eigentlich immer 8 für Rezepte, das kann man fest verdrahten. Ich habs mal in den Sourcerer reingeschubst und ein paar mal laufen lassen, die neuen Artikel sind einwandfrei erzeugt worden.

So, jetzt gilts: wie kriegen wir unsere WordPress-Datensätze hier rein?

Eigentlich müssen wir nur diese drei Felder ordentlich füllen:

$article->title            = 'This is my super cool title!';
$article->alias            = JFilterOutput::stringURLSafe('This is my super cool title!');
$article->introtext        = '<p>This is my super cool article!</p>';

Schön wärs natürlich, wenn wir die WordPress-Kategorien als Tags mit übernehmen könnten, aber das wär nur ein extra-Zuckerl, jetzt kümmere ich mich erstmal um den Überbau, und der erfordert etwas Planung. Ich geh mal mein Denkmützerl aufsetzen und melde mich dann wieder mit einem neuen Beitrag.

 

Jetzt fehlt nur noch : der Inhalt!

Im Original Inselfisch-Kochbuch gibt es über 300 Rezepte, und die will ich eigentlich wirklich nicht händisch nach Joomla  reinkopieren. Also habe ich mich mal auf die Suche nach Import-Tools gemacht, und das Ergebnis war leider äusserst mager. Genauer gesagt, da war aber auch schon gar nix brauchbares dabei, zumindest nicht im Public-Domain-Bereich.

Das einzige Tool, das anscheinend Artikel und Kategorien direkt aus der WordPress-Datenbank importieren kann ist JConverter, und der kostet 25 $, das hab ich jetzt erstmal nicht eingesehen.  Dann gibt es noch J2XML, aber da war die Dokumentation nicht besonders aussagekräftig. Es scheint aber so zu sein, dass J2XML für den Datenimport/Export zwischen verschiedenen Joomla-Sites gedacht ist, das ist jetzt auch nicht das was ich brauche.

Was heisst hier „Bulk create“?

OSContent macht Werbung damit, wieviel Zeit und Aufwand man mit ihrem Tool bei der Erstellung neuer Joomla-Inhalte sparen kann. Ich habe mir die Free-Version installiert, und das präsentiert sich dann so:

mass_content

mass_content

OSContent präsentiert sich als recht spartanisches Formular, in das man Artikeldaten per Copy&Paste einfügen kann, für bis zu 10 neue Artikel auf einmal. Man kann hier den Titel, Alias, Intro-Text und Fulltext eintragen. Für alle 10 Artikel kann man dann noch eine Kategorie, einen Menu Link und ein Access Level angeben, sowie das Erstellungsdatum setzen. Für die Schlagwörter habe ich leider keine Option gefunden. Na ja, so im Prinzip würde das schon reichen um ein paar Rezepte aus WordPress zu übernehmen…

Aber ich werd doch nicht allen Ernstes über 300 mal die Rezeptdaten händisch hier reinkopieren! Im richtigen Leben ist das der Job für den Praktikanten, wenn  man es gar nicht anders hinkriegt. Aber professionell ist das nicht, und auch nicht so wirklich praxistauglich. Das müsste doch auch anders gehen, vielleicht mit einem CSV-Import…

Gibts nicht sowas wie wp_insert-post()?

Erinnern sie sich an den kleinen CSV-Importer für den Turnverein Weiss-Blau? Der basierte auf der sehr komfortablen WordPress-Funktion wp_insert_post(), die man mit ein paar ausgesuchten Parametern füttern kann und die auch in einer sehr minimalistischen Version schon brauchbare Ergebnisse liefert.

So etwas habe ich bei Joomla bisher vergeblich gesucht. Am ehesten in der Richtung geht noch dieser Artikel bei Stack Exchange: Create categories, subcategories and articles using php

Aber da gehts schon heftig ans Eingemachte, die Erzeugung eines neuen Artikels ist bei Joomla offenbar ein absolut nicht-trivialer Prozess, das hab ich mir jetzt erstmal nicht angetan. Damit bleibt die Frage, wie ich denn meine WordPress-Beiträge ins Joomla reinkriege, erstmal offen. Ich recherchiere weiter!

Beitragskategorien aus der Datenbank abfassen

Für Spitzenklöppler: das WordPress-Kategorienmodell

Um an die Beitragskategorien heranzukommen, muss man sich mit sage und schreibe 5 Tabellen herumschlagen. Das kommt daher, weil die WordPress-Entwickler das Kategorienmodell unbedingt mehrstufig anlegen mussten. Das ist zwar wunderbar verschachtelbar und ergibt ganz eindrucksvolle Baumstrukturen, aber datenverarbeitungstechnisch ist es meiner Meinung nach mit Kanonen auf Spatzen geschossen. Mit einer winzigen Ausnahme (die Backrezepte im Inselfisch-Kochbuch) habe ich noch in keinem meiner Blogs eine Unterkategorien-Ebene gebraucht, und damit das hier nicht allzu unübersichtlich wird, lasse ich es auch bei der einen Ebene. Haben sie ein bißchen Zeit? dann wollen wir mal.

Die relevanten Tabellen

Erstens natürlich die wp_posts, aus der holen wir uns die ID, also den Primärschlüssel der Beiträge. Dann brauchen wir noch:

  • wp_term_relationships
  • wp_term_taxonomy
  • wp_terms
  • (wp_termmeta, nein, die brauchen wir nicht, nur der Vollständigkeit halber erwähnt)

Warum das ganze mit Term und nicht mit Category bezeichnet ist: rein theoretisch kann man sich auch noch eigene Taxonomien anlegen, die dann eben nicht Kategorie heissen sondern einen eigenen Namen kriegen. Sowas hab ich anno Dunnerkeil mal in meinem Bilderblog gemacht, da gabs eine eigene Taxonomie „Jahreszeiten“, die bestand aus genau vier Einträgen, nämlich „Frühling, Sommer, Herbst, Winter“. Bin ich wieder davon abgekommen, ich hab die Jahreszeiten einfach in die erste Kategorieebene mit aufgenommen, geht auch und ist wesentlich einfacher zu verwalten. Aber das nur am Rande bemerkt, wir holen uns die Tabellen jetzt mal ins Access rein und basteln uns die nötigen Verknüpfungen.

Das Datenmodell im Detail

Die ersten beiden Tabellen: wp_term_relationships und wp_posts

Wichtig ist hier erstens die object_id, das ist die ID des Beitrags aus der wp_posts. Einem Beitrag können ja mehrere Kategorien zugeordnet sein, deshalb tauchen die IDs hier auch mehrfach auf. Die term_taxonomy_id verweist auf die Kategorie. Die term_order könnte man für eine benutzerdefinierte Sortierung der Kategorien verwenden, aber das geht jetzt zu weit, das lassen wir weg.

screenshot_term_relationships

screenshot_term_relationships

Wir basteln uns also die erste Verknüpfung mit der object_id auf die wp_posts.

screenshot_beziehnungen_posts_relationships

screenshot_beziehnungen_posts_relationships

Die dritte Tabelle: wp_terms_taxonomy

Hier wird es schon ein bißchen undurchsichtiger. Die ersten drei Felder ID, term_taxonomy_id und term_id haben alle den selben Wert, da kann man nur raten wofür welches gut ist. Da wir nur die term_taxonomy_id aus der wp_term_relationships eindeutig zuordnen können, nehmen wir die halt, und merken uns als Hauptschlüssel die ID. Im Feld taxonomy steht immer der Wert category, wir haben ja nur diese eine Taxonomie, das können wir auch weglassen. Interessanter wäre da noch das Feld „parent“, das die übergeordnete Kategorie im Falle verschachtelter Kategorieebenen enthält, aber auch das lassen wir mal aussen vor, sonst blickt hier kein Schwein mehr durch.

Kleine Kuriosität am Rande: hier wird ein count mitgeführt, der die Anzahl der Beträge zu einer Kategorie wiederspiegelt. Kann man das nicht nachher im Rahmen einer Abfrage berechnen?

screenshot_term_taxonomies

screenshot_term_taxonomies

Unsere Beziehungen sollten jetzt so aussehen:

screenshot_beziehungen_3

screenshot_beziehungen_3

Die vierte Tabelle: wp_terms

Na gottseidank, da blickt man wenigstens halbwegs durch. Die term_id können wir aus der wp_term_taxonomy zuordnen, der name (na endlich!) ist der Name der Kategorie, slug ist auch klar, und die term_group ignorieren wir einfach.

screenshot_wp_terms

screenshot_wp_terms

Jetzt kommt endlich Butter bei die Fische, wir können unsere Beziehungen vervollständigen.

screenshot_beziehungen_4

screenshot_beziehungen_4

Haben wir da nicht noch was vergessen?

Die Tabelle wp_termmeta

Ja, die gibts auch noch, aber ehrlich gesagt weiß ich nicht so ganz genau, wofür man die verwenden könnte, die zieht nur wenn man mit mehreren Taxonomien arbeitet. Bei marketpress gibt es eine gelehrte Abhandlung dazu, ich hab sie allerdings nicht ganz verstanden, muss ich zugeben. Nachdem die Tabelle allerdings bei mir immer leer ist, ignoriere ich sie schlicht und ergreifend.

Sonst noch was? Ach ja, ich hätts beinah vergessen:

Die Tags = Schlagwörter stecken in der selben Logik

Und zwar wird für die Schlagwörter eine eigene Taxonomie „post_tag“ angelegt. Ich verwende prinzipiell keine Schlagwörter, wenn sie es getan haben lassen sie sich nicht irritieren, uns reichen die Beziehungen über die Kategorien.

Und jetzt: die Abfrage der Kategorien über alle vier Tabellen

Anmerkung: damit das hier nicht total uferlos wird, beschränke ich mich hier auf eine Kategorieebene. Sie sehen gleich, warum: Wir holen uns zunächst mal eine Auswahl relevanter Daten aus allen vier Tabellen, der SQL sieht dann so aus:

SELECT wp_posts.ID, wp_posts.post_title, wp_term_relationships.object_id, wp_term_relationships.term_taxonomy_id AS wp_term_relationships_term_taxonomy_id, wp_term_taxonomy.term_taxonomy_id AS wp_term_taxonomy_term_taxonomy_id, wp_term_taxonomy.term_id AS wp_term_taxonomy_term_id, wp_term_taxonomy.taxonomy, wp_term_taxonomy.count, wp_terms.term_id AS wp_terms_term_id, wp_terms.name
FROM wp_terms INNER JOIN ((wp_posts INNER JOIN wp_term_relationships ON wp_posts.[ID] = wp_term_relationships.[object_id]) INNER JOIN wp_term_taxonomy ON wp_term_relationships.[term_taxonomy_id] = wp_term_taxonomy.[term_taxonomy_id]) ON wp_terms.[term_id] = wp_term_taxonomy.[term_id];

Das Ergebnis: eine schon mal relativ übersichtliche Tabelle

Hier taucht jedes Rezept so oft auf, wie es Kategorien zugeordnet hat. Wenn wir jetzt ausser den Kategorien noch Schlagwörter mit drin hätten, müssten wir die herausfiltern, aber haben wir nicht, alles brav nur Kategorien.

screenshot_kategorien_rohdaten

screenshot_kategorien_rohdaten

Ein kleiner Kunstgriff: die Abfrage auf der Abfrage

Damit ich mir keinen Wolf parametrisiere, habe ich einfach auf die eben gezeigten Rohdaten (die Abfrage heisst auch kategorien_rohdaten) eine zweite Abfrage aufgesetzt, die ist schon übersichtlicher:

SELECT Count(kategorien_rohdaten.[ID]) AS AnzahlvonID, kategorien_rohdaten.[name]
FROM kategorien_rohdaten
GROUP BY kategorien_rohdaten.[name];

Auf Deutsch: ich zähle nur die Beitrags-IDs zu jeder genannten Kategorie, und fasse pro Kategorie die Summe zusammen. Das Ergebnis:

screenshot_kategorien_endergebnis

screenshot_kategorien_endergebnis

Na bitte, geht doch 🙂

Nur noch ein kleiner Glitch ist drin: die Summe beim Backwerk stimmt nicht. Das kommt daher, dass ich bei den Backwerken drei Unterkategorien angelegt habe, nämlich „Kuchen und Torten“, „Weihnachtsbäckerei“ und „Pikante Bäckereien“. Allerdings erlaubt es einem WordPress beim Erstellen oder Bearbeiten eines Beitrags, eine Unterkategorie anzugeben ohne auch die übergeordnete Hauptkategorie anzukreuzen, das habe ich offensichtlich einige Male gemacht, und daher stammt der Zählfehler. Die Korrektur ist einfach: ich entferne die Kategorie Backwerk und behandle die drei Unterkategorien wie Kategorien erster Ordnung, mein Excel für das Tortendiagramm kann mit Unterkategorien eh nix anfangen 🙂

Ich überlasse es jedem, der mit mehr als einer Kategorieebene gearbeitet hat selber, da die Logik entsprechend rauszupfriemeln, da muss man in der wp_terms_taxonomy den parent berücksichtigen, das ist mir jetzt hier zuviel Gedöns. Das hier langt jetzt nämlich echt für einen Beitrag, der hier ist lang genug – schließlich ist ja schon fast Feiertag!

 

 

 

 

 

 

 

 

Kategorien im Inselfisch-Kochbuch, statistisch aufbereitet (kleine Schummelei)

Der einfache Weg – ich schummle ein bißchen

Ich lass mir ja die Beitrags-Kategorien im Inselfisch-Kochbuch in der Sidebar anzeigen, mit der Anzahl der jeweiligen Beiträge, das sieht so aus:

screenshot_kategorien

screenshot_kategorien

Und weil ich manchmal ein bißchen ein Faulpelz bin, kopier ich mir den ganzen Schamott als unformatierten Text in eine Spalte ins Excel rein, hacke mir in der zweiten Spalte die Anzahlen manuell rein und bastel mir mein erstes Tortendiagramm:

Rezeptkategorien-Diagramm

kategorien_torte

kategorien_torte

Nanü, ich hab also am allermeisten vegetarische Rezepte eingestellt? Darüber liesse sich debattieren, schließlich habe ich auch alle Kuchen, Torten und Süßspeisen als „vegetarisch“ kategorisiert. Kann ich aber damit leben, darunter fallen nämlich auch alle Salate und Gemüsezubereitungen, und sowas esse ich täglich, das hat schon seine Richtigkeit.

Rang zwei mit 99 Rezepten hat die Kategorie „Für Kinder“, und auch das hat seine Richtigkeit, denn schließlich stelle ich auch viele Rezepte aus meiner Kinderzeit aus Omas Küche ein, die werden von den Kiddies heute auch noch geliebt!

Der Rest spiegelt getreulich wieder was ich selber oft und gerne esse. Mir sind gute Saucen genauso wichtig wie das Stückchen Fleisch auf dem Teller, und meine ganz große Liebe gehört der Mittelmeerküche. Ausserdem esse ich viel Gemüse, und Kuchen gebacken wird bei mir auch regelmäßig.

Fazit: Ins Inselfisch-Kochbuch kommen nur Rezepte, die garantiert ausgetestet sind und die bei mir selber oft auf den Tisch kommen. Deshalb sind auch die Zubereitungsbeschreibungen sehr genau und gut nachzuvollziehen, so daß die Rezepte leicht und gelingsicher nachzukochen sind. Mein Publikum mag es so – Rezepte für jeden Tag sind gefragt, keine ausgefallenen Exoten! Ich bleibe bei dieser Philosophie, und schreibe weiter nur das hinein, was ich auch selber gern koche und esse.

Ja, aber das war doch geschummelt!

Klar wars geschummelt – aber die Kategorien zu den Beiträgen aus der WordPress-Datenbank zu holen ist ein Späßchen für sich, und dazu gibt es einen neuen Beitrag.