splide-1.0.x-dev/src/SplideSkinManager.php

src/SplideSkinManager.php
<?php

namespace Drupal\splide;

use Drupal\Component\Plugin\Mapper\MapperInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\splide\Entity\Splide;

/**
 * Provides Splide skin manager.
 */
class SplideSkinManager extends DefaultPluginManager implements SplideSkinManagerInterface, MapperInterface {

  /**
   * The app root.
   *
   * @var string
   */
  protected $root;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $config;

  /**
   * Static cache for the skin definition.
   *
   * @var array
   */
  protected $skinDefinition;

  /**
   * Static cache for the skins by group.
   *
   * @var array
   */
  protected $skinsByGroup;

  /**
   * The library info definition.
   *
   * @var array
   */
  protected $libraryInfoBuild;

  /**
   * The easing library path.
   *
   * @var string
   */
  protected $easingPath;

  /**
   * The splide library path.
   *
   * @var string
   */
  protected $splidePath;

  /**
   * {@inheritdoc}
   */
  protected static $namespace = 'splide';

  /**
   * {@inheritdoc}
   */
  protected static $path = 'Plugin/splide';

  /**
   * {@inheritdoc}
   */
  protected static $interface = 'Drupal\splide\SplideSkinPluginInterface';

  /**
   * {@inheritdoc}
   */
  protected static $annotation = 'Drupal\splide\Annotation\SplideSkin';

  /**
   * {@inheritdoc}
   */
  protected static $key = 'splide_skin';

  /**
   * {@inheritdoc}
   */
  protected static $methods = ['skins', 'arrows', 'dots'];

  /**
   * {@inheritdoc}
   */
  public function __construct(
    \Traversable $namespaces,
    CacheBackendInterface $cache_backend,
    ModuleHandlerInterface $module_handler,
    $root,
    ConfigFactoryInterface $config,
  ) {
    // parent::__construct(
    // 'Plugin/splide',
    // $namespaces,
    // $module_handler,
    // SplideSkinPluginInterface::class,
    // 'Drupal\splide\Annotation\SplideSkin'
    // );.
    parent::__construct(static::$path, $namespaces, $module_handler, static::$interface, static::$annotation);

    $this->root = $root;
    $this->config = $config;

    $this->alterInfo('splide_skin_info');
    $this->setCacheBackend($cache_backend, 'splide_skin_plugins');
  }

  /**
   * {@inheritdoc}
   */
  public function getCache() {
    return $this->cacheBackend;
  }

  /**
   * {@inheritdoc}
   */
  public function root() {
    return $this->root;
  }

  /**
   * {@inheritdoc}
   */
  public function attach(array &$load, array $attach, $blazies = NULL): void {
    $this->attachCore($load, $attach, $blazies);
    $load['drupalSettings']['splide'] = $this->getSafeSettings(Splide::defaultSettings());

    if (!empty($attach['pagination_tab'])) {
      $load['library'][] = 'splide/pagination.tab';

      // @todo move it into [data-splide] to support multiple instances on page.
      $load['drupalSettings']['splide']['paginationTexts'] = $attach['pagination_texts'] ?? [];
    }
  }

  /**
   * {@inheritdoc}
   */
  public function attachCore(array &$load, array $attach, $blazies = NULL): void {
    // @todo remove BC at 2.x with non-optional $blazies.
    $blazies = $blazies ?: $attach['blazies'] ?? NULL;
    if ($this->config('splide_css')) {
      $load['library'][] = 'splide/splide.css';
    }

    if ($blazies && !$blazies->is('unlazy')) {
      $load['library'][] = 'blazy/loading';
    }

    if ($blazies->get('libs.media')) {
      $attach['media'] = TRUE;
    }

    if ($blazies->is('blazy')) {
      $attach['blazy'] = TRUE;
    }

    foreach ($this->getComponents() as $key) {
      if (!empty($attach[$key])) {
        $load['library'][] = 'splide/' . $key;
      }
    }

    $load['library'][] = 'splide/load';
    if (!empty($attach['_vanilla'])) {
      $load['library'][] = 'splide/vanilla';
    }

    $load['library'][] = 'splide/nav';

    if (!empty($attach['skin'])) {
      $this->attachSkin($load, $attach, $blazies);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function config($key = '', $group = 'splide.settings') {
    return $this->config->get($group)->get($key);
  }

  /**
   * {@inheritdoc}
   */
  public function getConstantSkins(): array {
    return [
      'browser',
      'lightbox',
      'overlay',
      'main',
      'nav',
      'arrows',
      'dots',
      'widget',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getComponents(): array {
    return array_merge($this->getModuleComponents(), [
      'autoscroll',
      'intersection',
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getSkins(): array {
    if (!isset($this->skinDefinition)) {
      $cid = 'splide_skins_data';
      $cache = $this->cacheBackend->get($cid);

      if ($cache && $data = $cache->data) {
        $this->skinDefinition = $data;
      }
      else {
        $methods = static::$methods;
        $skins = $items = [];
        foreach ($this->loadMultiple() as $skin) {
          foreach ($methods as $method) {
            $items[$method] = $skin->{$method}();
          }
          $skins = NestedArray::mergeDeep($skins, $items);
        }

        $count = isset($items['skins']) ? count($items['skins']) : count($items);
        $tags = Cache::buildTags($cid, ['count:' . $count]);
        $this->cacheBackend->set($cid, $skins, Cache::PERMANENT, $tags);

        $this->skinDefinition = $skins;
      }
    }
    return $this->skinDefinition ?: [];
  }

  /**
   * {@inheritdoc}
   */
  public function getSkinsByGroup($group = '', $option = FALSE): array {
    if (!isset($this->skinsByGroup[$group])) {
      $skins         = $groups = $ungroups = [];
      $nav_skins     = in_array($group, ['arrows', 'dots']);
      $defined_skins = $nav_skins ? $this->getSkins()[$group] : $this->getSkins()['skins'];

      foreach ($defined_skins as $skin => $properties) {
        $item = $option ? strip_tags($properties['name']) : $properties;
        if (!empty($group)) {
          if (isset($properties['group'])) {
            if ($properties['group'] != $group) {
              continue;
            }
            $groups[$skin] = $item;
          }
          elseif (!$nav_skins) {
            $ungroups[$skin] = $item;
          }
        }
        $skins[$skin] = $item;
      }
      $this->skinsByGroup[$group] = $group ? array_merge($ungroups, $groups) : $skins;
    }
    return $this->skinsByGroup[$group] ?: [];
  }

  /**
   * {@inheritdoc}
   */
  public function getSplidePath(
    $base = 'splide',
    $packagist = 'splidejs--splide',
  ): ?string {
    if (!isset($this->splidePath[$base])) {
      if ($manager = self::service('splide.manager')) {
        $libs = [$packagist, $base];
        $this->splidePath[$base] = $manager->getLibrariesPath($libs);
      }
    }
    return $this->splidePath[$base];
  }

  /**
   * {@inheritdoc}
   */
  public function libraryInfoBuild(): array {
    if (!isset($this->libraryInfoBuild)) {
      $this->libraryInfoBuild = $this->getSkinLibraries();
    }
    return $this->libraryInfoBuild;
  }

  /**
   * {@inheritdoc}
   */
  public function libraryInfoAlter(array &$libraries, $extension): void {
    if ($path = $this->getSplidePath()) {
      $js = [
        '/' . $path . '/dist/js/splide.min.js' => [
          'weight' => -3,
          'minified' => TRUE,
        ],
      ];
      $base = ['/' . $path . '/dist/css/splide-core.min.css' => []];
      $theme = ['/' . $path . '/dist/css/splide.min.css' => []];

      $libraries['splide']['js'] = $js;
      $libraries['splide']['css']['base'] = $base;
      $libraries['splide.css']['css']['base'] = $theme;
    }

    $plugins = [
      'autoscroll' => 'auto-scroll',
      'intersection' => 'intersection',
    ];

    foreach ($plugins as $key => $value) {
      $base = 'splide-extension-' . $value;
      if ($path = $this->getSplidePath($base, 'splidejs--' . $base)) {
        $js = [
          '/' . $path . '/dist/js/' . $base . '.min.js' => [
            'weight' => -2.9,
            'minified' => TRUE,
          ],
        ];
        $libraries[$key]['js'] = $js;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function load($plugin_id): SplideSkinPluginInterface {
    return $this->createInstance($plugin_id);
  }

  /**
   * {@inheritdoc}
   */
  public function loadMultiple(): array {
    $skins = [];
    foreach ($this->getDefinitions() as $definition) {
      array_push($skins, $this->createInstance($definition['id']));
    }
    return $skins;
  }

  /**
   * Provides skins only if required.
   *
   * @param array $load
   *   The loaded libraries being modified.
   * @param array $attach
   *   The settings which determine what library to attach.
   * @param object $blazies
   *   The settings.blazies object for convenient, optional for BC.
   */
  protected function attachSkin(array &$load, array $attach, $blazies = NULL): void {
    if ($this->config('module_css', 'splide.settings')) {
      $load['library'][] = 'splide/theme';
    }

    if ($pagination_fx = $attach['pagination_fx'] ?? NULL) {
      $load['library'][] = 'splide/pagination.' . $pagination_fx;
    }

    if (!empty($attach['down'])) {
      $load['library'][] = 'splide/arrow.down';
    }

    if (!empty($attach['autoplay'])) {
      $load['library'][] = 'splide/autoplay';
    }

    foreach ($this->getConstantSkins() as $group) {
      $skin = $group == 'main' ? $attach['skin'] : ($attach['skin_' . $group] ?? '');
      if (!empty($skin)) {
        $skins = $this->getSkinsByGroup($group);
        $provider = $skins[$skin]['provider'] ?? 'splide';
        $load['library'][] = 'splide/' . $provider . '.' . $group . '.' . $skin;
      }
    }
  }

  /**
   * Returns typecast settings.
   */
  protected function getSafeSettings(array $settings): array {
    // Attach default JS settings to allow responsive displays have a lookup,
    // excluding wasted/trouble options, e.g.: PHP string vs JS object.
    $excludes = explode(' ', 'breakpoints classes i18n padding easingOverride downTarget downOffset');
    $excludes = array_combine($excludes, $excludes);
    $settings = Splide::typecast($settings, FALSE);

    // The library assumes some object FALSE explicitly by default.
    // @todo recheck others like breakpoints classes i18n padding, etc.
    foreach (Splide::getObjectsAsBool() as $key) {
      $settings[$key] = FALSE;
    }

    $breakpoints = SplideDefault::validBreakpointOptions();
    $breakpoints = array_combine($breakpoints, $breakpoints);
    $extras = ['destroy' => FALSE];

    foreach ($settings as $key => $value) {
      if (isset($breakpoints[$key])) {
        $extras[$key] = $value;
      }
    }

    $settings['destroy'] = FALSE;
    $config = ['defaults' => array_diff_key($settings, $excludes)];
    $config['extras'] = Splide::typecast($extras, FALSE);
    $config['resets'] = SplideDefault::unsplide();

    return $config;
  }

  /**
   * {@inheritdoc}
   */
  protected function getSkinLibraries(): array {
    $libraries = [];
    $libraries['splide.css'] = [
      'dependencies' => ['splide/splide'],
      'css' => [
        'base' => ['/' . $this->getSplidePath() . '/dist/css/splide.min.css' => []],
      ],
    ];

    $fullscreen = ['css/components/splide.fullscreen.css' => []];
    foreach ($this->getModuleComponents() as $key) {
      $libraries[$key] = [
        'dependencies' => ['splide/base'],
        'js' => [
          'js/components/splide.' . $key . '.min.js' => [
            'minified' => TRUE,
            'weight' => -0.03,
          ],
        ],
      ];
      if ($key == 'fullscreen') {
        $libraries[$key]['css']['component'] = $fullscreen;
      }
    }

    $libraries['colorbox']['dependencies'][] = 'blazy/colorbox';
    $libraries['media']['dependencies'][] = 'splide/blazy';
    $libraries['zoom']['dependencies'][] = 'splide/swipedetect';

    foreach ($this->getConstantSkins() as $group) {
      if ($skins = $this->getSkinsByGroup($group)) {
        foreach ($skins as $key => $skin) {
          $provider = $skin['provider'] ?? 'splide';
          $id = $provider . '.' . $group . '.' . $key;

          $libraries[$id]['dependencies'] = [];
          foreach (['css', 'js', 'dependencies'] as $property) {
            if (isset($skin[$property]) && is_array($skin[$property])) {
              $libraries[$id][$property] = $skin[$property];
            }
          }

          $libraries[$id]['version'] = 'VERSION';

          if ($dependencies = $this->getDependencies()) {
            $libraries[$id]['dependencies'] = array_merge(
              $libraries[$id]['dependencies'],
              $dependencies
            );
          }
        }
      }
    }

    return $libraries;
  }

  /**
   * {@inheritdoc}
   */
  protected function getDependencies(): array {
    return ['blazy/dblazy'];
  }

  /**
   * Splide module-managed/ builtin library components.
   */
  private function getModuleComponents(): array {
    return [
      'blazy',
      'colorbox',
      'fullscreen',
      'media',
      'swipedetect',
      'zoom',
    ];
  }

  /**
   * Returns a wrapper to pass tests, or DI where adding params is troublesome.
   */
  private static function service($service) {
    return \Drupal::hasService($service) ? \Drupal::service($service) : NULL;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc