bynder-4.0.0-beta1/src/Plugin/EntityBrowser/Widget/BynderSearch.php
src/Plugin/EntityBrowser/Widget/BynderSearch.php
<?php
namespace Drupal\bynder\Plugin\EntityBrowser\Widget;
use Drupal\bynder\Exception\BundleNotBynderException;
use Drupal\bynder\Exception\BundleNotExistException;
use Drupal\bynder\Plugin\media\Source\Bynder;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Markup;
use Drupal\media\MediaInterface;
/**
* Uses a Bynder API to search and provide entity listing in a browser's widget.
*
* @EntityBrowserWidget(
* id = "bynder_search",
* label = @Translation("Bynder search"),
* description = @Translation("Adds an Bynder search field browser's widget.")
* )
*/
class BynderSearch extends BynderWidgetBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'media_type_document' => NULL,
'media_type_video' => NULL,
'single_file_selection' => FALSE,
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['submit_text']['#access'] = FALSE;
foreach ($this->entityTypeManager->getStorage('media_type')->loadMultiple() as $type) {
/** @var \Drupal\media\MediaTypeInterface $type */
if ($type->getSource() instanceof Bynder) {
$form['media_type']['#options'][$type->id()] = $type->label();
}
}
$form['media_type']['#title'] = $this->t('Media type (Image)');
if (empty($form['media_type']['#options'])) {
$form['media_type']['#disabled'] = TRUE;
$form['media_type']['#description'] = $this->t('You must @create_type before using this widget.', [
'@create_type' => Link::createFromRoute($this->t('create a Bynder media type'), 'entity.media_type.add_form')
->toString(),
]);
}
else {
$form['media_type']['#required'] = FALSE;
$form['media_type']['#empty_option'] = $this->t('- Hide images -');
$form['media_type_document'] = [
'#type' => 'select',
'#title' => $this->t('Media type (Document)'),
'#default_value' => $this->configuration['media_type_document'],
'#required' => FALSE,
'#options' => $form['media_type']['#options'],
'#empty_option' => $this->t('- Hide documents -'),
];
$form['media_type_video'] = [
'#type' => 'select',
'#title' => $this->t('Media type (Video)'),
'#default_value' => $this->configuration['media_type_video'],
'#required' => FALSE,
'#options' => $form['media_type']['#options'],
'#empty_option' => $this->t('- Hide videos -'),
];
$form['single_file_selection'] = [
'#type' => 'checkbox',
'#title' => $this->t('Use single file selection mode'),
'#description' => $this->t('Allows users can create a custom DAT transformation on the file.'),
'#default_value' => $this->configuration['single_file_selection'],
];
}
return $form;
}
/**
* {@inheritdoc}
*/
protected function prepareEntities(array $form, FormStateInterface $form_state) {
if (!$this->checkType()) {
return [];
}
/** @var \Drupal\media\Entity\Media[] $medias */
$medias = [];
$selection = Json::decode($form_state->getValue('bynder_selection', ''));
$storage = $this->entityTypeManager->getStorage('media');
if (!$selection) {
return [];
}
$image_type = NULL;
$image_source_field = NULL;
$source_fields = [];
if ($this->configuration['media_type']) {
/** @var \Drupal\media\MediaTypeInterface $image_type */
$image_type = $this->entityTypeManager->getStorage('media_type')
->load($this->configuration['media_type']);
$image_source_field = $image_type->getSource()->getConfiguration()['source_field'];
$source_fields[] = $image_source_field;
}
$document_type = NULL;
$document_source_field = NULL;
if ($this->configuration['media_type_document']) {
/** @var \Drupal\media\MediaTypeInterface $document_type */
$document_type = $this->entityTypeManager->getStorage('media_type')
->load($this->configuration['media_type_document']);
$document_source_field = $document_type->getSource()->getConfiguration()['source_field'];
if ($document_source_field != $image_source_field) {
$source_fields[] = $document_source_field;
}
}
$video_type = NULL;
$video_source_field = NULL;
if ($this->configuration['media_type_video']) {
/** @var \Drupal\media\MediaTypeInterface $video_type */
$video_type = $this->entityTypeManager->getStorage('media_type')
->load($this->configuration['media_type_video']);
$video_source_field = $video_type->getSource()->getConfiguration()['source_field'];
if ($video_source_field != $image_source_field) {
$source_fields[] = $video_source_field;
}
}
foreach ($selection as $bynder_info) {
$query = $storage->getQuery();
$query->accessCheck(FALSE);
$source_field_condition = $query->orConditionGroup();
foreach ($source_fields as $source_field) {
$source_field_condition->condition($source_field, $bynder_info['id']);
}
if ($transformation = $this->getTransformations($bynder_info)) {
$query->condition(Bynder::TRANSFORMATIONS_FIELD_NAME, $transformation);
}
$mid = $query
->condition($source_field_condition)
->range(0, 1)
->execute();
if ($mid) {
$medias[] = $storage->load(reset($mid));
}
else {
if ($bynder_info['type'] == 'IMAGE' && $image_type) {
$medias[] = $storage->create([
'bundle' => $image_type->id(),
$image_source_field => $bynder_info['id'],
'name' => $bynder_info['name'],
Bynder::TRANSFORMATIONS_FIELD_NAME => $transformation,
]);
}
elseif ($bynder_info['type'] == 'DOCUMENT' && $document_type) {
$medias[] = $storage->create([
'bundle' => $document_type->id(),
$document_source_field => $bynder_info['id'],
'name' => $bynder_info['name'],
]);
}
elseif ($bynder_info['type'] == 'VIDEO' && $video_type) {
$medias[] = $storage->create([
'bundle' => $video_type->id(),
$video_source_field => $bynder_info['id'],
'name' => $bynder_info['name'],
]);
}
}
}
$language_manager = \Drupal::languageManager();
// Ensure translations exist for all languages that have mapping overrides.
if ($language_manager ->isMultilingual()) {
foreach ($medias as $media) {
$source = $media->getSource();
$language_added = FALSE;
foreach (array_keys($source->getConfiguration()['mapping_language_overrides'] ?? []) as $langcode) {
if ($language_manager->getLanguage($langcode) && !$media->hasTranslation($langcode)) {
$media->addTranslation($langcode, $media->toArray());
$language_added = TRUE;
}
}
// If translations were added and the media entity is not new,
// explicitly save it.
if ($language_added && !$media->isNew()) {
$media->save();
}
}
}
return $medias;
}
/**
* {@inheritdoc}
*/
public function getForm(array &$original_form, FormStateInterface $form_state, array $additional_widget_parameters) {
$form = parent::getForm($original_form, $form_state, $additional_widget_parameters);
if ($form_state->getValue('errors')) {
$form['actions']['submit']['#access'] = FALSE;
return $form;
}
$form['bynder_selection'] = [
'#type' => 'hidden',
'#weight' => -1,
];
$form['#attached']['library'][] = 'bynder/search_view';
$form['#attached']['drupalSettings']['bynder']['domain'] = $this->config->get('bynder.settings')->get('account_domain');
$form['#attached']['drupalSettings']['bynder']['types'] = [];
if ($this->configuration['media_type']) {
$form['#attached']['drupalSettings']['bynder']['types'][] = 'image';
}
if ($this->configuration['media_type_document']) {
$form['#attached']['drupalSettings']['bynder']['types'][] = 'document';
}
if ($this->configuration['media_type_video']) {
$form['#attached']['drupalSettings']['bynder']['types'][] = 'video';
}
if ($this->configuration['single_file_selection']) {
$form['#attached']['drupalSettings']['bynder']['compactviewMode'] = 'SingleSelectFile';
}
else {
$cardinality = (int) $form_state->get(['entity_browser', 'validators', 'cardinality', 'cardinality']);
$form['#attached']['drupalSettings']['bynder']['compactviewMode'] = $cardinality === 1 ? 'SingleSelect' : 'MultiSelect';
}
$form['actions']['submit']['#attributes']['class'][] = 'js-hide';
$form['browser']['#markup'] = Markup::create('<div style="position: fixed; top: 44px; left: 0; right: 0; bottom: 0;" id="bynder-compactview"><div style="display: flex; height: 100%;"></div></div>');
return $form;
}
/**
* {@inheritdoc}
*/
public function submit(array &$element, array &$form, FormStateInterface $form_state) {
if (!empty($form_state->getTriggeringElement()['#eb_widget_main_submit'])) {
try {
$media = $this->prepareEntities($form, $form_state);
array_walk($media, function (MediaInterface $media_item) {
$media_item->save();
});
$this->selectEntities($media, $form_state);
}
catch (\UnexpectedValueException $e) {
$this->messenger()->addError($this->t('Bynder integration is not configured correctly. Please contact the site administrator.'));
}
}
}
/**
* {@inheritdoc}
*/
protected function checkType() {
if (parent::checkType()) {
return TRUE;
}
if ($this->configuration['media_type_document']) {
/** @var \Drupal\media\MediaTypeInterface $type */
$type = $this->entityTypeManager->getStorage('media_type')
->load($this->configuration['media_type_document']);
if (!$type) {
(new BundleNotExistException(
$this->configuration['media_type_document']
))->logException()->displayMessage();
return FALSE;
}
elseif (!($type->getSource() instanceof Bynder)) {
(new BundleNotBynderException($type->label()))->logException()
->displayMessage();
return FALSE;
}
return TRUE;
}
if ($this->configuration['media_type_video']) {
/** @var \Drupal\media\MediaTypeInterface $type */
$type = $this->entityTypeManager->getStorage('media_type')
->load($this->configuration['media_type_video']);
if (!$type) {
(new BundleNotExistException(
$this->configuration['media_type_video']
))->logException()->displayMessage();
return FALSE;
}
elseif (!($type->getSource() instanceof Bynder)) {
(new BundleNotBynderException($type->label()))->logException()
->displayMessage();
return FALSE;
}
return TRUE;
}
return FALSE;
}
/**
* Get user-selected transformations string.
*
* @param array $bynder_info
* Info received from bynder.
*
* @return string|NULL
* Transformations query or empty string if not available.
*/
public function getTransformations(array $bynder_info) {
if (isset($bynder_info['derivative']) && $bynder_info['derivative'] !== NULL && $bynder_info['derivative'] != 'transformBaseUrl') {
return "preset:{$bynder_info['derivative'] }";
}
elseif (!empty($bynder_info['fileUrl'])) {
$url = $bynder_info['fileUrl'];
// Cannot use UrlHelper here, because Bynder uses the same query arg for
// all transformations. E.g. ?io=transform:fo&io=filter:bar.
if ($transformations = parse_url($url, PHP_URL_QUERY)){
return $transformations;
}
}
return NULL;
}
}
