

„Adott egy paragraph, ami további paragraphokra hivatkozik. Szeretnék a hivatkozó elemre egy plusz classt tenni, ami a hivatkozott elem típusától függ. Ha egy képre hivatkozik, akkor »aside-image«, ha szövegre, »aside-text«.” Ezzel a kéréssel fordultam nemrégiben a többiekhez.
A segítségemre Vince sietett, aki néhány tisztázó kérdés után szállította a működő kódot. Én meg – amellett, hogy örültem nagyon – csak néztem, hogy miként oldotta meg ezt így, pikk-pakk!
Pár nappal ezelőtt ezt is elmesélte.
Jó, jó de minek ez az egész?
A látványterven, amit kaptam, kéthasábos elrendezés szerepel. A fő hasáb mindig szöveg, mellette azonban kép vagy szöveg is megjelenhet. És attól függően, hogy mi van oldalt, más-más a két hasáb közötti távolság illetve a kiegészítő mérete is.
Nem szerettem volna emiatt két külön hivatkozó paragraph típust létrehozni. És a leendő tartalomszerkesztőket sem akartam azzal terhelni, hogy külön be kelljen jelölniük, milyen típusú kiegészítőt választottak. Az tűnt az elegáns megoldásnak, hogy automatizáltan jelenítünk meg egy classt, amivel a doboz layoutot tudom befolyásolni. Hiszen a szükséges típus adat elérhető a rendszerben!
No igen. Elérhető. Hogyan is?
Első lépés: theme suggestions és preprocess
A paragraphs modul háromféle theme hook suggestion-t ad meg.
-
paragraph__[view_mode]
(pl.paragraph--default.html.twig
) -
paragraph__[type]
(pl.paragraph--image.html.twig
) -
paragraph__[type]__[view_mode]
(pl.paragraph--image--default.html.twig
)
Ez az információ még megtalálható a dokumentációban is, Vince azonban – az egyszerűség kedvéért – a modul forráskódjában kereste meg.
Fontos tudni, hogy a theme hook suggestion-ök, nem csak a használandó template-re adnak javaslatot, hanem az elem renderelése során meghívandó preprocess függvények listáját is bővítik.
Így a következő logikus lépés a paragraphs alapértelmezett preprocess funkciójának a megvizsgálása volt.
Eredet, avagy: mélyebbre kell menni
„Szerencsére” a hivatkozás szabványos módon, mezőn keresztül történik. A mezőkhöz mindig tartozik adatbázis tábla, aminek a felépítése meghatározott struktúrát követ.
A field táblák első 3 mezője az értéket tartalmazó entitást írja le (bundle, entity_id, revision_id). A következő 3 (deleted, langcode, delta) a konkrét értékre vonatkozik: Törölt érték? Milyen nyelvű az érték, hányadik elem a több elemű listában?
Minden további oszlopot a mező típusa határoz meg. Egyszerű típusoknál egy plusz oszlop lesz, aminek a neve általában a [field neve]_value
mintát követi.
Az összetett esetben a mező típusa határozza meg, hogy milyen nevű és típusú oszlopok lesznek a táblában.
Sorról-sorra
Íme a kész megoldás:
/** * Implements hook_preprocess_paragraph(). * * Paragraph preprocess for ‘Text and Aside’ typed paragraphs. */ function THEMENAME_preprocess_paragraph__text_and_aside(&$variables) { /** @var Drupal\paragraphs\Entity\Paragraph $paragraph */ $paragraph = $variables['elements']['#paragraph']; foreach ($paragraph->get('field_paph_aside')->getValue() as $item) { /** @var Drupal\paragraphs\Entity\Paragraph $sub_item */ $sub_item = \Drupal\paragraphs\Entity\Paragraph::load($item['target_id']); $variables['attributes']['class'][] = 'aside-' . $sub_item->bundle(); } }
Nézzük meg, mi micsoda a fenti kódban:
function THEMENAME_preprocess_paragraph__text_and_aside(&$variables)
Ez a függvény a sminkben egy preprocess hook-ot valósít meg, ami a Text and aside típusú paragraph-ok megjelenítésére lesz hatással.
/** @var Drupal\paragraphs\Entity\Paragraph $paragraph */
A @var
komment sorokat a fejlesztő környezet (ld: IDE, PHPStorm) számára ad információt, hogy a $paragraph
változó milyen típusú értéket tartalmaz. Erre az információra építve tudja a kódkiegészítést építeni.
A $variables
-ben megkaptuk az éppen megjelenített paragraph entitást is.
$paragraph = $variables['elements']['#paragraph'];
Az éppen megjelenített $paragraph
-tól elkérjük az általa hivatkozott paragraphokat és végignézzük mindegyiket.
foreach ($paragraph->get('field_paph_aside')->getValue() as $item) {
A hivatkozott paragraph-ot az azonosítója alapján betöltjük...
$sub_item = \Drupal\paragraphs\Entity\Paragraph::load($item['target_id']);
... majd elkérjük, hogy milyen típusú (bundle). Ezt az értéket használva a hivatkozó paragraph class listájához adunk egy új elemet.
$variables['attributes']['class'][] = 'aside-' . $sub_item->bundle();
Az eredmény
Epilógus: Preprocess nélkül
A preprocess nem az egyetlen módja, hogy a szükséges class-t hozzáadjuk a hivatkozó paragraph-hoz. Létrehozhatunk egy saját twig sablont (paragraph--text-and-aside.html.twig) a számára. Ebben a következőképp hozhatjuk létre a hivatkozott elem típusát tartalmazó változót (amit aztán class-ként hozzáadhatunk az attribútumokhoz):
{% set aside_bundle = paragraph.field_paph_aside.entity.type.0.target_id %}
Ez a megoldás Mark Conroy-tól származik, a DrupalTwig Slack csatornából.
…
Köszönet Vincének a fenti bejegyzés elkészítésében nyújtott segítségéért is!
Oszd meg ismerőseiddel!