You are here

bat_event.module in Booking and Availability Management Tools for Drupal 8

Same filename and directory in other branches
  1. 7 modules/bat_event/bat_event.module

Manage Events - Events store the EventValue of a Unit over a period of time.

File

modules/bat_event/bat_event.module
View source
<?php

/**
 * @file
 * Manage Events - Events store the EventValue of a Unit over a period of time.
 */
use Roomify\Bat\Calendar\Calendar;
use Roomify\Bat\Store\DrupalDBStore;
use Roomify\Bat\Unit\Unit;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\Core\Database\Database;
use Drupal\Core\Render\Element;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\views\ViewExecutable;
use Drupal\bat_event\Entity\Event;
use Drupal\bat_event\Entity\EventType;
use Drupal\bat_event\Entity\State;

/**
 * Create a field of type 'Bat Event State Reference' to reference an Event State.
 */
function bat_event_type_add_event_state_reference($entity) {

  // Prevent interruption of config sync.
  if (Drupal::isConfigSyncing()) {
    return;
  }
  $field_name = 'event_state_reference';
  $field_storage = FieldStorageConfig::loadByName('bat_event', $field_name);
  $field = FieldConfig::loadByName('bat_event', $entity
    ->id(), $field_name);
  if (empty($field_storage)) {
    $field_storage = FieldStorageConfig::create([
      'field_name' => $field_name,
      'entity_type' => 'bat_event',
      'type' => 'entity_reference',
      'cardinality' => 1,
      'locked' => 1,
      'settings' => [
        'target_type' => 'state',
      ],
    ]);
    $field_storage
      ->save();
  }
  if (empty($field)) {
    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'entity_type' => 'bat_event',
      'label' => 'State',
      'bundle' => $entity
        ->id(),
      'required' => TRUE,
      'settings' => [
        'handler' => 'default',
        'handler_settings' => [],
      ],
    ]);
    $field
      ->save();
    $form_display = \Drupal::entityTypeManager()
      ->getStorage('entity_form_display')
      ->load('bat_event.' . $entity
      ->id() . '.default');
    if (!$form_display) {
      $form_display = EntityFormDisplay::create([
        'targetEntityType' => 'bat_event',
        'bundle' => $entity
          ->id(),
        'mode' => 'default',
        'status' => TRUE,
      ]);
    }
    $form_display
      ->setComponent($field_name, [
      'type' => 'entity_reference_autocomplete',
      'weight' => 3,
    ]);
    $form_display
      ->save();
  }
}

/**
 * Create "Event Dates" field.
 */
function bat_event_type_add_event_dates_field($entity) {

  // Prevent interruption of config sync.
  if (Drupal::isConfigSyncing()) {
    return;
  }
  $field_name = 'event_dates';
  $field_storage = FieldStorageConfig::loadByName('bat_event', $field_name);
  $field = FieldConfig::loadByName('bat_event', $entity
    ->id(), $field_name);
  if (empty($field_storage)) {
    $field_storage = FieldStorageConfig::create([
      'field_name' => $field_name,
      'entity_type' => 'bat_event',
      'type' => 'daterange',
      'cardinality' => 1,
      'locked' => 1,
      'settings' => [
        'datetime_type' => 'datetime',
      ],
    ]);
    $field_storage
      ->save();
  }
  if (empty($field)) {
    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'entity_type' => 'bat_event',
      'label' => 'Event Dates',
      'bundle' => $entity
        ->id(),
      'required' => TRUE,
      'settings' => [
        'datetime_type' => 'datetime',
      ],
    ]);
    $field
      ->save();
    $form_display = \Drupal::entityTypeManager()
      ->getStorage('entity_form_display')
      ->load('bat_event.' . $entity
      ->id() . '.default');
    if (!$form_display) {
      $form_display = EntityFormDisplay::create([
        'targetEntityType' => 'bat_event',
        'bundle' => $entity
          ->id(),
        'mode' => 'default',
        'status' => TRUE,
      ]);
    }
    $form_display
      ->setComponent($field_name, [
      'type' => 'daterange_default',
      'weight' => 1,
    ]);
    $form_display
      ->save();
  }
}

/**
 * Create fields of type 'Entity Reference' to reference the target entity.
 *
 * We need to create a field/instance for each possible target entity type.
 */
function bat_event_type_add_target_entity_field($entity) {

  // Prevent interruption of config sync.
  if (Drupal::isConfigSyncing()) {
    return;
  }
  $entity_info = \Drupal::entityTypeManager()
    ->getDefinition($entity
    ->getTargetEntityType());
  $field_name = 'event_' . $entity
    ->getTargetEntityType() . '_reference';
  $field_storage = FieldStorageConfig::loadByName('bat_event', $field_name);
  $field = FieldConfig::loadByName('bat_event', $entity
    ->id(), $field_name);
  if (empty($field_storage)) {
    $field_storage = FieldStorageConfig::create([
      'field_name' => $field_name,
      'entity_type' => 'bat_event',
      'type' => 'entity_reference',
      'cardinality' => 1,
      'locked' => 1,
      'settings' => [
        'target_type' => $entity
          ->getTargetEntityType(),
      ],
    ]);
    $field_storage
      ->save();
  }
  if (empty($field)) {
    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'entity_type' => 'bat_event',
      'label' => $entity_info
        ->getLabel()
        ->__toString(),
      'bundle' => $entity
        ->id(),
      'required' => TRUE,
      'settings' => [
        'handler' => 'default',
        'handler_settings' => [],
      ],
    ]);
    $field
      ->save();
    $form_display = \Drupal::entityTypeManager()
      ->getStorage('entity_form_display')
      ->load('bat_event.' . $entity
      ->id() . '.default');
    if (!$form_display) {
      $form_display = EntityFormDisplay::create([
        'targetEntityType' => 'bat_event',
        'bundle' => $entity
          ->id(),
        'mode' => 'default',
        'status' => TRUE,
      ]);
    }
    $form_display
      ->setComponent($field_name, [
      'type' => 'entity_reference_autocomplete',
      'weight' => 3,
    ]);
    $form_display
      ->save();
  }
}

/**
 * Checks event access for various operations.
 */
function bat_event_access(EntityInterface $entity, $operation, AccountInterface $account) {
  return bat_entity_access($entity, $operation, $account);
}

/**
 * Access callback for the entity API.
 */
function bat_event_type_access(EntityInterface $entity, $operation, AccountInterface $account) {
  $account
    ->hasPermission('administer bat_event_type entities');
}

/**
 * Implements hook_query_TAG_alter().
 */
function bat_event_query_bat_event_access_alter(AlterableInterface $query) {

  // Look for an event base table to pass to the query altering function or
  // else assume we don't have the tables we need to establish order related
  // altering right now.
  foreach ($query
    ->getTables() as $table) {
    if ($table['table'] === 'event') {
      bat_entity_access_query_alter($query, 'bat_event', $table['alias']);
      break;
    }
  }
}

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 *
 * Limit BAT state reference fields to valid states.
 */
function bat_event_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {

  // See if this form is editing a BAT event.
  $form_object = $form_state
    ->getFormObject();
  if ($form_object instanceof EntityFormInterface) {
    $entity = $form_object
      ->getEntity();
    if ($entity
      ->getEntityTypeId() == 'bat_event') {
      $entity_type_bundle = $entity
        ->bundle();

      // Limit options for select widgets.
      if (isset($element['#key_column']) && $element['#key_column'] == 'target_id' && $element['#type'] == 'select') {
        $valid_state_ids = array_keys(bat_event_get_states($entity_type_bundle));
        foreach ($element['#options'] as $key => $val) {
          if (!in_array($key, $valid_state_ids)) {
            unset($element['#options'][$key]);
          }
        }
      }
      elseif (isset($element['target_id']) && $element['target_id']['#type'] == 'entity_autocomplete' && $element['target_id']['#target_type'] == 'state') {

        // Use our custom selection handler.
        $element['target_id']['#selection_handler'] = 'bat_event:state';

        // Pass the bundle id to the handler.
        $element['target_id']['#selection_settings']['event_type_bundle'] = $entity_type_bundle;
      }
    }
  }
}

/**
 * @param int $state_id
 */
function bat_event_load_state($state_id) {
  return State::load($state_id);
}

/**
 * @param array $values
 */
function bat_event_create_state($values = []) {
  return State::create($values);
}

/**
 * @param State $state
 */
function bat_event_save_state(State $state) {
  return $state
    ->save();
}

/**
 * Helper function to easily get event types in an array for use in forms, etc.
 *
 * @return array
 *  An array of event types keyed by type id and labels
 */
function bat_event_types_ids() {
  $event_types = [];
  $types = bat_event_get_types();
  foreach ($types as $type) {
    $event_types[$type
      ->id()] = $type
      ->label();
  }
  return $event_types;
}

/**
 * Gets an array of all event types, keyed by the type name.
 *
 * @param string $type_name
 *   If set, the type with the given name is returned.
 * @param bool $reset
 *   A boolean indicating that the internal cache should be reset.
 *
 * @return \Drupal\bat_event\Entity\EventType[]
 *   Depending whether $type isset, an array of event types or a single one.
 */
function bat_event_get_types($type_name = NULL, $reset = FALSE) {
  if ($reset) {
    \Drupal::entityTypeManager()
      ->getStorage('bat_event_type')
      ->resetCache();
  }
  $types = EventType::loadMultiple();
  return isset($type_name) ? $types[$type_name] : $types;
}

/**
 * Menu argument loader; Load a event type by string.
 *
 * @param string $type
 *   The machine-readable name of a event type to load.
 *
 * @return \Drupal\bat_event\Entity\EventType|null
 *   An event type array or NULL if $type does not exist.
 */
function bat_event_type_load($type) {
  return EventType::load($type);
}

/**
 * Fetches an event object.
 *
 * @param int $event_id
 *   Integer specifying the event id.
 * @param bool $reset
 *   A boolean indicating that the internal cache should be reset.
 *
 * @return object
 *   A fully-loaded $event object or FALSE if it cannot be loaded.
 *
 * @see bat_event_load_multiple()
 */
function bat_event_load($event_id = NULL, $reset = FALSE) {
  if ($reset) {
    \Drupal::entityTypeManager()
      ->getStorage('bat_event')
      ->resetCache([
      $event_id,
    ]);
  }
  return Event::load($event_id);
}

/**
 * Load multiple events based on certain conditions.
 *
 * @param array $event_ids
 *   An array of event IDs.
 * @param bool $reset
 *   A boolean indicating that the internal cache should be reset.
 *
 * @return array
 *   An array of event objects, indexed by event_id.
 *
 * @see bat_event_load()
 */
function bat_event_load_multiple(array $event_ids = NULL, $reset = FALSE) {
  if ($reset) {
    \Drupal::entityTypeManager()
      ->getStorage('bat_event')
      ->resetCache($event_ids);
  }
  return Event::loadMultiple($event_ids);
}

/**
 * Deletes a event.
 *
 * @param \Drupal\bat_event\Entity\Event $event
 *   The Event object that represents the event to delete
 */
function bat_event_delete(Event $event) {
  $event
    ->delete();
}

/**
 * Delete multiple events.
 *
 * @param array $event_ids
 *   An array of event IDs.
 */
function bat_event_delete_multiple(array $event_ids) {
  $events = Event::loadMultiple($event_ids);
  foreach ($events as $event) {
    $event
      ->delete();
  }
}

/**
 * Create a event object.
 */
function bat_event_create($values = []) {
  return Event::create($values);
}

/**
 * Saves a event to the database.
 *
 * @param \Drupal\bat_event\Entity\Event $event
 *   The Event object.
 */
function bat_event_save(Event $event) {
  return $event
    ->save();
}

/**
 * Create a event object.
 */
function bat_event_type_create($values = []) {
  return EventType::create($values);
}

/**
 * Saves a event type to the db.
 */
function bat_event_type_save(EventType $type) {
  $type
    ->save();
}

/**
 * Deletes a event type from the db.
 */
function bat_event_type_delete(EventType $type) {
  $type
    ->delete();
}

/**
 * URI callback for events.
 */
function bat_event_uri(Event $event) {
  return [
    'path' => 'event/' . $event->event_id,
  ];
}

/**
 * Get a list of Event keyed by id and name in value.
 */
function bat_event_ids($conditions = []) {
  $events = [];
  $query = \Drupal::entityQuery('bat_event');
  $result = $query
    ->execute();
  if (count($result) > 0) {
    $entities = bat_event_load_multiple($result, $conditions);
    foreach ($entities as $event) {
      $events[$event
        ->id()] = $event
        ->label();
    }
  }
  return $events;
}

/**
 * Implements hook_theme().
 */
function bat_event_theme() {
  return [
    'bat_event' => [
      'render element' => 'elements',
      'template' => 'bat_event',
    ],
    'bat_event_add_list' => [
      'variables' => [
        'content' => NULL,
      ],
    ],
  ];
}

/**
 * Given an event machine name drop all the tables that store event data for that event.
 *
 * @param string $machine_name
 */
function bat_event_delete_event_type_schema($machine_name) {
  foreach (bat_event_get_event_type_tables($machine_name) as $name) {
    Database::getConnection()
      ->schema()
      ->dropTable($name);
  }
}

/**
 * Utility function to return the table names
 * required to start an event using BAT conventions.
 *
 * @param string $machine_name
 */
function bat_event_get_event_type_tables($machine_name) {
  return [
    'bat_event_' . $machine_name . '_day_state',
    'bat_event_' . $machine_name . '_day_event',
    'bat_event_' . $machine_name . '_hour_state',
    'bat_event_' . $machine_name . '_hour_event',
    'bat_event_' . $machine_name . '_minute_state',
    'bat_event_' . $machine_name . '_minute_event',
  ];
}

/**
 * Create 6 tables for store events of type $machine_name.
 *
 * @param string $machine_name
 */
function bat_event_create_event_type_schema($machine_name) {
  $schema = [];
  $schema['bat_event_' . $machine_name . '_day_state'] = [
    'description' => 'Holds the state of each unit for a given day',
    'fields' => bat_event_generate_day_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'month_key' => [
        'unit_id',
        'year',
        'month',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  $schema['bat_event_' . $machine_name . '_day_event'] = [
    'description' => 'Holds the event that determined the state of a unit',
    'fields' => bat_event_generate_day_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'month_key' => [
        'unit_id',
        'year',
        'month',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  $schema['bat_event_' . $machine_name . '_hour_state'] = [
    'description' => 'Holds the state of the unit',
    'fields' => bat_event_generate_hour_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'day_key' => [
        'unit_id',
        'year',
        'month',
        'day',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  $schema['bat_event_' . $machine_name . '_hour_event'] = [
    'description' => 'Holds the event that determined the state of a unit',
    'fields' => bat_event_generate_hour_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'day_key' => [
        'unit_id',
        'year',
        'month',
        'day',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  $schema['bat_event_' . $machine_name . '_minute_state'] = [
    'description' => 'Holds the state of the unit',
    'fields' => bat_event_generate_minute_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'day_key' => [
        'unit_id',
        'year',
        'month',
        'day',
        'hour',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  $schema['bat_event_' . $machine_name . '_minute_event'] = [
    'description' => 'Holds the event that determined the state of a unit',
    'fields' => bat_event_generate_minute_schema_fields(),
    'indexes' => [
      'unit_id' => [
        'unit_id',
      ],
      'year' => [
        'year',
      ],
      'month' => [
        'month',
      ],
    ],
    'unique keys' => [
      'day_key' => [
        'unit_id',
        'year',
        'month',
        'day',
        'hour',
      ],
    ],
    'foreign keys' => [
      'unit_id' => [
        'table' => 'unit',
        'columns' => [
          'unit_id' => 'id',
        ],
      ],
    ],
  ];
  foreach ($schema as $name => $table) {
    Database::getConnection()
      ->schema()
      ->createTable($name, $table);
  }
}

/**
 * Creates the necessary day schema fields.
 *
 * @return array
 */
function bat_event_generate_day_schema_fields() {
  $fields = [
    'unit_id' => [
      'description' => 'Identifier for a unit.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ],
    'year' => [
      'description' => 'The calendar year for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'month' => [
      'description' => 'The month for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
  ];
  for ($i = 1; $i <= 31; $i++) {
    $fields['d' . $i] = [
      'description' => 'D' . $i,
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ];
  }
  return $fields;
}

/**
 * Creates the necessary hour schema fields.
 *
 * @return array
 */
function bat_event_generate_hour_schema_fields() {
  $fields = [
    'unit_id' => [
      'description' => 'Identifier for a unit.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ],
    'year' => [
      'description' => 'The calendar year for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'month' => [
      'description' => 'The month for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'day' => [
      'description' => 'The day for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
  ];
  for ($i = 0; $i <= 23; $i++) {
    $fields['h' . $i] = [
      'description' => 'H' . $i,
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ];
  }
  return $fields;
}

/**
 * Creates the necessary minute schema fields.
 *
 * @return array
 */
function bat_event_generate_minute_schema_fields() {
  $fields = [
    'unit_id' => [
      'description' => 'Identifier for a unit.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
    ],
    'year' => [
      'description' => 'The calendar year for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'month' => [
      'description' => 'The month for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'day' => [
      'description' => 'The day for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
    'hour' => [
      'description' => 'The hour for which this availability row is relevant',
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ],
  ];
  for ($i = 0; $i <= 59; $i++) {

    // PHP has no clean way to get the minutes without leading zeros so setting table
    // fields names to contain the leading zeros to save strangeness in code elsewhere.
    if ($i <= 9) {
      $m = '0' . $i;
    }
    else {
      $m = $i;
    }
    $fields['m' . $m] = [
      'description' => 'M' . $m,
      'type' => 'int',
      'not null' => TRUE,
      'default' => '0',
    ];
  }
  return $fields;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * FORM_ID = bat_type_bundle_edit_form
 */
function bat_event_form_bat_type_bundle_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $type_bundle = $form_state
    ->getFormObject()
    ->getEntity();
  $fields_options = [];
  $fields = \Drupal::service('entity_field.manager')
    ->getFieldDefinitions('bat_unit_type', $type_bundle
    ->id());
  foreach ($fields as $field) {
    if ($field instanceof FieldConfig) {
      $fields_options[$field
        ->getName()] = $field
        ->getLabel() . ' (' . $field
        ->getName() . ')';
    }
  }
  $form['events'] = [
    '#type' => 'details',
    '#group' => 'advanced',
    '#title' => t('Events'),
    '#tree' => TRUE,
    '#weight' => 80,
  ];
  $event_types = bat_event_get_types();
  foreach ($event_types as $event_type) {
    $form['events'][$event_type
      ->id()] = [
      '#type' => 'select',
      '#title' => t('Select your default @event field', [
        '@event' => $event_type
          ->label(),
      ]),
      '#options' => $fields_options,
      '#default_value' => isset($type_bundle->default_event_value_field_ids[$event_type
        ->id()]) ? $type_bundle->default_event_value_field_ids[$event_type
        ->id()] : NULL,
      '#empty_option' => t('- Select a field -'),
    ];
  }
  $form['actions']['submit']['#submit'][] = 'bat_event_form_bat_type_bundle_form_submit';
}

/**
 * Submit callback for bat_event_form_bat_type_bundle_form form.
 */
function bat_event_form_bat_type_bundle_form_submit($form, FormStateInterface $form_state) {
  $type_bundle = $form_state
    ->getFormObject()
    ->getEntity();
  foreach ($form_state
    ->getValues()['events'] as $event => $field) {
    $type_bundle->default_event_value_field_ids[$event] = $field;
  }
  $type_bundle
    ->save();
}

/**
 * Implements hook_views_pre_render().
 */
function bat_event_views_pre_render(ViewExecutable $view) {

  // Use "BAT PHP Date Format" for event Start date and End date.
  if (in_array('event', $view
    ->getBaseTables())) {
    $date_format = \Drupal::config('bat.settings')
      ->get('date_format') ?: 'Y-m-d H:i';
    if (isset($view->field['start_date']->options['custom_date_format'])) {
      $view->field['start_date']->options['custom_date_format'] = $date_format;
    }
    if (isset($view->field['end_date']->options['custom_date_format'])) {
      $view->field['end_date']->options['custom_date_format'] = $date_format;
    }
  }
}

/**
 * Implements hook_entity_bundle_delete().
 */
function bat_event_entity_bundle_delete($entity_type_id, $bundle) {
  if ($entity_type_id == 'bat_event') {
    $query = \Drupal::entityQuery('bat_event')
      ->condition('type', $bundle);
    $event_ids = $query
      ->execute();
    bat_event_delete_multiple($event_ids);
  }
}

/**
 * Given a date range and a set of valid states it will return all units within the
 * set of valid states.
 *
 * @param DateTime $start_date
 * @param DateTime $end_date
 * @param $valid_name_states
 * @param $type_id
 * @param $event_type
 * @param $intersect
 * @param $drupal_units
 *
 * @return array
 */
function bat_event_get_matching_units(DateTime $start_date, DateTime $end_date, $valid_name_states, $type_id, $event_type, $intersect = FALSE, $drupal_units = []) {

  // Instantiate a BAT Calendar.
  $calendar = bat_event_get_calendar($type_id, $event_type, $drupal_units);
  return bat_event_get_matching_units_from_calendar($calendar, $start_date, $end_date, $valid_name_states, $intersect);
}

/**
 * Retrieves relevant units and instantiates a BAT calendar object than can be reused. It is preferred to
 * use this function to reduce the cost of setting up a calendar (i.e. loading units).
 *
 * @param $type_id
 * @param $event_type
 *
 * @return \Roomify\Bat\Calendar\Calendar
 */
function bat_event_get_calendar($type_id, $event_type, $drupal_units = []) {
  $database = Database::getConnectionInfo('default');
  $prefix = isset($database['default']['prefix']['default']) ? $database['default']['prefix']['default'] : '';
  $state_store = new DrupalDBStore($event_type, DrupalDBStore::BAT_STATE, $prefix);
  if (empty($drupal_units)) {
    $drupal_units = bat_unit_load_multiple(FALSE, [
      'unit_type_id' => $type_id,
    ]);
  }
  $bat_units = [];
  foreach ($drupal_units as $unit_id => $unit) {
    $bat_units[] = new Unit($unit_id, $unit
      ->getEventDefaultValue($event_type));
  }
  $calendar = new Calendar($bat_units, $state_store);
  return $calendar;
}

/**
 * Returns matching units based on a provided Calendar. A Calendar can be instantiated in a number
 * of ways - bat_event offers bat_event_get_calendar. Using an already setup calendar multiple times
 * reduces overall load.
 *
 * @param $calendar
 * @param DateTime $start_date
 * @param DateTime $end_date
 * @param $valid_name_states
 * @param $intersect
 * @param $reset
 *
 * @return array
 */
function bat_event_get_matching_units_from_calendar($calendar, DateTime $start_date, DateTime $end_date, $valid_name_states, $intersect = FALSE, $reset = TRUE) {
  $valid_states = [];
  foreach ($valid_name_states as $name) {
    $state = bat_event_load_state_by_machine_name($name);
    $valid_states[] = $state
      ->id();
  }
  $constraints = [];
  foreach (bat_event_constraints_get_info() as $constraint) {
    $constraints[] = $constraint['constraint'];
  }
  $response = $calendar
    ->getMatchingUnits($start_date, $end_date, $valid_states, $constraints, $intersect, $reset);
  $valid_unit_ids = array_keys($response
    ->getIncluded());
  if (count($valid_unit_ids)) {
    return $valid_unit_ids;
  }
  return [];
}

/**
 * Given a date range and a set of valid states it will return all units within the
 * set of valid states.
 *
 * @param DateTime $start_date
 * @param DateTime $end_date
 * @param $valid_name_states
 * @param $type_id
 * @param $event_type
 * @param $intersect
 *
 * @return array
 */
function bat_event_get_calendar_response(DateTime $start_date, DateTime $end_date, $valid_name_states, $type_id, $event_type, $intersect = FALSE) {
  $results = [
    'included' => [],
    'excluded' => [],
  ];
  $valid_states = [];
  foreach ($valid_name_states as $name) {
    $state = bat_event_load_state_by_machine_name($name);
    $valid_states[] = $state
      ->id();
  }
  $constraints = [];
  foreach (bat_event_constraints_get_info() as $constraint) {
    $constraints[] = $constraint['constraint'];
  }
  $calendar = bat_event_get_calendar($type_id, $event_type);
  $response = $calendar
    ->getMatchingUnits($start_date, $end_date, $valid_states, $constraints, $intersect);
  $valid_unit_ids = array_keys($response
    ->getIncluded());
  $excluded = [];
  foreach ($response
    ->getExcluded() as $unit_id => $ex) {
    if (isset($ex['constraint'])) {
      $p = $ex['constraint']
        ->toString();
      $excluded[$unit_id] = t($p['text'], $p['args']);
    }
    else {
      $excluded[$unit_id] = '';
    }
  }
  $results['excluded'] = $excluded;
  if (count($valid_unit_ids)) {
    $results['included'] = $valid_unit_ids;
  }
  return $results;
}

/**
 * @see hook_event_constraints_info()
 * @see hook_event_constraints_info_alter()
 */
function bat_event_constraints_get_info() {

  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast['bat_event_constraints_info'] =& drupal_static(__FUNCTION__);
  }
  $constraints_info =& $drupal_static_fast['bat_event_constraints_info'];
  if (empty($constraints_info)) {
    if ($cache = \Drupal::cache()
      ->get('bat_event_constraints_info')) {
      $constraints_info = $cache->data;
    }
    else {
      $constraints_info = \Drupal::moduleHandler()
        ->invokeAll('bat_event_constraints_info');

      // Let other modules alter the entity info.
      \Drupal::moduleHandler()
        ->alter('bat_event_constraints_info', $constraints_info);
      \Drupal::cache()
        ->get('bat_event_constraints_info', $constraints_info);
    }
  }
  return $constraints_info;
}

/**
 * Prepares variables for list of available event types templates.
 *
 * Default template: bat-event-add-list.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - content: An array of event types.
 */
function template_preprocess_bat_event_add_list(&$variables) {
  $variables['types'] = [];
  if (!empty($variables['content'])) {
    foreach ($variables['content'] as $type) {
      $variables['types'][$type
        ->id()] = [
        'type' => $type
          ->id(),
        'add_link' => Link::fromTextAndUrl($type
          ->label(), new Url('entity.bat_event.add_form', [
          'event_type' => $type
            ->id(),
        ])),
      ];
    }
  }
}

/**
 * @param string|null $event_type
 * @param array $conditions
 *
 * @return array|false
 */
function bat_event_get_states($event_type = NULL, $conditions = []) {
  $query = \Drupal::entityQuery('state');
  if ($event_type !== NULL) {
    $query
      ->condition('event_type', $event_type);
  }
  foreach ($conditions as $key => $value) {
    $query
      ->condition($key, $value);
  }
  $result = $query
    ->execute();
  if (count($result) > 0) {
    return State::loadMultiple($result);
  }
  return FALSE;
}

/**
 * Prepares variables for Event templates.
 *
 * Default template: bat_event.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An associative array containing the user information and any
 *   - attributes: HTML attributes for the containing element.
 */
function template_preprocess_bat_event(array &$variables) {

  // Fetch Event Entity Object.
  $event = $variables['elements']['#bat_event'];

  // Helpful $content variable for templates.
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
}

/**
 * @param string $machine_name
 */
function bat_event_load_state_by_machine_name($machine_name) {
  return State::loadbyMachineName($machine_name);
}

Functions

Namesort descending Description
bat_event_access Checks event access for various operations.
bat_event_constraints_get_info
bat_event_create Create a event object.
bat_event_create_event_type_schema Create 6 tables for store events of type $machine_name.
bat_event_create_state
bat_event_delete Deletes a event.
bat_event_delete_event_type_schema Given an event machine name drop all the tables that store event data for that event.
bat_event_delete_multiple Delete multiple events.
bat_event_entity_bundle_delete Implements hook_entity_bundle_delete().
bat_event_field_widget_form_alter Implements hook_field_widget_WIDGET_TYPE_form_alter().
bat_event_form_bat_type_bundle_edit_form_alter Implements hook_form_FORM_ID_alter().
bat_event_form_bat_type_bundle_form_submit Submit callback for bat_event_form_bat_type_bundle_form form.
bat_event_generate_day_schema_fields Creates the necessary day schema fields.
bat_event_generate_hour_schema_fields Creates the necessary hour schema fields.
bat_event_generate_minute_schema_fields Creates the necessary minute schema fields.
bat_event_get_calendar Retrieves relevant units and instantiates a BAT calendar object than can be reused. It is preferred to use this function to reduce the cost of setting up a calendar (i.e. loading units).
bat_event_get_calendar_response Given a date range and a set of valid states it will return all units within the set of valid states.
bat_event_get_event_type_tables Utility function to return the table names required to start an event using BAT conventions.
bat_event_get_matching_units Given a date range and a set of valid states it will return all units within the set of valid states.
bat_event_get_matching_units_from_calendar Returns matching units based on a provided Calendar. A Calendar can be instantiated in a number of ways - bat_event offers bat_event_get_calendar. Using an already setup calendar multiple times reduces overall load.
bat_event_get_states
bat_event_get_types Gets an array of all event types, keyed by the type name.
bat_event_ids Get a list of Event keyed by id and name in value.
bat_event_load Fetches an event object.
bat_event_load_multiple Load multiple events based on certain conditions.
bat_event_load_state
bat_event_load_state_by_machine_name
bat_event_query_bat_event_access_alter Implements hook_query_TAG_alter().
bat_event_save Saves a event to the database.
bat_event_save_state
bat_event_theme Implements hook_theme().
bat_event_types_ids Helper function to easily get event types in an array for use in forms, etc.
bat_event_type_access Access callback for the entity API.
bat_event_type_add_event_dates_field Create "Event Dates" field.
bat_event_type_add_event_state_reference Create a field of type 'Bat Event State Reference' to reference an Event State.
bat_event_type_add_target_entity_field Create fields of type 'Entity Reference' to reference the target entity.
bat_event_type_create Create a event object.
bat_event_type_delete Deletes a event type from the db.
bat_event_type_load Menu argument loader; Load a event type by string.
bat_event_type_save Saves a event type to the db.
bat_event_uri URI callback for events.
bat_event_views_pre_render Implements hook_views_pre_render().
template_preprocess_bat_event Prepares variables for Event templates.
template_preprocess_bat_event_add_list Prepares variables for list of available event types templates.