You are here

GridStackLayoutBase.php in GridStack 8.2

File

src/Plugin/Layout/GridStackLayoutBase.php
View source
<?php

namespace Drupal\gridstack\Plugin\Layout;

use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformStateInterface;
use Drupal\Core\Layout\LayoutDefault;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\gridstack\GridStackDefault;
use Drupal\gridstack\Entity\GridStack;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a GridStack base class for Layout plugins.
 */
abstract class GridStackLayoutBase extends LayoutDefault implements ContainerFactoryPluginInterface, PluginFormInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The gridstack manager service.
   *
   * @var \Drupal\gridstack\GridStackManagerInterface
   */
  protected $manager;

  /**
   * The gridstack stylizer service.
   *
   * @var \Drupal\gridstack\GridStackStylizerInterface
   */
  protected $stylizer;

  /**
   * The gridstack stylizer form plugin.
   *
   * @var \Drupal\gridstack\GridStackStylizerPluginInterface
   */
  protected $styleForm;

  /**
   * The gridstack admin service.
   *
   * @var \Drupal\gridstack\Form\GridStackAdminInterface
   */
  protected $admin;

  /**
   * The field name to store media.
   *
   * @var string
   */
  protected $fieldName;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);
    $instance->currentUser = $container
      ->get('current_user');
    $instance->manager = $container
      ->get('gridstack.manager');
    $instance->stylizer = $instance->manager
      ->stylizer();
    $config = [];
    foreach ([
      'field_name',
      'optionset',
    ] as $key) {
      if (isset($configuration[$key])) {
        $config[$key] = $configuration[$key];
      }
    }
    $instance->styleForm = $instance->stylizer
      ->form($config);
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'regions' => [],
    ] + GridStackDefault::layoutSettings() + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);
    if ($settings = $form_state
      ->getValue('settings')) {
      $this->styleForm
        ->cleanupStyles($settings['styles']);
      if (isset($settings['global'])) {
        foreach ($settings['global'] as $key => $value) {
          $settings[$key] = $value;
        }
        unset($settings['global']);
      }
      unset($settings['current_selection'], $settings['preset_classes'], $settings['preset_row_classes']);
      foreach ($settings as $key => &$value) {
        $this
          ->massageValues($value, $key);
        $this->configuration[$key] = $value;
      }
    }
    unset($this->configuration['global'], $this->configuration['settings']);
    $regions = [];
    if ($values = $form_state
      ->getValue('regions')) {
      foreach ($values as $name => &$region) {
        $this->styleForm
          ->cleanupStyles($region['styles']);
        foreach ($region as $key => &$value) {
          $this
            ->massageValues($value, $key);
          if (in_array($key, [
            'preset_classes',
            'preset_row_classes',
          ])) {
            continue;
          }
          $regions[$name][$key] = $value;
        }
      }
    }
    $this->configuration['regions'] = $regions;
  }

  /**
   * Massage form values.
   */
  protected function massageValues(&$value, $key) {
    if ($key == 'styles') {
      foreach ([
        'alpha',
        'opacity',
      ] as $k) {
        if (isset($value[$k]) && $value[$k] == '1') {
          $value[$k] = '';
        }
      }
    }
    $value = is_string($value) ? trim($value) : $value;
    $value = is_array($value) ? array_filter($value) : $value;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::validateConfigurationForm($form, $form_state);
    $this->styleForm
      ->validateConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {

    // This form may be loaded as a subform Layout Builder, etc.
    // More info: #2536646, #2798261, #2774077.
    $form_state2 = $form_state instanceof SubformStateInterface ? $form_state
      ->getCompleteFormState() : $form_state;
    $form = parent::buildConfigurationForm($form, $form_state2);
    $access_ui = $this->currentUser
      ->hasPermission('administer gridstack');
    $config = $this
      ->getConfiguration();
    $definition = $this
      ->getPluginDefinition();
    $name = $definition
      ->get('optionset');
    $optionset = GridStack::loadWithFallback($name);
    $settings = [];
    $entity_form = $form_state2
      ->getFormObject();
    $extras = $this->styleForm
      ->getEntityData($entity_form);
    if (isset($form['label'])) {
      $name_nice = Unicode::ucfirst($name);
      $form['label']['#attributes']['placeholder'] = $this
        ->t('@name', [
        '@name' => $name_nice,
      ]);
      $form['label']['#wrapper_attributes']['class'][] = 'is-gs-aside';
      $form['label']['#description'] = $this
        ->t('A region has direct contents. A container contains multiple regions.');
      $default = empty($config['label']) ? str_replace('_', ' ', $name_nice) : $config['label'];
      $form['label']['#default_value'] = $form_state2
        ->getValue('label', $default);
    }
    foreach (GridStackDefault::layoutSettings() as $key => $value) {
      $default = isset($config[$key]) ? $config[$key] : $value;
      $settings[$key] = $form_state2
        ->getValue([
        'settings',
        $key,
      ], $default);
    }
    $this->manager
      ->getEngine($settings, 'variant')
      ->override($optionset, $settings);

    // Allows regions being modified by variants.
    $regions = $optionset
      ->prepareRegions(FALSE);
    $settings['_fullwidth'] = TRUE;
    $settings['_container'] = TRUE;
    $settings['_scope'] = GridStackDefault::ROOT;
    $settings['_delta'] = 0;
    $this->fieldName = $settings['field_name'];
    $field_options = $extras ? $this->styleForm
      ->getLayoutFieldOptions() : [];
    $settings['access_media'] = $access_media = $this->currentUser
      ->hasPermission('access media overview');
    if (empty($settings['field_name']) && $field_options) {
      $this->fieldName = $settings['field_name'] = reset($field_options);
    }
    $extras['field_options'] = $field_options;
    $style_config = [
      'field_name' => $this->fieldName,
      'optionset' => $name,
    ];
    $this->styleForm
      ->setConfiguration($style_config);
    $this->styleForm
      ->setFieldName($this->fieldName);
    $description = $this
      ->t('Options require saving the form first.');
    if ($this->manager
      ->getModuleHandler()
      ->moduleExists('gridstack_ui') && $access_ui) {
      $description .= '<br>' . $this
        ->t('[<a href=":url" class="is-gs-edit-link">Edit @id</a>]', [
        ':url' => $optionset
          ->toUrl('edit-form')
          ->toString(),
        '@id' => Xss::filter($optionset
          ->label()),
      ]);
    }
    $form['settings'] = [
      '#type' => 'details',
      '#tree' => TRUE,
      '#open' => TRUE,
      '#weight' => 30,
      '#title' => $this
        ->t('Global settings'),
      '#description' => $description,
      '#attributes' => [
        'class' => [
          'form-wrapper--gs',
          'is-gs-main-settings',
        ],
        'data-gs-region' => $settings['_scope'],
      ],
      '#field_name' => $this->fieldName,
      '#parents' => [
        'layout_settings',
        'settings',
      ],
    ];
    $form['settings'] = array_merge($form['settings'], $this->styleForm
      ->buildConfigurationForm($optionset, $form_state2, $settings, $extras));
    $form['regions'] = [
      '#type' => 'container',
      '#tree' => TRUE,
      '#parents' => [
        'layout_settings',
        'regions',
      ],
    ];

    // Reset settings. The delta is faked for Media Library where 0 is
    // reserved by the non-region, top-level settings. Also to support the
    // styling of non-region, aka. container. The rid is faked, too.
    $delta = 1;
    $rid = 0;
    $settings2 = [];
    foreach ($regions as $region => $info) {
      foreach (GridStackDefault::regionSettings() as $key => $value) {
        $default = isset($config['regions'][$region][$key]) ? $config['regions'][$region][$key] : $value;
        $default = $form_state2
          ->getValue([
          'regions',
          $region,
          $key,
        ], $default);
        $settings2['regions'][$region][$key] = $default;
      }
      $form['regions'][$region] = [
        '#type' => 'details',
        '#title' => $this
          ->t('@type: <em>@label</em>', [
          '@type' => $info['type'],
          '@label' => $info['label'],
        ]),
        '#open' => FALSE,
        '#tree' => TRUE,
        '#attributes' => [
          'data-gs-region' => $region,
          'class' => [
            'form-wrapper--gs',
          ],
        ],
        '#field_name' => $this->fieldName,
        '#parents' => [
          'layout_settings',
          'regions',
          $region,
        ],
      ];
      if (isset($info['cid'])) {
        $form['regions'][$region]['#attributes']['data-gs-region-container'] = $info['cid'];
      }
      $settings2['regions'][$region]['field_name'] = $this->fieldName;
      $settings2['regions'][$region]['access_media'] = $access_media;
      $settings2['regions'][$region]['_fullwidth'] = !empty($info['_fw']);
      $settings2['regions'][$region]['_rid'] = $rid;
      $settings2['regions'][$region]['_scope'] = $region;
      $settings2['regions'][$region]['_delta'] = $delta;
      $settings2['regions'][$region]['_container'] = $info['type'] == GridStackDefault::CONTAINER;
      $form['regions'][$region] = array_merge($form['regions'][$region], $this->styleForm
        ->buildConfigurationForm($optionset, $form_state2, $settings2['regions'][$region], $extras));
      if ($info['type'] == 'Region') {
        $rid++;
      }
      $delta++;
    }

    // Provides color palettes and assets.
    $this->styleForm
      ->closingForm($form, $settings);
    return $form;
  }

}

Classes

Namesort descending Description
GridStackLayoutBase Provides a GridStack base class for Layout plugins.