elevatezoomplus-8.x-1.x-dev/src/ElevateZoomPlusManager.php
src/ElevateZoomPlusManager.php
<?php
namespace Drupal\elevatezoomplus;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\blazy\BlazyManagerInterface;
use Drupal\elevatezoomplus\Entity\ElevateZoomPlus;
/**
* Provides ElevateZoom Plus library methods mainly for hooks.
*/
class ElevateZoomPlusManager implements ElevateZoomPlusManagerInterface {
use StringTranslationTrait;
/**
* The blazy manager service.
*
* @var \Drupal\blazy\BlazyManagerInterface
*/
protected $manager;
/**
* Static cache for the optionset options.
*
* @var array
*/
protected $optionsetOptions;
/**
* Constructs a ElevateZoomPlusManager instance.
*/
public function __construct(BlazyManagerInterface $manager) {
$this->manager = $manager;
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks() {
return ['preRenderBuild'];
}
/**
* {@inheritdoc}
*/
public function manager() {
return $this->manager;
}
/**
* {@inheritdoc}
*/
public function isApplicable(array $settings): bool {
$obj = $this->manager->verifySafely($settings);
return $obj->get('elevatezoomplus') || !empty($settings['elevatezoomplus']);
}
/**
* {@inheritdoc}
*
* @todo remove some settings after Splick/Splide.
*/
public function getOptions(array $settings): array {
$blazies = $this->manager->verifySafely($settings);
$id = $settings['elevatezoomplus'] ?? 'default';
$id = $blazies->get('elevatezoomplus') ?: $id;
$filters = ['blazy_filter', 'splide_filter', 'slick_filter'];
$switch = $settings['media_switch'] ?? '';
$fallback = $blazies->get('ui.extras.elevatezoomplus', 'default');
$plugin_id = $blazies->get('filter.plugin_id');
$switch = $blazies->get('switch') ?: $switch;
$nav = $blazies->is('nav');
$is_filter = $plugin_id && in_array($plugin_id, $filters);
$option_id = $is_filter ? $fallback : $id;
$optionset = ElevateZoomPlus::loadWithFallback($option_id);
$options = $optionset->getSettings(TRUE);
// If not using Slick/ Splide, provides a static grid gallery.
if (!$nav) {
$options['galleryItem'] = '[data-elevatezoomplus-trigger]';
$options['galleryActiveClass'] = 'is-active';
$options['gallerySelector'] = '[data-elevatezoomplus-gallery]';
}
if (isset($options['zoomWindowPosition'])
&& is_numeric($options['zoomWindowPosition'])) {
$options['zoomWindowPosition'] = (int) $options['zoomWindowPosition'];
}
if (empty($options['loadingIcon'])) {
unset($options['loadingIcon']);
}
return $options;
}
/**
* {@inheritdoc}
*/
public function getOptionsetOptions($entity_type): array {
if (!isset($this->optionsetOptions)) {
$this->optionsetOptions = $this->manager->getEntityAsOptions($entity_type);
}
return $this->optionsetOptions;
}
/**
* {@inheritdoc}
*
* @todo use hook_blazy_element_alter(&$element, &$settings) post blazy:2.17.
*/
public function preRenderBuild(array $element): array {
$build = $element['#build'];
unset($element['#build']);
// Supported themes: Blazy (field|item_list), slick|splide_wrapper,
// gridstack.
$settings = [];
foreach (['blazy', 'build', 'context', 'settings'] as $key) {
$k = '#' . $key;
if (isset($build[$k])) {
// @todo use the second at blazy:3.x when refactored.
$settings = $build[$k]['#settings'] ?? $build[$k]['settings'] ?? [];
$settings = ($key == 'build' || $key == 'context')
? $settings : $build[$k];
break;
}
}
// The AJAX class was already excluded at Blazymanager line #505 and passed
// into #container_attributes below, gone at 2021, likely changed somewhere.
$attributes = (array) ($element['#container_attributes'] ?? []);
// Preserves the AJAX class for the container, then removes it later for the
// the theme. This is because product container shares the same attributes
// array which cause unwanted double AJAX classes.
// Not available if `Use field template` is checked.
$ajax_class = $element['#ajax_replace_class'] ?? '';
if (empty($ajax_class)) {
if ($classes = ($build['#attributes']['class'] ?? [])) {
foreach ($classes as $key => $class) {
if (mb_strpos($class, 'product--variation-field--variation') !== FALSE) {
$attributes['class'][] = $class;
break;
}
}
}
}
else {
$attributes['class'][] = $ajax_class;
}
$settings['ajax_replace_class'] = $ajax_class;
$element['#settings'] = $settings;
$element['#attributes'] = $attributes;
$element['#content'] = $build;
unset($build);
return $element;
}
/**
* {@inheritdoc}
*/
public function preprocessBlazy(array &$variables): void {
$settings = $variables['settings'];
$blazies = $settings['blazies'];
$zoom_url = $variables['url'];
$is_nav = $blazies->is('nav') || !empty($settings['nav']);
$box_url = $blazies->get('lightbox.url');
$multimedia = $blazies->is('multimedia');
$data_b = $blazies->use('data_b', TRUE);
// Support video thumbnail since `url` points to a provider site.
if ($multimedia && $box_url) {
$zoom_url = $box_url;
}
// Re-use thumbnail style for the stage/ preview image.
$prefix = $data_b ? 'data-b-' : 'data-';
$thumb = $variables['attributes'][$prefix . 'thumb'] ?? NULL;
$stage_url = $thumb ?: $zoom_url;
// @todo remove post blazy:3.0.9.
if ($blazies->get('media.type') === 'image') {
$variables['url_attributes']['class'][] = 'litebox--image';
}
// Provides the expected attributes for JS, except for lighboxes which
// support (local|remote) videos.
if (!$multimedia) {
$variables['url_attributes']['data-image'] = $stage_url;
$variables['url_attributes']['data-zoom-image'] = $zoom_url;
// If using Slick asNavFor, make the litebox link as a zoom trigger, too.
$id = $this->manager->getHtmlId('elevatezoomplus');
if ($is_nav) {
$variables['url_attributes']['class'][] = 'elevatezoomplus';
$variables['url_attributes']['id'] = $id;
}
else {
$variables['item_attributes']['id'] = $id;
}
}
}
/**
* {@inheritdoc}
*/
public function attachAlter(array &$load, array $attach): void {
// @todo more robust dynamic mixed media. Not easy due to no video suports.
// if (empty($attach['media']) && !empty($attach['bundles'])
// && in_array('remote_video', $attach['bundles'])) {
// $load['library'][] = 'blazy/media';
// }
$load['drupalSettings']['elevateZoomPlus'] = ElevateZoomPlus::defaultSettings();
$load['library'][] = 'elevatezoomplus/load';
}
/**
* {@inheritdoc}
*/
public function buildAlter(array &$build, array $settings): void {
$this->manager->verifySafely($settings);
if ($this->isApplicable($settings)) {
$build = [
'#theme' => 'elevatezoomplus',
'#build' => $build,
'#pre_render' => [[$this, 'preRenderBuild']],
];
}
}
/**
* {@inheritdoc}
*/
public function formElementAlter(array &$form, array $definition): void {
$blazies = $definition['blazies'] ?? NULL;
$scopes = $definition['scopes'] ?? NULL;
$field_type = $definition['field_type'] ?? NULL;
$settings = $definition['settings'] ?? [];
$texts = ['link', 'string', 'string_long'];
$no_image = $definition['no_image_style'] ?? FALSE;
if ($blazies) {
$field_type = $scopes->get('field.type') ?: $field_type;
}
if ($scopes) {
$no_image = $scopes->is('no_image_style') || $no_image;
}
// Exclude from blazy text formatters, or blazy views grid.
$applicable = $field_type && !in_array($field_type, $texts);
if (!$no_image && !isset($settings['grouping'])) {
$elevatezoomplus = [
'#type' => 'select',
'#title' => $this->t('ElevateZoom Plus'),
'#options' => $this->getOptionsetOptions('elevatezoomplus'),
'#empty_option' => $this->t('- None -'),
'#default_value' => $settings['elevatezoomplus'] ?? '',
'#description' => $this->t('Choose an optionset.'),
'#weight' => -98.99,
'#enforce' => FALSE,
];
// Hooks into Blazy UI to support Blazy Filter.
if (isset($settings['admin_css'])) {
$form['extras']['#access'] = TRUE;
$form['extras']['elevatezoomplus'] = $elevatezoomplus;
$form['extras']['elevatezoomplus']['#default_value'] = $settings['extras']['elevatezoomplus'] ?? '';
$form['extras']['elevatezoomplus']['#description'] .= ' ' . $this->t('Blazy/Splide/Slick Filter only. Warning! Not working nicely. This needs extra image styles which are lacking with inline images.');
}
else {
if ($applicable) {
$form['elevatezoomplus'] = $elevatezoomplus;
$form['elevatezoomplus']['#description'] .= ' ' . $this->t('Requires any lightbox (<b>not: Image to iFrame, Image linked to content, Image rendered</b>) for <b>Media switcher</b> if using Splide/Slick with asNavFor. If not, choose only <b>Image to Elevatezoomplus</b>. Be sure to read <a href=":url">Elevatezoomplus Help</a>.', [
':url' => '/admin/help/elevatezoomplus_ui',
]);
if ($this->manager->config('admin_css', 'blazy.settings')) {
$form['closing']['#attached']['library'][] = 'elevatezoomplus/admin';
}
}
}
}
}
/**
* {@inheritdoc}
*/
public function libraryInfoAlter(array &$libraries, $extension): void {
$gitdir = 'elevatezoom-plus';
$dirs = [$gitdir, 'ez-plus'];
if ($library = $this->manager->getLibrariesPath($dirs)) {
$ext = is_file($library . '/src/jquery.ez-plus.min.js') ? 'min.js' : 'js';
$libraries['elevatezoomplus']['js']['/' . $library . '/src/jquery.ez-plus.' . $ext] = ['weight' => -1];
// Due to soft dependencies.
if ($this->manager->moduleExists('splide')) {
$libraries['load']['dependencies'][] = 'splide/load';
$libraries['load']['dependencies'][] = 'splide/nav';
}
if ($this->manager->moduleExists('slick')) {
$libraries['load']['dependencies'][] = 'slick/slick.load';
}
// In case both github and packagist are present, remove github.
if (!$this->manager->getLibrariesPath($gitdir)) {
unset($libraries['elevatezoomplus']['js']['/libraries/' . $gitdir . '/src/jquery.ez-plus.js']);
}
}
}
}
