Skip to content
Snippets Groups Projects
Commit ce6422e5 authored by Primoz Hmeljak's avatar Primoz Hmeljak Committed by Sascha Grossenbacher
Browse files

Issue #3396271: Integrate single file selection (with on the fly transformations)

parent 7f3c5a12
No related branches found
No related tags found
1 merge request!223396271: Integrate single file selection (with on the fly transformations)
......@@ -6,6 +6,7 @@
*/
use Drupal\bynder\Plugin\Field\FieldType\BynderMetadataItem;
use Drupal\bynder\Plugin\media\Source\Bynder;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Utility\UpdateException;
use Drupal\field\Entity\FieldStorageConfig;
......@@ -203,3 +204,34 @@ function bynder_update_8400() {
return t('Bynder configuration has changed, a permanent token and optionally client id/secret is now required instead of the previous API keys. Reconfigure it on the configuration page.');
}
/**
* Creates bynder_tranformation field.
*/
function bynder_update_8401() {
// Do nothing if the field already exists.
if ($transformations_field_storage = FieldStorageConfig::loadByName('media', Bynder::TRANSFORMATIONS_FIELD_NAME)) {
if ($transformations_field_storage->getType() !== 'text') {
throw new UpdateException('The "bynder_transformations" media field already exists. Please remove the it before running the update function.');
}
return;
}
$entity_type_manager = \Drupal::entityTypeManager();
$transformations_field_storage = NULL;
// Create a field instance for each of the Bynder media types.
foreach (\Drupal::service('bynder')->getBynderMediaTypes() as $media_type_id => $media_type) {
/** @var \Drupal\bynder\Plugin\media\Source\Bynder $source */
$source = $media_type->getSource();
if (!$transformations_field_storage) {
$transformations_field_storage = $source->createTransformationsFieldStorage();
$transformations_field_storage->save();
}
$transformations_field = $source->createTransformationsField($media_type);
$transformations_field->save();
}
}
......@@ -42,7 +42,7 @@ compactview:
name: proprietary
gpl-compatible: false
js:
https://d8ejoa1fys2rk.cloudfront.net/5.0.5/modules/compactview/bynder-compactview-2-latest.js: { type: external }
https://d8ejoa1fys2rk.cloudfront.net/5.0.5/modules/compactview/bynder-compactview-3-latest.js: { type: external }
formatter:
version: VERSION
......
......@@ -250,6 +250,15 @@ function bynder_media_type_insert(MediaTypeInterface $media_type) {
$metadata_field = $source->createMetadataField($media_type);
$metadata_field->save();
$transformations_field_storage = FieldStorageConfig::loadByName('media', Bynder::TRANSFORMATIONS_FIELD_NAME);
if (!$transformations_field_storage) {
$transformations_field_storage = $source->createTransformationsFieldStorage();
$transformations_field_storage->save();
}
$transformations_field = $source->createTransformationsField($media_type);
$transformations_field->save();
}
}
......
......@@ -72,6 +72,9 @@ field.formatter.settings.bynder:
dat_query_responsive:
type: string
label: 'DAT for Responsive images'
use_custom_transformations:
type: boolean
lable: 'Use user-selected transformations if available'
field.formatter.settings.bynder_document:
type: mapping
......@@ -123,6 +126,9 @@ entity_browser.browser.widget.bynder_search:
media_type_video:
type: string
label: 'Media type for created video entities'
single_file_selection:
type: boolean
label: 'Use single file selection'
entity_browser.browser.widget.bynder_upload:
type: mapping
......
......@@ -15,14 +15,14 @@
const $compactView = $(once('bynder-compactview', '#bynder-compactview', context));
$compactView.each(function() {
BynderCompactView.open({
mode: 'MultiSelect',
mode: drupalSettings.bynder.compactviewMode,
portal: {
editable: false,
url: drupalSettings.bynder.domain
},
assetTypes: drupalSettings.bynder.types,
container: this,
onSuccess: function(assets) {
container: this,
onSuccess: function(assets, AdditionalInfo) {
var selectedValues = [];
// Simplify the data structure, only keep what we need.
......@@ -37,12 +37,18 @@
'type': asset.type,
'name': asset.name
});
// If there are no assets, do not submit the form.
if (selectedValues.length === 0) {
return;
}
if (AdditionalInfo.selectedFile !== undefined) {
selectedValues[0].fileUrl = AdditionalInfo.selectedFile.url;
}
});
// If there are no assets, do not submit the form.
if (selectedValues.length === 0) {
return;
}
// Append the selected assets ids to the bynder_selection hidden
// input field, separated by a comma.
......@@ -53,7 +59,7 @@
$('.is-entity-browser-submit').click();
}
});
})
});
}
};
......
......@@ -29,6 +29,7 @@ class BynderSearch extends BynderWidgetBase {
return [
'media_type_document' => NULL,
'media_type_video' => NULL,
'single_file_selection' => FALSE,
] + parent::defaultConfiguration();
}
......@@ -78,6 +79,13 @@ class BynderSearch extends BynderWidgetBase {
'#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;
......@@ -142,6 +150,11 @@ class BynderSearch extends BynderWidgetBase {
$source_field_condition->condition($source_field, $bynder_info['id']);
}
$transformation = NULL;
if (!empty($bynder_info['fileUrl']) && $transformation = $this->getTransformations($bynder_info['fileUrl'])) {
$query->condition(Bynder::TRANSFORMATIONS_FIELD_NAME, $transformation);
}
$mid = $query
->condition($source_field_condition)
->range(0, 1)
......@@ -155,6 +168,7 @@ class BynderSearch extends BynderWidgetBase {
'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) {
......@@ -205,6 +219,13 @@ class BynderSearch extends BynderWidgetBase {
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';
......@@ -277,4 +298,22 @@ class BynderSearch extends BynderWidgetBase {
return FALSE;
}
/**
* Get user-selected transformations string.
*
* @param string $url
* The url string as returned by the compact viewer.
*
* @return string|NULL
* Transformations query or empty string if not available.
*/
public function getTransformations(string $url) {
// 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;
}
}
......@@ -49,6 +49,7 @@ class BynderFormatter extends BynderFormatterBase implements ContainerFactoryPlu
'dat_query' => '',
'responsive_sizes' => '',
'dat_query_responsive' => '',
'use_custom_transformations' => '',
] + parent::defaultSettings();
}
......@@ -141,6 +142,13 @@ class BynderFormatter extends BynderFormatterBase implements ContainerFactoryPlu
],
];
$elements['use_custom_transformations'] = [
'#type' => 'checkbox',
'#title' => $this->t('Use user-selected asset transformations if available'),
'#description' => $this->t('If the search widget is in single_file_selection mode, on-the-fly transformations may be applied. Use them if the asset has a corresponding transformation.'),
'#default_value' => $this->getSetting('use_custom_transformations'),
];
return $elements;
}
......@@ -178,6 +186,10 @@ class BynderFormatter extends BynderFormatterBase implements ContainerFactoryPlu
$summary[] = $this->t('Alt attribute field: @field', ['@field' => $field_candidates[$settings['alt_field']]]);
}
if (!empty($settings['use_custom_transformations'])) {
$summary[] = $this->t('Using user-selected transformations if available.');
}
return $summary;
}
......@@ -204,8 +216,23 @@ class BynderFormatter extends BynderFormatterBase implements ContainerFactoryPlu
'class' => ['bynder-wrapper'],
],
];
if ($settings['thumbnail'] == 'DAT' && isset($thumbnails['transformBaseUrl']) && !empty($settings['dat_query'])) {
$thumbnail_uri = $thumbnails['transformBaseUrl'] . '?' . $this->getSetting('dat_query');
// DAT and on-the-fly transformation query.
$use_transform_base = FALSE;
$transform_query = [];
if (isset($thumbnails['transformBaseUrl'])) {
if ($this->getSetting('use_custom_transformations') && !$media_entity->get(Bynder::TRANSFORMATIONS_FIELD_NAME)->isEmpty()) {
$transform_query[] = $media_entity->get(Bynder::TRANSFORMATIONS_FIELD_NAME)->value;
$use_transform_base = TRUE;
}
elseif ($settings['thumbnail'] == 'DAT' && !empty($settings['dat_query'])) {
$transform_query[] = $this->getSetting('dat_query');
$use_transform_base = TRUE;
}
}
if ($use_transform_base) {
$thumbnail_uri = $thumbnails['transformBaseUrl'] . '?' . implode('&', $transform_query);;
}
else {
$thumbnail_uri = $thumbnails[$settings['thumbnail']] ?? $thumbnails['webimage'];
......
......@@ -37,6 +37,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class Bynder extends MediaSourceBase {
const TRANSFORMATIONS_FIELD_NAME = 'bynder_transformations';
/**
* Bynder api service.
*
......@@ -464,6 +466,45 @@ class Bynder extends MediaSourceBase {
]);
}
/**
* Creates the transformations field storage definition.
*
* @return \Drupal\field\FieldStorageConfigInterface
* The unsaved field storage definition.
*/
public function createTransformationsFieldStorage() {
return $this->entityTypeManager->getStorage('field_storage_config')
->create([
'entity_type' => 'media',
'field_name' => static::TRANSFORMATIONS_FIELD_NAME,
'type' => 'text',
'cardinality' => 1,
'locked' => TRUE,
]);
}
/**
* Creates the transformations field definition.
*
* @param \Drupal\media\MediaTypeInterface $type
* The media type.
*
* @return \Drupal\field\FieldConfigInterface
* The unsaved field definition. The field storage definition, if new,
* should also be unsaved.
*/
public function createTransformationsField(MediaTypeInterface $type) {
return $this->entityTypeManager->getStorage('field_config')
->create([
'entity_type' => 'media',
'field_name' => static::TRANSFORMATIONS_FIELD_NAME,
'bundle' => $type->id(),
'label' => 'Bynder Transformations',
'translatable' => FALSE,
'field_type' => 'text',
]);
}
/**
* Checks if remote images should be used.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment