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

src/Form/ComponentLibraryAssetForm.php
<?php

declare(strict_types=1);

namespace Drupal\component_library\Form;

use Drupal\component_library\Entity\ComponentLibraryAsset;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;

/**
 * The configuration form for component_library_asset entities.
 */
final class ComponentLibraryAssetForm extends EntityForm {

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form = parent::buildForm($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_asset.'),
      '#required' => TRUE,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $this->entity->id(),
      '#machine_name' => [
        'exists' => '\Drupal\component_library\Entity\ComponentLibraryAsset::load',
      ],
      '#disabled' => !$this->entity->isNew(),
    ];

    $form['files'] = [
      '#type' => 'fieldset',
      '#tree' => TRUE,
      '#title' => $this->t('Files'),
      '#attributes' => ['id' => 'asset-files'],
    ];
    $files = $this->getFiles($form_state);
    if ($files) {
      $delta = 0;
      $asset_type_count = [
        'css' => 0,
        'js' => 0,
      ];
      foreach ($files as $file) {
        // Keep track of how many of each type of file we have.
        // The first js or css file name will be the same as the Asset ID. Then
        // the files will be numbered sequentially if there are multiple of the
        // same type. e.g. script.js, script-1.js.
        $count = &$asset_type_count[$file['type']];
        $name = \sprintf('%s%s', \str_replace('_', '-', $this->entity->id()), $count > 0 ? '-' . $count : '');
        $filename = \sprintf('%s.%s', $name, $file['type']);
        $form['files'][$delta] = [
          'name' => [
            '#type' => 'value',
            '#value' => $name,
          ],
          'type' => [
            '#type' => 'value',
            '#value' => $file['type'],
          ],
          'code' => [
            '#type' => 'codemirror',
            '#codemirror' => [
              'autoCloseTags' => TRUE,
              'buttons' => [
                'undo',
                'redo',
                'enlarge',
                'shrink',
              ],
              'foldGutter' => TRUE,
              'lineNumbers' => TRUE,
              'lineWrapping' => TRUE,
              'styleActiveLine' => TRUE,
              'toolbar' => TRUE,
              'lineSeparator' => "\n",
              'mode' => $file['type'] == 'js' ? 'javascript' : $file['type'],
            ],
            '#title' => $filename,
            '#default_value' => $file['code'],
          ],
          'delete' => [
            '#tree' => FALSE,
            '#type' => 'submit',
            '#value' => $this->t('Delete @filename', ['@filename' => $filename]),
            '#name' => "delete::$delta",
            '#submit' => [[$this, 'deleteFile']],
            '#ajax' => [
              'callback' => [$this, 'fileAjax'],
              'wrapper' => 'asset-files',
              'effect' => 'fade',
            ],
            '#attributes' => [
              'class' => [
                'button',
                'button--danger',
              ],
            ],
            '#delta' => $delta,
          ],
        ];

        // Reset the codemirror value when a file is deleted.
        [$delete] = explode('::', $form_state->getUserInput()['_triggering_element_name'] ?? '');
        if ($delete === 'delete') {
          $form['files'][$delta]['code']['#value'] = $file['code'];
        }
        $delta++;
        $count++;
      }
    }

    $form['actions']['add_css'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add CSS'),
      '#name' => 'add_css',
      '#submit' => [[$this, 'addFile']],
      '#ajax' => [
        'callback' => [$this, 'fileAjax'],
        'wrapper' => 'asset-files',
        'effect' => 'fade',
      ],
      '#asset_type' => 'css',
      '#weight' => 6,
    ];
    $form['actions']['add_js'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add JS'),
      '#name' => 'add_js',
      '#submit' => [[$this, 'addFile']],
      '#ajax' => [
        'callback' => [$this, 'fileAjax'],
        'wrapper' => 'asset-files',
        'effect' => 'fade',
      ],
      '#asset_type' => 'js',
      '#weight' => 7,
    ];

    $form['#entity_builders']['update_form_langcode'] = [$this, 'entityFormEntityBuild'];;
    $form['#attached']['library'][] = 'codemirror_editor/editor';
    return $form;
  }

  /**
   * Entity builder callback.
   *
   * Keeps files in sync if there are no more file fields but the entity still
   * lists contains some.
   */
  public function entityFormEntityBuild($entity_type_id, ComponentLibraryAsset $asset, &$form, FormStateInterface &$form_state) {
    if ($this->entity->getFiles() && !$form_state->getValue('files') ) {
      $this->entity->setFiles([]);
    }
  }

  /**
   * Submit button handler.
   */
  public function addFile(array $form, FormStateInterface $form_state) {
    $files = $this->getFiles($form_state);
    $files[] = [
      'type' => $form_state->getTriggeringElement()['#asset_type'],
    ];
    $this->setFiles($files, $form_state);
  }

  /**
   * Submit button handler.
   */
  public function deleteFile(array $form, FormStateInterface $form_state) {
    $files = $this->getFiles($form_state);
    unset($files[$form_state->getTriggeringElement()['#delta']]);
    $this->setFiles($files, $form_state);
  }

  /**
   * AJAX callback to add/remove a file.
   */
  public function fileAjax(array $form, FormStateInterface $form_state): array {
    return $form['files'];
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $result = parent::save($form, $form_state);

    $message_args = ['%label' => $this->entity->label()];
    $message = $result == \SAVED_NEW
      ? $this->t('Created new component_library_asset %label.', $message_args)
      : $this->t('Updated component_library_asset %label.', $message_args);
    $this->messenger()->addStatus($message);
    return $result;
  }

  /**
   * Get files.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   An array of file values.
   */
  private function getFiles(FormStateInterface $form_state) {
    return $form_state->getValue('files') ?? $this->entity->getFiles();
  }

  /**
   * Set files.
   *
   * @param array $files
   *   An array of file values.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  private function setFiles(array $files, FormStateInterface $form_state) {
    if (count($files) > 1) {
      \ksort($files);
    }
    elseif (count($files) == 1) {
      // If ksort doesn't run, lets still set the delta to 0.
      $key = \array_key_first($files);
      $files = [$files[$key]];
    }
    $form_state->setValue('files', $files);
    $form_state->setRebuild();
  }

}

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

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