View source
<?php
namespace Drupal\video\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\file\Plugin\Field\FieldWidget\FileWidget;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\TraversableTypedDataInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Field\FieldFilteredMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\SortArray;
use Drupal\Core\Render\Element;
class VideoEmbedWidget extends FileWidget {
public static function defaultSettings() {
$settings = [
'file_directory' => 'video-thumbnails/[date:custom:Y]-[date:custom:m]',
'allowed_providers' => [
"youtube" => "youtube",
],
'uri_scheme' => 'public',
];
return $settings;
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$element = [];
$settings = $this
->getSettings();
$provider_manager = \Drupal::service('video.provider_manager');
$element['allowed_providers'] = [
'#title' => t('Video Providers'),
'#type' => 'checkboxes',
'#default_value' => $this
->getSetting('allowed_providers'),
'#options' => $provider_manager
->getProvidersOptionList(),
];
$element['file_directory'] = [
'#type' => 'textfield',
'#title' => t('Thumbnail directory'),
'#default_value' => $settings['file_directory'],
'#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
'#element_validate' => [
[
get_class($this),
'validateDirectory',
],
],
'#weight' => 3,
];
$scheme_options = \Drupal::service('stream_wrapper_manager')
->getNames(StreamWrapperInterface::WRITE_VISIBLE);
$element['uri_scheme'] = [
'#type' => 'radios',
'#title' => t('Thumbnail destination'),
'#options' => $scheme_options,
'#default_value' => $this
->getSetting('uri_scheme'),
'#description' => t('Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.'),
'#weight' => 6,
];
return $element;
}
public static function validateDirectory($element, FormStateInterface $form_state) {
$value = trim($element['#value'], '\\/');
$form_state
->setValueForElement($element, $value);
}
public function settingsSummary() {
$summary = [];
$summary[] = t('Providers : @allowed_providers<br/>Thumbnail directory : @file_directory', [
'@allowed_providers' => implode(', ', array_filter($this
->getSetting('allowed_providers'))),
'@file_directory' => $this
->getSetting('uri_scheme') . '://' . $this
->getSetting('file_directory'),
]);
return $summary;
}
public function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition
->getName();
$cardinality = $this->fieldDefinition
->getFieldStorageDefinition()
->getCardinality();
$parents = $form['#parents'];
$field_state = static::getWidgetState($parents, $field_name, $form_state);
if (isset($field_state['items'])) {
$items
->setValue($field_state['items']);
}
switch ($cardinality) {
case FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED:
$field_state = static::getWidgetState($parents, $field_name, $form_state);
$max = $field_state['items_count'];
$is_multiple = TRUE;
break;
default:
$max = $cardinality - 1;
$is_multiple = $cardinality > 1;
break;
}
$title = $this->fieldDefinition
->getLabel();
$description = FieldFilteredMarkup::create(\Drupal::token()
->replace($this->fieldDefinition
->getDescription()));
$elements = [];
for ($delta = 0; $delta <= $max; $delta++) {
if (!isset($items[$delta])) {
$items
->appendItem();
}
if ($is_multiple) {
$element = [
'#title' => $this
->t('@title (value @number)', [
'@title' => $title,
'@number' => $delta + 1,
]),
'#title_display' => 'invisible',
'#description' => '',
];
}
else {
$element = [
'#title' => $title,
'#title_display' => 'before',
'#description' => $description,
];
}
$element = $this
->formSingleElement($items, $delta, $element, $form, $form_state);
if ($element) {
if ($is_multiple) {
$element['_weight'] = [
'#type' => 'weight',
'#title' => $this
->t('Weight for row @number', [
'@number' => $delta + 1,
]),
'#title_display' => 'invisible',
'#delta' => $max,
'#default_value' => $items[$delta]->_weight ?: $delta,
'#weight' => 100,
];
}
$elements[$delta] = $element;
}
}
if ($elements) {
$elements += [
'#theme' => 'field_multiple_value_form',
'#field_name' => $field_name,
'#cardinality' => $cardinality,
'#cardinality_multiple' => $this->fieldDefinition
->getFieldStorageDefinition()
->isMultiple(),
'#required' => $this->fieldDefinition
->isRequired(),
'#title' => $title,
'#description' => $description,
'#max_delta' => $max,
];
if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && !$form_state
->isProgrammed()) {
$id_prefix = implode('-', array_merge($parents, [
$field_name,
]));
$wrapper_id = Html::getUniqueId($id_prefix . '-add-more-wrapper');
$elements['add_more'] = [
'#type' => 'submit',
'#name' => strtr($id_prefix, '-', '_') . '_add_more',
'#value' => t('Add another item'),
'#attributes' => [
'class' => [
'field-add-more-submit',
],
],
'#limit_validation_errors' => [
array_merge($parents, [
$field_name,
]),
],
'#submit' => [
[
get_class($this),
'addMoreSubmit',
],
],
'#ajax' => [
'callback' => [
get_class($this),
'addMoreAjax',
],
'effect' => 'fade',
],
'#weight' => 1000,
];
}
}
if ($is_multiple) {
$elements['#file_upload_delta'] = $delta;
$elements['#process'] = [
[
get_class($this),
'processMultiple',
],
];
$elements['#field_name'] = $field_name;
$elements['#language'] = $items
->getLangcode();
}
return $elements;
}
public static function processMultiple($element, FormStateInterface $form_state, $form) {
$element_children = Element::children($element, TRUE);
$count = count($element_children);
if (!$form_state
->isRebuilding()) {
$count_items_before = 0;
foreach ($element_children as $children) {
if (!empty($element[$children]['#default_value']['fids'])) {
$count_items_before++;
}
}
$form_state
->set('file_upload_delta_initial', $count_items_before);
}
foreach ($element_children as $delta => $key) {
if ($delta != $element['#file_upload_delta']) {
$description = static::getDescriptionFromElement($element[$key]);
$element[$key]['_weight'] = [
'#type' => 'weight',
'#title' => $description ? t('Weight for @title', [
'@title' => $description,
]) : t('Weight for new file'),
'#title_display' => 'invisible',
'#delta' => $count,
'#default_value' => $delta,
];
}
else {
$element[$key]['#title'] = $element['#title'];
$element[$key]['_weight'] = [
'#type' => 'hidden',
'#default_value' => $delta,
];
}
}
$element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
$element['#suffix'] = '</div>';
$element['add_more']['#ajax']['wrapper'] = $element['#id'] . '-ajax-wrapper';
return $element;
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
if (isset(NestedArray::getValue($form_state
->getUserInput(), $element['#field_parents'])[$items
->getName()][0]['value'])) {
$value = NestedArray::getValue($form_state
->getUserInput(), $element['#field_parents'])[$items
->getName()][0]['value'];
}
if (empty($items[$delta]
->getValue()) || !empty($value)) {
$element['value'] = $element + [
'#type' => 'textfield',
'#attributes' => [
'class' => [
'js-text-full',
'text-full',
],
],
'#default_value' => empty($value) ? '' : $value,
'#element_validate' => [
[
get_class($this),
'validateFormElement',
],
],
'#allowed_providers' => $this
->getSetting('allowed_providers'),
];
}
else {
$element += parent::formElement($items, $delta, $element, $form, $form_state);
}
return $element;
}
public static function process($element, FormStateInterface $form_state, $form) {
$element = parent::process($element, $form_state, $form);
$item = $element['#value'];
$element['data']['#value'] = $item['data'];
$element['data']['#type'] = 'hidden';
return $element;
}
public static function validateFormElement(array &$element, FormStateInterface $form_state) {
$value = $element['#value'];
if (empty($value)) {
return;
}
$provider_manager = \Drupal::service('video.provider_manager');
$enabled_providers = $provider_manager
->loadDefinitionsFromOptionList($element['#allowed_providers']);
if (!$provider_manager
->loadApplicableDefinitionMatches($enabled_providers, $value)) {
$form_state
->setError($element, t('Could not find a video provider to handle the given URL.'));
}
}
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition
->getName();
$path = array_merge($form['#parents'], [
$field_name,
]);
$key_exists = NULL;
$values = NestedArray::getValue($form_state
->getValues(), $path, $key_exists);
if ($key_exists) {
if (!$this
->handlesMultipleValues()) {
unset($values['add_more']);
foreach ($values as $delta => &$value) {
$value['_original_delta'] = $delta;
}
usort($values, function ($a, $b) {
return SortArray::sortByKeyInt($a, $b, '_weight');
});
}
foreach ($values as $delta => &$value) {
if (!empty($value['value']) && empty($value['fids'])) {
$provider_manager = \Drupal::service('video.provider_manager');
$allowed_providers = $this
->getSetting('allowed_providers');
$enabled_providers = $provider_manager
->loadDefinitionsFromOptionList($allowed_providers);
if ($provider_matches = $provider_manager
->loadApplicableDefinitionMatches($enabled_providers, $value['value'])) {
$definition = $provider_matches['definition'];
$matches = $provider_matches['matches'];
$uri = $definition['stream_wrapper'] . '://' . $matches['id'];
$storage = \Drupal::entityManager()
->getStorage('file');
$results = $storage
->getQuery()
->condition('uri', $uri)
->execute();
if (!(count($results) > 0)) {
$user = \Drupal::currentUser();
$file = File::Create([
'uri' => $uri,
'filemime' => $definition['mimetype'],
'filesize' => 1,
'uid' => $user
->id(),
]);
$file
->save();
unset($values[$delta]);
$values[] = [
'fids' => [
$file
->id(),
],
'data' => serialize($matches),
];
}
else {
unset($values[$delta]);
$values[] = [
'fids' => [
reset($results),
],
'data' => serialize($matches),
];
}
}
}
if (!isset($value['fids'])) {
unset($values[$delta]);
}
}
$values = $this
->massageFormValues($values, $form, $form_state);
$items
->setValue($values);
$items
->filterEmptyItems();
$field_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
foreach ($items as $delta => $item) {
$field_state['original_deltas'][$delta] = isset($item->_original_delta) ? $item->_original_delta : $delta;
unset($item->_original_delta, $item->_weight);
}
static::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
}
}
}