bee-8.x-1.1/bee.module
bee.module
<?php
/**
* @file
* Contains bee.module features.
*/
use Drupal\bat_booking\Entity\Booking;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Render\Markup;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\views\ViewExecutable;
use Drupal\office_hours\OfficeHoursDateHelper;
use Drupal\commerce_price\Price;
use Drupal\commerce_product\Entity\ProductType;
use Drupal\commerce_product\Entity\ProductVariationType;
use Drupal\commerce_product\Entity\Product;
use Drupal\commerce_product\Entity\ProductVariation;
use Drupal\commerce_order\Entity\OrderItemType;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_store\Entity\Store;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
function bee_page_attachments(array &$page) {
}
/**
* Theme function for FullCalendar.
*/
function bee_preprocess_bat_fullcalendar(&$variables) {
$data = [];
// Feb25: get site wide preferences from BAT config page.
$data['config'] = \Drupal::config('bat_fullcalendar.settings');
// $data['variables_before'] = $variables;
$data['requestRouteName'] = \Drupal::requestStack()->getCurrentRequest()->attributes->get('_route');
$data['eventType'] = $variables['calendar_settings']['fc_settings']['batCalendar'][0]['eventType'];
if ($data['requestRouteName'] == 'bee.node.availability') {
if ($data['eventType'] == 'availability_hourly') {
// // https://fullcalendar.io/docs/timeline-standard-view-demo
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'] = $data['config']->get('bat_fullcalendar_calendar_edit_hourly');
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'] = $variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'];
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['Swe3r'] = "1.1";
$data['bat_library'] = "bat_fullcalendar/bat-fullcalendar-scheduler";
}
else {
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'] = $data['config']->get('bat_fullcalendar_calendar_edit_daily');
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'] = $variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'];
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['Swe3r'] = "1.2";
$data['bat_library'] = "bat_fullcalendar/bat-fullcalendar";
}
}
elseif ($data['requestRouteName'] == 'entity.node.canonical') {
if ($data['eventType'] == 'availability_hourly') {
// https://fullcalendar.io/docs/timeline-standard-view-demo
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'] = $data['config']->get('bat_fullcalendar_calendar_view_hourly');
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'] = $variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'];
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['Swe3r'] = "2.1";
$data['bat_library'] = "bat_fullcalendar/bat-fullcalendar-scheduler";
}
else {
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'] = $data['config']->get('bat_fullcalendar_calendar_view_daily');
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['defaultView'] = $variables['calendar_settings']['fc_settings']['batCalendar'][0]['initialView'];
$variables['calendar_settings']['fc_settings']['batCalendar'][0]['Swe3r'] = "2.2";
$data['bat_library'] = "bat_fullcalendar/bat-fullcalendar";
}
}
else {
// Base library for teaser etc. Do we need more here?
$data['bat_library'] = "bat_fullcalendar/bat-fullcalendar";
}
// Attributes.
if (!empty($variables['attributes'])) {
$attributes = $variables['attributes'];
}
else {
$attributes = [
'id' => Html::getUniqueId('calendar'),
'class' => [
'calendar-set',
'clearfix',
],
];
if (isset($variables['calendar_settings']['class']) && !empty($variables['calendar_settings']['class'])) {
$attributes['class'] = array_merge($attributes['class'], $variables['calendar_settings']['class']);
}
}
// Override default settings with ones coming from BAT.
$settings = bat_fullcalendar_configure($variables['calendar_settings']['fc_settings']);
// Apr25: Override settings with UI settings.
$settings = bat_fullcalendar_ui_settings($settings);
$settings['batCalendar'][0]['id'] = $attributes['id'];
$attributes = new Attribute($attributes);
$variables['#attached'] = [
'library' => [
$data['bat_library'],
// 'core/drupal.ajax',
// 'core/jquery.form',
],
'drupalSettings' => $settings,
];
$variables['content'] = ['#markup' => '<div' . $attributes->__toString() . '></div>'];
}
/**
* Implements hook_form_alter().
*/
function bee_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$data = [];
$current_path = \Drupal::service('path.current')->getPath();
$route_name = Url::fromUserInput($current_path)->getRouteName();
if ($form_id == 'node_type_edit_form' || $form_id == 'node_type_add_form') {
if (\Drupal::currentUser()->hasPermission('administer bee settings')) {
$node_type = $form_state->getFormObject()->getEntity();
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
$form['bee'] = [
'#type' => 'details',
'#title' => t('BEE'),
'#group' => 'additional_settings',
'#tree' => TRUE,
];
$form['bee']['bookable'] = [
'#type' => 'checkbox',
'#title' => t('Make this entity type bookable'),
'#default_value' => $bee_settings['bookable'] ?? 0,
];
$form['bee']['bookable_type'] = [
'#type' => 'container',
'radios' => [
'#type' => 'radios',
'#title' => t('Booking Length'),
'#options' => [
'daily' => t('Daily Bookings (allows bookings of 1 or more full days)'),
'hourly' => t('Flexible Bookings (allows bookings of any length)'),
],
'#default_value' => $bee_settings['bookable_type'] ?? 'daily',
'#disabled' => isset($bee_settings['bookable_type']),
],
'#states' => [
'visible' => [
':input[name="bee[bookable]"]' => ['checked' => TRUE],
],
],
];
$form['bee']['availability'] = [
'#type' => 'container',
'radios' => [
'#type' => 'radios',
'#title' => t('Availability'),
'#options' => [
'available' => t('Generally available (Use for resources that are usually available unless there is a booking. Examples are meeting rooms and equipment)'),
'unavailable' => t('Periodically available (Use for resources that are only available on certain days or times. Examples are tours and open mic nights)'),
],
'#default_value' => $bee_settings['availability'] ?? 'available',
'#disabled' => isset($bee_settings['availability']),
],
'#states' => [
'visible' => [
':input[name="bee[bookable]"]' => ['checked' => TRUE],
],
],
];
$form['bee']['payment'] = [
'#type' => 'checkbox',
'#title' => t('Enable payment for bookings'),
'#default_value' => $bee_settings['payment'] ?? 0,
'#states' => [
'visible' => [
':input[name="bee[bookable]"]' => ['checked' => TRUE],
],
],
];
if (!(\Drupal::moduleHandler()->moduleExists('commerce_checkout') &&
\Drupal::moduleHandler()->moduleExists('commerce_payment'))) {
$form['bee']['payment']['#disabled'] = TRUE;
$form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules and configure a Commerce Store.');
}
elseif (\Drupal::moduleHandler()->moduleExists('commerce')) {
if (empty(Store::loadMultiple())) {
$form['bee']['payment']['#disabled'] = TRUE;
$form['bee']['payment']['#description'] = t('To enable payments for bookings, install and enable the Drupal Commerce checkout and payment modules and configure a Commerce Store.');
}
}
if (isset($bee_settings['type_id'])) {
$form['bee']['type_id'] = [
'#type' => 'hidden',
'#value' => $bee_settings['type_id'],
];
}
$form['actions']['submit']['#submit'][] = 'bee_node_type_edit_form_submit';
$form['#attached']['library'][] = 'bee/bee';
}
}
elseif ($route_name == 'bee.node.availability') {
$form['#attached']['library'][] = 'bee/bee';
$form['#attached']['library'][] = 'bat_fullcalendar/bat-fullcalendar-scheduler';
}
elseif (preg_match('/^node_.*_edit_form$/', $form_id)) {
$node = $form_state->getFormObject()->getEntity();
$node_type = NodeType::load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
if (!isset($form['field_open_hours'])) {
$form['field_open_hours']['#weight'] = 0;
$form['field_open_hours']['#access'] = FALSE;
}
if (isset($bee_settings['bookable']) && $bee_settings['bookable']) {
$units_count = count($node->get('field_availability_' . $bee_settings['bookable_type'])->getValue());
$form['bee'] = [
'#type' => 'details',
'#title' => t('BEE'),
'#tree' => TRUE,
'#prefix' => '<div id="bee-node-wrapper">',
'#suffix' => '</div>',
'#weight' => 9000,
];
$form['bee']['units_count'] = [
'#type' => 'item',
'#title' => t('Number of referenced units'),
'#markup' => $units_count,
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'#weight' => $form['field_open_hours']['#weight'] + 1,
];
$form['bee']['number_units'] = [
'#type' => 'number',
'#title' => t('Number of units to add'),
'#min' => 1,
'#step' => 1,
'#weight' => $form['field_open_hours']['#weight'] + 1,
];
$form['bee']['add_more'] = [
'#type' => 'submit',
'#value' => t('Add units'),
'#limit_validation_errors' => [
['bee', 'number_units'],
['changed'],
],
'#submit' => ['bee_node_add_more_units_submit'],
'#ajax' => [
'callback' => 'bee_node_add_more_units_ajax_callback',
'wrapper' => 'bee-node-wrapper',
],
'#weight' => $form['field_open_hours']['#weight'] + 1,
];
if ($bee_settings['payment']) {
$form['payments'] = [
'#type' => 'details',
'#title' => t('Payments'),
'#open' => TRUE,
'#group' => 'bee',
'#weight' => $form['field_open_hours']['#weight'] + 1,
];
if ($bee_settings['bookable_type'] == 'daily') {
$form['field_price']['#group'] = 'payments';
$form['field_price']['widget'][0]['#title'] = t('Price per day');
$form['field_price_frequency']['#access'] = FALSE;
$form['field_price']['#prefix'] = '<div class="container-inline">';
$form['field_price']['#suffix'] = '</div>';
}
else {
$form['field_price']['#group'] = 'payments';
$form['field_price']['widget'][0]['#title'] = t('Price');
$form['field_price_frequency']['#group'] = 'payments';
$form['field_price_frequency']['widget']['#default_value'] = 'hour';
$form['field_price_frequency']['widget']['#title'] = t('per');
unset($form['field_price_frequency']['widget']['#options']['_none']);
$form['field_price']['#prefix'] = '<div class="container-inline">';
$form['field_price_frequency']['#suffix'] = '</div>';
}
}
else {
$form['field_price']['#access'] = FALSE;
$form['field_price_frequency']['#access'] = FALSE;
}
if ($bee_settings['bookable_type'] == 'hourly') {
$form['field_use_open_hours']['#group'] = 'bee';
$form['field_use_open_hours']['#weight'] = $form['field_open_hours']['#weight'] - 1;
$form['field_open_hours']['#group'] = 'bee';
$form['field_open_hours']['#states'] = [
'visible' => [
':input[name="field_use_open_hours[value]"]' => ['checked' => TRUE],
],
];
}
else {
$form['field_use_open_hours']['#access'] = FALSE;
$form['field_open_hours']['#access'] = FALSE;
}
}
else {
if (isset($form['field_use_open_hours'])) {
$form['field_use_open_hours']['#access'] = FALSE;
}
$form['field_open_hours']['#access'] = FALSE;
}
}
elseif (preg_match('/^node_.*_form$/', $form_id)) {
if (isset($form['field_price'])) {
$form['field_price']['#access'] = FALSE;
}
if (isset($form['field_price_frequency'])) {
$form['field_price_frequency']['#access'] = FALSE;
}
if (isset($form['field_use_open_hours'])) {
$form['field_use_open_hours']['#access'] = FALSE;
}
if (isset($form['field_open_hours'])) {
$form['field_open_hours']['#access'] = FALSE;
}
}
}
/**
* Submit function for the "Add units" button.
*/
function bee_node_add_more_units_submit($form, FormStateInterface $form_state) {
$number_units = $form_state->getValue(['bee', 'number_units']);
if (is_numeric($number_units) && $number_units > 0) {
$node = $form_state->getFormObject()->getEntity();
$node_type = NodeType::load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
$units_ids = $node->get('field_availability_' . $bee_settings['bookable_type'])->getValue();
for ($i = 0; $i < $number_units; $i++) {
$index = count($units_ids) + 1;
$bat_unit = bat_unit_create(
[
'name' => mb_substr($node->label(), 0, 49 - mb_strlen($index)) . ' ' . $index,
'type' => 'default',
'unit_type_id' => $bee_settings['type_id'],
]
);
bat_unit_save($bat_unit);
$units_ids[]['target_id'] = $bat_unit->id();
}
$node->set('field_availability_' . $bee_settings['bookable_type'], $units_ids);
$node->changed_time = $form_state->getValue('changed');
$node->setNewRevision(FALSE);
$node->save();
$units_count = count($node->get('field_availability_' . $bee_settings['bookable_type'])->getValue());
$form['bee']['units_count']['#markup'] = $units_count;
$form['bee']['number_units']['#value'] = '';
\Drupal::messenger()->addMessage(t('@number Units added.', ['@number' => $number_units]));
}
elseif ($number_units === '') {
\Drupal::messenger()->addError(t('Number of units is required.'));
}
else {
\Drupal::messenger()->addError(t('Number of units must be a positive integer.'));
}
$form['bee']['#open'] = TRUE;
}
/**
* Ajax callback for the "Add units" button.
*/
function bee_node_add_more_units_ajax_callback($form, FormStateInterface $form_state) {
return $form['bee'];
}
/**
* Custom submit function for the node_type_edit_form and node_type_add_form.
*/
function bee_node_type_edit_form_submit(array &$form, FormStateInterface $form_state) {
$node_type = $form_state->getFormObject()->getEntity();
assert($node_type instanceof NodeType);
$bee_settings = $form_state->getValue('bee');
$bee_settings['bookable_type'] = $bee_settings['bookable_type']['radios'];
$bee_settings['availability'] = $bee_settings['availability']['radios'];
$bee_settings['payment_default_value'] = $form['bee']['payment']['#default_value'];
bee_set_bee_to_node($node_type, $bee_settings);
}
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function bee_node_presave(EntityInterface $node) {
if (isset($node->changed_time)) {
$node->setChangedTime($node->changed_time);
}
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function bee_node_insert(EntityInterface $node) {
$node_type = NodeType::load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
if (isset($bee_settings['bookable']) && $bee_settings['bookable']) {
if ($bee_settings['payment']) {
$product = bee_create_node_product($node);
$node->set('field_product', $product->id());
}
$bat_unit = bat_unit_create(
[
'name' => mb_substr($node->label(), 0, 48) . ' 1',
'type' => 'default',
'unit_type_id' => $bee_settings['type_id'],
]
);
bat_unit_save($bat_unit);
$node->set('field_availability_' . $bee_settings['bookable_type'], $bat_unit->id());
$node->setNewRevision(FALSE);
$node->save();
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function bee_node_delete(EntityInterface $node) {
$node_type = NodeType::load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
if (!empty($bee_settings['bookable_type']) && $node->hasField('field_availability_' . $bee_settings['bookable_type'])) {
if ($bat_unit = $node->get('field_availability_' . $bee_settings['bookable_type'])->entity) {
bat_unit_delete($bat_unit);
}
if ($bee_settings['payment']) {
if ($product = $node->get('field_product')->entity) {
$product->delete();
}
}
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function bee_commerce_order_item_delete(OrderItemInterface $order_item) {
if ($order_item->bundle() == 'bee') {
if ($booking = $order_item->get('field_booking')->entity) {
$booking->delete();
}
}
}
/**
* Implements hook_theme_registry_alter().
*/
function bee_theme_registry_alter(&$theme_registry) {
$theme_registry['field__node__field_availability_hourly'] = [
'template' => 'field-availability-hourly',
'path' => \Drupal::service('extension.list.module')->getPath('bee') . '/templates',
'render element' => 'element',
'base hook' => 'field',
'type' => 'module',
'theme path' => \Drupal::service('extension.list.module')->getPath('bee'),
'preprocess functions' => [
'template_preprocess',
'template_preprocess_field',
],
];
$theme_registry['field__node__field_availability_daily'] = [
'template' => 'field-availability-daily',
'path' => \Drupal::service('extension.list.module')->getPath('bee') . '/templates',
'render element' => 'element',
'base hook' => 'field',
'type' => 'module',
'theme path' => \Drupal::service('extension.list.module')->getPath('bee'),
'preprocess functions' => [
'template_preprocess',
'template_preprocess_field',
],
];
}
/**
* Implements hook_entity_view_display_alter().
*/
function bee_entity_view_display_alter(EntityViewDisplayInterface $display, $context) {
if ($context['entity_type'] == 'node') {
if ($node = \Drupal::routeMatch()->getParameter('node')) {
if ($display->getComponent('field_open_hours')) {
if (!($node->get('field_use_open_hours')->value)) {
$display->removeComponent('field_open_hours');
}
}
}
}
}
/**
* Implements hook_entity_view_alter().
*/
function bee_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
if ($entity->getEntityTypeId() == 'bat_unit') {
if ($display->id() == 'bat_unit.default.daily_calendar' || $display->id() == 'bat_unit.default.hourly_calendar') {
$bat_type = $entity->get('unit_type_id')->entity;
$unit_type = $bat_type->id();
$node = $build['#bat_unit']->_referringItem->getEntity();
$units_ids = [];
foreach ($node->get('field_availability_' . $bat_type->bundle()) as $unit) {
if ($unit->entity) {
$units_ids[] = $unit->entity->id();
}
}
if ($bat_type->bundle() == 'daily') {
$event_type = 'availability_daily';
$event_granularity = 'bat_daily';
$fc_settings = [
'batCalendar' => [
[
'background' => 'hide-book',
// See https://www.drupal.org/project/bat/issues/3515537
'defaultView' => 'month',
'eventType' => $event_type,
'eventGranularity' => $event_granularity,
'editable' => FALSE,
'headerLeft' => 'today',
'headerCenter' => 'title',
'headerRight' => 'prev, next',
'selectable' => FALSE,
'unitType' => $unit_type,
'unitIds' => implode(',', $units_ids),
'views' => 'month',
'test_da_bee' => '2w3',
],
],
];
}
else {
if ($node->get('field_use_open_hours')) {
$business_hours = [];
foreach ($node->get('field_open_hours')->getValue() as $value) {
$business_hours[] = [
'dow' => [$value['day']],
'start' => OfficeHoursDateHelper::format($value['starthours'], 'H:i'),
'end' => OfficeHoursDateHelper::format($value['endhours'], 'H:i'),
];
}
}
else {
$business_hours = [
'start' => '00:00',
'end' => '24:00',
'dow' => [0, 1, 2, 3, 4, 5, 6],
];
}
$event_type = 'availability_hourly';
$event_granularity = 'bat_hourly';
// See https://www.drupal.org/project/bat/issues/3515537.
// view
$fc_settings = [
'batCalendar' => [
[
'background' => 'hide-book',
'businessHours' => $business_hours,
// See https://www.drupal.org/project/bat/issues/3515537
'defaultView' => 'timelineDay',
'eventType' => $event_type,
'eventGranularity' => $event_granularity,
'editable' => FALSE,
'headerLeft' => 'today',
'headerCenter' => 'title',
'headerRight' => 'prev, next',
'nid' => $node->Id(),
'selectable' => FALSE,
'unitType' => $unit_type,
'unitIds' => implode(',', $units_ids),
'views' => 'timelineDay',
'viewsTimelineDaySlotDuration' => '01:00',
'bee_call' => '2w3w',
],
],
];
}
$calendar_settings['fc_settings'] = $fc_settings;
$calendar_settings['calendar_id'] = 'fullcalendar-scheduler';
$render_array = [
'calendar' => [
'#theme' => 'bat_fullcalendar',
'#calendar_settings' => $calendar_settings,
// 'bat_fullcalendar/bat-fullcalendar-scheduler'
'#attached' => ['library' => ['bat_event_ui/bat_event_ui']],
],
];
$build = [
'#markup' => \Drupal::service('renderer')->render($render_array),
];
}
}
}
/**
* Implements hook_bat_api_events_index_calendar_alter().
*/
function bee_bat_api_events_index_calendar_alter(&$events, $context) {
$data = [];
foreach ($events as $id => $event) {
// @todo We may need here nid for current event.
if (isset($event['type']) && ($event['type'] == 'availability_daily' || $event['type'] == 'availability_hourly')) {
unset($events[$id]['rendering']);
if ($event['blocking']) {
if ($event['type'] == 'availability_daily') {
$state = bat_event_load_state_by_machine_name('bee_daily_not_available');
}
else {
$state = bat_event_load_state_by_machine_name('bee_hourly_not_available');
}
$events[$id]['color'] = $state->getColor();
$events[$id]['title'] = $state->getCalendarLabel();
}
$start_date = new DateTime($event['start']);
$end_date = new DateTime($event['end']);
if ($start_date->format('Y-m-d') != $end_date->format('Y-m-d')) {
$events[$id]['end'] = $end_date->add(new DateInterval('P1D'))->format('Y-m-d') . 'T00:00:00';
}
}
}
}
/**
* Implements hook_views_pre_render().
*/
function bee_views_pre_render(ViewExecutable $view) {
if ($view->id() == 'commerce_order_item_table') {
foreach ($view->result as $id => $result) {
if ($result->_entity->bundle() == 'bee') {
if (($booking = $result->_entity->get('field_booking')->entity) &&
($node = $result->_entity->get('field_node')->entity)) {
$url = Url::fromRoute('entity.node.canonical', ['node' => $node->id()]);
$link = Link::fromTextAndUrl($node->label(), $url)->toString();
$start_date = $booking->get('booking_start_date')->value;
$end_date = $booking->get('booking_end_date')->value;
$title = Markup::create('Booking for ' . $link . ' from ' . $start_date . ' to ' . $end_date);
$view->result[$id]->_entity->set('title', $title);
}
}
}
}
}
/**
* Add "Availability" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type object.
*/
function bee_add_availability_field($field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'entity_reference',
'cardinality' => -1,
'locked' => 1,
'settings' => [
'target_type' => 'bat_unit',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Availability',
'bundle' => $node_type->id(),
'required' => FALSE,
'settings' => [
'handler' => 'default',
'handler_settings' => [],
],
]);
$field->save();
}
}
/**
* Add "Open Hours" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type object.
*/
function bee_add_open_hours_field($field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'office_hours',
'cardinality' => -1,
'locked' => 1,
'settings' => [
'cardinality_per_day' => 2,
'time_format' => 'G',
'element_type' => 'office_hours_datetime',
'increment' => 60,
'comment' => FALSE,
'valhrs' => FALSE,
'limit_start' => '',
'limit_end' => '',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Open Hours',
'bundle' => $node_type->id(),
'required' => FALSE,
'settings' => [
'handler' => 'default',
'handler_settings' => [],
],
]);
$field->save();
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default');
if ($form_display !== NULL) {
$form_display->setComponent($field_name, [
'type' => 'office_hours_default',
'weight' => 3,
]);
$form_display->save();
}
$view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('node.' . $node_type->id() . '.default');
if ($view_display !== NULL) {
$view_display->setComponent($field_name, [
'type' => 'office_hours_table',
'region' => 'content',
'label' => 'above',
'settings' => [],
]);
$view_display->save();
}
}
}
/**
* Add "Set Open Hours" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type.
*/
function bee_add_use_open_hours_field($field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'boolean',
'cardinality' => 1,
'locked' => 1,
'settings' => [],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Set Open Hours',
'bundle' => $node_type->id(),
'required' => FALSE,
'settings' => [
'handler' => 'default',
'handler_settings' => [],
],
]);
$field->save();
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default');
if ($form_display !== NULL) {
$form_display->setComponent($field_name, [
'type' => 'boolean_checkbox',
'weight' => 2,
]);
$form_display->save();
}
}
}
/**
* Add "Product" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type object.
*/
function bee_add_product_reference_field($field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'entity_reference',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'target_type' => 'commerce_product',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Product',
'bundle' => $node_type->id(),
'required' => FALSE,
'settings' => [
'handler' => 'default:commerce_product',
'handler_settings' => [
'target_bundles' => [
'bee_' . $node_type->id() => 'bee_' . $node_type->id(),
],
],
],
]);
$field->save();
}
}
/**
* Add "Price" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type object.
*/
function bee_add_price_field($field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'commerce_price',
'cardinality' => 1,
'locked' => 1,
'settings' => [],
]);
$field_storage->save();
}
if (empty($field)) {
$store_storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
$default_store = $store_storage->loadDefault();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Price',
'bundle' => $node_type->id(),
'required' => TRUE,
'default_value' => [
'number' => 0,
'currency_code' => $default_store->getDefaultCurrencyCode(),
],
'settings' => [],
]);
$field->save();
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default');
if ($form_display !== NULL) {
$form_display->setComponent($field_name, [
'type' => 'commerce_price_default',
'weight' => 3,
]);
$form_display->save();
}
}
}
/**
* Add "Price frequency" field to the node type.
*
* @param string $field_name
* A string.
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node object.
*/
function bee_add_price_frequency_field(string $field_name, NodeType $node_type) {
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$field = FieldConfig::loadByName('node', $node_type->id(), $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'type' => 'list_string',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'allowed_values' => [
'hour' => 'Hour',
'minute' => 'Minute',
],
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'node',
'label' => 'Price frequency',
'bundle' => $node_type->id(),
'required' => FALSE,
'settings' => [],
]);
$field->save();
$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $node_type->id() . '.default');
if ($form_display !== NULL) {
$form_display->setComponent($field_name, [
'type' => 'options_select',
'weight' => 4,
]);
$form_display->save();
}
}
}
/**
* Create "Product variation" type for BEE.
*/
function bee_create_bee_product_variation_type() {
if (ProductVariationType::load('bee') === NULL) {
$variation_type = ProductVariationType::create([
'id' => 'bee',
'label' => 'BEE',
'orderItemType' => 'default',
'generateTitle' => TRUE,
]);
$variation_type->save();
$view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('commerce_product_variation.bee.default');
if (!$view_display) {
$view_display = EntityViewDisplay::create([
'targetEntityType' => 'commerce_product_variation',
'bundle' => 'bee',
'mode' => 'default',
'status' => TRUE,
]);
}
$view_display->setComponent('price', ['type' => 'commerce_price_calculated']);
$view_display->save();
}
}
/**
* Create a "Product" type for each node type in BEE.
*
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node type object.
*/
function bee_create_node_product_type(NodeType $node_type) {
$id = 'bee_' . $node_type->id();
if (ProductType::load($id) === NULL) {
$product_type = ProductType::create([
'id' => $id,
'label' => $node_type->label(),
'variationType' => 'bee',
]);
$product_type->save();
}
}
/**
* Create "Order item" type for BEE.
*/
function bee_create_bee_order_item_type() {
$id = 'bee';
if (OrderItemType::load($id) === NULL) {
OrderItemType::create([
'id' => $id,
'label' => 'BEE',
'purchasableEntityType' => 'commerce_product_variation',
'orderType' => 'default',
])->save();
$view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('commerce_order_item.bee.default');
if (!$view_display) {
$view_display = EntityViewDisplay::create([
'targetEntityType' => 'commerce_order_item',
'bundle' => 'bee',
'mode' => 'default',
'status' => TRUE,
]);
$view_display->setComponent('total_price', [
'type' => 'commerce_price_default',
'region' => 'content',
'label' => 'above',
'settings' => [
'strip_trailing_zeroes' => FALSE,
'display_currency_code' => FALSE,
],
]);
$view_display->setComponent('purchased_entity', [
'type' => 'entity_reference_entity_view',
'region' => 'content',
'label' => 'above',
'settings' => [
'view_mode' => 'default',
'link' => FALSE,
],
]);
$view_display->setComponent('quantity', [
'type' => 'number_decimal',
'region' => 'content',
'label' => 'above',
'settings' => [
'thousand_separator' => '',
'decimal_separator' => '.',
'scale' => 2,
'prefix_suffix' => TRUE,
],
]);
$view_display->setComponent('unit_price', [
'type' => 'commerce_price_default',
'region' => 'content',
'label' => 'above',
'settings' => [
'strip_trailing_zeroes' => FALSE,
'display_currency_code' => FALSE,
],
]);
$view_display->save();
}
}
$field_name = 'field_booking';
$field_storage = FieldStorageConfig::loadByName('commerce_order_item', $field_name);
$field = FieldConfig::loadByName('commerce_order_item', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'commerce_order_item',
'type' => 'entity_reference',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'target_type' => 'bat_booking',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'commerce_order_item',
'label' => 'Booking',
'bundle' => 'bee',
'required' => FALSE,
'settings' => [
'handler' => 'default:bat_booking',
'handler_settings' => [
'target_bundles' => [
'bee' => 'bee',
],
],
],
]);
$field->save();
}
$field_name = 'field_node';
$field_storage = FieldStorageConfig::loadByName('commerce_order_item', $field_name);
$field = FieldConfig::loadByName('commerce_order_item', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'commerce_order_item',
'type' => 'entity_reference',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'target_type' => 'node',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'commerce_order_item',
'label' => 'Node',
'bundle' => 'bee',
'required' => FALSE,
'settings' => [
'handler' => 'default:node',
'handler_settings' => [
'target_bundles' => [],
],
],
]);
$field->save();
}
}
/**
* Create "Booking" type for BEE.
*/
function bee_create_bee_booking_type() {
$id = 'bee';
if (bat_booking_type_load($id) === NULL) {
$booking_type = bat_booking_type_create([
'name' => 'BEE',
'type' => $id,
]);
$booking_type->save();
bee_set_booking_event_reference_field_cardinality();
bee_create_booking_capacity_field();
bee_create_booking_repeat_frequency_field();
bee_create_booking_repeat_until_field();
bee_create_booking_event_series_reference_field();
}
}
/**
* Set cardinality as unlimited for the "booking_event_reference" field.
*/
function bee_set_booking_event_reference_field_cardinality() {
$field_storage = FieldStorageConfig::loadByName('bat_booking', 'booking_event_reference');
$field_storage->setCardinality(-1);
$field_storage->save();
}
/**
* Add booking "Repeat frequency" field.
*/
function bee_create_booking_repeat_frequency_field() {
$field_name = 'booking_repeat_frequency';
$field_storage = FieldStorageConfig::loadByName('bat_booking', $field_name);
$field = FieldConfig::loadByName('bat_booking', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'type' => 'list_string',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'allowed_values' => [
'daily' => 'Daily',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
],
'allowed_values_function' => '',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'bat_booking',
'label' => 'Repeat frequency',
'bundle' => 'bee',
'required' => FALSE,
]);
$field->save();
}
}
/**
* Add booking "Repeat until" field.
*/
function bee_create_booking_repeat_until_field() {
$field_name = 'booking_repeat_until';
$field_storage = FieldStorageConfig::loadByName('bat_booking', $field_name);
$field = FieldConfig::loadByName('bat_booking', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'type' => 'datetime',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'datetime_type' => 'date',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'bat_booking',
'label' => 'Repeat until',
'bundle' => 'bee',
'required' => FALSE,
]);
$field->save();
}
}
/**
* Add booking "Capacity" field.
*
* Description: Capacity can be seats or persons involved in the same booking.
*
* @todo Verify description.
*/
function bee_create_booking_capacity_field() {
$field_name = 'booking_capacity';
$field_storage = FieldStorageConfig::loadByName('bat_booking', $field_name);
$field = FieldConfig::loadByName('bat_booking', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'type' => 'integer',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'unsigned' => TRUE,
'size' => 'normal',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'bat_booking',
'label' => 'Capacity',
'bundle' => 'bee',
'required' => FALSE,
'settings' => [
'min' => NULL,
'max' => NULL,
'prefix' => '',
'suffix' => '',
],
]);
$field->save();
}
}
/**
* Add booking "Event series" reference field.
*/
function bee_create_booking_event_series_reference_field() {
$field_name = 'booking_event_series_reference';
$field_storage = FieldStorageConfig::loadByName('bat_booking', $field_name);
$field = FieldConfig::loadByName('bat_booking', 'bee', $field_name);
if (empty($field_storage)) {
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'type' => 'entity_reference',
'cardinality' => 1,
'locked' => 1,
'settings' => [
'target_type' => 'bat_event_series',
],
]);
$field_storage->save();
}
if (empty($field)) {
$field = FieldConfig::create([
'field_name' => $field_name,
'entity_type' => 'bat_booking',
'label' => 'Event series',
'bundle' => 'bee',
'required' => FALSE,
]);
$field->save();
}
}
/**
* Create a Product instance for this node.
*/
function bee_create_node_product($node) {
$store_storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
$default_store = $store_storage->loadDefault();
$variation = ProductVariation::create([
'type' => 'bee',
'sku' => 'bee_' . $node->bundle() . '_' . $node->id(),
'price' => [
'number' => 0,
'currency_code' => $default_store->getDefaultCurrencyCode(),
],
]);
$variation->save();
$product = Product::create([
'type' => 'bee_' . $node->bundle(),
'title' => $node->label(),
'variations' => [$variation],
'stores' => Store::loadMultiple(),
]);
$product->save();
return $product;
}
/**
* Add fields to event serie type.
*/
function bee_event_series_types_add_fields() {
bat_event_series_type_add_event_dates_field('availability_daily');
bat_event_series_type_add_target_entity_field('availability_daily', 'bat_unit');
bat_event_series_type_add_event_state_reference('availability_daily');
bat_event_series_type_add_event_dates_field('availability_hourly');
bat_event_series_type_add_target_entity_field('availability_hourly', 'bat_unit');
bat_event_series_type_add_event_state_reference('availability_hourly');
}
/**
* Implements template_preprocess_bat_event_series().
*/
function bee_preprocess_bat_event_series(array &$variables) {
// Fetch Event series Entity Object.
$event_series = $variables['elements']['#bat_event_series'];
if (!in_array($event_series->bundle(), [
'availability_daily',
'availability_hourly',
])) {
return;
}
$bat_unit = $event_series->get('event_bat_unit_reference')->entity;
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$query = \Drupal::entityQuery('node')->accessCheck(FALSE);
if ($event_series->bundle() == 'availability_daily') {
$query->condition('field_availability_daily', $bat_unit->id());
}
else {
$query->condition('field_availability_hourly', $bat_unit->id());
}
$query->accessCheck(FALSE);
$nids = $query->execute();
$node = $node_storage->load(reset($nids));
$variables['content']['add_reservation'] = [
'#theme' => 'menu_local_action',
'#link' => [
'title' => t('Add reservation'),
'url' => Url::fromRoute('bee.bat_event_series.add_reservation', [
'node' => $node->id(),
'bat_event_series' => $event_series->id(),
]),
],
'#prefix' => '<div class="action-links">',
'#suffix' => '</div>',
'#weight' => -100,
];
}
/**
* Get unit price.
*
* @param \Drupal\node\Entity\Node $node
* A node object.
* @param \Drupal\bat_booking\Entity\Booking $booking
* A Booking object.
* @param DateTime $start_date
* A drupal date object.
* @param DateTime $end_date
* A drupal date object.
*
* @return \Drupal\commerce_price\Price
* A Commerce price object.
*/
function bee_get_unit_price(Node $node, Booking $booking, DateTime $start_date, DateTime $end_date) {
$node_type = NodeType::load($node->bundle());
assert($node_type instanceof NodeType);
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
$interval = $start_date->diff($end_date);
$reservation_context = [
'booking' => $booking,
'node' => $node,
];
$base_price = $node->get('field_price')->number;
$currency_code = $node->get('field_price')->currency_code;
if ($bee_settings['bookable_type'] == 'daily') {
$days = $interval->days;
$amount = number_format($base_price * $days, 2, '.', '');
}
else {
$field_price_frequency = $node->get('field_price_frequency')->value;
if ($field_price_frequency == 'hour') {
$hours = ($interval->days * 24) + $interval->h;
$amount = number_format($base_price * $hours, 2, '.', '');
}
else {
$minutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i;
$amount = number_format($base_price * $minutes, 2, '.', '');
}
}
$price = new Price($amount, $currency_code);
\Drupal::moduleHandler()->alter('bee_reservation_price', $price, $reservation_context);
return $price;
}
/**
* Validate bee settings on nodes.
*
* @param \Drupal\node\Entity\NodeType $node_type
* A drupal node_type object.
*
* @return array
* An array.
*/
function bee_validate_thirdpartysetting(NodeType $node_type) {
$bee_settings = $node_type->getThirdPartySetting('bee', 'bee');
if (!isset($bee_settings)) {
\Drupal::messenger()->addwarning(t('@nodetype content type has no valid BEE setting.', ['@nodetype' => $node_type->Id()]));
$url = URL::fromUserInput('/admin/structure/types/manage/' . $node_type->Id());
$link = Link::fromTextAndUrl(t('Update BEE settings'), $url);
// @todo Add some action.
}
return $bee_settings;
}
/**
* Add BEE features to a given instance of NodeType.
*
* @param string $node_type
* The node type.
* @param array $bee_settings
* An associative array containing:
* - bookable: integer.
* - bookable_type: string.
* - availability: string.
* - payment: integer.
* - payment_default_value: integer.
*/
function bee_set_bee_to_node($node_type, array $bee_settings) {
if ($bee_settings['bookable']) {
bee_add_use_open_hours_field('field_use_open_hours', $node_type);
bee_add_open_hours_field('field_open_hours', $node_type);
bee_add_availability_field('field_availability_' . $bee_settings['bookable_type'], $node_type);
$view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('node.' . $node_type->id() . '.default');
if ($view_display !== NULL) {
$view_display->setComponent('field_availability_' . $bee_settings['bookable_type'], [
'type' => 'entity_reference_entity_view',
'region' => 'content',
'label' => 'above',
'settings' => [
'view_mode' => $bee_settings['bookable_type'] . '_calendar',
],
]);
$view_display->save();
}
if (!isset($bee_settings['type_id'])) {
$bat_type = bat_unit_type_create(
[
'name' => $node_type->label(),
'type' => $bee_settings['bookable_type'],
]
);
if ($bee_settings['availability'] == 'available') {
$state = bat_event_load_state_by_machine_name('bee_' . $bee_settings['bookable_type'] . '_available');
}
else {
$state = bat_event_load_state_by_machine_name('bee_' . $bee_settings['bookable_type'] . '_not_available');
}
$bat_type->set('field_availability_' . $bee_settings['bookable_type'], $state->id());
bat_unit_type_save($bat_type);
$bee_settings['type_id'] = $bat_type->id();
}
if ($bee_settings['payment']) {
bee_create_bee_product_variation_type();
bee_create_bee_order_item_type();
bee_create_bee_booking_type();
bee_create_node_product_type($node_type);
bee_add_product_reference_field('field_product', $node_type);
bee_add_price_field('field_price', $node_type);
bee_add_price_frequency_field('field_price_frequency', $node_type);
if (!$bee_settings['payment_default_value']) {
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$query = \Drupal::entityQuery('node')
->accessCheck(FALSE)
->condition('type', $node_type->id());
$nids = $query->execute();
foreach ($node_storage->loadMultiple($nids) as $node) {
if (!$node->get('field_product')->entity) {
$product = bee_create_node_product($node);
$node->set('field_product', $product->id());
$node->save();
}
}
}
}
$node_type->setThirdPartySetting('bee', 'bee', $bee_settings)->save();
}
else {
if (isset($bee_settings['type_id'])) {
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$query = \Drupal::entityQuery('node')
->accessCheck(FALSE)
->condition('type', $node_type->id());
$nids = $query->execute();
foreach ($node_storage->loadMultiple($nids) as $node) {
if ($node->hasField('field_availability_' . $bee_settings['bookable_type'])) {
if ($bat_unit = $node->get('field_availability_' . $bee_settings['bookable_type'])->entity) {
bat_unit_delete($bat_unit);
}
}
}
$bat_type = bat_unit_type_load($bee_settings['type_id']);
$bat_type->delete();
}
$node_type->unsetThirdPartySetting('bee', 'bee')->save();
}
}
/**
* Create require bat states.
*/
function bee_create_require_bat_states() {
$states = [
'bee_daily_available' => [
'name' => 'Available',
'color' => '#42f649',
'calendar_label' => 'AV',
'blocking' => 0,
'machine_name' => 'bee_daily_available',
'event_type' => 'availability_daily',
],
'bee_daily_not_available' => [
'name' => 'Not available',
'color' => '#f04b4b',
'calendar_label' => 'N/A',
'blocking' => 0,
'machine_name' => 'bee_daily_not_available',
'event_type' => 'availability_daily',
],
'bee_daily_booked' => [
'name' => 'Booked',
'color' => '#4b3cea',
'calendar_label' => 'BOOK',
'blocking' => 1,
'machine_name' => 'bee_daily_booked',
'event_type' => 'availability_daily',
],
'bee_hourly_available' => [
'name' => 'Available',
'color' => '#42f649',
'calendar_label' => 'AV',
'blocking' => 0,
'machine_name' => 'bee_hourly_available',
'event_type' => 'availability_hourly',
],
'bee_hourly_not_available' => [
'name' => 'Not available',
'color' => '#f04b4b',
'calendar_label' => 'N/A',
'blocking' => 0,
'machine_name' => 'bee_hourly_not_available',
'event_type' => 'availability_hourly',
],
'bee_hourly_booked' => [
'name' => 'Booked',
'color' => '#4b3cea',
'calendar_label' => 'BOOK',
'blocking' => 1,
'machine_name' => 'bee_hourly_booked',
'event_type' => 'availability_hourly',
],
];
foreach ($states as $state) {
bat_event_create_state($state)->save();
}
}
