You are here

SlickViews.php in Slick Views 8

File

src/Plugin/views/style/SlickViews.php
View source
<?php

namespace Drupal\slick_views\Plugin\views\style;

use Drupal\Core\Form\FormStateInterface;
use Drupal\blazy\Blazy;
use Drupal\blazy\BlazyManagerInterface;
use Drupal\blazy\Dejavu\BlazyStylePluginBase;
use Drupal\slick\SlickDefault;
use Drupal\slick\SlickManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Slick style plugin.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "slick",
 *   title = @Translation("Slick Carousel"),
 *   help = @Translation("Display the results in a Slick carousel."),
 *   theme = "slick_wrapper",
 *   register_theme = FALSE,
 *   display_types = {"normal"}
 * )
 */
class SlickViews extends BlazyStylePluginBase {

  /**
   * The slick service manager.
   *
   * @var \Drupal\slick\SlickManagerInterface
   */
  protected $manager;

  /**
   * Constructs a SlickManager object.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, BlazyManagerInterface $blazy_manager, SlickManagerInterface $manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $blazy_manager);
    $this->manager = $manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('blazy.manager'), $container
      ->get('slick.manager'));
  }

  /**
   * Returns the slick admin.
   */
  public function admin() {
    return \Drupal::service('slick.admin');
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = [];
    foreach (SlickDefault::extendedSettings() as $key => $value) {
      $options[$key] = [
        'default' => $value,
      ];
    }
    return $options + parent::defineOptions();
  }

  /**
   * Overrides parent::buildOptionsForm().
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    $fields = [
      'captions',
      'classes',
      'images',
      'layouts',
      'links',
      'overlays',
      'thumbnails',
      'thumb_captions',
      'thumb_positions',
      'titles',
    ];
    $definition = $this
      ->getDefinedFieldOptions($fields);
    foreach ([
      'fieldable_form',
      'grid_form',
      'id',
      'nav',
      'vanilla',
    ] as $key) {
      $definition[$key] = TRUE;
    }
    $this
      ->admin()
      ->buildSettingsForm($form, $definition);
    $count = count($definition['captions']);
    $wide = $count > 2 ? ' form--wide form--caption-' . $count : ' form--caption-' . $count;
    $title = '<p class="form__header form__title">';
    $title .= $this
      ->t('Check Vanilla if using content/custom markups, not fields. <small>See it under <strong>Format > Show</strong> section. Otherwise slick markups apply which require some fields added below.</small>');
    $title .= '</p>';
    $form['opening']['#markup'] = '<div class="form--slick form--views form--half form--vanilla has-tooltip' . $wide . '">' . $title;
    if (isset($form['image'])) {
      $form['image']['#description'] .= ' ' . $this
        ->t('Use Blazy formatter to have it lazyloaded. Other supported Formatters: Colorbox, Intense, Responsive image, Video Embed Field, Youtube Field.');
    }
    if (isset($form['overlay'])) {
      $form['overlay']['#description'] .= ' ' . $this
        ->t('Be sure to CHECK "<strong>Style settings > Use field template</strong>" _only if using Slick formatter for nested sliders, otherwise keep it UNCHECKED!');
    }
  }

  /**
   * Overrides StylePluginBase::render().
   */
  public function render() {
    $view = $this->view;
    $count = count($view->result);
    $settings = $this->options;
    $view_name = $view->storage
      ->id();
    $view_mode = $view->current_display;
    $id = Blazy::getHtmlId("slick-views-{$view_name}-{$view_mode}", $settings['id']);
    $settings += [
      'cache_metadata' => [
        'keys' => [
          $id,
          $view_mode,
          $settings['optionset'],
        ],
      ],
    ];

    // Prepare needed settings to work with.
    $settings['id'] = $id;
    $settings['item_id'] = 'slide';
    $settings['cache_tags'] = $view
      ->getCacheTags();
    $settings['caption'] = array_filter($settings['caption']);
    $settings['count'] = $count;
    $settings['current_view_mode'] = $view_mode;
    $settings['namespace'] = 'slick';
    $settings['nav'] = !$settings['vanilla'] && $settings['optionset_thumbnail'] && isset($view->result[1]);
    $settings['overridables'] = empty($settings['override']) ? array_filter($settings['overridables']) : $settings['overridables'];
    $settings['view_name'] = $view_name;
    $elements = [];
    foreach ($this
      ->renderGrouping($view->result, $settings['grouping']) as $rows) {
      $build = $this
        ->buildElements($settings, $rows);

      // Supports Blazy formatter multi-breakpoint images if available.
      if (empty($settings['vanilla'])) {
        $this
          ->blazyManager()
          ->isBlazy($settings, $build['items'][0]);
      }
      $build['settings'] = $settings;
      $elements = $this->manager
        ->build($build);
      unset($build);
    }
    return $elements;
  }

  /**
   * Returns slick contents.
   */
  public function buildElements(array $settings, $rows) {
    $build = [];
    $view = $this->view;
    $keys = array_keys($view->field);
    $item_id = $settings['item_id'];
    foreach ($rows as $index => $row) {
      $view->row_index = $index;
      $slide = [];
      $thumb = $slide[$item_id] = [];

      // Provides a potential unique thumbnail different from the main image.
      if (!empty($settings['thumbnail'])) {
        $thumbnail = $this
          ->getFieldRenderable($row, 0, $settings['thumbnail']);
        if (isset($thumbnail['rendered']['#item'])) {
          $item = $thumbnail['rendered']['#item'];
          $settings['thumbnail_uri'] = ($entity = $item->entity) && empty($item->uri) ? $entity
            ->getFileUri() : $item->uri;
        }
      }
      $slide['settings'] = $settings;

      // Use Vanilla slick if so configured, ignoring Slick markups.
      if (!empty($settings['vanilla'])) {
        $slide[$item_id] = $view->rowPlugin
          ->render($row);
      }
      else {

        // Otherwise, extra works. With a working Views cache, no big deal.
        $this
          ->buildElement($slide, $row, $index);

        // Build thumbnail navs if so configured.
        if (!empty($settings['nav'])) {
          $thumb[$item_id] = empty($settings['thumbnail']) ? [] : $this
            ->getFieldRendered($index, $settings['thumbnail']);
          $thumb['caption'] = empty($settings['thumbnail_caption']) ? [] : $this
            ->getFieldRendered($index, $settings['thumbnail_caption']);
          $build['thumb']['items'][$index] = $thumb;
        }
      }
      if (!empty($settings['class'])) {
        $classes = $this
          ->getFieldString($row, $settings['class'], $index);
        $slide['settings']['class'] = empty($classes[$index]) ? [] : $classes[$index];
      }
      if (empty($slide[$item_id])) {
        $slide[$item_id] = $this
          ->getFieldRendered($index, $settings['image']);
      }
      $build['items'][$index] = $slide;
      unset($slide, $thumb);
    }
    unset($view->row_index);
    return $build;
  }

}

Classes

Namesort descending Description
SlickViews Slick style plugin.