Jak na import kategorií a obsahu do WordPressu z libovolného zdroje

Nedávno jsem byl postaven před úkol importovat do WordPressu obsah webového magazínu, pro který původní dodavatel poskytl data jako XML. Bez dokumentace a ve vlastní struktuře. API WordPressu naštěstí umožňuje vytvářet jak obsah, tak třeba kategorie programovou cestou.

Reklama

Pokud stavíte weby na WordPressu častěji, pak jste se asi někdy s potřebou importu dat už setkali. Tento redakční systém má nějaký import v sobě. Podporuje vlastní formát WXR, WordPress eXtended RSS. To může obsahovat příspěvky, stránky, vlastní typy obsahu, políčka, komentáře, kategorie, tagy, slovníky a uživatele.

Nevím, jaká je vaše praxe, ale já se často setkávám s tím, že při importu je potřeba data nějak jinak zařadit. Zároveň je potřeba při importu hromadně nahradit některé řetězce (třeba URL adresy). Je potřeba stáhnout obrázky a rozházet je do jiných než původních složek. A tak by se dalo pokračovat.

V takovém případě pak WXR není cesta, po které se vydat. A to nemluvím o tom, že jen málokdy se dostanete k WXR u dat, která nepocházejí z jiné instalace WordPressu, ale z nějakých na míru psaných řešení.

Nedávno jsem podobný případ opět řešil. K dispozici byla sada různých souborů ve formátu XML. Když to zjednoduším, samostatně byl seznam kategorií, v jiném souboru pak byly články.

Zvolil jsem řešení v příkazovém řádku

Netuším, jestli má WordPress nějaké API na dávkové zpracování jako například Drupal. Spíše bych pochyboval. Měl jsem k dispozici vstupní XML v řádech horních desítek megabajtů a potřeboval jsem při importu stahovat obrázky z externího zdroje.

Rovnou jsem zavrhl nějaké vytváření formuláře pro upload XML a zpracování importu přes administrační rozhraní WordPressu. Pravděpodobně by to bez dávkového zpracovávání spadlo na timeoutu v PHP.

Příkazový řádek však na timeouty nehraje, takže po dobrých zkušenostech s importem do Drupalu přes drush a příkazový řádek jsem chtěl provést něco podobného i ve WordPressu. A povedlo se.

Připravil jsem jediný soubor spouštěný příkazem php soubor-pro-import.php. V tomto souboru připojuji jádro WordPressu, abych měl k dispozici jeho funkce a průběžně do příkazového řádku vypisuji názvy importovaných položek, abych měl nějakou vizuální kontrolu.

Základ souboru umístěného v kořenové složce WordPressu je tedy následující:

<?php
$time_start = microtime(true);
print "Import započal \n";
require( dirname(__FILE__) . '/wp-load.php' );
require(dirname(__FILE__) . '/wp-config.php');
require(dirname(__FILE__) . '/wp-admin/includes/taxonomy.php');
importKategorii();
importClanku();
$time_end = microtime(true);
$time = $time_end - $time_start;
print sprintf("Import ukončen, trvání %.4f sekund.\n", abs($time));
?>

V případě, že nebudete importovat kategorie či tagy, pak nepotřebujete třetí require se souborem taxonomy.php.

Každý výpis přes print (měl bych ve WP používat echo?) je ukončen znakem pro nový řádek. Musí tedy být v uvozovkách, ne v apostrofech.

Import kategorií

Začínám importem kategorií, případně tagů. Články do nich budu následně párovat, takže je třeba mít kategorie připravené jako první. Následující kód předpokládá tuto strukturu souboru s kategoriemi:

<categories>
  <row>
    <name>nějaká kategorie</name>
    <description>popisek kategorie</description>
    <url>nejaka-kategorie</url>
  </row>
<categories>

Samotný kód pro import kategorií je pak následující:

function importKategorii(){
  $content = file_get_contents(dirname(__FILE__) . '/kategorie.xml');
  $categories = new SimpleXmlElement($content);
  foreach($categories->row as $category){
    $result = wp_insert_term(
      $category->name, 
      'category', 
      [
        'description' => $category->description, 
        'slug' => $category->url
      ]
    );
    if( is_wp_error( $result ) ) {
      print $result->get_error_message()."\n";
      die;
    }    
  }
}

Načte se celý soubor XML, zpracuje se přes SimpleXmlElement v PHP a smyčkou se projdou jednotlivé záznamy row v tomto XML.

Ve smyčce je volána funkce WordPressu pro vytvoření nového termínu v kategorii. Zároveň vyplňuji popisek kategorie a její URL adresu, slug. Poté následuje pouze ukončení procesu při výskytu chyby.

Pokročilejší ošetření chyb nemám. Pokud se vyskytla chyba, například kvůli nekonzistenci dat, opravil jsem XML, obnovil databázi WordPressu a pustil jsem import znovu. Přišlo mi to jako nejrychlejší řešení, byť ne příliš sofistikované. Ale šlo o jednorázový import.

Tip: pokud nechcete ukládat kategorie, ale tagy, pak nahraďte ve funkci wp_insert_term() řetězec category coby druhý parametr řetězcem post_tag.

Import článků a stažení obrázků

Funkce pro import článků začíná podobně, jako výše uvedený import kategorií. Načtu XML soubor se seznamem článků, zpracuji je jako SimpleXmlElement a smyčkou projdu jednotlivé řádky.

function importClanku(){
  $content = file_get_contents(dirname(__FILE__) . '/clanky.xml');
  $clanky =  new SimpleXmlElement($content);
  foreach ($clanky as $clanek){
    $cats = array();
    $tags = array();
    // do $cats a $tags přiřaďte IDčka kategorií, resp. tagů
    $postarr = [
      'post_date' => (string)$clanek->date,
      'post_author' => 2,
      'post_content' => (string)$clanek->content,
      'post_title' => (string)$clanek->title,
      'post_status' => 'publish',
      'post_type' => 'post',
      'comment_status' => 'closed',
      'ping_status' => 'closed',
      'post_category' => $cats,
      'tags_input' => $tags,
      'post_name' => (string)$clanek->url,
      'meta_input' => [
        '_yoast_wpseo_title' => (string)$clanek->page_title,
        '_yoast_wpseo_metadesc' => (string)$clanek->description,
        //'wpcf-policko' => (string)$clanek->policko,
      ],
    ];
    $result = wp_insert_post($postarr, true); 
    if( is_wp_error( $result ) ) {
      print $result->get_error_message()."\n";
    }
    else{
      $imgUrl = (string)$clanek->image;
      Generate_Featured_Image( $imgUrl, $result );         
      print 'Importován článek '.(string)$clanek->title."\n";
    }   
  }
}

Ve smyčce si připravím pole obsahující data k importovanému článku. Kompletní info najdete v dokumentaci, já jsem použil pouze základní položky, které měly vliv na daný web. Datum se vkládá v ISO formátu, autor jako číslo uživatele v databázi. Následuje řetězec s tělem článku a také jeho titulek.

Čtveřice řetězcových hodnot udává, že je článek publikovaný, že je o článek (nikoli o stránku page), že jsou zavřeny komentáře a zakázáno pingování.

Kategorie a tagy jsou definovány pomocí pole obsahujícího IDčka všech termínů, které zde chcete zařadit. ID příslušného termínu získáte následovně:

$tag_obj = get_term_by('name','Nějaká kategorie', 'post_tag');
$tags[] = $tag_obj->term_taxonomy_id;

Zastavil bych se ještě u možnosti importovat titulek stránky a popisek pro vyhledávače. Ve výše uvedené ukázce kódu vidíte, jak vypadá definice pro import těchto dat v případě, že používáte plugin Yoast SEO.

Zastavil bych se ještě u možnosti importu dat do vlastních políček. Já s oblibou používám plugin WP Types ze sady Toolset, který na políčkách stojí. Tato část se importuje pod meta_input, kde uvedete strojový název pole a k němu přiřazenou hodnotu. WP Types zde mají vždy prefix wpcf-.

K vytvoření záznamu poslouží funkce wp_insert_post(). Zde po zjištění, že nedošlo k chybě, ale na rozdíl od kategorií ještě pokračuji. Články potřebují svoje úvodní obrázky. V tomto případě jsem ještě do kódu doplnil funkci Generate_Featured_Image(), která ze zadané adresy stáhne obrázek, uloží jej do WordPressu a přiřadí jej k článku, který máme v proměnné $result vystoupivší z funkce wp_insert_post().

Tělo funkce pro uložení obrázku jsem si vypůjčil ze StackExchange, kde ji najdete v první odpovědi.

Import do WordPressu není složitý

Jak vidíte, import dat do WordPressu není složitá záležitost. Dost záleží na konzistenci vstupních dat. Já se třeba potýkám s propojením článků a kategorií přes ID, která samozřejmě neodpovídají těm ve WordPressu a bylo je potřeba ošetřit.

Také jsem musel pospojovat tělo článku z několik segmentů ve vstupním XML tak, aby výsledkem byl článek zobrazující kapitoly přes Multipage Plugin. Kvůli zachování URL adres jsem potřeboval ještě plugin Custom Permalinks umožňující vkládat do adresy článku lomítka.

Jinak jsem na vážnější problém zatím nenarazil. Jak importujete data do WordPressu vy? Sázíte na nějaký univerzální plugin nebo používáte vlastní řešení?

Tagy: 

Reklama

Přidat komentář