bat-8.x-1.x-dev/modules/bat_event_series/src/Form/EditRepeatingRuleConfirmationModalForm.php

modules/bat_event_series/src/Form/EditRepeatingRuleConfirmationModalForm.php
<?php

namespace Drupal\bat_event_series\Form;

use Drupal\bat_roomify\Calendar\Calendar;
use Drupal\bat_roomify\Store\DrupalDBStore;
use Drupal\bat_roomify\Unit\Unit;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\bat_event_series\Entity\EventSeries;
use RRule\RRule;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Edit Repeating.
 */
class EditRepeatingRuleConfirmationModalForm extends FormBase {

  /**
   * The tempstore object.
   *
   * @var \Drupal\user\SharedTempStore
   */
  protected $tempStore;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs a new EditRepeatingRuleModalForm object.
   *
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
   *   The tempstore factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager) {
    $this->tempStore = $temp_store_factory->get('edit_repeating_rule');
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('tempstore.private'),
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'edit_repeating_rule_confirmation_modal_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, EventSeries $bat_event_series = NULL) {
    $this->event_series = $bat_event_series;

    $values = $this->tempStore->get($this->currentUser()->id());

    $events = $this->getEvents(new \DateTime($values['start_date']), new \DateTime($values['end_date']), $values['repeat_frequency'], $values['repeat_until']);

    if (!empty($events['delete_events'])) {
      $form['delete_events'] = [
        '#type' => 'details',
        '#title' => $this->t('Events to delete'),
        '#description' => $this->t('The following events will be deleted.'),
        '#open' => TRUE,
      ];

      $form['delete_events'][] = [
        '#theme' => 'item_list',
        '#items' => $events['delete_events'],
      ];
    }

    if (!empty($events['add_events'])) {
      $form['add_events'] = [
        '#type' => 'details',
        '#title' => $this->t('Events to add'),
        '#description' => $this->t('The following events will be added.'),
        '#open' => TRUE,
      ];

      $form['add_events'][] = [
        '#theme' => 'item_list',
        '#items' => $events['add_events'],
      ];
    }

    if (!empty($events['not_available_events'])) {
      $form['not_available_events'] = [
        '#type' => 'details',
        '#title' => $this->t('Events not available'),
        '#description' => $this->t('The following events are not available and will not be added.'),
        '#open' => TRUE,
      ];

      $form['not_available_events'][] = [
        '#theme' => 'item_list',
        '#items' => $events['not_available_events'],
      ];
    }

    $form['events'] = [
      '#type' => 'value',
      '#value' => $events,
    ];

    $form['actions'] = [
      '#type' => 'actions',
    ];

    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Continue'),
      '#attributes' => [
        'class' => ['button--primary'],
      ],
      '#ajax' => [
        'callback' => [$this, 'ajaxSubmit'],
        'url' => Url::fromRoute('entity.bat_event_series.edit_confirmation_form_modal', ['bat_event_series' => $bat_event_series->id()]),
        'options' => [
          'query' => [
            FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
          ],
        ],
      ],
    ];

    if (empty($events['delete_events']) && empty($events['add_events']) && empty($events['not_available_events'])) {
      $form['no_events'] = [
        '#markup' => $this->t('No events will be created or deleted'),
      ];

      unset($form['actions']['submit']['#ajax']);
      $form['actions']['submit']['#attributes']['class'][] = 'dialog-cancel';
    }

    $form['actions']['cancel'] = [
      '#type' => 'submit',
      '#value' => $this->t('Cancel'),
      '#attributes' => [
        'class' => ['button--danger', 'dialog-cancel'],
      ],
    ];

    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValues();

    $event_series_type = bat_event_series_type_load($this->event_series->bundle());
    $event_granularity = $event_series_type->getEventGranularity();

    $events = $values['events'];

    if (!empty($events['delete_events_ids'])) {
      $this->deleteEvents($events['delete_events_ids']);
    }
    if (!empty($events['add_events'])) {
      $this->addEvents($events['add_events']);
    }

    $new_values = $this->tempStore->get($this->currentUser()->id());

    $rrule = new RRule([
      'FREQ' => strtoupper($new_values['repeat_frequency']),
      'UNTIL' => $new_values['repeat_until'] . 'T235959Z',
    ]);

    if ($event_granularity == 'bat_daily') {
      $event_dates = [
        'value' => $new_values['start_date']->format('Y-m-d\T00:00:00'),
        'end_value' => $new_values['end_date']->format('Y-m-d\T00:00:00'),
      ];
    }
    else {
      $event_dates = [
        'value' => $new_values['start_date']->format('Y-m-d\TH:i:00'),
        'end_value' => $new_values['end_date']->format('Y-m-d\TH:i:00'),
      ];
    }

    $this->event_series->set('event_dates', $event_dates);
    $this->event_series->set('rrule', $rrule->rfcString());
    $this->event_series->save();
  }

  /**
   * Ajax Submit.
   */
  public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    $url = Url::fromRoute('entity.bat_event_series.edit_form', ['bat_event_series' => $this->event_series->id()]);
    $response->addCommand(new RedirectCommand($url->toString()));

    return $response;
  }

  /**
   * Get events.
   */
  private function getEvents($start, $end, $repeat_frequency, $repeat_until) {
    $event_series_type = bat_event_series_type_load($this->event_series->bundle());
    $event_granularity = $event_series_type->getEventGranularity();
    $event_type = bat_event_type_load($event_series_type->getTargetEventType());

    $field_name = 'event_' . $event_series_type->getTargetEntityType() . '_reference';
    $unit = $this->event_series->get($field_name)->entity;

    $query = $this->entityTypeManager
      ->getStorage('bat_event')
      ->getQuery()
      ->condition('event_series.target_id', $this->event_series->id())
      ->condition('event_dates.value', date('Y-m-d\TH:i:s'), '>')
      ->accessCheck(FALSE);
    $events = $query->execute();

    $current_event_dates = [];

    foreach ($events as $event_id) {
      $event = bat_event_load($event_id);

      $start_event_date = new \DateTime($event->get('event_dates')->value);
      $end_event_date = new \DateTime($event->get('event_dates')->end_value);

      if ($event_granularity == 'bat_daily') {
        $formatted_dates = $start_event_date->format('Y-m-d') . ' - ' . $end_event_date->format('Y-m-d');
      }
      else {
        $formatted_dates = $start_event_date->format('Y-m-d H:i') . ' - ' . $end_event_date->format('Y-m-d H:i');
      }

      $current_event_dates[$formatted_dates] = $event_id;
    }

    $rrule = new RRule([
      'FREQ' => strtoupper($repeat_frequency),
      'UNTIL' => $repeat_until . 'T235959Z',
      'DTSTART' => $start,
    ]);

    $not_available_events = [];
    $event_dates = [];

    $now = new \DateTime();
    foreach ($rrule as $occurrence) {
      if ($occurrence > $now) {
        $start_date = clone($occurrence);
        $end_date = clone($occurrence);

        if ($event_granularity == 'bat_daily') {
          $end_date->add($start->diff($end));

          $start_date->setTime(0, 0);
          $end_date->setTime(0, 0);

          if ($this->checkAvailability($start_date, $end_date, $event_type, $unit, $events)) {
            $event_dates[] = $start_date->format('Y-m-d') . ' - ' . $end_date->format('Y-m-d');
          }
          else {
            $not_available_events[] = $start_date->format('Y-m-d') . ' - ' . $end_date->format('Y-m-d');
          }
        }
        else {
          $start_date->setTime($start->format('H'), $start->format('i'));
          $end_date->setTime($start->format('H'), $start->format('i'));

          $end_date->add($start->diff($end));

          if ($this->checkAvailability($start_date, $end_date, $event_type, $unit, $events)) {
            $event_dates[] = $start_date->format('Y-m-d H:i') . ' - ' . $end_date->format('Y-m-d H:i');
          }
          else {
            $not_available_events[] = $start_date->format('Y-m-d H:i') . ' - ' . $end_date->format('Y-m-d H:i');
          }
        }
      }
    }

    $add_events = array_diff($event_dates, array_keys($current_event_dates));
    $delete_events = array_diff(array_keys($current_event_dates), $event_dates);

    $delete_events_ids = [];
    if (!empty($delete_events)) {
      $delete_events_ids = array_intersect_key($current_event_dates, array_flip($delete_events));
    }

    return [
      'add_events' => $add_events,
      'delete_events' => $delete_events,
      'delete_events_ids' => $delete_events_ids,
      'not_available_events' => $not_available_events,
    ];
  }

  /**
   * Check Availability.
   *
   * @return bool
   *   Description.
   */
  private function checkAvailability($start_date, $end_date, $event_type, $unit, $current_events) {

    $database = Database::getConnectionInfo('default');

    $prefix = (isset($database['default']['prefix']['default'])) ? $database['default']['prefix']['default'] : '';

    $event_store = new DrupalDBStore($event_type->id(), DrupalDBStore::BAT_EVENT, $prefix);

    $temp_end_date = clone($end_date);
    $temp_end_date->sub(new \DateInterval('PT1M'));

    $bat_units = [
      new Unit($unit->id(), 0),
    ];

    $calendar = new Calendar($bat_units, $event_store);

    $events = $calendar->getEvents($start_date, $temp_end_date);
    foreach ($events[$unit->id()] as $event) {
      $event_id = $event->getValue();

      if (!in_array($event_id, $current_events)) {
        if ($event = bat_event_load($event_id)) {
          $state = $event->get('event_state_reference')->entity;

          if ($state->getBlocking()) {
            return FALSE;
          }
        }
      }
    }

    return TRUE;
  }

  /**
   * Add events.
   */
  private function addEvents($events) {
    $event_series_type = bat_event_series_type_load($this->event_series->bundle());
    $event_granularity = $event_series_type->getEventGranularity();
    $event_type = bat_event_type_load($event_series_type->getTargetEventType());

    $field_name = 'event_' . $event_series_type->getTargetEntityType() . '_reference';
    $unit = $this->event_series->get($field_name)->entity;

    foreach ($events as $dates) {
      $event = bat_event_create([
        'type' => $event_type->id(),
      ]);

      // list($start_date, $end_date) = explode(' - ', $dates);
      // Drupal Code standard
      // 392 | ERROR | [x] list(...) is forbidden, use [...] instead.
      [$start_date, $end_date] = explode(' - ', $dates);

      $start_date = new \DateTime($start_date);
      $end_date = new \DateTime($end_date);

      if ($event_granularity == 'bat_daily') {
        $start_date->setTime(0, 0);
        $end_date->setTime(0, 0);

        $event_dates = [
          'value' => $start_date->format('Y-m-d\T00:00:00'),
          'end_value' => $end_date->format('Y-m-d\T00:00:00'),
        ];
      }
      else {
        $event_dates = [
          'value' => $start_date->format('Y-m-d\TH:i:00'),
          'end_value' => $end_date->format('Y-m-d\TH:i:00'),
        ];
      }

      $event->set('event_dates', $event_dates);
      $event->set('event_state_reference', $this->event_series->get('event_state_reference')->entity->id());
      $event->set($field_name, $unit->id());
      $event->set('event_series', $this->event_series->id());
      $event->save();
    }
  }

  /**
   * Delete events.
   */
  private function deleteEvents($events) {
    bat_event_delete_multiple($events);
  }

}

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

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