bee-8.x-1.1/modules/bee_webform/src/Element/WebformBeeReservationForm.php

modules/bee_webform/src/Element/WebformBeeReservationForm.php
<?php

namespace Drupal\bee_webform\Element;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\NodeType;
use Drupal\webform\Element\WebformCompositeBase;
use RRule\RRule;

/**
 * BEE reservation form.
 *
 * @FormElement("webform_bee_reservation_form")
 */
class WebformBeeReservationForm extends WebformCompositeBase {

  /**
   * {@inheritdoc}
   */
  public static function getCompositeElements(array $element) {
    $elements = [];

    if (isset($element['#content_types'])) {
      $bookable_type = FALSE;
      $content_type_options = [];

      foreach (array_filter($element['#content_types']) as $node_type) {
        $node_type = NodeType::load($node_type);
        $content_type_options[$node_type->id()] = $node_type->label();
        assert($node_type instanceof NodeType);
        $bee_settings = $node_type->getThirdPartySetting('bee', 'bee');

        if (isset($bee_settings['bookable_type'])) {
          $bookable_type = $bee_settings['bookable_type'];
        }
      }

      if ($content_type_options) {
        $elements['start_date'] = [
          '#type' => ($bookable_type == 'daily') ? 'date' : 'datetime',
          '#title' => t('Start date'),
        ];
        $elements['end_date'] = [
          '#type' => ($bookable_type == 'daily') ? 'date' : 'datetime',
          '#title' => t('End date'),
        ];

        if ($element['#collect_capacity']) {
          $elements['capacity'] = [
            '#type' => 'number',
            '#title' => t('Capacity'),
          ];
        }

        $elements['repeat'] = [
          '#type' => 'checkbox',
          '#title' => t('This booking repeats'),
          '#prefix' => '<div class="form-row">',
        ];

        $elements['repeat_frequency'] = [
          '#type' => 'select',
          '#title' => t('Repeat frequency'),
          '#options' => [
            'daily' => t('Daily'),
            'weekly' => t('Weekly'),
            'monthly' => t('Monthly'),
          ],
          '#states' => [
            'visible' => [
              ':input[name="bee[repeat]"]' => ['checked' => TRUE],
            ],
          ],
        ];

        $elements['repeat_until'] = [
          '#type' => 'date',
          '#title' => t('Repeat until'),
          '#states' => [
            'visible' => [
              ':input[name="bee[repeat]"]' => ['checked' => TRUE],
            ],
          ],
          '#suffix' => '</div>',
        ];

        $elements['check_available_nodes'] = [
          '#type' => 'submit',
          '#value' => t('Check for available nodes'),
          '#prefix' => '<div>',
          '#suffix' => '</div>',
          '#submit' => [get_called_class(), 'ajaxCallback'],
          '#limit_validation_errors' => [
            [$element['#parents'][0]],
          ],
          '#ajax' => [
            'callback' => [get_called_class(), 'ajaxCallback'],
            'wrapper' => 'bee-node-wrapper',
          ],
        ];

        $elements['node'] = [
          '#type' => 'select',
          '#title' => t('Node'),
          '#options' => [],
          '#prefix' => '<div id="bee-node-wrapper">',
          '#suffix' => '</div>',
          '#disabled' => TRUE,
          '#empty_option' => '',
        ];

        $elements['#attached']['library'][] = 'bee/bee_form';
      }
    }

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public static function validateWebformComposite(&$element, FormStateInterface $form_state, &$complete_form) {
    $key = $element['#parents'][0];

    $triggeringElement = $form_state->getTriggeringElement();

    $value = NestedArray::getValue($form_state->getValues(), $element['#parents']);

    $capacity = (isset($value['capacity'])) ? $value['capacity'] : 1;

    if ($triggeringElement['#parents'][0] == 'submit') {
      if (!$value['node']) {
        $form_state->setErrorByName($key . '][node', t('Select a Node before submitting'));
      }

      if ($value['node'] && $value['start_date'] && $value['end_date']) {
        $units = bee_webform_get_available_units($value);
        $available_units = count($units);

        if ($available_units < $capacity) {
          $form_state->setErrorByName($key . '][node', t('Unfortunately, not enough units of this type are available'));
        }
      }
    }
    elseif ($triggeringElement['#parents'][0] == $key) {
      if (!$value['start_date']) {
        $form_state->setErrorByName($key . '][start_date', t('Enter a value for the Start date field'));
      }
      if (!$value['end_date']) {
        $form_state->setErrorByName($key . '][end_date', t('Enter a value for the End date field'));
      }
      if (isset($value['capacity']) && !$value['capacity']) {
        $form_state->setErrorByName($key . '][capacity', t('Enter a value for the Capacity field'));
      }
      if ($value['repeat']) {
        if (!$value['repeat_frequency']) {
          $form_state->setErrorByName($key . '][repeat_frequency', t('Enter a value for the Repeat frequency field'));
        }
        if (!$value['repeat_until']) {
          $form_state->setErrorByName($key . '][repeat_until', t('Enter a value for the Repeat until field'));
        }
      }
    }
  }

  /**
   * A method for ajax callback.
   */
  public static function ajaxCallback($form, FormStateInterface $form_state) {
    $element = $form_state->getTriggeringElement();
    $key = $element['#parents'][0];

    $values = $form_state->getValue($key);

    if (!empty($values['start_date']) && !empty($values['end_date']) &&
        (!isset($values['capacity']) || (isset($values['capacity']) && !empty($values['capacity'])))) {
      $content_types = array_filter($form['elements'][$key]['#content_types']);

      $capacity = (isset($values['capacity'])) ? $values['capacity'] : 1;

      $start_date = new \DateTime($values['start_date']);
      $end_date = new \DateTime($values['end_date']);
      $end_date->sub(new \DateInterval('PT1M'));

      $repeat = $values['repeat'];
      $repeat_until = $values['repeat_until'];
      $repeat_frequency = $values['repeat_frequency'];

      $node_options = self::getAvailableNodes($content_types, $start_date, $end_date, $capacity, $repeat, $repeat_until, $repeat_frequency);

      if (empty($node_options)) {
        \Drupal::messenger()->addError('There are no available nodes for the selected date/time(s). Please change your selections and try again.');

        $form['elements'][$key]['#webform_composite_elements']['node']['#options'] = [];
        $form['elements'][$key]['#webform_composite_elements']['node']['#attributes'] = [
          'disabled' => TRUE,
        ];
      }
      else {
        $node_options = ['' => t('- Select -')] + $node_options;

        $form['elements'][$key]['#webform_composite_elements']['node']['#options'] = $node_options;
      }
    }
    else {
      $form['elements'][$key]['#webform_composite_elements']['node']['#options'] = [];

      $form['elements'][$key]['#webform_composite_elements']['node']['#attributes'] = [
        'disabled' => TRUE,
      ];
    }

    $form['elements'][$key]['#webform_composite_elements']['node']['#prefix'] = '<div id="bee-node-wrapper">';
    $form['elements'][$key]['#webform_composite_elements']['node']['#suffix'] = '</div>';

    $form['elements'][$key]['#webform_composite_elements']['node']['#name'] = $key . '[node]';

    return $form['elements'][$key]['#webform_composite_elements']['node'];
  }

  /**
   * A method to get Available nodes.
   */
  private static function getAvailableNodes($content_types, $start_date, $end_date, $capacity, $repeat, $repeat_until, $repeat_frequency) {
    $node_options = [];

    $node_storage = \Drupal::entityTypeManager()->getStorage('node');

    $query = \Drupal::entityQuery('node')
      ->condition('type', array_keys($content_types), 'IN');

    $nids = $query->execute();
    foreach ($node_storage->loadMultiple($nids) as $node) {
      $node_type = NodeType::load($node->bundle());
      assert($node_type instanceof NodeType);
      $bee_settings = $node_type->getThirdPartySetting('bee', 'bee');

      $drupal_units = [];
      foreach ($node->get('field_availability_' . $bee_settings['bookable_type']) as $unit) {
        $drupal_units[$unit->entity->id()] = $unit->entity;
      }

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

        foreach ($rrule as $occurrence) {
          $start = clone($occurrence);
          $end = clone($occurrence);

          if ($bee_settings['bookable_type'] == 'daily') {
            $end->add($start_date->diff($end_date));
          }
          else {
            $start->setTime($start_date->format('H'), $start_date->format('i'));
            $end->setTime($start_date->format('H'), $start_date->format('i'));

            $end->add($start_date->diff($end_date));
          }

          if ($bee_settings['bookable_type'] == 'daily') {
            $available_units_ids = bat_event_get_matching_units($start, $end, ['bee_daily_available'], [$bee_settings['type_id']], 'availability_daily', FALSE, $drupal_units);
          }
          else {
            $available_units_ids = bat_event_get_matching_units($start, $end, ['bee_hourly_available'], [$bee_settings['type_id']], 'availability_hourly', FALSE, $drupal_units);
          }

          if (count($available_units_ids) < $capacity) {
            continue 2;
          }

          $node_options[$node->id()] = $node->label();
        }
      }
      else {
        if ($bee_settings['bookable_type'] == 'daily') {
          $available_units_ids = bat_event_get_matching_units($start_date, $end_date, ['bee_daily_available'], [$bee_settings['type_id']], 'availability_daily', FALSE, $drupal_units);
        }
        else {
          $available_units_ids = bat_event_get_matching_units($start_date, $end_date, ['bee_hourly_available'], [$bee_settings['type_id']], 'availability_hourly', FALSE, $drupal_units);
        }

        if (count($available_units_ids) >= $capacity) {
          $node_options[$node->id()] = $node->label();
        }
      }
    }

    return $node_options;
  }

}

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

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