tour-2.0.x-dev/src/Form/TourTipsListForm.php

src/Form/TourTipsListForm.php
<?php

namespace Drupal\tour\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Url;
use Drupal\tour\TipPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form controller for the tour entity tips forms.
 */
class TourTipsListForm extends EntityForm {

  use MessengerTrait;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('language_manager'),
      $container->get('plugin.manager.tour.tip')
    );
  }

  /**
   * Constructs a TourForm object.
   *
   * @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
   *   The Language Manager service.
   * @param \Drupal\tour\TipPluginManager $tipPluginManager
   *   The Tip Plugin Manager service.
   */
  public function __construct(
    protected LanguageManagerInterface $languageManager,
    protected TipPluginManager $tipPluginManager,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state): array {
    if ($this->operation == 'edit_tips') {
      $form['#title'] = $this->t('Edit <em>%label</em> tour tips', ['%label' => $this->entity->label()]);
    }

    $tour = $this->entity;
    $form = parent::form($form, $form_state);

    // Start building the list of tips assigned to this tour.
    $form['tips'] = [
      '#type' => 'table',
      '#header' => [
        $this->t('Label'),
        $this->t('Type'),
        $this->t('Weight'),
        $this->t('Operations'),
      ],
      '#caption' => [['#markup' => $this->t('Tips provided by this tour. By clicking on the operations buttons, every change that has not been saved will be lost.')]],
      '#tabledrag' => [
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'tip-order-weight',
        ],
      ],
      '#weight' => 40,
    ];

    // Populate the table with the assigned tips.
    $tips = $tour->getTips();
    if (!empty($tips)) {
      foreach ($tips as $tip) {
        $tip_id = $tip->get('id');
        try {
          $form['#data'][$tip_id] = $tip->getConfiguration();
        }
        catch (\Error $e) {
          $this->messenger->addMessage($this->t('Tip %tip is not configurable. You cannot save this tour.', ['%tip' => $tip->getLabel()]), 'warning');
        }
        $form['tips'][$tip_id]['#attributes']['class'][] = 'draggable';
        $form['tips'][$tip_id]['label'] = [
          '#plain_text' => $tip->get('label'),
        ];

        $tip_definition = $this->tipPluginManager->getDefinition($tip->getPluginId());
        $form['tips'][$tip_id]['plugin_id'] = [
          '#plain_text' => $tip_definition['title'] ?? $tip->getPluginId(),
        ];

        $form['tips'][$tip_id]['weight'] = [
          '#type' => 'weight',
          '#title' => $this->t('Weight for @title', ['@title' => $tip->get('label')]),
          '#delta' => 100,
          '#title_display' => 'invisible',
          '#default_value' => $tip->get('weight'),
          '#attributes' => [
            'class' => ['tip-order-weight'],
          ],
        ];

        // Provide operations links for the tip.
        $links = [];
        if (method_exists($tip, 'buildConfigurationForm')) {
          $links['edit'] = [
            'title' => $this->t('Edit'),
            'url' => Url::fromRoute('tour.tip.edit', [
              'tour' => $tour->id(),
              'tip' => $tip_id,
            ]),
          ];
        }
        $links['delete'] = [
          'title' => $this->t('Delete'),
          'url' => Url::fromRoute('tour.tip.delete', [
            'tour' => $tour->id(),
            'tip' => $tip_id,
          ]),
        ];
        $form['tips'][$tip_id]['operations'] = [
          '#type' => 'operations',
          '#links' => $links,
        ];
      }
    }

    // Build the new tour tip addition form and add it to the tips list.
    $tip_definitions = $this->tipPluginManager->getDefinitions();
    $tip_definition_options = [];
    foreach ($tip_definitions as $tip => $definition) {
      if (method_exists($definition['class'], 'buildConfigurationForm')) {
        $tip_definition_options[$tip] = $definition['title'];
      }
    }

    $user_input = $form_state->getUserInput();
    $form['tips']['new'] = [
      '#tree' => FALSE,
      '#weight' => $user_input['weight'] ?? 0,
      '#attributes' => [
        'class' => ['draggable'],
      ],
    ];
    $form['tips']['new']['new'] = [
      '#type' => 'select',
      '#title' => $this->t('Tip'),
      '#title_display' => 'invisible',
      '#options' => $tip_definition_options,
      '#empty_option' => $this->t('Select a new tip'),
    ];
    $form['tips']['new']['plugin_id'] = [];
    $form['tips']['new']['weight'] = [
      '#type' => 'weight',
      '#title' => $this->t('Weight for new tip'),
      '#title_display' => 'invisible',
      '#default_value' => count($form['tips']) - 1,
      '#attributes' => [
        'class' => ['tip-order-weight'],
      ],
    ];
    $form['tips']['new']['add'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add'),
      '#validate' => [[$this, 'tipValidate']],
      '#submit' => [[$this, 'tipAdd']],
    ];

    return $form;
  }

  /**
   * Validate handler.
   */
  public function tipValidate($form, FormStateInterface $form_state): void {
    if (!$form_state->getValue('new')) {
      $form_state->setError($form['tips']['new']['new'], $this->t('Select a new tip.'));
    }
  }

  /**
   * Submit handler.
   */
  public function tipAdd($form, FormStateInterface $form_state): void {
    $tour = $this->getEntity();

    $weight = 0;
    if (!$form_state->isValueEmpty('tips')) {
      // Get last weight.
      foreach ($form_state->getValue('tips') as $tip) {
        if ($tip['weight'] > $weight) {
          $weight = $tip['weight'] + 1;
        }
      }
    }

    $stub = $this->tipPluginManager->createInstance($form_state->getValue('new'));

    // If a form is available for this tip then redirect to an add page.
    $stub_form = $stub->buildConfigurationForm([], new FormState());
    if (isset($stub_form)) {
      // Redirect to the appropriate page to add this new tip.
      $form_state->setRedirect('tour.tip.add', [
        'tour' => $tour->id(),
        'type' => $form_state->getValue('new'),
      ], ['query' => ['weight' => $weight]]);
    }

  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    // Form cannot be validated if a tip has no #data, so no way to export
    // configuration.
    if (!$form_state->isValueEmpty('tips')) {
      foreach ($form_state->getValue('tips') as $key => $values) {
        if (!isset($form['#data'][$key])) {
          $form_state->setError($form['tips'][$key], $this->t('You cannot save the tour while %tip tip cannot be exported.', ['%tip' => $this->getEntity()->getTip($key)->getLabel()]));
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    // Merge the form values in with the current configuration.
    if (!$form_state->isValueEmpty('tips')) {
      $tips = [];
      foreach ($form_state->getValue('tips') as $key => $values) {
        $data = $form['#data'][$key];
        $tips[$key] = array_merge($data, $values);
      }
      $form_state->setValue('tips', $tips);
    }
    else {
      $form_state->setValue('tips', []);
    }

    $this->messenger()->addMessage($this->t('Tip settings have been saved.'));

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

    // Redirect to Entity edition.
    $form_state->setRedirect('entity.tour.edit_form_tips', ['tour' => $this->entity->id()]);
  }

}

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

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