logo

Dodatni tipovi blokova (EBT) - Novo iskustvo rada sa Layout Builder-om❗

Dodatni tipovi blokova (EBT) – stilizovani, prilagodljivi tipovi blokova: slajdšouvi, kartice sa tabovima, kartice, akordeoni i mnogi drugi. Ugrađena podešavanja za pozadinu, DOM Box, javascript dodatke. Iskusite budućnost kreiranja rasporeda već danas.

Demo EBT moduli Preuzmite EBT module

❗Dodatni tipovi pasusa (EPT) – Novo iskustvo rada sa pasusima

Dodatni tipovi pasusa (EPT) – analogni skup modula zasnovan na pasusima.

Demo EPT moduli Preuzmite EPT module

Scroll
20/06/2025, by Ivan

Ovaj tutorijal je prvobitno objavljen na Web Wash. Međutim, Berdir je pitao mogu li da postavim tutorijal ovde, pa je sada ovde.

Modul za Drupal 7 omogućava skladištenje primera koda/fragmenata u polju. Dolazi sa prilagođenim poljem pod nazivom „Field Snippets“ koje prikazuje tri elementa forme: opis, izvorni kod i režim isticanja sintakse (koji programski jezik).

Ali sada je vreme da se modul ažurira za Drupal 8.

U ovom tutorijalu pokazaću vam kako sam napravio „osnovno“ prilagođeno polje u Drupalu 8. Neću ulaziti u detalje o PSR-4, anotacijama ili plugin API-ju, jer bi tada tutorijal bio preopsežan.

Umesto toga, dodaću linkove ka drugim sajtovima koji detaljnije objašnjavaju ove koncepte.

Ako tražite detaljnu dokumentaciju o Field API-ju u Drupalu 8, pogledajte sledeće serije:

U Drupalu 8 polja se ne implementiraju korišćenjem hook funkcija kao u Drupalu 7. Umesto toga, kreiraju se preko novog Drupal 8 plugin API-ja. To znači da umesto hook-ova definišemo klase za vidžet, formatere i tipove polja. Većina hook-ova iz Drupala 7, kao što su hook_field_schema, hook_field_is_empty i drugi, sada su metode u klasama.

Korak 1: Implementacija elementa polja

Prvi korak je definisati klasu elementa polja pod imenom SnippetsItem koja nasleđuje klasu FieldItemBase.

1. U Drupalu 8 klase se automatski učitavaju preko PSR-4 standarda.

Zato, da definišemo klasu SnippetsItem, potrebno je kreirati fajl SnippetsItem.php u „modulu“ na putanji /src/Plugin/Field/FieldType/SnippetsItem.php

/**
 * @file
 * Contains \Drupal\snippets\Plugin\Field\FieldType\SnippetsItem.
 */

namespace Drupal\snippets\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;

Zatim u fajl dodajemo namespace Drupal\snippets\Plugin\Field\FieldType i tri use naredbe:

  • Drupal\Core\Field\FieldItemBase,
  • Drupal\Core\Field\FieldStorageDefinitionInterface,
  • Drupal\Core\TypedData\DataDefinition.

2. Sada treba definisati detalje polja, kao što su ID polja, labela, podrazumevani vidžet, formaterski plugin itd. Ovo je ekvivalent hook_field_info u Drupalu 7.

U Drupalu 8 mnogi, ako ne i svi, info hook-ovi su zamenjeni anotacijama.

/**
 * Plugin implementacija tipa polja 'snippets'.
 *
 * @FieldType(
 *   id = "snippets_code",
 *   label = @Translation("Snippets field"),
 *   description = @Translation("Ovo polje čuva fragmente koda u bazi."),
 *   default_widget = "snippets_default",
 *   default_formatter = "snippets_default"
 * )
 */
class SnippetsItem extends FieldItemBase { }

Dakle, umesto implementacije hook_field_info, definišemo polje kao anotaciju u PHP komentaru iznad klase.

Atributi anotacije su jasni, samo pazite da default_widget i default_formatter koriste ID-jeve vidžeta i formatera, a ne klase.

Ako želite da saznate više o anotacijama, posetite dokumentaciju o anotacijama plugina na drupal.org.

3. Sada kada imamo klasu elementa polja, treba definisati nekoliko metoda. Prvi je schema().

U Drupalu 7, kod kreiranja prilagođenog polja definisali smo njegovu šemu kroz hook_field_schema. U Drupalu 8 to radimo tako što dodajemo metodu schema() u klasu SnippetsItem.

Dokumentacija za schema API sadrži detalje o strukturi i opcijama šema niza.

/**
 * {@inheritdoc}
 */
public static function schema(FieldStorageDefinitionInterface $field) {
  return [
    'columns' => [
      'source_description' => [
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ],
      'source_code' => [
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
      ],
      'source_lang' => [
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ],
    ],
  ];
}

4. Sada treba dodati metodu isEmpty() i definisati šta znači prazan element polja. Ovo je ekvivalent hook_field_is_empty iz Drupala 7.

/**
 * {@inheritdoc}
 */
public function isEmpty() {
  $value = $this->get('source_code')->getValue();
  return $value === NULL || $value === '';
}

5. Poslednji metod koji dodajemo je propertyDefinitions().

/**
 * {@inheritdoc}
 */
static $propertyDefinitions;

/**
 * {@inheritdoc}
 */
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['source_description'] = DataDefinition::create('string')
      ->setLabel(t('Opis fragmenta'));

    $properties['source_code'] = DataDefinition::create('string')
      ->setLabel(t('Kod fragmenta'));

    $properties['source_lang'] = DataDefinition::create('string')
      ->setLabel(t('Programski jezik'))
      ->setDescription(t('Jezik fragmenta koda'));

    return $properties;
  }

Ovaj metod definiše tipove podataka koje polje sadrži. „Snippets“ polje ima samo tri vrednosti: opis, kod i jezik, pa ih ovde definišemo kao stringove.

Za više informacija pogledajte kako Entity API implementira Typed Data API na drupal.org.

Kliknite ovde za ceo fajl. Napomena: fajl treba ažurirati da bude u skladu sa PSR-4 specifikacijom, više informacija na https://www.drupal.org/node/2128865

Korak 2: Implementacija vidžeta polja

Sada kada smo definisali element polja, kreiraćemo vidžet polja. Potreban nam je klasa SnippetsDefaultWidget koja nasleđuje WidgetBase.

1. Kreirajte fajl SnippetsDefaultWidget.php u „modulu“ na putanji /src/Plugin/Field/FieldWidget/SnippetsDefaultWidget.php.

/**
 * @file
 * Contains \Drupal\snippets\Plugin\Field\FieldWidget\SnippetsDefaultWidget.
 */

namespace Drupal\snippets\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;

Proverite da je namespace fajla Drupal\snippets\Plugin\Field\FieldWidget i dodajte sledeće use naredbe:

  • Drupal\Core\Field\FieldItemListInterface
  • Drupal\Core\Field\WidgetBase
  • Drupal\Core\Form\FormStateInterface

2. Zatim definišite vidžet koristeći anotaciju, što je ekvivalent hook_field_widget_info u Drupalu 7.

/**
 * Plugin implementacija vidžeta 'snippets_default'.
 *
 * @FieldWidget(
 *   id = "snippets_default",
 *   label = @Translation("Podrazumevani snippets"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultWidget extends WidgetBase { }

Napomena: atribut field_types u anotaciji treba da koristi ID tipa polja. U ovom slučaju to je snippets_code, jer smo u @FieldType anotaciji definisali id = "snippets_code".

3. Na kraju, definišite formu vidžeta dodavanjem metode formElement() u klasu SnippetsDefaultWidget. Ovo je ekvivalent hook_field_widget_form u Drupalu 7.

/**
 * {@inheritdoc}
 */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

  $element['source_description'] = [
        '#title' => $this->t('Opis'),
        '#type' => 'textfield',
        '#default_value' => isset($items[$delta]->source_description) ? $items[$delta]->source_description : NULL,
      ];
  $element['source_code'] = [
        '#title' => $this->t('Kod'),
        '#type' => 'textarea',
        '#default_value' => isset($items[$delta]->source_code) ? $items[$delta]->source_code : NULL,
      ];
  $element['source_lang'] = [
        '#title' => $this->t('Izvorni jezik'),
        '#type' => 'textfield',
        '#default_value' => isset($items[$delta]->source_lang) ? $items[$delta]->source_lang : NULL,
      ];
  return $element;
}

Kliknite ovde da vidite ceo fajl. Napomena: potrebno je ažurirati fajl da bude u skladu sa PSR-4, više informacija na https://www.drupal.org/node/2128865.

Korak 3: Implementacija formaterskog plugina za polja

Poslednji deo slagalice je formaterski plugin za polje, koji pravimo tako što definišemo klasu SnippetsDefaultFormatter koja nasleđuje FormatterBase.

1. Kreirajte fajl SnippetsDefaultFormatter.php u „modulu“ na putanji /src/Plugin/Field/FieldFormatter/SnippetsDefaultFormatter.php.

/**
 * @file
 * Contains \Drupal\snippets\Plugin\Field\FieldFormatter\SnippetsDefaultFormatter.
 */

namespace Drupal\snippets\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;

Proverite da je namespace fajla Drupal\snippets\Plugin\Field\FieldFormatter i dodajte sledeće use naredbe: Drupal\Core\Field\FormatterBase i Drupal\Core\Field\FieldItemListInterface.

2. Definišite formaterski plugin kao anotaciju, isto kao što smo uradili za vidžet i tip polja, što je ekvivalent hook_field_formatter_info u Drupalu 7.

/**
 * Plugin implementacija formaterskog plugina 'snippets_default'.
 *
 * @FieldFormatter(
 *   id = "snippets_default",
 *   label = @Translation("Podrazumevani snippets"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultFormatter extends FormatterBase { }

3. Sada dodajte metodu viewElements() i definišite stvarnu logiku formatiranja polja. Ovaj metod je ekvivalent hook_field_formatter_view u Drupalu 7.

/**
 * {@inheritdoc}
 */
public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  foreach ($items as $delta => $item) {
    // Renderovanje pomoću teme snippets_default.
    $source = [
      '#theme' => 'snippets_default',
      '#source_description' => $item->source_description,
      '#source_code' => $item->source_code,
    ];
    
    $elements[$delta] = ['#markup' => drupal_render($source)];
  }

  return $elements;
}

Važno je napomenuti da koristim prilagođeni Twig šablon snippets_default za renderovanje fragmenata pre nego što ih formaterski plugin prikaže.

Razlog za to je što nisam želeo da puno logike ili HTML koda bude direktno u metodi viewElements().

Kliknite ovde da vidite ceo fajl. Napomena: fajl treba ažurirati da bude u skladu sa PSR-4, više informacija na https://www.drupal.org/node/2128865.

Zaključak

Kao što je ranije pomenuto, najveća promena u Drupalu 8 je to što se polja kreiraju preko plugin API-ja, a ne preko hook-ova. Kada ovo razumete, koncept kreiranja polja je vrlo sličan kao u Drupalu 7. Mnogi metodi u Drupalu 8 odgovaraju hook-ovima iz Drupala 7.

Ako želite da testirate Snippets modul, preuzmite 8.x-dev verziju i probajte.

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.