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

src/Form/TourForm.php
<?php

namespace Drupal\tour\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\tour\TipPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;

/**
 * Form controller for the tour entity edit forms.
 */
class TourForm 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'),
      $container->get('cache_tags.invalidator')
    );
  }

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

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

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

    if ($tour->isNew()) {
      $form_state->set('is_new', TRUE);
    }

    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Tour name'),
      '#required' => TRUE,
      '#default_value' => $tour->label(),
    ];
    $form['id'] = [
      '#type' => 'machine_name',
      '#machine_name' => [
        'exists' => '\Drupal\tour\Entity\Tour::load',
      ],
      '#default_value' => $tour->id(),
      '#disabled' => !$tour->isNew(),
    ];

    $form['langcode'] = [
      '#type' => 'language_select',
      '#title' => $this->t('Language'),
      '#languages' => LanguageInterface::STATE_ALL,
      // Default to the content language opposed to und (no language).
      '#default_value' => empty($tour->language()) ? $this->languageManager->getCurrentLanguage()->getId() : $tour->language()->getId(),
    ];

    $modules_list = [];
    $dependencies = $tour->getDependencies();
    if ($dependencies && isset($dependencies['module'])) {
      $modules_list = implode(',', $dependencies['module']);
    }

    $form['module'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Module name'),
      '#description' => $this->t('Each tour can have a number of module dependencies. Separate by a comma.'),
      '#required' => FALSE,
      '#autocomplete_route_name' => 'tour.get_modules',
      '#default_value' => $modules_list,
    ];

    $default_routes = [];
    if ($routes = $tour->getRoutes()) {
      foreach ($routes as $route) {
        $default_routes[] = $route['route_name'];
        if (isset($route['route_params'])) {
          foreach ($route['route_params'] as $key => $value) {
            $default_routes[] = '- ' . $key . ':' . $value;
          }
        }
      }
    }
    $form['routes'] = [
      '#type' => 'textarea',
      '#required' => TRUE,
      '#title' => $this->t('Routes'),
      '#default_value' => implode("\n", $default_routes),
      '#rows' => 5,
      '#description' => $this->t('Provide a list of routes that this tour will be displayed on. Add route_name first then optionally route parameters. For example:<pre>entity.node.canonical<br>- node:2</pre> will only show on the <em>node/2</em> page.<pre>entity.dashboard.canonical<br/>- id:secondary_dashboard</pre> will only show on the<em>admin/dashboard/secondary_dashboard</em> page.<br><p>Other supported param keys are <em>taxonomy_term</em>, <em>bundle/node_type</em>, <em>taxonomy_vocabulary</em></p><br>NOTE: route parameters are <strong>not validated yet</strong>.'),
    ];

    $form['find-routes'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Find route or path fragment'),
      '#description' => $this->t('You can type a route name or path fragment.'),
      '#required' => FALSE,
      '#autocomplete_route_name' => 'tour.get_routes',
    ];

    $form['status'] = [
      '#type' => 'checkbox',
      '#title' => 'Enabled',
      "#default_value" => $tour->get('status'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    // @todo validate the routes
    $routes = $this->routesFromArray($form_state->getValue('routes'));
  }

  /**
   * Rebuild the lines into route structures.
   *
   * @param string $routes_in
   *   Inbound routes.
   *
   * @return array
   *   Matching routes.
   */
  protected function routesFromArray(string $routes_in): array {
    // Normalize the new lines.
    $routes_in = preg_replace("/(\r\n?|\n)/", "\n", $routes_in);
    $routes_in = explode("\n", $routes_in);
    // Trim each line.
    $routes_in = array_map('trim', $routes_in);

    $routes = [];
    $route = NULL;
    foreach ($routes_in as $line) {
      if (empty($line)) {
        continue;
      }
      if (!str_starts_with($line, '-')) {
        $routes[] = [];
        $route = &$routes[count($routes) - 1];
        $route['route_name'] = $line;
      }
      else {
        if (count($routes) === 0) {
          // Abort when having a route_params without a route_name.
          break;
        }
        [$key, $value] = explode(':', $line, 2);
        $key = trim(substr($key, 1));
        $value = trim($value);
        $route['route_params'][$key] = $value;
      }
    }
    return $routes;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    // Filter out invalid characters and convert to an array.
    $routes = $this->routesFromArray($form_state->getValue('routes'));

    $form_state->setValue('routes', array_filter($routes));
    $form_state->setValue('status', $form_state->getValue('status'));

    $input_values = $form_state->getUserInput();
    if (!empty($input_values) && !$form_state->get('is_new')) {
      $this->messenger()->addMessage($this->t('The tour %tour has been updated.', ['%tour' => $form_state->getValue('label')]));
    }
    else {
      $this->messenger()->addMessage($this->t('The tour %tour has been created.', ['%tour' => $form_state->getValue('label')]));
    }

    // Capture original routes BEFORE saving (only if not new).
    $original_routes = NULL;
    $entity_id = $this->entity->id();
    if (!$this->entity->isNew()) {
      $original_config = $this->configFactory()->get('tour.tour.' . $entity_id);
      if ($original_config) {
        $original_routes = $original_config->get('routes');
      }
    }

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

    // Compare pre/post routes; if changed, invalidate relevant cache tags.
    $new_routes = $this->entity->get('routes') ?? [];
    if ($original_routes !== $new_routes) {
      $this->cacheTagsInvalidator->invalidateTags([
        'config:tour.tour.' . $entity_id,
        'tour_settings',
      ]);
    }

    $form_state->setRedirect('entity.tour.edit_form', ['tour' => $this->entity->id()]);
  }

}

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

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