View source
<?php
namespace Drupal\juicebox\Plugin\views\style;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Utility\LinkGeneratorInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Component\Utility\Html;
use Drupal\juicebox\JuiceboxFormatterInterface;
use Drupal\juicebox\JuiceboxGalleryInterface;
class JuiceboxDisplayStyle extends StylePluginBase {
protected $juicebox;
protected $entityTypeManager;
protected $entityFieldManager;
protected $stringTranslation;
protected $request;
protected $usesGrouping = FALSE;
protected $usesFields = TRUE;
protected $usesRowPlugin = FALSE;
protected $usesRowClass = FALSE;
protected $usesOptions = TRUE;
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('link_generator'), $container
->get('string_translation'), $container
->get('request_stack'), $container
->get('juicebox.formatter'));
}
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, LinkGeneratorInterface $link_generator, TranslationInterface $translation, RequestStack $request_stack, JuiceboxFormatterInterface $juicebox) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->stringTranslation = $translation;
$this->request = $request_stack
->getCurrentRequest();
$this->juicebox = $juicebox;
}
protected function defineOptions() {
$options = parent::defineOptions();
$library = $this->juicebox
->getLibrary();
$base_settings = $this->juicebox
->confBaseOptions();
foreach ($base_settings as $setting => $value) {
$base_settings_default[$setting] = [
'default' => $value,
];
}
$options = array_merge($base_settings_default, [
'image_field' => [
'default' => '',
],
'image_field_style' => [
'default' => !empty($library['version']) && !in_array('juicebox_multisize_image_style', $library['disallowed_conf']) ? 'juicebox_multisize' : 'juicebox_medium',
],
'thumb_field' => [
'default' => '',
],
'thumb_field_style' => [
'default' => 'juicebox_square_thumb',
],
'title_field' => [
'default' => '',
],
'caption_field' => [
'default' => '',
],
'show_title' => [
'default' => 0,
],
]);
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$settings = $this->options;
$options = $this
->confGetFieldSources();
$missing_field_warning = '';
if (empty($options['field_options_images'])) {
$missing_field_warning = $this
->t('<strong>You must add a field of type image, file or file ID to your view display before this value can be set.</strong><br/>');
}
$form['image_field'] = [
'#type' => 'select',
'#title' => $this
->t('Image Source'),
'#default_value' => $settings['image_field'],
'#description' => $this
->t('The field source to use for each image in the gallery. Must be an image field, file field or a file ID. If using a multivalued field (*) only the <em>first</em> value from each entity will be used.'),
'#suffix' => $missing_field_warning,
'#options' => $options['field_options_images'],
'#empty_option' => $this
->t('- Select -'),
];
$form['thumb_field'] = [
'#type' => 'select',
'#title' => $this
->t('Thumbnail Source'),
'#default_value' => $settings['thumb_field'],
'#description' => $this
->t('The field source to use for each thumbnail in the gallery. Must be an image field, file field or a file ID. Typically you will choose the same value that was set in the "Image Source" option above.'),
'#suffix' => $missing_field_warning,
'#options' => $options['field_options_images'],
'#empty_option' => $this
->t('- Select -'),
];
$form['image_field_style'] = [
'#type' => 'select',
'#title' => $this
->t('Image Field Style'),
'#default_value' => $settings['image_field_style'],
'#description' => $this
->t('The style formatter for the image. Any formatting settings configured on the field itself will be ignored and this style setting will always be used.'),
'#options' => $this->juicebox
->confBaseStylePresets(),
'#empty_option' => $this
->t('None (original image)'),
];
$form['thumb_field_style'] = [
'#type' => 'select',
'#title' => $this
->t('Thumbnail Field Style'),
'#default_value' => $settings['thumb_field_style'],
'#description' => $this
->t('The style formatter for the thumbnail. Any formatting settings configured on the field itself will be ignored and this style setting will always be used.'),
'#options' => $this->juicebox
->confBaseStylePresets(FALSE),
'#empty_option' => $this
->t('None (original image)'),
];
$form['title_field'] = [
'#type' => 'select',
'#title' => $this
->t('Title Field'),
'#default_value' => $settings['title_field'],
'#description' => $this
->t("The view's field that should be used for the title of each image in the gallery. Any formatting settings configured on the field itself will be respected."),
'#options' => $options['field_options'],
'#empty_option' => $this
->t('None'),
];
$form['caption_field'] = [
'#type' => 'select',
'#title' => $this
->t('Caption Field'),
'#default_value' => $settings['caption_field'],
'#description' => $this
->t("The view's field that should be used for the caption of each image in the gallery. Any formatting settings configured on the field itself will be respected."),
'#options' => $options['field_options'],
'#empty_option' => $this
->t('None'),
];
$form['show_title'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Show Gallery Title'),
'#default_value' => $settings['show_title'],
'#description' => $this
->t('Show the view display title as the gallery title.'),
];
$form = $this->juicebox
->confBaseForm($form, $settings);
$linkurl_field_options = [];
foreach ($options['field_options'] as $field_key => $field_name) {
$linkurl_field_options[$field_key] = $this
->t('Field') . ' - ' . $field_name;
}
$form['linkurl_source']['#description'] = $form['linkurl_source']['#description'] . '</br><strong>' . $this
->t('If using a field source it must render a properly formatted URL and nothing else.') . '</strong>';
$form['linkurl_source']['#options'] = array_merge($form['linkurl_source']['#options'], $linkurl_field_options);
}
public function render() {
$element = [];
$view = $this->view;
$settings = $this->options;
$display_name = isset($view->current_display) ? $view->current_display : 'default';
$xml_route_info = [
'route_name' => 'juicebox.xml_viewsstyle',
'route_parameters' => [
'viewName' => $view
->id(),
'displayName' => $display_name,
],
'options' => [
'query' => $this
->argsToQuery() + $this->request->query
->all(),
],
];
if ($this->request
->get('_route') == 'entity.view.preview_form') {
$message = $this->stringTranslation
->translate("Juicebox galleries cannot be viewed as a live preview. Please save your view and visit the full page URL for this display to preview this gallery.");
$this
->messenger()
->addWarning($message);
return [
'#markup' => $message,
];
}
try {
$gallery = $this->juicebox
->newGallery($xml_route_info['route_parameters']);
$this
->buildGallery($gallery);
$contextual = $this
->buildContextualLinks($xml_route_info);
$element = $this->juicebox
->buildEmbed($gallery, $settings, $xml_route_info, TRUE, FALSE, $contextual);
} catch (\Exception $e) {
$message = 'Exception building Juicebox embed code for view: !message in %function (line %line of %file).';
watchdog_exception('juicebox', $e, $message);
}
return $element;
}
protected function buildGallery(JuiceboxGalleryInterface $gallery) {
$view = $this->view;
$settings = $this->options;
$this
->renderFields($view->result);
$image_items = $thumb_items = $this
->getItems($settings['image_field']);
if ($settings['image_field'] != $settings['thumb_field']) {
$thumb_items = $this
->getItems($settings['thumb_field']);
}
foreach ($image_items as $row_index => $image_item) {
$thumb_item = !empty($thumb_items[$row_index]) ? $thumb_items[$row_index] : $image_item;
$src_data = $this->juicebox
->styleImageSrcData($image_item, $settings['image_field_style'], $thumb_item, $settings['thumb_field_style'], $settings);
if (!$src_data['juicebox_compatible'] && $settings['incompatible_file_action'] == 'skip') {
continue;
}
if (!empty($settings['linkurl_source']) && !empty($this->rendered_fields[$row_index][$settings['linkurl_source']])) {
$src_data['linkURL'] = (string) $this->rendered_fields[$row_index][$settings['linkurl_source']];
}
$title = '';
if (!$src_data['juicebox_compatible'] && $settings['incompatible_file_action'] == 'show_icon_and_link') {
$anchor = !empty($image_item->description) ? $image_item->description : $image_item->filename;
$title = $this->linkGenerator
->generate($anchor, Url::fromUri($src_data['linkURL']));
}
elseif (!empty($settings['title_field']) && !empty($this->rendered_fields[$row_index][$settings['title_field']])) {
$title = (string) $this->rendered_fields[$row_index][$settings['title_field']];
}
$caption = '';
if (!empty($settings['caption_field']) && !empty($this->rendered_fields[$row_index][$settings['caption_field']])) {
$caption = (string) $this->rendered_fields[$row_index][$settings['caption_field']];
}
$gallery
->addImage($src_data, $title, $caption);
}
if ($settings['show_title']) {
$gallery
->addOption('gallerytitle', Html::escape($view
->getTitle()));
}
$this->juicebox
->runCommonBuild($gallery, $settings, $view);
}
protected function buildContextualLinks(array $xml_route_info) {
$contextual = [];
$xml_query = !empty($xml_route_info['options']['query']) ? $xml_route_info['options']['query'] : [];
$contextual['juicebox_xml_viewsstyle'] = [
'route_parameters' => $xml_route_info['route_parameters'] + $xml_query,
];
return $contextual;
}
protected function getItems($source_field) {
$view = $this->view;
$source_options = $this
->confGetFieldSources();
if (empty($source_options['field_options_images_type'][$source_field])) {
throw new \Exception('Empty or invalid field source @source detected for Juicebox view-based gallery.', [
'@source' => $source_field,
]);
}
else {
$source_type = $source_options['field_options_images_type'][$source_field];
}
$fids = [];
$items = [];
foreach ($view->result as $row_index => $row) {
switch ($source_type) {
case 'file_id_field':
$target_id = $view->field[$source_field]
->getValue($row);
if (!empty($target_id) && is_numeric($target_id)) {
$fids[$row_index] = $target_id;
}
continue 2;
case 'file_field':
$target_ids = $view->field[$source_field]
->getValue($row, 'target_id');
$target_id = is_array($target_ids) ? reset($target_ids) : $target_ids;
if (!empty($target_id) && is_numeric($target_id)) {
$fids[$row_index] = $target_id;
}
}
}
if (empty($items)) {
$file_entities = $this->entityTypeManager
->getStorage('file')
->loadMultiple($fids);
foreach ($fids as $row_index => $fid) {
$items[$row_index] = $file_entities[$fid];
}
}
return $items;
}
public function confGetFieldSources() {
$options = [
'field_options_images' => [],
'field_options_images_type' => [],
'field_options' => [],
];
$view = $this->view;
$field_handlers = $view->display_handler
->getHandlers('field');
$field_labels = $view->display_handler
->getFieldLabels();
foreach ($field_handlers as $viewfield => $handler) {
$is_image = FALSE;
$id = $handler
->getPluginId();
$name = $field_labels[$viewfield];
if ($id == 'field') {
$entity = $this->entityFieldManager
->getFieldStorageDefinitions($handler
->getEntityType());
if (isset($handler->field) && array_key_exists($handler->field, $entity)) {
$field_definition = $entity[$handler->field];
$field_type = $field_definition
->getType();
if ($field_type == 'image' || $field_type == 'file' || $field_type == 'entity_reference') {
$field_cardinality = $field_definition
->get('cardinality');
$options['field_options_images'][$viewfield] = $name . ($field_cardinality == 1 ? '' : '*');
$options['field_options_images_type'][$viewfield] = 'file_field';
$is_image = TRUE;
}
elseif ($field_type == 'integer' && $handler->field == 'fid') {
$options['field_options_images'][$viewfield] = $name;
$options['field_options_images_type'][$viewfield] = 'file_id_field';
$is_image = TRUE;
}
}
}
elseif ($id == 'file' && $viewfield == 'fid') {
$options['field_options_images'][$viewfield] = $name;
$options['field_options_images_type'][$viewfield] = 'file_id_field';
$is_image = TRUE;
}
if (!$is_image) {
$options['field_options'][$viewfield] = $name;
}
}
return $options;
}
public function validate() {
$errors = parent::validate();
$pager_options = $this->displayHandler
->getOption('pager');
if (isset($pager_options['type']) && !($pager_options['type'] == 'none' || $pager_options['type'] == 'some')) {
}
$style = $this->displayHandler
->getOption('style');
if (empty($style['options']['image_field']) || empty($style['options']['thumb_field'])) {
$this
->messenger()
->addWarning($this->stringTranslation
->translate("To ensure a fully functional Juicebox gallery please remember to add at least one field of type Image, File or File ID to your Juicebox view display, and to configure all Juicebox Gallery format settings. Once you have completed these steps, re-save your view to remove this warning."), FALSE);
}
return $errors;
}
protected function argsToQuery() {
$query = [];
foreach ($this->view->args as $key => $arg) {
$query['arg_' . $key] = $arg;
}
return $query;
}
}