component_library-1.0.x-dev/src/Form/ComponentLibraryPatternForm.php

src/Form/ComponentLibraryPatternForm.php
<?php

declare(strict_types=1);

namespace Drupal\component_library\Form;

use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
use Drupal\Component\Serialization\Yaml;
use Drupal\Component\Utility\Tags;
use Drupal\component_library\ComponentLibraryVariantInterface;
use Drupal\component_library\Entity\ComponentLibraryPattern;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;

/**
 * Component library pattern form.
 *
 * @property \Drupal\component_library\ComponentLibraryPatternInterface $entity
 */
final class ComponentLibraryPatternForm extends EntityForm {

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

    $form = parent::form($form, $form_state);

    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Label'),
      '#maxlength' => 255,
      '#default_value' => $this->entity->label(),
      '#description' => $this->t('Label for the component library pattern.'),
      '#required' => TRUE,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $this->entity->id(),
      '#maxlength' => 31,
      '#machine_name' => [
        'exists' => \sprintf('%s::load', ComponentLibraryPattern::class),
      ],
      '#disabled' => !$this->entity->isNew(),
    ];

    $form['description'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Description'),
      '#default_value' => $this->entity->get('description'),
      '#description' => $this->t('Description of the component library pattern.'),
      '#rows' => 3,
    ];

    $form['tags'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Administrative tags'),
      '#description' => $this->t('Enter a comma-separated list of words to describe your pattern.'),
      '#default_value' => Tags::implode($this->entity->get('tags')),
      '#autocomplete_route_name' => 'component_library.tags_autocomplete',
    ];

    $code_mirror_settings = [
      'autoCloseTags' => TRUE,
      'buttons' => [
        'undo',
        'redo',
        'enlarge',
        'shrink',
      ],
      'foldGutter' => TRUE,
      'lineNumbers' => TRUE,
      'lineWrapping' => TRUE,
      'styleActiveLine' => TRUE,
      'toolbar' => TRUE,
      'lineSeparator' => "\n",
      'mode' => 'yaml',
    ];
    $form['data'] = [
      '#type' => 'codemirror',
      '#codemirror' => $code_mirror_settings,
      '#title' => $this->t('Preview data'),
      '#default_value' => $this->entity->get('data'),
      '#element_validate' => [[self::class, 'yamlValidate']],
      '#suffix' => '<output id="component-library-variant"></output>',
    ];

    $rows = [];
    foreach ($this->entity->getVariants() as $variation) {
      $operations = [
        '#type' => 'operations',
        '#links' => $this->getVariationOperationLinks($variation),
      ];
      $rows[] = [
        'id' => $variation->id(),
        'label' => $variation->label(),
        'operations' => [
          'data' => $operations,
        ],
      ];
    }

    if (!$this->entity->isNew()) {
      $form['variants'] = [
        '#type' => 'table',
        '#caption' => $this->t('Variants'),
        '#empty' => $this->t('No variants have been created yet. <a href=":url">Add new variant</a>.', [
          ':url' => Url::fromRoute('entity.component_library_variant.add_form', [], [
            'query' => [
              'destination' => Url::fromRoute('<current>')->toString(),
              'pattern' => $this->entity->id(),
            ],
          ])->toString(),
        ]),
        '#header' => [
          'id' => $this->t('ID'),
          'label' => $this->t('Label'),
          'operations' => $this->t('Operations'),
        ],
        '#rows' => $rows,
      ];
    }

    return $form;
  }

  private function getVariationOperationLinks(ComponentLibraryVariantInterface $variant): array {
    $operations = [];
    if ($variant->access('update')) {
      $operations['edit'] = [
        'title' => $this->t('Edit'),
        'url' => $variant->toUrl('edit-form'),
      ];
    }
    if ($variant->access('view')) {
      $operations['view'] = [
        'title' => $this->t('View'),
        'url' => $variant->toUrl(),
      ];
    }
    if ($variant->access('delete')) {
      $operations['delete'] = [
        'title' => $this->t('Delete'),
        'url' => $variant->toUrl('delete-form'),
      ];
    }
    if ($variant->access('duplicate')) {
      $operations['delete'] = [
        'title' => $this->t('Duplicate'),
        'url' => $variant->toUrl('duplicate-form'),
      ];
    }

    return $operations;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state): int {
    $result = parent::save($form, $form_state);
    $message_args = ['%label' => $this->entity->label()];
    $message = $result == \SAVED_NEW
      ? $this->t('Created new component library pattern %label.', $message_args)
      : $this->t('Updated component library pattern %label.', $message_args);
    $this->messenger()->addStatus($message);
    $form_state->setRedirectUrl($this->entity->toUrl('collection'));
    return $result;
  }

  /**
   * {@inheritdoc}
   */
  protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state): void {
    // Convert config into line feed endings so YAML config is well formed.
    $data = \is_array($form_state->getValue('data')) ? $form_state->getValue('data') : \implode("\n", \preg_split('(\r\n|\r)', $form_state->getValue('data')));
    $form_state->setValue('data', $data);

    $tags = \is_array($form_state->getValue('tags')) ? $form_state->getValue('tags') : Tags::explode($form_state->getValue('tags'), '');
    $form_state->setValue('tags', $tags);
    parent::copyFormValuesToEntity($entity, $form, $form_state);
  }

  /**
   * Use element validator to make sure that YAML is valid.
   */
  public static function yamlValidate(array $element, FormStateInterface $form_state): void {
    $yaml_string = $form_state->getValue($element['#parents']);
    if ($yaml_string === '') {
      return;
    }

    try {
      $data = Yaml::decode($yaml_string);
      if (!\is_array($data)) {
        $form_state->setError($element, new TranslatableMarkup('The preview data should be defined as array.'));
      }
      else {
        // @see \Drupal\ui_patterns\TypedData\PatternDataDefinition::reserved
        $reserved_keys = [
          'id',
          'type',
          'theme',
          'context',
          'use',
          'attributes',
        ];
        foreach (\array_intersect($reserved_keys, \array_keys($data)) as $name) {
          $form_state->setError($element, new TranslatableMarkup('The name "@name" is a reserved keyword and cannot be used as Twig variable.', ['@name' => $name]));
        }
      }
    }

    catch (InvalidDataTypeException $exception) {
      $form_state->setError($element, new TranslatableMarkup('This value should be valid YAML.'));
    }
  }

}

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

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