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

9.10.3. Rad sa poljima u Drupalu. Kreirajte sopstveni tip polja, vidžet i format za ubacivanje video zapisa sa YouTube-a.

27/05/2025, by Ivan

Menu

U prethodnim člancima smo videli kako funkcioniše tip polja Link: skladištenje, vidžet, format. U ovom članku ćemo napraviti sopstveni osnovni tip polja za prikazivanje video zapisa sa YouTube-a na stranici sa dva različita formata i podešavanja.

Ovaj članak je fokusiran na Fields API, i ako vam je potrebno da dodate Youtube video polje na svoj sajt, bolje je koristiti gotov modul:

https://www.drupal.org/project/video_embed_field

Sve kodove sam dodao na GitHub u modul drupalbook_youtube, možete preuzeti modul i dodati ga na svoj sajt:

https://github.com/levmyshkin/drupalbook8

Pogledajmo listing ovog modula i pokušaću da opišem kako funkcioniše ovaj tip polja:

modules/custom/drupalbook_youtube/drupalbook_youtube.info.yml

name: DrupalBook Youtube
type: module
description: Youtube embed field
core: 8.x
package: Custom

Definišemo metapodatke za modul.

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldType/DrupalbookYoutubeItem.php

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;

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

/**
 * Plugin implementacija tipa polja 'drupalbook_youtube'.
 *
 * @FieldType(
 *   id = "drupalbook_youtube",
 *   label = @Translation("Embed Youtube video"),
 *   module = "drupalbook_youtube",
 *   description = @Translation("Prikaz video zapisa sa Youtube-a."),
 *   default_widget = "drupalbook_youtube",
 *   default_formatter = "drupalbook_youtube_thumbnail"
 * )
 */
class DrupalbookYoutubeItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
      ],
    ];
  }

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

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

    return $properties;
  }

}

Pravimo tip polja kako bi Drupal znao šta ćemo skladištiti u tabeli za ovo polje.

Sledeće je kreiranje vidžeta (widget) za unos podataka:

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldWidget/DrupalbookYoutubeWidget.php

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldWidget;

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

/**
 * Plugin implementacija vidžeta 'drupalbook_youtube'.
 *
 * @FieldWidget(
 *   id = "drupalbook_youtube",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Youtube video URL"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeWidget extends WidgetBase {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $value = isset($items[$delta]->value) ? $items[$delta]->value : '';
    $element += [
      '#type' => 'textfield',
      '#default_value' => $value,
      '#size' => 32,
      '#maxlength' => 256,
      '#element_validate' => [
        [$this, 'validate'],
      ],
    ];
    return ['value' => $element];
  }

  /**
   * Validacija unosa URL-a.
   */
  public function validate($element, FormStateInterface $form_state) {
    $value = $element['#value'];
    if (strlen($value) == 0) {
      $form_state->setValueForElement($element, '');
      return;
    }
    if (!preg_match("#(?=v=)[a-zA-Z0-9-]+(?=&)|(?=v\/)[^&\n]+(?=\?)|(?=v=)[^&\n]+|(?=youtu.be/)[^&\n]+#", $value, $matches)) {
      $form_state->setError($element, t("URL Youtube video zapisa nije ispravan."));
    }
  }

}

Vidžet nam omogućava unos podataka na formi za uređivanje entiteta.

Poslednji korak je kreiranje Formattera za prikaz podataka.

modules/custom/drupalbook_youtube/src/Plugin/FieldFieldFormatter/DrupalbookYoutubeThumbnailFormatter.php

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;

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

/**
 * Plugin implementacija formatera 'drupalbook_youtube_thumbnail'.
 *
 * @FieldFormatter(
 *   id = "drupalbook_youtube_thumbnail",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Prikazuje sličicu video zapisa"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeThumbnailFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    foreach ($items as $delta => $item) {
      preg_match("#(?=v=)[a-zA-Z0-9-]+(?=&)|(?=v\/)[^&\n]+(?=\?)|(?=v=)[^&\n]+|(?=youtu.be/)[^&\n]+#", $item->value, $matches);

      if (!empty($matches)) {
        $content = '';
        $elements[$delta] = [
          '#type' => 'html_tag',
          '#tag' => 'p',
          '#value' => $content,
        ];
      }

    }

    return $elements;
  }

}

U anotarionom delu klase definišemo tip polja za koji je formatter namenjen.

Sada ćemo pogledati složeniji formatter sa podešavanjima i templatom:

modules/custom/drupalbook_youtube/src/Plugin/FieldFieldFormatter/DrupalbookYoutubeVideoFormatter.php

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;

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

/**
 * Plugin implementacija formatera 'drupalbook_youtube_video'.
 *
 * @FieldFormatter(
 *   id = "drupalbook_youtube_video",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Prikazuje Youtube video"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeVideoFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'width' => '600',
      'height' => '450',
    ] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $elements['width'] = [
      '#type' => 'textfield',
      '#title' => t('Širina Youtube video zapisa'),
      '#default_value' => $this->getSetting('width'),
    ];
    $elements['height'] = [
      '#type' => 'textfield',
      '#title' => t('Visina Youtube video zapisa'),
      '#default_value' => $this->getSetting('height'),
    ];

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $width = $this->getSetting('width');
    $height = $this->getSetting('height');

    foreach ($items as $delta => $item) {
      preg_match("#(?=v=)[a-zA-Z0-9-]+(?=&)|(?=v\/)[^&\n]+(?=\?)|(?=v=)[^&\n]+|(?=youtu.be/)[^&\n]+#", $item->value, $matches);

      if (!empty($matches)) {
        $elements[$delta] = [
          '#theme' => 'drupalbook_youtube_video_formatter',
          '#width' => $width,
          '#height' => $height,
          '#video_id' => $matches[0],
        ];
      }

    }

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];

    $settings = $this->getSettings();

    if (!empty($settings['width']) && !empty($settings['height'])) {
      $summary[] = t('Veličina videa: @width x @height', ['@width' => $settings['width'], '@height' => $settings['height']]);
    }
    else {
      $summary[] = t('Definišite veličinu videa');
    }

    return $summary;
  }

}

U modulu definišemo temu i šablon za prikaz:

modules/custom/drupalbook_youtube/drupalbook_youtube.module

/**
 * Implements hook_theme().
 */
function drupalbook_youtube_theme() {
  return [
    'drupalbook_youtube_video_formatter' => [
      'variables' => ['width' => 600, 'height' => 450, 'video_id' => NULL],
    ],
  ];
}

Dodajemo Twig šablon:

modules/custom/drupalbook_youtube/templates/drupalbook-youtube-video-formatter.html.twig

{#
/**
 * @file
 * Podrazumevani šablon za jednostavan Youtube video.
 *
 * Dostupne promenljive:
 * - width: širina videa.
 * - height: visina videa.
 * - video_id: ID Youtube video zapisa.
 *
 * @ingroup themeable
 */
#}
{% spaceless %}
  
{% endspaceless %}

Sada možete kreirati Youtube video polje na svom sajtu i prikazivati ga na stranici.