From 602d5ba76a02df723e7a21ac3a9f35bf04c9f80b Mon Sep 17 00:00:00 2001 From: s j <sj@1729.be> Date: Fri, 10 Sep 2021 11:20:51 +0200 Subject: [PATCH 1/3] imp: add subevents to events and define separate subevent types --- config/schema/rp_event_type.schema.yml | 3 + src/Entity/Event.php | 35 ++++++---- src/Entity/EventType.php | 17 ++++- src/EventTypeListBuilder.php | 7 +- src/Form/EventForm.php | 7 ++ src/Form/EventInlineForm.php | 71 +++++++++++++++++++ src/Form/EventTypeForm.php | 97 +++++++++++++++++++++++++- 7 files changed, 219 insertions(+), 18 deletions(-) create mode 100644 src/Form/EventInlineForm.php diff --git a/config/schema/rp_event_type.schema.yml b/config/schema/rp_event_type.schema.yml index ddbefec..3476383 100644 --- a/config/schema/rp_event_type.schema.yml +++ b/config/schema/rp_event_type.schema.yml @@ -10,3 +10,6 @@ resource_planning.rp_event_type.*: label: 'Label' uuid: type: string + sub_event_type: + type: boolean + label: 'Is sub event type' diff --git a/src/Entity/Event.php b/src/Entity/Event.php index d73e325..7755641 100644 --- a/src/Entity/Event.php +++ b/src/Entity/Event.php @@ -35,6 +35,7 @@ use Drupal\user\UserInterface; * "html" = "Drupal\resource_planning\EventHtmlRouteProvider", * }, * "access" = "Drupal\resource_planning\EventAccessControlHandler", + * "inline_form" = "Drupal\resource_planning\Form\EventInlineForm", * }, * base_table = "rp_event", * translatable = FALSE, @@ -246,28 +247,32 @@ class Event extends ContentEntityBase implements EventInterface { ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); - $fields['parent_id'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('Parent event')) - ->setDescription(t('The parent event.')) + $fields['child_ids'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(t('Sub events')) + ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setSettings([ 'target_type' => 'rp_event', - 'default_value' => 0, - 'wkf-editable' => ['state' => ['draft']], - ]) - ->setDisplayOptions('view', [ - 'label' => 'above', - 'weight' => 2, ]) ->setDisplayOptions('form', [ - 'type' => 'entity_reference_autocomplete', - 'weight' => 2, + 'type' => 'inline_entity_form_complex', + 'weight' => 0, 'settings' => [ - 'match_operator' => 'CONTAINS', - 'size' => '60', - 'autocomplete_type' => 'tags', - 'placeholder' => '', + 'override_labels' => TRUE, + 'label_singular' => t('line'), + 'label_plural' => t('lines'), ], ]) + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE); + + $fields['parent_id'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(t('Parent event')) + ->setDescription(t('The parent event. Automatically filled backreference.')) + ->setReadOnly(TRUE) + ->setSettings([ + 'target_type' => 'rp_event', + 'default_value' => 0, + ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); diff --git a/src/Entity/EventType.php b/src/Entity/EventType.php index c4b5a43..c97cee9 100644 --- a/src/Entity/EventType.php +++ b/src/Entity/EventType.php @@ -39,7 +39,8 @@ use Drupal\Core\Config\Entity\ConfigEntityBundleBase; * }, * config_export = { * "id", - * "label" + * "label", + * "sub_event_type" * } * ) */ @@ -59,4 +60,18 @@ class EventType extends ConfigEntityBundleBase implements EventTypeInterface { */ protected $label; + /** + * Is this type a subevent type. + * + * @var bool + */ + protected $sub_event_type; + + /** + * {@inheritdoc} + */ + public function isSubEventType() { + return $this->sub_event_type; + } + } diff --git a/src/EventTypeListBuilder.php b/src/EventTypeListBuilder.php index d4043ba..204ca19 100644 --- a/src/EventTypeListBuilder.php +++ b/src/EventTypeListBuilder.php @@ -16,6 +16,9 @@ class EventTypeListBuilder extends ConfigEntityListBuilder { public function buildHeader() { $header['label'] = $this->t('Event type'); $header['id'] = $this->t('Machine name'); + + $header['subeventtype'] = $this->t('Sub event type'); + return $header + parent::buildHeader(); } @@ -25,7 +28,9 @@ class EventTypeListBuilder extends ConfigEntityListBuilder { public function buildRow(EntityInterface $entity) { $row['label'] = $entity->label(); $row['id'] = $entity->id(); - // You probably want a few more properties here... + + $row['subeventtype'] = $entity->isSubEventType() ? $this->t('Yes') : $this->t('No'); + return $row + parent::buildRow($entity); } diff --git a/src/Form/EventForm.php b/src/Form/EventForm.php index 7f52703..cc54003 100644 --- a/src/Form/EventForm.php +++ b/src/Form/EventForm.php @@ -37,6 +37,13 @@ class EventForm extends ContentEntityForm { /** @var \Drupal\resource_planning\Entity\Event $entity */ $form = parent::buildForm($form, $form_state); + // Disable fields for sub events. + $bundle = $this->getBundleEntity(); + if ($bundle->isSubEventType()) { + unset($form['name']); + unset($form['child_ids']); + } + return $form; } diff --git a/src/Form/EventInlineForm.php b/src/Form/EventInlineForm.php new file mode 100644 index 0000000..b6aefd1 --- /dev/null +++ b/src/Form/EventInlineForm.php @@ -0,0 +1,71 @@ +<?php + +namespace Drupal\resource_planning\Form; + +use Drupal\Core\Form\FormStateInterface; +use Drupal\inline_entity_form\Form\EntityInlineForm; + +/** + * Defines the inline form for event. + */ +class EventInlineForm extends EntityInlineForm { + + /** + * {@inheritdoc} + */ + public function getEntityTypeLabels() { + $labels = [ + 'singular' => $this->t('Child'), + 'plural' => $this->t('Children'), + ]; + return $labels; + } + + /** + * {@inheritdoc} + */ + public function getTableFields($bundles) { + $fields = parent::getTableFields($bundles); + /* + $fields['start'] = [ + 'type' => 'field', + 'label' => $this->t('Start'), + 'weight' => 2, + ]; + $fields['end'] = [ + 'type' => 'field', + 'label' => $this->t('End'), + 'weight' => 3, + ]; + */ + return $fields; + } + + /** + * {@inheritdoc} + */ + public function entityForm(array $entity_form, FormStateInterface $form_state) { + $entity_form = parent::entityForm($entity_form, $form_state); + $entity_form['#entity_builders'][] = [get_class($this), 'buildLine']; + + // Do not show child_ids on sub_events. + unset($entity_form['name']); + unset($entity_form['child_ids']); + + return $entity_form; + } + + /** + * {@inheritdoc} + */ + public static function buildLine($entity_type, $line, array $form, FormStateInterface $form_state) { + if ($line->isNew()) { + // Set backreference. + $line->set( + 'parent_id', + $form_state->getFormObject()->getEntity() + ); + } + } + +} diff --git a/src/Form/EventTypeForm.php b/src/Form/EventTypeForm.php index 02437e5..1ee2803 100644 --- a/src/Form/EventTypeForm.php +++ b/src/Form/EventTypeForm.php @@ -3,7 +3,9 @@ namespace Drupal\resource_planning\Form; use Drupal\Core\Entity\EntityForm; +use Drupal\Core\Field\Entity\BaseFieldOverride; use Drupal\Core\Form\FormStateInterface; +use Drupal\views\Views; /** * The EventType Form. @@ -35,11 +37,74 @@ class EventTypeForm extends EntityForm { '#disabled' => !$rp_event_type->isNew(), ]; - /* You will need additional form elements for your custom properties. */ + $form['sub_event_type'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Is this a sub event type?'), + '#default_value' => $rp_event_type->isSubEventType(), + '#disabled' => !$rp_event_type->isNew(), + ]; + + // $view_settings = $this->getConfiguration()['view']; + + $displays = Views::getApplicableViews('entity_reference_display'); + // Filter views that list the entity type we want, and group the separate + // displays by view. + $entity_type = $this->entityTypeManager->getDefinition('rp_calendar'); + $view_storage = $this->entityTypeManager->getStorage('view'); + + $options = []; + foreach ($displays as $data) { + list($view_id, $display_id) = $data; + $view = $view_storage->load($view_id); + if (in_array($view->get('base_table'), [$entity_type->getBaseTable(), $entity_type->getDataTable()])) { + $display = $view->get('display'); + $options[$view_id . ':' . $display_id] = $view_id . ' - ' . $display[$display_id]['display_title']; + } + } + + if ($options) { + $form['calendar_selection'] = [ + '#type' => 'fieldset', + '#title' => $this->t('Calendar selection'), + ]; + + // $default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : NULL; + $form['calendar_selection']['view_and_display'] = [ + '#type' => 'select', + '#title' => $this->t('View used to select the entities'), + '#options' => $options, + // '#default_value' => $default, + '#description' => '<p>' . $this->t('Choose the view and display that select the entities that can be referenced.<br />Only views with a display of type "Entity Reference" are eligible.') . '</p>', + '#empty_value' => '', + ]; + + // $default = !empty($view_settings['arguments']) ? implode(', ', $view_settings['arguments']) : ''; + $form['calendar_selection']['arguments'] = [ + '#type' => 'textfield', + '#title' => $this->t('View arguments'), + // '#default_value' => $default, + '#required' => FALSE, + '#description' => $this->t('Provide a comma separated list of arguments to pass to the view.'), + ]; + } return $form; } + /** + * {@inheritdoc} + */ + public function getCalendarFieldDefinition($rp_event_type) { + $definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('rp_event', $rp_event_type->id()); + if ($definitions['calendar_id'] instanceof BaseFieldOverride) { + $override = $definitions['calendar_id']; + } + else { + $override = BaseFieldOverride::createFromBaseFieldDefinition($definitions['calendar_id'], $rp_event_type->id()); + } + return $override; + } + /** * {@inheritdoc} */ @@ -47,6 +112,36 @@ class EventTypeForm extends EntityForm { $rp_event_type = $this->entity; $status = $rp_event_type->save(); + $override = $this->getCalendarFieldDefinition($rp_event_type); + + if ($form_state->getValue('view_and_display')) { + list($view, $display) = explode(':', $form_state->getValue('view_and_display')); + $override->setLabel($rp_event_type->label()); + $override->setSetting('handler', 'views'); + $override->setSetting('handler_settings', [ + 'view' => [ + 'view_name' => $view, + 'display_name' => $dispaly, + 'arguments' => $form_state->getValue('arguments'), + ], + ]); + } + else { + // Default entity reference selection settings. + $override->setLabel($this->t('Calendar')); + $override->setSetting('handler', 'default:rp_calendar'); + $override->setSetting('handler_settings', [ + 'target_bundles' => NULL, + 'sort' => [ + 'field' => '_none', + 'direction' => 'ASC', + ], + 'auto_create' => FALSE, + 'auto_create_bundle' => '', + ]); + } + $override->save(); + switch ($status) { case SAVED_NEW: $this->messenger()->addMessage($this->t('Created the %label Event type.', [ -- GitLab From 3a20679a1e9ff1901d4f7d6d38293ad4d3423a8b Mon Sep 17 00:00:00 2001 From: s j <sj@1729.be> Date: Sat, 11 Sep 2021 06:57:24 +0200 Subject: [PATCH 2/3] default start and end for new event --- resource_planning.module | 21 +++++++++++++++++++++ src/Entity/Event.php | 4 ++-- src/Form/EventTypeForm.php | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/resource_planning.module b/resource_planning.module index adf0531..8dc9877 100644 --- a/resource_planning.module +++ b/resource_planning.module @@ -5,8 +5,29 @@ * Contains resource_planning.module. */ +use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; + +/** + * Default value callback for rp_event date. + */ +function resource_planning_default_event_date($entity, $definition) { + $start_time = DrupalDateTime::createFromTimestamp(time()); + $start_time->modify('+ 1 hour'); + $start_time->setTime( + $start_time->format("H"), + 0 + ); + $end_time = clone $start_time; + $end_time->add(new \DateInterval('PT1H')); + return [ + 'value' => $start_time->format(DateTimeItem::DATETIME_STORAGE_FORMAT), + 'end_value' => $end_time->format(DateTimeItem::DATETIME_STORAGE_FORMAT), + ]; +} + /** * Implements hook_help(). */ diff --git a/src/Entity/Event.php b/src/Entity/Event.php index 7755641..6261f5c 100644 --- a/src/Entity/Event.php +++ b/src/Entity/Event.php @@ -273,7 +273,7 @@ class Event extends ContentEntityBase implements EventInterface { 'target_type' => 'rp_event', 'default_value' => 0, ]) - ->setDisplayConfigurable('form', TRUE) + ->setDisplayConfigurable('form', FALSE) ->setDisplayConfigurable('view', TRUE); $fields['date'] = BaseFieldDefinition::create('daterange') @@ -284,7 +284,7 @@ class Event extends ContentEntityBase implements EventInterface { 'datetime_type' => 'datetime', 'wkf-editable' => ['state' => ['draft']], ]) - ->setDefaultValue('') + ->setDefaultValueCallback('resource_planning_default_event_date') ->setDisplayOptions('view', [ 'label' => 'above', 'type' => 'string', diff --git a/src/Form/EventTypeForm.php b/src/Form/EventTypeForm.php index 1ee2803..a784dc6 100644 --- a/src/Form/EventTypeForm.php +++ b/src/Form/EventTypeForm.php @@ -121,7 +121,7 @@ class EventTypeForm extends EntityForm { $override->setSetting('handler_settings', [ 'view' => [ 'view_name' => $view, - 'display_name' => $dispaly, + 'display_name' => $display, 'arguments' => $form_state->getValue('arguments'), ], ]); -- GitLab From 41675d5082c366c2f1de7cc6096504bb37809b90 Mon Sep 17 00:00:00 2001 From: s j <sj@1729.be> Date: Sat, 11 Sep 2021 17:33:50 +0200 Subject: [PATCH 3/3] imp: subevent types calendar - use hook not basefieldoverride --- config/schema/rp_event_type.schema.yml | 6 ++ resource_planning.module | 25 +++++++ src/Entity/Event.php | 10 +++ src/Entity/EventType.php | 32 ++++++++- src/Form/EventTypeForm.php | 71 +++++-------------- .../views/argument/EntityCalendarArgument.php | 23 ++++-- 6 files changed, 106 insertions(+), 61 deletions(-) diff --git a/config/schema/rp_event_type.schema.yml b/config/schema/rp_event_type.schema.yml index 3476383..6b3414d 100644 --- a/config/schema/rp_event_type.schema.yml +++ b/config/schema/rp_event_type.schema.yml @@ -13,3 +13,9 @@ resource_planning.rp_event_type.*: sub_event_type: type: boolean label: 'Is sub event type' + calendar_view: + type: string + label: 'view' + calendar_arguments: + type: string + label: 'arguments' diff --git a/resource_planning.module b/resource_planning.module index 8dc9877..18f3c17 100644 --- a/resource_planning.module +++ b/resource_planning.module @@ -6,8 +6,11 @@ */ use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\resource_planning\Entity\EventType; + use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; /** @@ -106,3 +109,25 @@ function resource_planning_theme_suggestions_rp_calendar(array $variables) { $suggestions[] = 'rp_calendar__' . $entity->id() . '__' . $sanitized_view_mode; return $suggestions; } + +/** + * Implements hook_entity_bundle_field_info_alter(). + */ +function resource_planning_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { + if ($entity_type + ->id() == 'rp_event' && !empty($fields['calendar_id'])) { + + $type = EventType::load($bundle); + if ($info = $type->getCalendarView()) { + list($view, $display) = explode(':', $type->getCalendarView()); + $fields['calendar_id']->setSetting('handler', 'views'); + $fields['calendar_id']->setSetting('handler_settings', [ + 'view' => [ + 'view_name' => $view, + 'display_name' => $display, + 'arguments' => $type->getCalendarArguments(), + ], + ]); + } + } +} diff --git a/src/Entity/Event.php b/src/Entity/Event.php index 6261f5c..5994b4c 100644 --- a/src/Entity/Event.php +++ b/src/Entity/Event.php @@ -78,6 +78,16 @@ class Event extends ContentEntityBase implements EventInterface { ]; } + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageInterface $storage) { + // Automatically copy name from parent event. + if ($this->get('parent_id')->entity) { + $this->set('name', $this->get('parent_id')->entity->getName()); + } + } + /** * {@inheritdoc} */ diff --git a/src/Entity/EventType.php b/src/Entity/EventType.php index c97cee9..5558779 100644 --- a/src/Entity/EventType.php +++ b/src/Entity/EventType.php @@ -40,7 +40,9 @@ use Drupal\Core\Config\Entity\ConfigEntityBundleBase; * config_export = { * "id", * "label", - * "sub_event_type" + * "sub_event_type", + * "calendar_view", + * "calendar_arguments" * } * ) */ @@ -67,6 +69,20 @@ class EventType extends ConfigEntityBundleBase implements EventTypeInterface { */ protected $sub_event_type; + /** + * Calendar view and display. + * + * @var string + */ + protected $calendar_view; + + /** + * Calendar view and display. + * + * @var string + */ + protected $calendar_arguments; + /** * {@inheritdoc} */ @@ -74,4 +90,18 @@ class EventType extends ConfigEntityBundleBase implements EventTypeInterface { return $this->sub_event_type; } + /** + * {@inheritdoc} + */ + public function getCalendarView() { + return $this->calendar_view; + } + + /** + * {@inheritdoc} + */ + public function getCalendarArguments() { + return $this->calendar_arguments; + } + } diff --git a/src/Form/EventTypeForm.php b/src/Form/EventTypeForm.php index a784dc6..1d22702 100644 --- a/src/Form/EventTypeForm.php +++ b/src/Form/EventTypeForm.php @@ -3,7 +3,6 @@ namespace Drupal\resource_planning\Form; use Drupal\Core\Entity\EntityForm; -use Drupal\Core\Field\Entity\BaseFieldOverride; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Views; @@ -45,7 +44,6 @@ class EventTypeForm extends EntityForm { ]; // $view_settings = $this->getConfiguration()['view']; - $displays = Views::getApplicableViews('entity_reference_display'); // Filter views that list the entity type we want, and group the separate // displays by view. @@ -56,33 +54,42 @@ class EventTypeForm extends EntityForm { foreach ($displays as $data) { list($view_id, $display_id) = $data; $view = $view_storage->load($view_id); - if (in_array($view->get('base_table'), [$entity_type->getBaseTable(), $entity_type->getDataTable()])) { + if (in_array($view->get('base_table'), [ + $entity_type->getBaseTable(), + $entity_type->getDataTable(), + ])) { $display = $view->get('display'); $options[$view_id . ':' . $display_id] = $view_id . ' - ' . $display[$display_id]['display_title']; } } if ($options) { - $form['calendar_selection'] = [ + $form['calendar_info'] = [ '#type' => 'fieldset', '#title' => $this->t('Calendar selection'), ]; - // $default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : NULL; - $form['calendar_selection']['view_and_display'] = [ + $default = NULL; + if (!empty($this->entity->getCalendarView())) { + $default = $this->entity->getCalendarView(); + } + $form['calendar_info']['calendar_view'] = [ '#type' => 'select', '#title' => $this->t('View used to select the entities'), '#options' => $options, - // '#default_value' => $default, + '#default_value' => $default, '#description' => '<p>' . $this->t('Choose the view and display that select the entities that can be referenced.<br />Only views with a display of type "Entity Reference" are eligible.') . '</p>', '#empty_value' => '', ]; - // $default = !empty($view_settings['arguments']) ? implode(', ', $view_settings['arguments']) : ''; - $form['calendar_selection']['arguments'] = [ + $default = ''; + if (!empty($this->entity->getCalendarArguments())) { + $default = implode(', ', $this->entity->getCalendarArguments()); + } + $form['calendar_info']['calendar_arguments'] = [ '#type' => 'textfield', '#title' => $this->t('View arguments'), - // '#default_value' => $default, + '#default_value' => $default, '#required' => FALSE, '#description' => $this->t('Provide a comma separated list of arguments to pass to the view.'), ]; @@ -91,20 +98,6 @@ class EventTypeForm extends EntityForm { return $form; } - /** - * {@inheritdoc} - */ - public function getCalendarFieldDefinition($rp_event_type) { - $definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('rp_event', $rp_event_type->id()); - if ($definitions['calendar_id'] instanceof BaseFieldOverride) { - $override = $definitions['calendar_id']; - } - else { - $override = BaseFieldOverride::createFromBaseFieldDefinition($definitions['calendar_id'], $rp_event_type->id()); - } - return $override; - } - /** * {@inheritdoc} */ @@ -112,36 +105,6 @@ class EventTypeForm extends EntityForm { $rp_event_type = $this->entity; $status = $rp_event_type->save(); - $override = $this->getCalendarFieldDefinition($rp_event_type); - - if ($form_state->getValue('view_and_display')) { - list($view, $display) = explode(':', $form_state->getValue('view_and_display')); - $override->setLabel($rp_event_type->label()); - $override->setSetting('handler', 'views'); - $override->setSetting('handler_settings', [ - 'view' => [ - 'view_name' => $view, - 'display_name' => $display, - 'arguments' => $form_state->getValue('arguments'), - ], - ]); - } - else { - // Default entity reference selection settings. - $override->setLabel($this->t('Calendar')); - $override->setSetting('handler', 'default:rp_calendar'); - $override->setSetting('handler_settings', [ - 'target_bundles' => NULL, - 'sort' => [ - 'field' => '_none', - 'direction' => 'ASC', - ], - 'auto_create' => FALSE, - 'auto_create_bundle' => '', - ]); - } - $override->save(); - switch ($status) { case SAVED_NEW: $this->messenger()->addMessage($this->t('Created the %label Event type.', [ diff --git a/src/Plugin/views/argument/EntityCalendarArgument.php b/src/Plugin/views/argument/EntityCalendarArgument.php index 4adcc60..0e87f24 100644 --- a/src/Plugin/views/argument/EntityCalendarArgument.php +++ b/src/Plugin/views/argument/EntityCalendarArgument.php @@ -26,12 +26,23 @@ class EntityCalendarArgument extends ArgumentPluginBase { $calendar_ids = \Drupal::service('resource_planning.calendar')->getCalendarsForEntity( $user); - $this->query->addWhere( - 0, - "$this->tableAlias.$this->realField", - $calendar_ids, - 'IN' - ); + if (count($calendar_ids)) { + $this->query->addWhere( + 0, + "$this->tableAlias.$this->realField", + $calendar_ids, + 'IN' + ); + } + else { + // Add invalid where. + $this->query->addWhere( + 0, + "$this->tableAlias.$this->realField", + -1, + '=' + ); + } } } -- GitLab