View source
<?php
namespace Drupal\bynder\Plugin\EntityBrowser\Widget;
use Drupal\bynder\BynderApiInterface;
use Drupal\bynder\Exception\UnableToConnectException;
use Drupal\bynder\Plugin\Field\FieldType\BynderMetadataItem;
use Drupal\bynder\Plugin\media\Source\Bynder;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\entity_browser\Element\EntityBrowserPagerElement;
use Drupal\entity_browser\WidgetValidationManager;
use Drupal\media\Entity\Media;
use Drupal\media\MediaInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class BynderSearch extends BynderWidgetBase {
const TAG_LIST_LIMIT = 25;
protected $accountProxy;
protected $urlGenerator;
protected $loggerFactory;
protected $languageManager;
protected $entityQuery;
protected $cache;
protected $time;
protected $moduleHandler;
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, EntityTypeManagerInterface $entity_type_manager, WidgetValidationManager $validation_manager, BynderApiInterface $bynder_api, AccountProxyInterface $account_proxy, UrlGeneratorInterface $url_generator, LoggerChannelFactoryInterface $logger_factory, LanguageManagerInterface $language_manager, RequestStack $request_stack, ConfigFactoryInterface $config_factory, CacheBackendInterface $cache, TimeInterface $time, ModuleHandlerInterface $module_handler) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher, $entity_type_manager, $validation_manager, $bynder_api, $logger_factory, $language_manager, $request_stack, $config_factory);
$this->accountProxy = $account_proxy;
$this->urlGenerator = $url_generator;
$this->cache = $cache;
$this->time = $time;
$this->moduleHandler = $module_handler;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('event_dispatcher'), $container
->get('entity_type.manager'), $container
->get('plugin.manager.entity_browser.widget_validation'), $container
->get('bynder_api'), $container
->get('current_user'), $container
->get('url_generator'), $container
->get('logger.factory'), $container
->get('language_manager'), $container
->get('request_stack'), $container
->get('config.factory'), $container
->get('cache.data'), $container
->get('datetime.time'), $container
->get('module_handler'));
}
public function defaultConfiguration() {
return [
'items_per_page' => 15,
'tags_filter' => TRUE,
'allowed_properties' => [],
] + parent::defaultConfiguration();
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['items_per_page'] = [
'#type' => 'select',
'#title' => $this
->t('Items per page'),
'#default_value' => $this->configuration['items_per_page'],
'#options' => [
'10' => 10,
'15' => 15,
'25' => 25,
'50' => 50,
],
];
$form['tags_filter'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Enable tags filter'),
'#default_value' => $this->configuration['tags_filter'],
];
foreach ($this->entityTypeManager
->getStorage('media_type')
->loadMultiple() as $type) {
if ($type
->getSource() instanceof Bynder) {
$form['media_type']['#options'][$type
->id()] = $type
->label();
}
}
if (empty($form['media_type']['#options'])) {
$form['media_type']['#disabled'] = TRUE;
$form['items_per_page']['#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(),
]);
}
try {
$options = [];
foreach ($this->bynderApi
->getMetaproperties() as $key => $meta_property) {
if ($meta_property['isFilterable']) {
$options[$key] = bynder_get_applicable_label_translation($meta_property);
}
}
$form['allowed_properties'] = [
'#type' => 'select',
'#title' => $this
->t('Allowed metadata properties'),
'#description' => $this
->t('Select filters that should be available in the Entity Browser widget.'),
'#multiple' => TRUE,
'#default_value' => $this->configuration['allowed_properties'],
'#options' => $options,
];
} catch (\Exception $e) {
watchdog_exception('bynder', $e);
(new UnableToConnectException())
->displayMessage();
}
return $form;
}
protected function prepareEntities(array $form, FormStateInterface $form_state) {
if (!$this
->checkType()) {
return [];
}
$media = [];
$selected_ids = array_keys(array_filter($form_state
->getValue('selection', [])));
$media_list = $form_state
->get('bynder_media_list');
$type = $this->entityTypeManager
->getStorage('media_type')
->load($this->configuration['media_type']);
$plugin = $type
->getSource();
$source_field = $plugin
->getConfiguration()['source_field'];
foreach ($selected_ids as $bynder_id) {
$mid = $this->entityTypeManager
->getStorage('media')
->getQuery()
->condition($source_field, $bynder_id)
->range(0, 1)
->execute();
if ($mid) {
$entity = $this->entityTypeManager
->getStorage('media')
->load(reset($mid));
}
else {
$entity = Media::create([
'bundle' => $type
->id(),
$source_field => $bynder_id,
]);
}
if (!empty($media_list['media'][$bynder_id])) {
$filtered_remote_metadata = $entity
->getSource()
->filterRemoteMetadata($media_list['media'][$bynder_id]);
$entity
->set(BynderMetadataItem::METADATA_FIELD_NAME, Json::encode($filtered_remote_metadata));
}
$media[] = $entity;
}
return $media;
}
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['#attached']['library'][] = 'bynder/search_view';
$form['filters'] = [
'#type' => 'container',
'#tree' => TRUE,
'#attributes' => [
'class' => 'bynder-filters',
],
];
$form['filters']['search_bynder'] = [
'#type' => 'textfield',
'#weight' => -1,
'#title' => $this
->t('Search keyword'),
'#attributes' => [
'size' => 30,
],
];
if ($this->configuration['tags_filter']) {
try {
$all_tags = array_map(function ($item) {
return $item['tag'];
}, $this->bynderApi
->getTags([
'limit' => 500,
'orderBy' => 'mediaCount desc',
'minCount' => 1,
]));
$tags = array_combine($all_tags, $all_tags);
asort($tags);
} catch (\Exception $e) {
watchdog_exception('bynder', $e);
(new UnableToConnectException())
->displayMessage();
$form['actions']['submit']['#access'] = FALSE;
$form['filters']['#access'] = FALSE;
return $form;
}
if (\Drupal::service('module_handler')
->moduleExists('bynder_select2')) {
$form['filters']['tags'] = [
'#type' => 'bynder_select2_simple_element',
'#multiple' => TRUE,
'#title' => $this
->t('Tags'),
'#options' => $tags,
'#placeholder_text' => t('Search for a tag'),
];
}
else {
$form['filters']['tags'] = [
'#type' => 'select',
'#multiple' => TRUE,
'#title' => $this
->t('Tags'),
'#options' => $tags,
];
}
}
$max_option_weight = 0;
try {
$meta_properties = $this->bynderApi
->getMetaproperties();
} catch (\Exception $e) {
watchdog_exception('bynder', $e);
(new UnableToConnectException())
->displayMessage();
$form['actions']['submit']['#access'] = FALSE;
$form['filters']['#access'] = FALSE;
return $form;
}
foreach ($this->configuration['allowed_properties'] as $key) {
if (in_array($key, array_keys($meta_properties)) && ($option = $meta_properties[$key]) && $option['isFilterable']) {
$form['filters'][$option['name']] = [
'#title' => bynder_get_applicable_label_translation($option),
'#type' => 'select',
'#multiple' => $option['isMultiselect'] ? TRUE : FALSE,
'#required' => $option['isRequired'] ? TRUE : FALSE,
'#weight' => $option['zindex'],
'#empty_option' => $this
->t('- None -'),
'#parents' => [
'filters',
'meta_properties',
$option['name'],
],
];
foreach ($option['options'] as $value) {
$form['filters'][$option['name']]['#options'][$value['id']] = bynder_get_applicable_label_translation($value);
}
$max_option_weight = max($max_option_weight, $option['zindex']);
}
}
$form['search_button'] = [
'#type' => 'button',
'#weight' => $max_option_weight + 10,
'#value' => $this
->t('Search'),
'#name' => 'search_submit',
'#limit_validation_errors' => [
[
'filters',
],
],
];
$form['thumbnails'] = [
'#type' => 'container',
'#weight' => $max_option_weight + 15,
'#attributes' => [
'id' => 'thumbnails',
'class' => 'grid',
],
];
if ($form_state
->getTriggeringElement()['#name'] == 'search_submit') {
EntityBrowserPagerElement::setCurrentPage($form_state);
}
$page = EntityBrowserPagerElement::getCurrentPage($form_state);
$query = [
'limit' => $this->configuration['items_per_page'],
'page' => $page,
'type' => 'image',
'total' => 1,
];
if ($form_state
->getValue([
'filters',
'search_bynder',
])) {
$query['keyword'] = $form_state
->getValue([
'filters',
'search_bynder',
]);
}
foreach ($form_state
->getValue([
'filters',
'meta_properties',
], []) as $key => $option_id) {
if (is_array($option_id) && $option_id) {
$property_ids = implode(',', $option_id);
$query['property_' . $key] = $property_ids;
}
elseif (is_string($option_id) && $option_id) {
$property_ids = $option_id;
$query['property_' . $key] = $property_ids;
}
}
if ($selected_tags = $form_state
->getValue([
'filters',
'tags',
])) {
$selected_tags = array_values($selected_tags);
$query['tags'] = implode(',', $selected_tags);
}
$this->moduleHandler
->alter('bynder_search_query', $query, $form_state, $this);
try {
if (!empty($form_state
->get('bynder_media_list_hash')) && $form_state
->get('bynder_media_list_hash') == md5(implode('', $query))) {
$media_list = $form_state
->get('bynder_media_list');
}
else {
$media_list = $this->bynderApi
->getMediaList($query);
$media_list['media'] = array_combine(array_map(function ($media) {
return $media['id'];
}, $media_list['media']), array_values($media_list['media']));
$form_state
->set('bynder_media_list', $media_list);
$form_state
->set('bynder_media_list_hash', md5(implode('', $query)));
}
} catch (\Exception $e) {
watchdog_exception('bynder', $e);
(new UnableToConnectException())
->displayMessage();
$form['actions']['submit']['#access'] = FALSE;
$form['filters']['#access'] = FALSE;
return $form;
}
if (!empty($media_list['media'])) {
foreach ($media_list['media'] as $id => $media) {
$form['thumbnails']["thumbnail-{$id}"] = [
'#type' => 'container',
'#attributes' => [
'id' => $id,
'class' => [
'grid-item',
],
],
];
$form['thumbnails']["thumbnail-{$id}"]["check_{$id}"] = [
'#type' => 'checkbox',
'#parents' => [
'selection',
$id,
],
'#attributes' => [
'class' => [
'item-selector',
],
],
];
$form['thumbnails']["thumbnail-{$id}"]['image'] = [
'#theme' => 'bynder_search_item',
'#thumbnail_uri' => $media['thumbnails']['thul'],
'#name' => $media['name'],
'#type' => $media['type'],
];
}
$form['pager_eb'] = [
'#type' => 'entity_browser_pager',
'#total_pages' => (int) ceil($media_list['total']['count'] / $this->configuration['items_per_page']),
'#weight' => $max_option_weight + 15,
];
$form['actions']['submit']['#limit_validation_errors'] = [
[
'selection',
],
[
'widget',
],
];
$form['actions']['submit']['#submit'] = [
'::submitForm',
];
}
else {
$form['empty_message'] = [
'#prefix' => '<div class="empty-message">',
'#markup' => $this
->t('Not assets found for current search criteria.'),
'#suffix' => '</div>',
'#weight' => $max_option_weight + 20,
];
$form['actions']['submit']['#access'] = FALSE;
}
return $form;
}
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.'));
}
}
}
}