3 namespace Drupal\blazy\Form;
6 use Drupal\Core\Cache\Cache;
7 use Drupal\Core\Render\Element;
8 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
9 use Drupal\Core\Config\TypedConfigManagerInterface;
10 use Drupal\Core\StringTranslation\StringTranslationTrait;
11 use Drupal\Component\Utility\Html;
12 use Symfony\Component\DependencyInjection\ContainerInterface;
13 use Drupal\blazy\BlazyManagerInterface;
16 * A base for blazy admin integration to have re-usable methods in one place.
18 * @see \Drupal\gridstack\Form\GridStackAdmin
19 * @see \Drupal\mason\Form\MasonAdmin
20 * @see \Drupal\slick\Form\SlickAdmin
21 * @see \Drupal\blazy\Form\BlazyAdminFormatterBase
23 abstract class BlazyAdminBase implements BlazyAdminInterface {
25 use StringTranslationTrait;
28 * A state that represents the responsive image style is disabled.
30 const STATE_RESPONSIVE_IMAGE_STYLE_DISABLED = 0;
33 * A state that represents the media switch lightbox is enabled.
35 const STATE_LIGHTBOX_ENABLED = 1;
38 * A state that represents the media switch iframe is enabled.
40 const STATE_IFRAME_ENABLED = 2;
43 * A state that represents the thumbnail style is enabled.
45 const STATE_THUMBNAIL_STYLE_ENABLED = 3;
48 * A state that represents the custom lightbox caption is enabled.
50 const STATE_LIGHTBOX_CUSTOM = 4;
53 * A state that represents the image rendered switch is enabled.
55 const STATE_IMAGE_RENDERED_ENABLED = 5;
58 * The entity type manager service.
60 * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
62 protected $entityDisplayRepository;
65 * The typed config manager service.
67 * @var \Drupal\Core\Config\TypedConfigManagerInterface
69 protected $typedConfig;
72 * The blazy manager service.
74 * @var \Drupal\blazy\BlazyManagerInterface
76 protected $blazyManager;
79 * Constructs a BlazyAdminBase object.
81 * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
82 * The entity display repository.
83 * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
84 * The typed config service.
85 * @param \Drupal\slick\BlazyManagerInterface $blazy_manager
86 * The blazy manager service.
88 public function __construct(EntityDisplayRepositoryInterface $entity_display_repository, TypedConfigManagerInterface $typed_config, BlazyManagerInterface $blazy_manager) {
89 $this->entityDisplayRepository = $entity_display_repository;
90 $this->typedConfig = $typed_config;
91 $this->blazyManager = $blazy_manager;
97 public static function create(ContainerInterface $container) {
98 return new static($container->get('entity_display.repository'), $container->get('config.typed'), $container->get('blazy.manager'));
102 * Returns the entity display repository.
104 public function getEntityDisplayRepository() {
105 return $this->entityDisplayRepository;
109 * Returns the typed config.
111 public function getTypedConfig() {
112 return $this->typedConfig;
116 * Returns the blazy manager.
118 public function blazyManager() {
119 return $this->blazyManager;
123 * Returns shared form elements across field formatter and Views.
125 public function openingForm(array &$form, $definition = []) {
126 $this->blazyManager->getModuleHandler()->alter('blazy_form_element_definition', $definition);
128 // Display style: column, plain static grid, slick grid, slick carousel.
129 // https://drafts.csswg.org/css-multicol
130 if (!empty($definition['style'])) {
133 '#title' => $this->t('Display style'),
134 '#description' => $this->t('Either <strong>CSS3 Columns</strong> (experimental pure CSS Masonry) or <strong>Grid Foundation</strong> requires <strong>Grid</strong>. Difference: <strong>Columns</strong> is best with irregular image sizes (scale width, empty height), affects the natural order of grid items. <strong>Grid</strong> with regular cropped ones. Unless required, leave empty to use default formatter, or style.'),
136 '#empty_option' => '- None -',
138 'column' => $this->t('CSS3 Columns'),
139 'grid' => $this->t('Grid Foundation'),
142 '#wrapper_attributes' => ['class' => ['form-item--style', 'form-item--tooltip-bottom']],
146 if (!empty($definition['skins'])) {
149 '#title' => $this->t('Skin'),
150 '#options' => $definition['skins'],
152 '#description' => $this->t('Skins allow various layouts with just CSS. Some options below depend on a skin. Leave empty to DIY. Or use the provided hook_info() and implement the skin interface to register ones.'),
157 if (!empty($definition['background'])) {
158 $form['background'] = [
159 '#type' => 'checkbox',
160 '#title' => $this->t('Use CSS background'),
161 '#description' => $this->t('Check this to turn the image into CSS background. This opens up the goodness of CSS, such as background cover, fixed attachment, etc. <br /><strong>Important!</strong> Requires a consistent Aspect ratio, otherwise collapsed containers. Unless a min-height is added manually to <strong>.media--background</strong> selector. Not compatible with Responsive image.'),
166 if (!empty($definition['layouts'])) {
169 '#title' => $this->t('Layout'),
170 '#options' => $definition['layouts'],
171 '#description' => $this->t('Requires a skin. The builtin layouts affects the entire items uniformly. Leave empty to DIY.'),
176 if (!empty($definition['captions'])) {
178 '#type' => 'checkboxes',
179 '#title' => $this->t('Caption fields'),
180 '#options' => $definition['captions'],
181 '#description' => $this->t('Enable any of the following fields as captions. These fields are treated and wrapped as captions.'),
183 '#attributes' => ['class' => ['form-wrapper--caption']],
187 if (!empty($definition['target_type']) && !empty($definition['view_mode'])) {
188 $form['view_mode'] = $this->baseForm($definition)['view_mode'];
192 foreach (Element::children($form) as $key) {
193 if (!isset($form[$key]['#weight'])) {
194 $form[$key]['#weight'] = ++$weight;
200 * Defines re-usable breakpoints form.
202 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
203 * @see http://ericportis.com/posts/2014/srcset-sizes/
204 * @see http://www.sitepoint.com/how-to-build-responsive-images-with-srcset/
206 public function breakpointsForm(array &$form, $definition = []) {
207 $settings = isset($definition['settings']) ? $definition['settings'] : [];
208 $title = $this->t('Leave Breakpoints empty to disable multi-serving images. <small>If provided, Blazy lazyload applies. Ignored if core Responsive image is provided.<br /> If only two is needed, simply leave the rest empty. At any rate, the last should target the largest monitor. <br />It uses <strong>max-width</strong>, not <strong>min-width</strong>.</small>');
211 '#type' => 'textfield',
212 '#title' => $this->t('Sizes'),
213 '#description' => $this->t('E.g.: (min-width: 1290px) 1290px, 100vw. Use sizes to implement different size image (different height, width) on different screen sizes along with the <strong>w (width)</strong> descriptor below. Ignored by Responsive image.'),
215 '#attributes' => ['class' => ['form-text--sizes', 'js-expandable']],
216 '#wrapper_attributes' => ['class' => ['form-item--sizes']],
217 '#prefix' => '<h2 class="form__title form__title--breakpoints">' . $title . '</h2>',
220 $form['breakpoints'] = [
224 $this->t('Breakpoint'),
225 $this->t('Image style'),
226 $this->t('Max-width/Descriptor'),
228 '#attributes' => ['class' => ['form-wrapper--table', 'form-wrapper--table-breakpoints']],
233 // Unlike D7, D8 form states seem to not recognize individual field form.
234 $vanilla = ':input[name$="[vanilla]"]';
235 if (isset($definition['field_name'])) {
236 $vanilla = ':input[name="fields[' . $definition['field_name'] . '][settings_edit_form][settings][vanilla]"]';
239 if (!empty($definition['_views'])) {
240 $vanilla = ':input[name="options[settings][vanilla]"]';
243 $breakpoints = $this->breakpointElements($definition);
244 foreach ($breakpoints as $breakpoint => $elements) {
245 foreach ($elements as $key => $element) {
246 $form['breakpoints'][$breakpoint][$key] = $element;
248 if (isset($definition['vanilla'])) {
249 $form['breakpoints'][$breakpoint][$key]['#states']['enabled'][$vanilla] = ['checked' => FALSE];
251 $value = isset($settings['breakpoints'][$breakpoint][$key]) ? $settings['breakpoints'][$breakpoint][$key] : '';
252 $form['breakpoints'][$breakpoint][$key]['#default_value'] = $value;
258 * Defines re-usable breakpoints form.
260 public function breakpointElements($definition = []) {
261 foreach ($definition['breakpoints'] as $breakpoint) {
262 $form[$breakpoint]['breakpoint'] = [
264 '#markup' => $breakpoint,
266 '#wrapper_attributes' => ['class' => ['form-item--right']],
269 $form[$breakpoint]['image_style'] = [
271 '#title' => $this->t('Image style'),
272 '#title_display' => 'invisible',
273 '#options' => function_exists('image_style_options') ? image_style_options(FALSE) : [],
274 '#empty_option' => $this->t('- None -'),
276 '#wrapper_attributes' => ['class' => ['form-item--left']],
279 $form[$breakpoint]['width'] = [
280 '#type' => 'textfield',
281 '#title' => $this->t('Width'),
282 '#title_display' => 'invisible',
283 '#description' => $this->t('See <strong>XS</strong> for detailed info.'),
287 '#attributes' => ['class' => ['form-text--width', 'js-expandable']],
288 '#wrapper_attributes' => ['class' => ['form-item--width']],
291 if ($breakpoint == 'xs') {
292 $form[$breakpoint]['width']['#description'] = $this->t('E.g.: <strong>640</strong>, or <strong>2x</strong>, or for <strong>small devices</strong> may be combined into <strong>640w 2x</strong> where <strong>x (pixel density)</strong> descriptor is used to define the device-pixel ratio, and <strong>w (width)</strong> descriptor is the width of image source and works in tandem with <strong>sizes</strong> attributes. Use <strong>w (width)</strong> if any issue/ unsure. Default to <strong>w</strong> if no descriptor provided for backward compatibility.');
300 * Returns re-usable grid elements across field formatter and Views.
302 public function gridForm(array &$form, $definition = []) {
303 $range = range(1, 12);
304 $grid_options = array_combine($range, $range);
306 $header = $this->t('Group individual items as block grid<small>Depends on the <strong>Display style</strong>.</small>');
307 $form['grid_header'] = [
309 '#markup' => '<h3 class="form__title form__title--grid">' . $header . '</h3>',
314 '#title' => $this->t('Grid large'),
315 '#options' => $grid_options,
316 '#description' => $this->t('Select <strong>- None -</strong> first if trouble with changing form states. The amount of block grid columns for large monitors 64.063em+. <br /><strong>Requires</strong>:<ol><li>Visible items,</li><li>Skin Grid for starter,</li><li>A reasonable amount of contents.</li></ol>Leave empty to DIY, or to not build grids.'),
320 $form['grid_medium'] = [
322 '#title' => $this->t('Grid medium'),
323 '#options' => $grid_options,
324 '#description' => $this->t('The amount of block grid columns for medium devices 40.063em - 64em.'),
327 $form['grid_small'] = [
329 '#title' => $this->t('Grid small'),
330 '#options' => $grid_options,
331 '#description' => $this->t('The amount of block grid columns for small devices 0 - 40em. Specific to <strong>CSS3 Columns</strong>, only 1 - 2 column is respected due to small real estate at smallest device.'),
334 $form['visible_items'] = [
336 '#title' => $this->t('Visible items'),
337 '#options' => array_combine(range(1, 32), range(1, 32)),
338 '#description' => $this->t('How many items per display at a time.'),
341 $form['preserve_keys'] = [
342 '#type' => 'checkbox',
343 '#title' => $this->t('Preserve keys'),
344 '#description' => $this->t('If checked, keys will be preserved. Default is FALSE which will reindex the grid chunk numerically.'),
355 foreach ($grids as $key) {
356 $form[$key]['#enforced'] = TRUE;
357 $form[$key]['#states'] = [
359 'select[name$="[grid]"]' => ['!value' => ''],
366 * Returns shared ending form elements across field formatter and Views.
368 public function closingForm(array &$form, $definition = []) {
369 if (isset($definition['current_view_mode'])) {
370 $form['current_view_mode'] = [
372 '#default_value' => isset($definition['current_view_mode']) ? $definition['current_view_mode'] : '_custom',
377 $this->finalizeForm($form, $definition);
381 * Returns simple form elements common for Views field, EB widget, formatters.
383 public function baseForm($definition = []) {
384 $settings = isset($definition['settings']) ? $definition['settings'] : [];
385 $lightboxes = $this->blazyManager->getLightboxes();
386 $image_styles = function_exists('image_style_options') ? image_style_options(FALSE) : [];
387 $is_responsive = function_exists('responsive_image_get_image_dimensions') && !empty($definition['responsive_image']);
390 if (empty($definition['no_image_style'])) {
391 $form['image_style'] = [
393 '#title' => $this->t('Image style'),
394 '#options' => $image_styles,
395 '#description' => $this->t('The content image style. This will be treated as the fallback image, which is normally smaller, if Breakpoints are provided. Otherwise this is the only image displayed.'),
400 if (isset($settings['media_switch'])) {
401 $form['media_switch'] = [
403 '#title' => $this->t('Media switcher'),
405 'content' => $this->t('Image linked to content'),
407 '#empty_option' => $this->t('- None -'),
408 '#description' => $this->t('May depend on the enabled supported or supportive modules: colorbox, photobox etc. Be sure to add Thumbnail style if using Photobox. Try selecting "<strong>- None -</strong>" first before changing if trouble with this complex form states.'),
412 // Optional lightbox integration.
413 if (!empty($lightboxes)) {
414 foreach ($lightboxes as $lightbox) {
415 $form['media_switch']['#options'][$lightbox] = $this->t('Image to @lightbox', ['@lightbox' => $lightbox]);
418 // Re-use the same image style for both lightboxes.
419 $form['box_style'] = [
421 '#title' => $this->t('Lightbox image style'),
422 '#options' => $image_styles,
423 '#states' => $this->getState(static::STATE_LIGHTBOX_ENABLED, $definition),
427 if (!empty($definition['multimedia'])) {
428 $form['box_media_style'] = [
430 '#title' => $this->t('Lightbox video style'),
431 '#options' => $image_styles,
432 '#description' => $this->t('Allows different lightbox video dimensions. Or can be used to have a swipable video if Blazy PhotoSwipe installed.'),
433 '#states' => $this->getState(static::STATE_LIGHTBOX_ENABLED, $definition),
439 // Adds common supported entities for media integration.
440 if (!empty($definition['multimedia'])) {
441 $form['media_switch']['#options']['media'] = $this->t('Image to iFrame');
444 // http://en.wikipedia.org/wiki/List_of_common_resolutions
445 $ratio = ['1:1', '3:2', '4:3', '8:5', '16:9', 'fluid', 'enforced'];
446 if (empty($definition['no_ratio'])) {
449 '#title' => $this->t('Aspect ratio'),
450 '#options' => array_combine($ratio, $ratio),
451 '#empty_option' => $this->t('- None -'),
452 '#description' => $this->t('Aspect ratio to get consistently responsive images and iframes. And to fix layout reflow and excessive height issues. <a href="@dimensions" target="_blank">Image styles and video dimensions</a> must <a href="@follow" target="_blank">follow the aspect ratio</a>. If not, images will be distorted. Choose <strong>fluid</strong> if unsure. Choose <strong>enforced</strong> if you can stick to one aspect ratio and want multi-serving, or Responsive images. <a href="@link" target="_blank">Learn more</a>, or leave empty to DIY, or when working with multi-image-style plugin like GridStack. <br /><strong>Note!</strong> Only compatible with Blazy multi-serving images, but not Responsive image.', [
453 '@dimensions' => '//size43.com/jqueryVideoTool.html',
454 '@follow' => '//en.wikipedia.org/wiki/Aspect_ratio_%28image%29',
455 '@link' => '//www.smashingmagazine.com/2014/02/27/making-embedded-content-work-in-responsive-design/',
460 if ($is_responsive) {
461 $form['ratio']['#states'] = $this->getState(static::STATE_RESPONSIVE_IMAGE_STYLE_DISABLED, $definition);
466 if (!empty($definition['target_type']) && !empty($definition['view_mode'])) {
467 $form['view_mode'] = [
469 '#options' => $this->getViewModeOptions($definition['target_type']),
470 '#title' => $this->t('View mode'),
471 '#description' => $this->t('Required to grab the fields, or to have custom entity display as fallback display. If it has fields, be sure the selected "View mode" is enabled, and the enabled fields here are not hidden there.'),
476 if ($this->blazyManager()->getModuleHandler()->moduleExists('field_ui')) {
477 $form['view_mode']['#description'] .= $this->t('Manage view modes on the <a href=":view_modes">View modes page</a>.', [':view_modes' => Url::fromRoute('entity.entity_view_mode.collection')->toString()]);
481 if (!empty($definition['thumbnail_style'])) {
482 $form['thumbnail_style'] = [
484 '#title' => $this->t('Thumbnail style'),
485 '#options' => function_exists('image_style_options') ? image_style_options(TRUE) : [],
486 '#description' => $this->t('Usages: Photobox/PhotoSwipe thumbnail, or custom work with thumbnails. Leave empty to not use thumbnails.'),
491 $this->blazyManager->getModuleHandler()->alter('blazy_base_form_element', $form, $definition);
497 * Returns re-usable media switch form elements.
499 public function mediaSwitchForm(array &$form, $definition = []) {
500 $settings = isset($definition['settings']) ? $definition['settings'] : [];
501 $lightboxes = $this->blazyManager->getLightboxes();
502 $is_token = function_exists('token_theme');
504 if (isset($settings['media_switch'])) {
505 $form['media_switch'] = $this->baseForm($definition)['media_switch'];
506 $form['media_switch']['#prefix'] = '<h3 class="form__title form__title--media-switch">' . $this->t('Media switcher') . '</h3>';
508 if (empty($definition['no_ratio'])) {
509 $form['ratio'] = $this->baseForm($definition)['ratio'];
513 if (!empty($definition['multimedia']) && empty($definition['no_iframe_lazy'])) {
514 $form['iframe_lazy'] = [
515 '#type' => 'checkbox',
516 '#title' => $this->t('Lazy iframe'),
517 '#description' => $this->t('Check to make the video/audio iframes truly lazyloaded, and speed up loading time. Depends on JS enabled at client side. <a href=":more" target="_blank">Read more</a> to <a href=":url" target="_blank">decide</a>.', [':more' => '//goo.gl/FQLFQ6', ':url' => '//goo.gl/f78pMl']),
519 '#states' => $this->getState(static::STATE_IFRAME_ENABLED, $definition),
523 // Optional lightbox integration.
524 if (!empty($lightboxes) && isset($settings['media_switch'])) {
525 $form['box_style'] = $this->baseForm($definition)['box_style'];
527 if (!empty($definition['multimedia'])) {
528 $form['box_media_style'] = $this->baseForm($definition)['box_media_style'];
532 'auto' => $this->t('Automatic'),
533 'alt' => $this->t('Alt text'),
534 'title' => $this->t('Title text'),
535 'alt_title' => $this->t('Alt and Title'),
536 'title_alt' => $this->t('Title and Alt'),
537 'entity_title' => $this->t('Content title'),
538 'custom' => $this->t('Custom'),
541 if (!empty($definition['box_captions'])) {
542 $form['box_caption'] = [
544 '#title' => $this->t('Lightbox caption'),
545 '#options' => $box_captions,
547 '#states' => $this->getState(static::STATE_LIGHTBOX_ENABLED, $definition),
548 '#description' => $this->t('Automatic will search for Alt text first, then Title text. Try selecting <strong>- None -</strong> first when changing if trouble with form states.'),
551 $form['box_caption_custom'] = [
552 '#title' => $this->t('Lightbox custom caption'),
553 '#type' => 'textfield',
555 '#states' => $this->getState(static::STATE_LIGHTBOX_CUSTOM, $definition),
556 '#description' => $this->t('Multi-value rich text field will be mapped to each image by its delta.'),
560 $types = isset($definition['entity_type']) ? [$definition['entity_type']] : [];
561 $types = isset($definition['target_type']) ? array_merge($types, [$definition['target_type']]) : $types;
562 $form['box_caption_custom']['#field_suffix'] = [
563 '#theme' => 'token_tree_link',
564 '#text' => $this->t('Tokens'),
565 '#token_types' => $types,
571 $this->blazyManager->getModuleHandler()->alter('blazy_media_switch_form_element', $form, $definition);
575 * Returns re-usable logic, styling and assets across fields and Views.
577 public function finalizeForm(array &$form, $definition = []) {
578 $namespace = isset($definition['namespace']) ? $definition['namespace'] : 'slick';
579 $settings = isset($definition['settings']) ? $definition['settings'] : [];
580 $vanilla = isset($definition['vanilla']) ? ' form--vanilla' : '';
581 $captions = empty($definition['captions']) ? 0 : count($definition['captions']);
582 $wide = $captions > 2 ? ' form--wide form--caption-' . $captions : ' form--caption-' . $captions;
583 $fallback = $namespace == 'slick' ? 'form--slick' : 'form--' . $namespace . ' form--slick';
584 $classes = isset($definition['form_opening_classes'])
585 ? $definition['form_opening_classes']
586 : $fallback . ' form--half has-tooltip' . $wide . $vanilla;
588 if (!empty($definition['field_type'])) {
589 $classes .= ' form--' . str_replace('_', '-', $definition['field_type']);
593 '#markup' => '<div class="' . $classes . '">',
598 '#markup' => '</div>',
602 $admin_css = isset($definition['admin_css']) ? $definition['admin_css'] : '';
603 $admin_css = $admin_css ?: $this->blazyManager->configLoad('admin_css', 'blazy.settings');
605 // @todo: Check if needed: 'button', 'container', 'submit'.
606 $excludes = ['details', 'fieldset', 'hidden', 'markup', 'item', 'table'];
607 $selects = ['cache', 'optionset', 'view_mode'];
609 foreach (Element::children($form) as $key) {
610 if (isset($form[$key]['#type']) && !in_array($form[$key]['#type'], $excludes)) {
611 if (!isset($form[$key]['#default_value']) && isset($settings[$key])) {
612 $value = is_array($settings[$key]) ? array_values((array) $settings[$key]) : $settings[$key];
613 $form[$key]['#default_value'] = $value;
615 if (!isset($form[$key]['#attributes']) && isset($form[$key]['#description'])) {
616 $form[$key]['#attributes'] = ['class' => ['is-tooltip']];
620 if ($form[$key]['#type'] == 'checkbox' && $form[$key]['#type'] != 'checkboxes') {
621 $form[$key]['#field_suffix'] = ' ';
622 $form[$key]['#title_display'] = 'before';
624 elseif ($form[$key]['#type'] == 'checkboxes' && !empty($form[$key]['#options'])) {
625 $form[$key]['#attributes']['class'][] = 'form-wrapper--checkboxes';
626 $form[$key]['#attributes']['class'][] = 'form-wrapper--' . str_replace('_', '-', $key);
627 $count = count($form[$key]['#options']);
628 $form[$key]['#attributes']['class'][] = 'form-wrapper--count-' . ($count > 3 ? 'max' : $count);
630 foreach ($form[$key]['#options'] as $i => $option) {
631 $form[$key][$i]['#field_suffix'] = ' ';
632 $form[$key][$i]['#title_display'] = 'before';
637 if ($form[$key]['#type'] == 'select' && !in_array($key, $selects)) {
638 if (!isset($form[$key]['#empty_option']) && !isset($form[$key]['#required'])) {
639 $form[$key]['#empty_option'] = $this->t('- None -');
643 if (!isset($form[$key]['#enforced']) && isset($definition['vanilla']) && isset($form[$key]['#type'])) {
644 $states['visible'][':input[name*="[vanilla]"]'] = ['checked' => FALSE];
645 if (isset($form[$key]['#states'])) {
646 $form[$key]['#states']['visible'][':input[name*="[vanilla]"]'] = ['checked' => FALSE];
649 $form[$key]['#states'] = $states;
654 $form[$key]['#wrapper_attributes']['class'][] = 'form-item--' . str_replace('_', '-', $key);
656 if (isset($form[$key]['#access']) && $form[$key]['#access'] == FALSE) {
657 unset($form[$key]['#default_value']);
662 $form['closing']['#attached']['library'][] = 'blazy/admin';
665 $this->blazyManager->getModuleHandler()->alter('blazy_complete_form_element', $form, $definition);
669 * Returns time in interval for select options.
671 public function getCacheOptions() {
688 $period = array_map([\Drupal::service('date.formatter'), 'formatInterval'], array_combine($period, $period));
689 $period[0] = '<' . $this->t('No caching') . '>';
690 return $period + [Cache::PERMANENT => $this->t('Permanent')];
694 * Returns available optionsets for select options.
696 public function getOptionsetOptions($entity_type = '') {
698 if (empty($entity_type)) {
702 $entities = $this->blazyManager->entityLoadMultiple($entity_type);
703 foreach ((array) $entities as $entity) {
704 $optionsets[$entity->id()] = Html::escape($entity->label());
711 * Returns available view modes for select options.
713 public function getViewModeOptions($target_type) {
714 return $this->entityDisplayRepository->getViewModeOptions($target_type);
718 * Get one of the pre-defined states used in this form.
720 * Thanks to SAM152 at colorbox.module for the little sweet idea.
722 * @param string $state
723 * The state to get that matches one of the state class constants.
726 * A corresponding form API state.
728 protected function getState($state, $definition = []) {
731 foreach ($this->blazyManager->getLightboxes() as $key => $lightbox) {
732 $lightboxes[$key]['value'] = $lightbox;
736 static::STATE_RESPONSIVE_IMAGE_STYLE_DISABLED => [
738 'select[name$="[responsive_image_style]"]' => ['value' => ''],
741 static::STATE_LIGHTBOX_ENABLED => [
743 'select[name*="[media_switch]"]' => $lightboxes,
746 static::STATE_LIGHTBOX_CUSTOM => [
748 'select[name$="[box_caption]"]' => ['value' => 'custom'],
749 'select[name*="[media_switch]"]' => $lightboxes,
752 static::STATE_IFRAME_ENABLED => [
754 'select[name*="[media_switch]"]' => ['value' => 'media'],
757 static::STATE_THUMBNAIL_STYLE_ENABLED => [
759 'select[name$="[thumbnail_style]"]' => ['!value' => ''],
762 static::STATE_IMAGE_RENDERED_ENABLED => [
764 'select[name$="[media_switch]"]' => ['!value' => 'rendered'],
768 return $states[$state];