recurring_events-2.0.x-dev/src/Form/EventSeriesForm.php

src/Form/EventSeriesForm.php
<?php

declare(strict_types=1);

namespace Drupal\recurring_events\Form;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\recurring_events\EventCreationService;
use Drupal\recurring_events\Plugin\Field\FieldWidget\ConsecutiveRecurringDateWidget;
use Drupal\user\UserInterface;

/**
 * Form controller for the eventseries entity create form.
 *
 * @ingroup recurring_events
 */
class EventSeriesForm extends ContentEntityForm {

  use AutowireTrait;

  /**
   * The current step of the form.
   *
   * @var int
   */
  protected $step = 0;

  public function __construct(
    EntityRepositoryInterface $entity_repository,
    EntityTypeBundleInfoInterface $entity_type_bundle_info,
    TimeInterface $time,
    EntityTypeManagerInterface $entityTypeManager,
    ModuleHandlerInterface $moduleHandler,
    ConfigFactoryInterface $configFactory,
    protected EventCreationService $creationService,
    protected DateFormatterInterface $dateFormatter,
    protected EntityFieldManagerInterface $entityFieldManager,
    protected FieldTypePluginManagerInterface $fieldTypePluginManager,
    protected AccountProxyInterface $currentUser,
  ) {
    parent::__construct($entity_repository, $entity_type_bundle_info, $time);

    $this->entityTypeManager = $entityTypeManager;
    $this->moduleHandler = $moduleHandler;
    $this->configFactory = $configFactory;
  }

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

    $config = $this->configFactory->get('recurring_events.eventseries.config');

    /** @var \Drupal\recurring_events\Entity\EventSeries $entity */
    $entity = $this->entity;

    $editing = ($form_state->getBuildInfo()['form_id'] == 'eventseries_' . $entity->bundle() . '_edit_form');

    // Set author name.
    $display_name = '';
    $owner = $entity->getOwner();
    if ($owner instanceof UserInterface) {
      $display_name = $owner->getDisplayName();
    }
    else {
      $entity->setOwnerId(0);
      $owner = $entity->getOwner();
      $display_name = $owner->getDisplayName();
    }

    $form['custom_date']['#states'] = [
      'visible' => [
        ':input[name="recur_type"]' => ['value' => 'custom'],
      ],
    ];

    if (!empty($form['included_dates'])) {
      $form['included_dates']['#states'] = [
        'visible' => [
          ':input[name="recur_type"]' => ['!value' => 'custom'],
        ],
      ];
    }

    if (!empty($form['excluded_dates'])) {
      $form['excluded_dates']['#states'] = [
        'visible' => [
          ':input[name="recur_type"]' => ['!value' => 'custom'],
        ],
      ];
    }

    // Get all the available recur type fields. Suppress altering so that we can
    // get a list of all the fields, so that after we alter, we can remove the
    // necessary fields from the entity form.
    $recur_fields = $this->creationService->getRecurFieldTypes(FALSE);
    $all_recur_fields = $recur_fields;
    $this->moduleHandler->alter('recurring_events_recur_field_types', $recur_fields);

    $form['recur_type']['widget']['#options'] = $recur_fields;

    // Loop through all the recurring date configuration fields and if any were
    // suppressed then also suppress the fields associated with that.
    foreach ($all_recur_fields as $field_name => $field_label) {
      if (!isset($recur_fields[$field_name])) {
        $form[$field_name]['#access'] = FALSE;
      }
    }

    if ($editing) {
      $original = $this->entityTypeManager->getStorage('eventseries')->loadUnchanged($entity->id());
      if ($this->step === 1) {
        $diff_array = $this->creationService->buildDiffArray($original, $form_state);

        if (!empty($diff_array)) {
          $this->step = 0;
          $form['diff'] = [
            '#type' => 'container',
            '#weight' => -10,
          ];

          $form['diff']['diff_title'] = [
            '#type' => '#markup',
            '#prefix' => '<h2>',
            '#markup' => $this->t('Confirm Date Changes'),
            '#suffix' => '</h2>',
          ];

          $form['diff']['diff_message'] = [
            '#type' => '#markup',
            '#prefix' => '<p>',
            '#markup' => $this->t('Recurrence configuration has been changed, as a result all instances will be removed and recreated. This action cannot be undone.'),
            '#suffix' => '</p>',
          ];

          $form['diff']['table'] = [
            '#type' => 'table',
            '#header' => [
              $this->t('Data'),
              $this->t('Stored'),
              $this->t('Overridden'),
            ],
            '#rows' => $diff_array,
          ];

          $consecutive_date_enabled = str_contains(
            $config->get('enabled_fields'),
            'consecutive_recurring_date'
          );

          if ($consecutive_date_enabled && $config->get('threshold_warning')) {
            $total = ConsecutiveRecurringDateWidget::checkDuration($form_state);
            if ($total > $config->get('threshold_count')) {
              $message = $config->get('threshold_message');
              $message = str_replace('@total', (string) $total, $message);
              $form['diff']['count_warning'] = [
                '#type' => 'markup',
                '#prefix' => '<p class="form-item--error-message">',
                '#markup' => $message,
                '#suffix' => '</p>',
              ];
            }
          }

          $form['diff']['confirm'] = [
            '#type' => 'submit',
            '#value' => $this->t('Confirm Date Changes'),
            '#submit' => [
              '::submitForm',
              '::save',
            ],
          ];
        }
      }
    }

    $form['advanced']['#attributes']['class'][] = 'entity-meta';

    $form['meta'] = [
      '#type' => 'details',
      '#group' => 'advanced',
      '#weight' => -10,
      '#title' => $this->t('Status'),
      '#attributes' => ['class' => ['entity-meta__header']],
      '#tree' => TRUE,
      '#access' => $this->currentUser->hasPermission('administer eventseries'),
    ];
    $form['meta']['published'] = [
      '#type' => 'item',
      '#markup' => $entity->isPublished() ? $this->t('Published') : $this->t('Not published'),
      '#access' => !$entity->isNew(),
      '#wrapper_attributes' => ['class' => ['entity-meta__title']],
    ];
    $form['meta']['changed'] = [
      '#type' => 'item',
      '#title' => $this->t('Last saved'),
      '#markup' => !$entity->isNew() ? $this->dateFormatter->format($entity->getChangedTime(), 'short') : $this->t('Not saved yet'),
      '#wrapper_attributes' => ['class' => ['entity-meta__last-saved']],
    ];
    $form['meta']['author'] = [
      '#type' => 'item',
      '#title' => $this->t('Author'),
      '#markup' => $display_name ?? '',
      '#wrapper_attributes' => ['class' => ['entity-meta__author']],
    ];

    $form['#attached']['library'][] = 'recurring_events/recurring_events.create_form';

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    /** @var \Drupal\recurring_events\Entity\EventSeries $entity */
    $entity = parent::validateForm($form, $form_state);

    $editing = ($form_state->getBuildInfo()['form_id'] == 'eventseries_' . $entity->bundle() . '_edit_form');
    $trigger = $form_state->getTriggeringElement();

    // We only want to trigger the diff generation when the main form submit has
    // been clicked, rather than on any AJAX field submit. This causes problems
    // with multi-value fields, which use AJAX to add more field options. The
    // main submit button of the form has the #name of 'op'. We also do not want
    // to trigger this when the confirm box edit button is clicked, this is the
    // one which shows underneath the diff.
    if ($trigger['#id'] !== 'edit-confirm' && $trigger['#name'] === 'op' && $editing) {
      $original = $this->entityTypeManager->getStorage('eventseries')->loadUnchanged($entity->id());
      if (empty($form_state->getErrors()) && $this->creationService->checkForFormRecurConfigChanges($original, $form_state)) {
        $this->step = 1;
        $form_state->setRebuild(TRUE);
      }
    }

    return $entity;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $entity = $this->getEntity();

    // Save as a new revision if requested to do so.
    if (!$form_state->isValueEmpty('revision') && $form_state->getValue('revision') != FALSE) {
      $entity->setNewRevision();

      // If a new revision is created, save the current user as revision author.
      $entity->setRevisionCreationTime($this->time->getRequestTime());
      $entity->setRevisionUserId($this->currentUser->id());
    }
    else {
      $entity->setNewRevision(FALSE);
    }

    if ($entity->isDefaultTranslation()) {
      $this->messenger()->addStatus($this->t('Successfully saved the %name event series', [
        '%name' => $entity->title->value,
      ]));
    }
    else {
      $this->messenger()->addStatus($this->t('@language translation of the @type %label has been saved.', [
        '@language' => $entity->language()->getName(),
        '@type' => 'Event ',
        '%label' => $entity->getUntranslated()->title->value,
      ]));
    }

    $status = parent::save($form, $form_state);
    $form_state->setRedirect('entity.eventseries.canonical', ['eventseries' => $entity->id()]);

    return $status;
  }

}

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

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