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;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc