Import dat z CSV do Drupalu 8

Jan Nobilis   28. 6. 2019


Potřebujete dostat CSV data z podnikového informačního systému na web? Ukážeme si, jak správně nastavit redakční systém a vytvořit vlastní importy. A pokud narazíte na problém s různým  kódováním textu v rámci jiných operačních systémů, mám pro vás jednoduché řešení.

Pokud tvoříte nový web, dříve nebo později za vámi přijdou klienti s požadavkem, že by se jim vlastně hodila nějaká část stránek dostupná pouze pro obchodní partnery. Měla by sloužit jako přehled objednávek, faktur a kontaktních údajů, ideálně také zobrazovat vybraný obsah pouze některým uživatelům.

Podobný požadavek přišel ze společnosti Fenstar s.r.o., pro kterou jsme realizovali webové stránky v několika grafických variantách dle trhu, kde působí. U webů jsme museli nově vyřešit například vícejazyčnost, omezení obsahu na konkrétní uživatelské skupiny a rozdílná práva uživatelů v administraci redakčního systému.

Řešení jsme měli postavené na redakčním systému Drupal 8, museli jsme ho ale propojit s daty z uzavřeného interního systému zadavatele. Jenže jak na to? API ani žádný můstek použít nešlo. Rozhodli jsme se pro automatický export dat z podnikového informačního systému ve formátu CSV, a následné uložení na privátní úložiště, ze kterého si data načítá webová prezentace.

V následujícím textu vám ukáži, jak na to – tedy jak importovat CSV data do Drupalu 8. Projdeme si jednotlivé kroky:

  1. základní nastavení redakčního systému
  2. instalaci nezbytných modulů, které nám s vložením do systému pomůžou
  3. konkrétní příklad importu obsahu
  4. automatizaci celého procesu

Pokusím se také shrnout problémy, na které můžete při zpracovávání souborů narazit – často je na vině jiný operační systém než ten, na kterém běží vaše aplikace/web.

O každém kroku bych mohl napsat samostatný článek, a je možné, že některé části budou jen klouzat po povrchu. Zajímá vás nějaké téma podrobněji? Určitě napište do komentářů – můžeme se na něj zaměřit v dalším článku.

Příprava redakčního systému:

Pro začátek budeme potřebovat redakční systém Drupal 8, v době psaní článku byl ve verzi 8.7.1. Povolíme v něm modul Migrate, díky kterému můžeme exportovat a importovat jeho nastavení.

Jestli ještě nemáte Drush, nainstalujte ho. Díky němu můžeme ovládat redakční systém z příkazové řádky, což oceníme později při nastavování automatických úloh.

Dále nainstalujeme a povolíme moduly:

Pokud máme uvedené moduly správně nainstalované, Drush nám nabídne následující akce pro práci s migracemi:

migrate:
   migrate:status (ms)                        List all migrations with current status.
   migrate:import (mim)                       Perform one or more migration processes.
   migrate:rollback (mr)                      Rollback one or more migrations.
   migrate:stop (mst)                         Stop an active migration operation.
   migrate:reset-status (mrs)                 Reset a active migration status to idle.
   migrate:messages (mmsg)                    View any messages associated with a migration.
   migrate:fields-source (mfs)                List the fields available for mapping in a source.

K nim se ještě vrátíme. Teď se pustíme do vytváření naší první migrace, a v ní importujeme hodnoty do konkrétního typu obsahu z automaticky generovaného CSV souboru.

Vytvoření migrací

Migraci si ukážeme na příkladu importu informací k fakturám do partnerské zóny redakčního systému. Data v příkladech jsou anonymizována.

Nejdříve se podívejme na pole, které chceme klientovi v partnerské zóně zobrazit. Na obrázku níže vidíte jejich názvy a definici datových typů.

  • Cena bez DPH a Cena celkem - definovali jsme je jako číselné hodnoty typu float,
  • Datum vystavení - zvolili jsme typ datum,
  • Čísla objednávek - pro jednoduchost jsme použili typ řetězec,
  • Číslo faktury - jde vlastně o duplicitní hodnotu, už ji vkládáme do titulku obsahu.

Kdybychom měli konzistentní data, čísla objednávek jde přiřadit ke konkrétním objednávkám jako reference, a tím jednotlivé typy obsahu provázat.

Získali jsme výčet polí, které potřebujeme z CSV souboru naplnit - strukturu vidíte na obrázku níže, názvy sloupců se liší od strojových názvů v redakčním systému. Jako oddělovač jsme použili znak | (hex 7Fh):

Nyní se můžeme pustit do přípravy samotné migrace. V administraci redakčního systému na adrese [vaše_doména]/admin/config/development/configuration/single/import
(v menu: Nastavení > Configuration synchronization > Import > Jednotlivá položka) vybereme „Typ konfigurace: Migrace“ a vytvoříme migraci, kterou chceme v systému používat.

Následující migrace umožňuje vložení faktur do redakčního systému. Souboru je ve formátu YAML, komentáře přidávám vždy na konkrétní řádek.

langcode: en
status: true
dependencies: { }
id: Migrate_import_invoices # zde nastavíme jedinečný název migrace
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags: null
migration_group: null
label: 'Invoice import from CSV' # můžeme nastavit název migrace
source:
  plugin: csv # nadefinujeme plugin, který se má použít pro zpracování souborů – v našem případě import z CSV
  path: /home/sobol/clanek/faktury-UTF.csv # cesta k souboru s daty, které chceme vložit do systému
  delimiter: '|' # oddělovač sloupců v CSV souboru
  header_row_count: 1 # nadefinujeme řádek s hlavičkou
  keys:
    - c_faktury # unikátní klíč, podle kterého může Drupal importovat záznamy. Je ho potřeba vhodně zvolit, většinou to bude ID záznamu
process:
  default_value: faktury # typ obsahu, do kterého chceme importovat
  title: c_faktury # titulek obsahu – použili jsme číslo faktury
  field_due_date: # pro importování data splatnosti musíme převést datum na formát, který bude Drupal ochoten uložit do databáze
    plugin: format_date # Drupal při importu podporuje využití  různých pluginu. Vždy záleží, co potřebujeme s daty provádět
    from_format: d.m.Y
    to_format: 'Y-m-d\TH:i:s' # můžeme použít stejnou interpretaci času, jak ji známe z PHP
    timezone: GMT
    source: datum_vytvoreni_faktury # vstupní pole s datem splatnosti
  field_invoiceamount: netto # pole s částkou bez DPH
  field_salesbalance: brutto # pole s částkou s DPH
  field_invoice_number: c_faktury
  field_order_numbers: prodejni_objednavky # pole s informacemi o objednávkách, kterých se faktura týká
  uid: # faktury přiřazujeme konkrétním uživatelům; musíme ověřit, že zadaný uživatel existuje
    plugin: entity_exists
    source: ucet_faktury # pole s ID uživatele, který vytvořil danou objednávku
    entity_type: user
  destination: # definice typu obsahu, který se má vytvořit
    plugin: 'entity:node'
    default_bundle: faktury
  migration_dependencies:
    required: { }

Jestli jsme udělali vše správně, po stisknutí tlačítka Import dojde k importu konfigurace migrace. Příkaz

$ drush migrate:status

nám vypíše:

S vytvořenou migrací a souborem se zdrojovými daty můžeme import spustit i příkazem:

$ drush migrate:import Název_migrace

Importujete tisíce řádků obsahu? V tom případě se pro testování hodí nějaké omezení. Pro limit importu například na 100 položek použijeme:

$ drush migrate:import Název_migrace --limit="100 items"

Chceme raději omezit čas importu? Stačí vyměnit „items“ za „seconds“:

$ drush migrate:import Název_migrace --limit="60 seconds"

Po úspěšném importu nám příkaz

$ drush migrate:status

vypíše počty záznamů, které se (ne)úspěšně vložily do systému a jejich celkový počet.

Něco se nepodařilo podle našich představ? Právě importovaná data vymažeme z databáze pomocí:

$ drush migrate:rollback Název_migrace

V administraci si pak můžeme chybnou migraci upravit. Na adrese [vaše_doména]/admin/config/development/configuration/single/export(nebo v menu: Nastavení > Configuration synchronization > Export > Jednotlivá položka) zvolíme typ konfigurace „Migrace“ a vybereme tu, kterou chceme editovat. Zobrazí se v textovém poli níže, odkud ji jednoduše zkopírujeme, podle potřeby upravíme, a znovu naimportujeme. Pozor, aby ji Drupal správně nahradil a nevytvářel novou migraci, musíme na stránce pro import rozkliknout „Pokročilé“ a vložit její ID.

Finišujeme

Pokud vše funguje jak má, nastavíme automatické úlohy, které nám budou pravidelně importovat záznamy do redakčního systému. Můžeme ale narazit na problém s různým kódováním vstupních souborů – nejčastěji se objeví, když importujeme data exportována z MSSQL do aplikace, která poběží na Linuxu. U těchto vstupních souborů musíme nejdřív změnit kódování,

$ iconv -f UCS-2LE -t UTF-8 vstup.csv > vstup-UTF.csv

a také odstranit systémové a bílé znaky, které nepotřebujeme:

$ cat vstup-UTF.csv | sed $'s/[^[:print:]\t]//g'|sed '1 s/^\xef\xbb\xbf//' > vstup-UTF-ok.csv

Teprve tento výstup s upraveným kódováním a ořezaný o systémové znaky můžeme použít. Pokud je vše v pořádku a systém detekuje CSV, stačí v Linuxu použít příkaz

$ file nazev_souboru

Jestli ale ohlásí datový soubor, nezbude vám než řádek po řádku hledat znaky, které správné načtení znemožnily.

Automatické spouštění importů můžeme následně nastavit pomoci cron úloh. Zadejte čas, kdy se mají vstupní soubory zpracovat, a pomocí Drushe je pak vložte do systému.

To by bylo ve zkratce vše. V seznamu zdrojů najdete více informací o pluginech, které je možné použít pro práci s migracemi, úpravu vstupů nebo nastavení vazeb mezi typy obsahu. Chcete se o nějaké části dozvědět více? Určitě napište do komentáře.

Zdroje: