outlayer-8.x-1.4/src/OutlayerManager.php

src/OutlayerManager.php
<?php

namespace Drupal\outlayer;

use Drupal\Component\Serialization\Json;
use Drupal\gridstack\GridStackManager;
use Drupal\outlayer\Entity\Outlayer;

/**
 * Provides outlayer manager.
 */
class OutlayerManager extends GridStackManager implements OutlayerManagerInterface {

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

  /**
   * The Outlayer optionset.
   *
   * @var \Drupal\outlayer\Entity\Outlayer
   */
  protected $outLayerOptionset;

  /**
   * Supports the new native CSS Grid layout, or disable here if broken.
   *
   * @var bool
   */
  protected $supportGridNative = TRUE;

  /**
   * {@inheritdoc}
   */
  public function prepareAttributes(array &$build) {
    $attributes  = parent::prepareAttributes($build);
    $settings    = &$build['#settings'];
    $outlayers   = $settings['outlayers'] ?? NULL;
    $plugin_id   = $settings['plugin_id'] ?? NULL;
    $instance_id = $settings['instance_id'] ?? NULL;

    $attributes['class'][] = 'outlayer';

    $js = isset($this->outLayerOptionset) ? $this->outLayerOptionset->getOptions() : [];

    $this->massageOptions($js, $settings);

    if ($outlayers) {
      $instance_id = $outlayers->get('view.base_id') ?: $instance_id;
    }

    // Pass data to template.
    $plugin = 'isotope';
    $layout = $js['layoutMode'];
    if ($plugin_id == 'outlayer_grid') {
      $plugin = $settings['style'];
      if (!empty($js[$layout])) {
        foreach ($js[$layout] as $key => $value) {
          $js[$key] = $value;
        }
      }
      unset($js['layoutMode'], $js[$layout]);
    }

    // Take over Masonry/Packery JS with just native CSS Grid if configured so.
    // Except for Isotope which might combine both for its layout and filtering.
    if ($this->supportGridNative && in_array($plugin, ['masonry', 'packery'])) {
      $attributes['class'][] = 'outlayer--native';
    }
    else {
      // Regular Masonry/Packery/Isotope JS layout applies.
      $attributes['class'][] = 'outlayer--' . $plugin;

      $defaults = Outlayer::defaultSettings();
      $js = array_diff_assoc($js, $defaults);

      $attributes['data-outlayer-' . $plugin] = Json::encode($js);

      // Sync filters, sorters with the main grid display via similar ID.
      if ($instance_id) {
        $attributes['data-instance-id'] = $instance_id;
      }
    }

    return $attributes;
  }

  /**
   * {@inheritdoc}
   */
  public function extractGridCustom(array $settings): array {
    $dimensions = [];
    if (!empty($settings['grid_custom'])) {
      $values = array_map('trim', explode(" ", $settings['grid_custom']));
      foreach ($values as $value) {
        $width = $value;
        $height = 0;
        if (strpos($value, 'x') !== FALSE) {
          [$width, $height] = array_pad(array_map('trim', explode("x", $value, 2)), 2, NULL);
        }

        $dimensions[] = ['width' => (int) $width, 'height' => (int) $height];
      }
    }

    return $dimensions;
  }

  /**
   * {@inheritdoc}
   */
  public function getIsotopeExtraLibrary(array $attach): ?string {
    $layout = empty($attach['layoutMode']) ? '' : $attach['layoutMode'];
    foreach (OutlayerDefault::extraLayouts() as $name => $id) {
      if ($layout == $name) {
        return 'outlayer/isotope-' . $id;
      }
    }
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function prepareSettings(array &$settings) {
    parent::prepareSettings($settings);

    $settings += OutlayerDefault::htmlSettings();

    if (isset($this->outLayerOptionset)) {
      $settings['layoutMode'] = $this->outLayerOptionset->getOption('layoutMode');
      $settings['fluid'] = $this->outLayerOptionset->getOption('percentPosition');
    }

    $gridstacks     = $settings['gridstacks'];
    $engine         = $gridstacks->get('engine');
    $ungridstack    = $gridstacks->is('ungridstack');
    $use_gridnative = $gridstacks->use('gridnative');

    $this->supportGridNative = $this->supportGridNative && $use_gridnative;
    $this->outLayerOptionset = Outlayer::loadSafely($settings['outlayer']);

    if (!$this->supportGridNative) {
      // Tells Gridstack to not load any asset with this.
      $ungridstack = !empty($settings['grid_custom']);
      if ($ungridstack) {
        $engine = 'outlayer_ungridstack';
      }
    }

    $gridstacks->set('engine', $engine)
      ->set('is.ungridstack', $ungridstack)
      ->set('use.gridnative', $use_gridnative);
  }

  /**
   * {@inheritdoc}
   */
  protected function attachments(array &$load, array $attach, $blazies): void {
    $attach['blazy'] = TRUE;
    parent::attachments($load, $attach, $blazies);

    // Masonry and Packery might be replaced by native CSS Grid entirely.
    // No JS libraries are needed for static grid display. CSS Grid takes over.
    // However Isotope still needs extra JS for filtering, or sorting.
    if (!empty($attach['plugin_id'])) {
      switch ($attach['plugin_id']) {
        case 'outlayer_grid':
          if (!empty($attach['style']) && !$this->supportGridNative) {
            $load['library'][] = 'outlayer/load.' . $attach['style'];
          }
          break;

        case 'outlayer_isotope':
          if ($layout = $this->getIsotopeExtraLibrary($attach)) {
            $load['library'][] = $layout;
          }

          $load['library'][] = 'outlayer/load.isotope';
          break;

        default:
          break;
      }
    }

    if ($this->supportGridNative) {
      $load['library'][] = 'outlayer/native';
    }

    $js = Outlayer::defaultSettings();
    foreach (['columnWidth', 'gutter', 'rowHeight'] as $key) {
      if (isset($js['layout'][$key]) && is_numeric($js['layout'][$key])) {
        $js['layout'][$key] = (int) $js['layout'][$key];
      }
    }
    $load['drupalSettings']['outLayer'] = $js;

    $this->moduleHandler->alter('outlayer_attach', $load, $attach, $blazies);
  }

  /**
   * Massages the options.
   */
  protected function massageOptions(array &$js, array &$settings) {
    Outlayer::massageOptions($js);
    $layout = $js['layoutMode'];

    // Have no option for this as we don't offer many templates.
    if (empty($js['itemSelector'])) {
      $js['itemSelector'] = '.gridstack__box';
    }

    // If having stamps, provides relevant classes.
    if (!empty($settings['stamp'])) {
      $js['stamp'] = '.box--stamp';
      $js['itemSelector'] = '.gridstack__box:not(.box--stamp)';
    }

    // Provides sorters.
    if (!empty($settings['sorters'])) {
      $sorts = [];
      foreach ($settings['sorters'] as $key) {
        $sorts[$key] = '[data-srtr-' . $key . ']';
      }
      $js['getSortData'] = $sorts;

      // @todo extract correct data.
      if (!empty($settings['sortBy'])) {
        $js['sortBy'] = $settings['sortBy'];
      }
    }

    // Sizing options columnWidth, rowHeight, and gutter can be set with an
    // element. The size of the element is then used as the value of the option.
    foreach (['columnWidth', 'gutter', 'rowHeight'] as $key) {
      if (!empty($js[$layout][$key])) {
        if (is_numeric($js[$layout][$key])) {
          $js[$layout][$key] = (int) $js[$layout][$key];
        }
        else {
          $settings[$key . 'Sizer'] = str_replace('.', '', $js[$layout][$key]);
        }
      }
    }

    foreach (['stagger', 'transitionDuration'] as $key) {
      if (!empty($js[$key]) && is_numeric($js[$key])) {
        $js[$key] = (int) $js[$key];
      }
    }
  }

}

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

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