You are here

GridStackVariantSelectionForm.php in GridStack 8.2

File

modules/gridstack_ui/src/Form/GridStackVariantSelectionForm.php
View source
<?php

namespace Drupal\gridstack_ui\Form;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\gridstack\GridStackDefault;
use Drupal\gridstack\Entity\GridStack;
use Drupal\gridstack\Entity\GridStackVariant;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides variant selection form.
 */
class GridStackVariantSelectionForm extends FormBase {

  /**
   * The gridstack optionset.
   *
   * @var \Drupal\gridstack\Entity\GridStack
   */
  protected $optionset;

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

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $instance = parent::create($container);
    $instance
      ->setStringTranslation($container
      ->get('string_translation'));
    $instance->manager = $container
      ->get('gridstack.manager');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'gridstack_variant_selection_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $args = $form_state
      ->getBuildInfo()['args'];
    $name = $args[0];
    $gid = $args[1];
    $vid = $args[2];
    $pub = $args[3];
    if (!isset($this->optionset)) {
      $this->optionset = GridStack::loadWithFallback($name);
    }
    $variants = $this->manager
      ->stylizer()
      ->builder()
      ->getVariants($name, TRUE);
    $settings = [
      'gid' => $gid,
      'optionset' => $name,
      'vid' => $vid,
      'pub' => $pub,
    ];
    $links = $this->manager
      ->stylizer()
      ->builder()
      ->getVariantLinks($settings, $this->optionset, TRUE);
    $back = empty($links['edit']) ? [] : $links['edit'];
    if ($back) {
      $back['#title'] = $this
        ->t('Back');
    }
    $vid_wrapper_id = 'edit-vid-' . $gid;
    $button_wrapper_id = 'edit-variant-actions-' . $gid;
    $form_wrapper_id = GridStackDefault::variantWrapperId($gid);
    $form['#attributes']['class'][] = 'form form--gridstack-variant-selection';
    $form['container'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => [
          'btn-group',
        ],
      ],
      '#prefix' => '<div id="' . $button_wrapper_id . '" class="form--gridstack-variant__actions">',
      '#suffix' => '</div>',
      'back' => $back,
      'delete' => [
        '#type' => 'button',
        '#value' => $this
          ->t('Delete'),
        '#ajax' => [
          'callback' => '::deleteVariant',
          'effect' => 'fade',
          'wrapper' => $form_wrapper_id,
          'method' => 'html',
        ],
        '#attributes' => [
          'class' => [
            'btn',
            'btn-danger',
            'btn--variant-delete',
            'visually-hidden',
          ],
          'data-gs-vid' => '',
          'data-gs-variant-ajax' => 'delete',
          'data-gs-variant-message' => $this
            ->t('Deleting'),
        ],
        '#limit_validation_errors' => [],
      ],
      'edit' => [],
      'cancel' => [
        '#type' => 'button',
        '#value' => $this
          ->t('Cancel'),
        '#ajax' => [
          'callback' => '::cancelSelection',
          'effect' => 'fade',
          'wrapper' => $form_wrapper_id,
        ],
        '#attributes' => [
          'class' => [
            'btn',
            'btn-warning',
            'btn--selection-cancel',
          ],
        ],
      ],
    ];
    $icons = [];
    if ($uri = $this->optionset
      ->getIconUri()) {
      $icons['base'] = [
        '#theme' => 'image',
        '#uri' => $uri,
        '#alt' => $this
          ->t('Thumbnail'),
        '#suffix' => $this
          ->t('@label <br>(original layout)', [
          '@label' => $this->optionset
            ->label(),
        ]),
      ];
    }
    $form['icon'] = [
      '#theme' => 'item_list',
      '#items' => $icons,
      '#wrapper_attributes' => [
        'class' => [
          'item-list--icon',
        ],
      ],
    ];
    $form['vid'] = [
      '#title' => $this
        ->t("Choose/ re-use an existing variant"),
      '#type' => 'radios',
      '#options' => $variants,
      '#default_value' => '',
      '#after_build' => [
        [
          $this,
          'afterBuildSelection',
        ],
      ],
      '#ajax' => [
        'callback' => '::editVariant',
        'wrapper' => $button_wrapper_id,
        'method' => 'replace',
      ],
      '#settings' => $settings,
      '#prefix' => '<div id="' . $vid_wrapper_id . '" class="form-wrapper--selection">',
      '#suffix' => '</div>',
    ];
    return $form;
  }

  /**
   * Provides preview classes.
   */
  public function afterBuildSelection(array $element) {
    $settings = $element['#settings'];
    $removed = [
      'form-wrapper--selection',
    ];
    foreach (Element::children($element) as $key) {
      if ($variant = GridStackVariant::load($key)) {
        if ($uri = $variant
          ->getIconUri()) {
          $token_query = [
            IMAGE_DERIVATIVE_TOKEN => time(),
          ];
          $image_url = \file_url_transform_relative(\file_create_url($uri));
          $image_url .= (strpos($image_url, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($token_query);
          $icon = [
            '#theme' => 'image',
            '#uri' => $image_url,
            '#alt' => $this
              ->t('Thumbnail'),
          ];
          $element[$key]['#field_suffix'] = $this->manager
            ->getRenderer()
            ->render($icon);
        }
      }

      // Unfortunately container classes are also inherited by each item.
      if (isset($element[$key]['#attributes']['class'])) {
        $classes = $element[$key]['#attributes']['class'];
        $classes = array_diff($classes, $removed);
        $element[$key]['#attributes']['class'] = $classes;
      }
      $title = '';
      if ($key == $settings['vid']) {
        $element[$key]['#wrapper_attributes']['class'][] = 'was-gs-selected';
        $title .= $this
          ->t('selected');
      }
      if ($key == $settings['pub']) {
        $element[$key]['#wrapper_attributes']['class'][] = 'was-gs-selected is-gs-applied';
        $title .= $this
          ->t('currently applied');
      }
      if ($key == $settings['pub'] && $key == $settings['vid']) {
        $element[$key]['#wrapper_attributes']['class'][] = 'was-gs-selected is-gs-applied';
        $title = $this
          ->t('selected, currently applied');
      }
      if ($title) {
        $element[$key]['#title'] .= '<br>(' . $title . ')';
      }
    }
    return $element;
  }

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

    // @todo pass vid to layout_settings.
  }

  /**
   * Callback for cancelling a layout variant.
   */
  public function cancelSelection(array $form, FormStateInterface $form_state) {
    $config = $form['vid']['#settings'];
    $gridstack = $this->optionset;
    $editor = $this->manager
      ->stylizer()
      ->builder()
      ->getVariantEditor($config, $gridstack);
    return $editor['form'];
  }

  /**
   * Callback for deleting a layout variant.
   */
  public function deleteVariant(array &$form, FormStateInterface $form_state) {
    $vid = $form_state
      ->getValue('vid');
    if ($vid && ($variant = GridStackVariant::load($vid))) {
      $variant
        ->delete();
    }
    return $form;
  }

  /**
   * Handles switching the available variants based on the selected one.
   */
  public function editVariant(array &$form, FormStateInterface $form_state) {
    $element = $form['container'];
    $settings = $form['vid']['#settings'];
    $vid = $settings['vid'] = $form_state
      ->getValue('vid');
    if ($vid && GridStackVariant::load($vid)) {
      $links = $this->manager
        ->stylizer()
        ->builder()
        ->getVariantLinks($settings, $this->optionset, TRUE);
      if (!empty($links['edit'])) {
        $element['edit'] = $links['edit'];

        // Cannot use #access for this.
        $classes = $element['delete']['#attributes']['class'];
        $classes = array_diff($classes, [
          'visually-hidden',
        ]);
        $element['delete']['#attributes']['class'] = $classes;
      }
    }
    else {
      $element['back'] = [];
    }
    return $element;
  }

}

Classes

Namesort descending Description
GridStackVariantSelectionForm Provides variant selection form.