diff --git a/config/schema/rng.data_types.schema.yml b/config/schema/rng.data_types.schema.yml index 9cc4807..ce859db 100644 --- a/config/schema/rng.data_types.schema.yml +++ b/config/schema/rng.data_types.schema.yml @@ -26,3 +26,19 @@ rng_event_type_people_type: entity_form_mode: type: string label: 'Form display mode used when the entity is created inline.' + +rng_event_type_default_message: + type: mapping + mapping: + trigger: + type: string + label: 'Trigger' + status: + type: boolean + label: 'Whether this entity bundle can be created inline.' + subject: + type: string + label: 'Subject of the message.' + body: + type: string + label: 'Message body.' diff --git a/config/schema/rng.schema.yml b/config/schema/rng.schema.yml index 82d8310..dcb635a 100644 --- a/config/schema/rng.schema.yml +++ b/config/schema/rng.schema.yml @@ -63,6 +63,11 @@ rng.event_type.*.*: label: 'Types of people types allowed to be associated with this event type.' sequence: type: rng_event_type_people_type + default_messages: + type: sequence + label: 'Default messages for this event type.' + sequence: + type: rng_event_type_default_message condition.plugin.rng_user_role: type: condition.plugin.user_role diff --git a/rng.links.action.yml b/rng.links.action.yml index b91c82f..2eca628 100644 --- a/rng.links.action.yml +++ b/rng.links.action.yml @@ -2,6 +2,12 @@ rng.local_actions: class: \Drupal\Core\Menu\LocalActionDefault deriver: \Drupal\rng\Plugin\Derivative\LocalActions +rng.default_messages.add_form: + route_name: entity.event_type.default_messages.add + title: 'Add message' + appears_on: + - entity.event_type.default_messages + rng.registration_type.add: route_name: entity.registration_type.add title: 'Add registration type' @@ -18,4 +24,4 @@ rng.event_type.add: route_name: entity.event_type.add title: 'Add event type' appears_on: - - rng.event_type.overview \ No newline at end of file + - rng.event_type.overview diff --git a/rng.links.task.yml b/rng.links.task.yml index d1fdb59..813b241 100644 --- a/rng.links.task.yml +++ b/rng.links.task.yml @@ -24,6 +24,11 @@ entity.event_type.access_defaults: base_route: entity.event_type.edit_form title: 'Access Defaults' +entity.event_type.default_messages: + route_name: entity.event_type.default_messages + base_route: entity.event_type.edit_form + title: 'Default messages' + # Registration type entity.registration_type.edit_form: title: 'Edit' @@ -91,4 +96,4 @@ entity.rng_rule_component.edit: rng.config.settings: route_name: rng.config.settings title: 'Settings' - base_route: rng.config.settings \ No newline at end of file + base_route: rng.config.settings diff --git a/rng.module b/rng.module index 0a592d0..45778a3 100644 --- a/rng.module +++ b/rng.module @@ -62,6 +62,13 @@ function rng_entity_operation(EntityInterface $entity) { ]), 'weight' => 20, ); + $operations['default_messages'] = array( + 'title' => t('Default messages'), + 'url' => Url::fromRoute('entity.event_type.default_messages', [ + 'event_type' => $entity->id(), + ]), + 'weight' => 25, + ); } return $operations; diff --git a/rng.routing.yml b/rng.routing.yml index 51085d4..4e74d39 100644 --- a/rng.routing.yml +++ b/rng.routing.yml @@ -159,6 +159,26 @@ entity.event_type.access_defaults: requirements: _permission: 'administer event types' +entity.event_type.default_messages: + path: '/admin/structure/rng/event_types/manage/{event_type}/messages' + defaults: + _entity_form: 'event_type.event_default_messages' + _title: 'Event type Default messages' + requirements: + _permission: 'administer event types' + +entity.event_type.default_messages.add: + path: '/admin/structure/rng/event_types/manage/{event_type}/messages/add' + defaults: + _form: '\Drupal\rng\Form\EventTypeDefaultMessagesAddForm' + _title: 'Add message' + options: + parameters: + event_type: + type: entity:event_type + requirements: + _permission: 'administer event types' + entity.event_type.field_mapping: path: '/admin/structure/rng/event_types/manage/{event_type}/field_mapping' defaults: diff --git a/src/Entity/EventType.php b/src/Entity/EventType.php index 7b0abaa..c8c3954 100644 --- a/src/Entity/EventType.php +++ b/src/Entity/EventType.php @@ -24,6 +24,7 @@ * "edit" = "Drupal\rng\Form\EventTypeForm", * "delete" = "Drupal\rng\Form\EventTypeDeleteForm", * "event_access_defaults" = "Drupal\rng\Form\EventTypeAccessDefaultsForm", + * "event_default_messages" = "Drupal\rng\Form\EventTypeDefaultMessagesListForm", * "field_mapping" = "Drupal\rng\Form\EventTypeFieldMappingForm", * } * }, @@ -106,6 +107,13 @@ class EventType extends ConfigEntityBase implements EventTypeInterface { */ protected $people_types = []; + /** + * Default messages configured for this event type. + * + * @var array + */ + protected $default_messages = []; + /** * Fields to add to event bundles. * @@ -189,6 +197,21 @@ function getDefaultRegistrantType() { return $this->default_registrant; } + /** + * {@inheritdoc} + */ + function getDefaultMessages() { + return $this->default_messages; + } + + /** + * {@inheritdoc} + */ + function setDefaultMessages($messages) { + $this->default_messages = $messages; + return $this; + } + /** * {@inheritdoc} */ diff --git a/src/EventMeta.php b/src/EventMeta.php index c65a4e5..63d691b 100644 --- a/src/EventMeta.php +++ b/src/EventMeta.php @@ -10,6 +10,9 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\rng\Entity\Rule; use Drupal\rng\Entity\RuleComponent; +use Drupal\courier\Entity\TemplateCollection; +use Drupal\courier\Service\CourierManagerInterface; +use Drupal\Core\Action\ActionManager; /** * Meta event wrapper for RNG. @@ -65,6 +68,20 @@ class EventMeta implements EventMetaInterface { */ protected $eventManager; + /** + * The courier manager. + * + * @var \Drupal\courier\Service\CourierManagerInterface + */ + protected $courier_manager; + + /** + * The action manager. + * + * @var \Drupal\Core\Action\ActionManager + */ + protected $action_manager; + /** * Constructs a new EventMeta object. * @@ -80,16 +97,22 @@ class EventMeta implements EventMetaInterface { * The RNG configuration service. * @param \Drupal\rng\EventManagerInterface $event_manager * The RNG event manager. + * @param \Drupal\courier\Service\CourierManagerInterface $courier_manager + * The courier manager. + * @param \Drupal\Core\Action\ActionManager $action_manager + * The action manager. * @param \Drupal\Core\Entity\EntityInterface $entity * The event entity. */ - public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, SelectionPluginManagerInterface $selection_plugin_manager, IdentityChannelManagerInterface $identity_channel_manager, RngConfigurationInterface $rng_configuration, EventManagerInterface $event_manager, EntityInterface $entity) { + public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, SelectionPluginManagerInterface $selection_plugin_manager, IdentityChannelManagerInterface $identity_channel_manager, RngConfigurationInterface $rng_configuration, EventManagerInterface $event_manager, CourierManagerInterface $courier_manager, ActionManager $action_manager, EntityInterface $entity) { $this->entityManager = $entity_manager; $this->configFactory = $config_factory; $this->selectionPluginManager = $selection_plugin_manager; $this->identityChannelManager = $identity_channel_manager; $this->rngConfiguration = $rng_configuration; $this->eventManager = $event_manager; + $this->courier_manager = $courier_manager; + $this->action_manager = $action_manager; $this->entity = $entity; } @@ -104,6 +127,8 @@ public static function createInstance(ContainerInterface $container, EntityInter $container->get('plugin.manager.identity_channel'), $container->get('rng.configuration'), $container->get('rng.event_manager'), + $container->get('courier.manager'), + $container->get('plugin.manager.action'), $entity ); } @@ -608,4 +633,59 @@ protected function entityTypeHasBundles($entity_type_id) { return ($entity_type->getBundleEntityType() !== NULL); } + /** + * {@inheritdoc} + */ + function createDefaultEventMessages() { + // Get Default messages for this Event type. + $default_messages = $this->getEventType()->getDefaultMessages(); + if ($default_messages) { + foreach ($default_messages as $default_message) { + // Create Event Messages from Default Messages. + $template_collection = TemplateCollection::create(); + $template_collection->save(); + $this->courier_manager->addTemplates($template_collection); + $template_collection->setOwner($this->getEvent()); + $template_collection->save(); + + $templates = $template_collection->getTemplates(); + /** @var \Drupal\courier\EmailInterface $courier_email */ + $courier_email = $templates[0]; + $courier_email->setSubject($default_message['subject']); + $courier_email->setBody($default_message['body']); + $courier_email->save(); + + $rule = Rule::create([ + 'event' => ['entity' => $this->getEvent()], + 'trigger_id' => $default_message['trigger'], + ]); + $rule->setIsActive($default_message['status']); + + $actionPlugin = $this->action_manager->createInstance('rng_courier_message'); + $configuration = $actionPlugin->getConfiguration(); + $configuration['template_collection'] = $template_collection->id(); + $action = RuleComponent::create([]) + ->setPluginId($actionPlugin->getPluginId()) + ->setConfiguration($configuration) + ->setType('action'); + $rule->addComponent($action); + $rule->save(); + + // Handle custom date trigger. + if ($default_message['trigger'] == 'rng:custom:date') { + $rule_component = RuleComponent::create() + ->setRule($rule) + ->setType('condition') + ->setPluginId('rng_rule_scheduler'); + $rule_component->save(); + // Save the ID into config. + $rule_component->setConfiguration([ + 'rng_rule_component' => $rule_component->id(), + ]); + $rule_component->save(); + } + } + } + } + } diff --git a/src/EventMetaInterface.php b/src/EventMetaInterface.php index e335acd..92cd721 100644 --- a/src/EventMetaInterface.php +++ b/src/EventMetaInterface.php @@ -366,4 +366,9 @@ public function identitiesCanRegister($entity_type, array $entity_ids); */ function addDefaultAccess(); + /** + * Create messages for Event from Default messages for this Event Type. + */ + function createDefaultEventMessages(); + } diff --git a/src/EventTypeInterface.php b/src/EventTypeInterface.php index 57044b0..dd5a2c0 100644 --- a/src/EventTypeInterface.php +++ b/src/EventTypeInterface.php @@ -84,6 +84,21 @@ function setAllowCustomRules($allow); */ function getDefaultRegistrantType(); + /** + * Default messages configured for this event type. + * + * @return array + */ + function getDefaultMessages(); + + /** + * Set default messages for this event type. + * + * @param array $messages + * Default messages array. + */ + function setDefaultMessages($messages); + /** * Whether a identity type can be created. * diff --git a/src/Form/EventTypeDefaultMessagesAddForm.php b/src/Form/EventTypeDefaultMessagesAddForm.php new file mode 100644 index 0000000..8e44065 --- /dev/null +++ b/src/Form/EventTypeDefaultMessagesAddForm.php @@ -0,0 +1,105 @@ +eventType = $event_type; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('current_route_match')->getParameter('event_type') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'rng_event_default_message_add'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + // @TODO : Move this and other occurences into a common place?. + $triggers = [ + 'rng:custom:date' => $this->t('To all registrations, on a date.'), + (string) $this->t('Registrations') => [ + 'entity:registration:new' => $this->t('To a single registration, when it is created.'), + 'entity:registration:update' => $this->t('To a single registration, when it is updated.'), + ], + ]; + + $form['trigger'] = [ + '#type' => 'select', + '#options' => $triggers, + '#title' => $this->t('Trigger'), + ]; + $form['status'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enabled'), + ]; + $form['subject'] = [ + '#type' => 'textfield', + '#title' => $this->t('Subject'), + '#required' => TRUE, + ]; + $form['body'] = [ + '#type' => 'textarea', + '#title' => $this->t('Body'), + '#required' => TRUE, + ]; + $form['actions'] = [ + '#type' => 'actions', + ]; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Save'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $messages = $this->eventType->getDefaultMessages(); + array_push($messages, [ + 'trigger' => $form_state->getValue('trigger'), + 'status' => $form_state->getValue('status'), + 'subject' => $form_state->getValue('subject'), + 'body' => $form_state->getValue('body'), + ]); + $this->eventType->setDefaultMessages($messages)->save(); + + $this->messenger()->addMessage($this->t('New message added.')); + $form_state->setRedirect('entity.event_type.default_messages', ['event_type' => $this->eventType->id()]); + } + +} diff --git a/src/Form/EventTypeDefaultMessagesListForm.php b/src/Form/EventTypeDefaultMessagesListForm.php new file mode 100644 index 0000000..cccf071 --- /dev/null +++ b/src/Form/EventTypeDefaultMessagesListForm.php @@ -0,0 +1,226 @@ +redirectDestination = $redirect_destination; + $this->actionManager = $actionManager; + $this->conditionManager = $conditionManager; + $this->eventTypeRuleStorage = $entity_type_manager->getStorage('rng_event_type_rule'); + $this->eventManager = $event_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('redirect.destination'), + $container->get('plugin.manager.action'), + $container->get('plugin.manager.condition'), + $container->get('entity_type.manager'), + $container->get('rng.event_manager') + ); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $form = parent::buildForm($form, $form_state); + /** @var \Drupal\rng\EventTypeInterface $event_type */ + $event_type = $this->entity; + /** @var array $default_messages */ + $default_messages = $form_state->get('default_messages'); + if (empty($default_messages)) { + $default_messages = $event_type->getDefaultMessages(); + $form_state->set('default_messages', $default_messages); + } + + // @TODO : Move this and other occurences into a common place?. + // @see EventTypeDefaultMessagesAddForm::buildForm. + $trigger_options = [ + 'rng:custom:date' => $this->t('To all registrations, on a date.'), + (string) $this->t('Registrations') => [ + 'entity:registration:new' => $this->t('To a single registration, when it is created.'), + 'entity:registration:update' => $this->t('To a single registration, when it is updated.'), + ], + ]; + $trigger_labels = [ + 'entity:registration:new' => $this->t('Registration creation'), + 'entity:registration:update' => $this->t('Registration updated'), + 'rng:custom:date' => $this->t('Send on a date'), + ]; + + $form['messages'] = [ + '#type' => 'container', + '#attributes' => [ + 'id' => 'rng-default-messages-wrapper', + ], + '#tree' => TRUE, + ]; + foreach ($default_messages as $key => $message) { + $form['messages'][$key] = [ + '#type' => 'details', + '#tree' => TRUE, + '#title' => $this->t('@label (@status)', [ + '@label' => isset($trigger_labels[$message['trigger']]) ? $trigger_labels[$message['trigger']] : $message['trigger'], + '@status' => $message['status'] ? $this->t('active') : $this->t('disabled'), + ]), + ]; + $form['messages'][$key]['trigger'] = [ + '#type' => 'select', + '#options' => $trigger_options, + '#title' => $this->t('Trigger'), + '#default_value' => $message['trigger'], + ]; + $form['messages'][$key]['status'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enabled'), + '#default_value' => $message['status'], + ]; + $form['messages'][$key]['subject'] = [ + '#type' => 'textfield', + '#title' => $this->t('Subject'), + '#default_value' => $message['subject'], + '#required' => TRUE, + ]; + $form['messages'][$key]['body'] = [ + '#type' => 'textarea', + '#title' => $this->t('Body'), + '#default_value' => $message['body'], + '#required' => TRUE, + ]; + $form['messages'][$key]['remove'] = [ + '#type' => 'submit', + '#value' => $this->t('Remove this message'), + '#message_key' => $key, + '#name' => 'button-message-remove-' . $key, + '#submit' => ['::removeMessageCallback'], + '#ajax' => [ + 'callback' => '::processMessageCallback', + 'wrapper' => 'rng-default-messages-wrapper', + ] + ]; + } + + return $form; + } + + /** + * {@inheritdoc} + */ + public function processMessageCallback(array &$form, FormStateInterface $form_state) { + // This function may be used for other ajax callbacks, too. + $triggering_element = $form_state->getTriggeringElement(); + if (strpos($triggering_element['#name'], 'button-message-remove') !== FALSE) { + unset($form['messages'][$triggering_element['#message_key']]); + + return $form['messages']; + } + } + + /** + * {@inheritdoc} + */ + public function removeMessageCallback(array &$form, FormStateInterface $form_state) { + $key = $form_state->getTriggeringElement()['#message_key']; + $default_messages = $form_state->get('default_messages'); + unset($default_messages[$key]); + + $form_state->set('default_messages', $default_messages); + $form_state->setRebuild(); + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + /** @var \Drupal\rng\EventTypeInterface $event_type */ + $event_type = $this->entity; + /** @var array $default_messages */ + $default_messages = $form_state->getValue('messages'); + + $event_type->setDefaultMessages($default_messages)->save(); + + // Site cache needs to be cleared after enabling this setting as there are + // issue regarding caching. + Cache::invalidateTags(['rendered']); + + $this->messenger()->addMessage($this->t('Event type default messages saved.')); + $this->eventManager->invalidateEventType($event_type); + } +} diff --git a/src/RngEntityModel.php b/src/RngEntityModel.php index b996beb..f24b69e 100644 --- a/src/RngEntityModel.php +++ b/src/RngEntityModel.php @@ -106,6 +106,10 @@ public function hook_entity_postsave(EntityInterface $entity, $update = TRUE) { ->setEntityId($entity->id()); $this->operationRecords[] = $operation_record; } + if ($this->eventManager->isEvent($entity) && $update == FALSE) { + $event = $this->eventManager->getMeta($entity); + $event->createDefaultEventMessages(); + } } /** @@ -229,4 +233,4 @@ protected function deleteRngRuleComponent(RuleComponentInterface $entity) { } } -} \ No newline at end of file +}