9.10.3. Rad sa poljima u Drupalu. Kreirajte sopstveni tip polja, vidžet i format za ubacivanje video zapisa sa YouTube-a.
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.