diff --git a/modules/recurring_events_registration/config/install/recurring_events_registration.registrant.config.yml b/modules/recurring_events_registration/config/install/recurring_events_registration.registrant.config.yml index 02e809cf7a9f29cc44e6935c2c7bfed14b506149..6f648d3d3cc2a5886512263e05c48b97c43b3ac4 100644 --- a/modules/recurring_events_registration/config/install/recurring_events_registration.registrant.config.yml +++ b/modules/recurring_events_registration/config/install/recurring_events_registration.registrant.config.yml @@ -3,23 +3,24 @@ limit: 10 date_format: 'F jS, Y h:iA' email_notifications: true registration_notification_enabled: true +registration_notification_enabled: true registration_notification_subject: 'You''ve Successfully Registered' -registration_notification_body: 'Your registration for the [eventinstance:title] [eventinstance:reg_type] was successful.' +registration_notification_body: "Your registration for the [eventinstance:title] [eventinstance:reg_type] was successful.\r\n\r\nModify your registration: [registrant:edit_url]\r\nDelete your registration: [registrant:delete_url]" waitlist_notification_enabled: true waitlist_notification_subject: 'You''ve Been Added To The Waitlist' -waitlist_notification_body: 'You have been added to the waitlist for the [eventinstance:title] [eventinstance:reg_type].' +waitlist_notification_body: "You have been added to the waitlist for the [eventinstance:title] [eventinstance:reg_type].\r\n\r\nModify your registration: [registrant:edit_url]\r\nDelete your registration: [registrant:delete_url]" promotion_notification_enabled: true promotion_notification_subject: 'You''ve Been Added To The Registration List' -promotion_notification_body: 'You have been promoted from the waitlist to the registration list for the [eventinstance:title] [eventinstance:reg_type].' +promotion_notification_body: "You have been promoted from the waitlist to the registration list for the [eventinstance:title] [eventinstance:reg_type].\r\n\r\nModify your registration: [registrant:edit_url]\r\nDelete your registration: [registrant:delete_url]" instance_deletion_notification_enabled: true instance_deletion_notification_subject: 'An Event Has Been Deleted' -instance_deletion_notification_body: 'Unfortunately, the [eventinstance:title] [eventinstance:reg_type] has been deleted.' +instance_deletion_notification_body: 'Unfortunately, the [eventinstance:title] [eventinstance:reg_type] has been deleted. Your registration has been deleted.' series_deletion_notification_enabled: true series_deletion_notification_subject: 'An Event Series Has Been Deleted' -series_deletion_notification_body: 'Unfortunately, the [eventinstance:title] [eventinstance:reg_type] has been deleted.' +series_deletion_notification_body: 'Unfortunately, the [eventinstance:title] [eventinstance:reg_type] has been deleted. Your registration has been deleted.' instance_modification_notification_enabled: true instance_modification_notification_subject: 'An Event Has Been Modified' -instance_modification_notification_body: 'The [eventinstance:title] [eventinstance:reg_type] has been modified, please check back for details.' +instance_modification_notification_body: "The [eventinstance:title] [eventinstance:reg_type] has been modified, please check back for details.\r\n\r\nModify your registration: [registrant:edit_url]\r\nDelete your registration: [registrant:delete_url]" series_modification_notification_enabled: true series_modification_notification_subject: 'An Event Series Has Been Modified' -series_modification_notification_body: 'The [eventinstance:title] [eventinstance:reg_type] has been modified, and all instances have been removed.' \ No newline at end of file +series_modification_notification_body: 'The [eventinstance:title] [eventinstance:reg_type] has been modified, and all instances have been removed, and your registration has been deleted.' \ No newline at end of file diff --git a/modules/recurring_events_registration/recurring_events_registration.permissions.yml b/modules/recurring_events_registration/recurring_events_registration.permissions.yml index bdfdc2010bc8d03c9290a8d65e9c2f5f6caab965..2608e783add9c8cd88294362425ebaaae4bd093d 100644 --- a/modules/recurring_events_registration/recurring_events_registration.permissions.yml +++ b/modules/recurring_events_registration/recurring_events_registration.permissions.yml @@ -1,13 +1,20 @@ +# Registrant Entities. add registrant entities: - title: 'Create new Registrant entities' - -administer registrant entities: - title: 'Administer Registrant entities' - description: 'Allow to access the administration form to configure Registrant entities.' - restrict access: true - -delete registrant entities: - title: 'Delete Registrant entities' - + title: 'Create new registrant entities' + description: 'Create new registrant entities' edit registrant entities: - title: 'Edit Registrant entities' + title: 'Edit registrant entities' + description: 'Edit registrant entities' +delete registrant entities: + title: 'Delete registrant entities' + description: 'Delete registrant entities' +edit registrant entities anonymously: + title: 'Edit registrant entities anonymously' + description: 'Modify a registrant using the UUID path' +delete registrant entities anonymously: + title: 'Delete registrant entities anonymously' + description: 'Delete a registrant using the UUID path' +administer registrant entities: + title: 'Administer registrant entities' + description: 'Allow to access the administration form to configure registrant entities.' + restrict access: true \ No newline at end of file diff --git a/modules/recurring_events_registration/recurring_events_registration.routing.yml b/modules/recurring_events_registration/recurring_events_registration.routing.yml index 71a153a2f7e0d90cc424ab855ee504330f6f9ee9..16a0b9691853b614fd838abb72812c2fb15de1fb 100644 --- a/modules/recurring_events_registration/recurring_events_registration.routing.yml +++ b/modules/recurring_events_registration/recurring_events_registration.routing.yml @@ -80,33 +80,37 @@ entity.registrant.delete_form: # Registrant anonymous edit route. entity.registrant.anon_edit_form: - path: '/events/{eventinstance}/registrant/{registrant}/{uuid}/edit' + path: '/events/{eventinstance}/registration/{registrant}/{uuid}/edit' defaults: # Calls the form.edit controller, defined in the Registrant entity. _entity_form: registrant.edit requirements: - _access: 'TRUE' + _entity_access: 'registrant.anon-update' uuid: '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}' options: parameters: eventinstance: type: entity:eventinstance + registrant: + type: entity:registrant uuid: type: string # Registrant anonymous delete route. entity.registrant.anon_delete_form: - path: '/events/{eventinstance}/registrant/{registrant}/{uuid}/delete' + path: '/events/{eventinstance}/registration/{registrant}/{uuid}/delete' defaults: # Calls the form.delete controller, defined in the Registrant entity. _entity_form: registrant.delete requirements: - _access: 'TRUE' + _entity_access: 'registrant.anon-delete' uuid: '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}' options: parameters: eventinstance: type: entity:eventinstance + registrant: + type: entity:registrant uuid: type: string diff --git a/modules/recurring_events_registration/recurring_events_registration.tokens.inc b/modules/recurring_events_registration/recurring_events_registration.tokens.inc index 3f1d1ecf6d85456f63c2560730cd8a2dac61967b..9ef50d474cb805cec87bc7c1305efb73b238d5d8 100644 --- a/modules/recurring_events_registration/recurring_events_registration.tokens.inc +++ b/modules/recurring_events_registration/recurring_events_registration.tokens.inc @@ -12,9 +12,9 @@ use Drupal\Core\Render\BubbleableMetadata; */ function recurring_events_registration_token_info() { $eventinstance = []; - $type = [ + $eventinstance_type = [ 'name' => t('Event Instance Registration'), - 'description' => t('Tokens from the Recurring Events Registration module.'), + 'description' => t('Event Instance tokens from the Recurring Events Registration module.'), 'needs-data' => 'eventinstance', ]; @@ -28,12 +28,31 @@ function recurring_events_registration_token_info() { 'description' => t('The registration type of the event instance.'), ]; + $registrant = []; + $registrant_type = [ + 'name' => t('Registrant'), + 'description' => t('Registrant tokens from the Recurring Events Registration module.'), + 'needs-data' => 'registrant', + ]; + + $registrant['edit_url'] = [ + 'name' => t('Edit Registrant URL'), + 'description' => t('The URL to edit a registrant.'), + ]; + + $registrant['delete_url'] = [ + 'name' => t('Delete Registrant URL'), + 'description' => t('The URL to delete a registrant.'), + ]; + return [ 'types' => [ - 'eventinstance' => $type, + 'eventinstance' => $eventinstance_type, + 'registrant' => $registrant_type, ], 'tokens' => [ 'eventinstance' => $eventinstance, + 'registrant' => $registrant, ], ]; @@ -52,7 +71,7 @@ function recurring_events_registration_tokens($type, $tokens, array $data, array foreach ($tokens as $name => $original) { switch ($name) { case 'reg_url': - $replacements[$original] = $event_instance->toUrl('canonical') . '/registration/add'; + $replacements[$original] = $event_instance->toUrl('canonical')->setAbsolute(TRUE)->toString() . '/registration/add'; break; case 'reg_type': @@ -61,5 +80,28 @@ function recurring_events_registration_tokens($type, $tokens, array $data, array } } } + + if ($type == 'registrant' && !empty($data['registrant'])) { + $registrant = $data['registrant']; + foreach ($tokens as $name => $original) { + switch ($name) { + case 'edit_url': + $url = $registrant->toUrl('edit-form')->setAbsolute(TRUE)->toString(); + if ($registrant->user_id->target_id === '0') { + $url = $registrant->toUrl('anon-edit-form')->setAbsolute(TRUE)->toString(); + } + $replacements[$original] = $url; + break; + + case 'delete_url': + $url = $registrant->toUrl('delete-form')->setAbsolute(TRUE)->toString(); + if ($registrant->user_id->target_id === '0') { + $url = $registrant->toUrl('anon-delete-form')->setAbsolute(TRUE)->toString(); + } + $replacements[$original] = $url; + break; + } + } + } return $replacements; } diff --git a/modules/recurring_events_registration/src/Entity/Registrant.php b/modules/recurring_events_registration/src/Entity/Registrant.php index d2037b0e7cae1cc4f19a1763d343b2d89db869c5..a4951859968444760f2be85d122341f45d59b217 100644 --- a/modules/recurring_events_registration/src/Entity/Registrant.php +++ b/modules/recurring_events_registration/src/Entity/Registrant.php @@ -29,7 +29,7 @@ use Drupal\recurring_events\Entity\EventSeries; * "add" = "Drupal\recurring_events_registration\Form\RegistrantForm", * "edit" = "Drupal\recurring_events_registration\Form\RegistrantForm", * "delete" = "Drupal\recurring_events_registration\Form\RegistrantDeleteForm", - * "anon-edit" = "Drupal\recurring_events_registration\Form\RegistrantForm", + * "anon-edit" = "Drupal\recurring_events_registration\Form\RegistrantForm", * "anon-delete" = "Drupal\recurring_events_registration\Form\RegistrantDeleteForm", * }, * "access" = "Drupal\recurring_events_registration\RegistrantAccessControlHandler", diff --git a/modules/recurring_events_registration/src/RegistrantAccessControlHandler.php b/modules/recurring_events_registration/src/RegistrantAccessControlHandler.php index b78c4cb0a3f845c79870c469f901c4653a316dfc..544b5675b56d094fdc59def8ad1479a3030b5902 100644 --- a/modules/recurring_events_registration/src/RegistrantAccessControlHandler.php +++ b/modules/recurring_events_registration/src/RegistrantAccessControlHandler.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityAccessControlHandler; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Access\AccessResult; +use Drupal\Component\Uuid\Uuid; /** * Access controller for the Registrant entity. @@ -28,6 +29,10 @@ class RegistrantAccessControlHandler extends EntityAccessControlHandler { case 'delete': return AccessResult::allowedIfHasPermission($account, 'delete registrant entities'); + + case 'anon-update': + case 'anon-delete': + return $this->checkAnonymousAccess($entity, $operation, $account); } // Unknown operation, no opinion. @@ -50,4 +55,54 @@ class RegistrantAccessControlHandler extends EntityAccessControlHandler { return AccessResult::neutral(); } + /** + * Check if the user can edit or delete this registrant anonymously. + * + * @param Drupal\Core\Entity\EntityInterface $registrant + * The registrant to be edited. + * @param string $operation + * The operation being attempted. + * @param Drupal\Core\Session\AccountInterface $account + * The user attempting to gain access. + * + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. + */ + protected function checkAnonymousAccess(EntityInterface $registrant, $operation, AccountInterface $account) { + $params = \Drupal::request()->attributes->all(); + if (!empty($params['uuid'])) { + $uuid = $params['uuid']; + // We should not be allowed to edit anonymously if the registrant belongs + // to a user. + if ($registrant->user_id->target_id !== '0') { + return AccessResult::forbidden('This registrant cannot be edited using a UUID.'); + } + + // If UUID was not passed in, then this is an invalid request. + if (empty($uuid)) { + return AccessResult::forbidden('No UUID was specified.'); + } + + // If this is not a valid UUID, then this is an invalid request. + if (!Uuid::isValid($uuid)) { + return AccessResult::forbidden('The provided UUID is invalid.'); + } + + // If the UUID specified is not for the registrant being edited. + if ($uuid !== $registrant->uuid->value) { + return AccessResult::forbidden('The provided UUID is not valid for this registrant'); + } + + switch ($operation) { + case 'anon-update': + return AccessResult::allowedIfHasPermission($account, 'edit registrant entities anonymously'); + + case 'anon-delete': + return AccessResult::allowedIfHasPermission($account, 'delete registrant entities anonymously'); + } + + } + return AccessResult::forbidden(); + } + } diff --git a/recurring_events.api.php b/recurring_events.api.php index c13ab85355a84368bacf9dac467f8d358b4adfa3..1720f8fe28696a93e94f073918e7a4baee32d70d 100644 --- a/recurring_events.api.php +++ b/recurring_events.api.php @@ -174,7 +174,7 @@ function hook_recurring_events_pre_delete_instances(EventSeries $event_series) { * in that this hook fires after deleting instances by deleting the series * rather than as a result of changing series date configuration. */ -function hook_recurring_events_post_delete_instance(EventSeries $event_series) { +function hook_recurring_events_post_delete_instances(EventSeries $event_series) { } /** diff --git a/recurring_events.permissions.yml b/recurring_events.permissions.yml index fa37cd704bdf12ee13d3293fa3144628c6cfefac..491cdc3fb4dda7ec1d38d68b4a3b164d543081e8 100644 --- a/recurring_events.permissions.yml +++ b/recurring_events.permissions.yml @@ -5,6 +5,9 @@ add eventseries entity: view eventseries entity: title: 'View eventseries entity' description: 'View existing event series entities' +view unpublished eventseries entity: + title: 'View unpublished eventseries entity' + description: 'View exisiting unpublished event series entities' edit eventseries entity: title: 'Edit eventseries entity' description: 'Modify existing event series entities' diff --git a/recurring_events.tokens.inc b/recurring_events.tokens.inc index b26e571fea3b5bd17da30c3f670cefaad46f96f2..d46b3f850bb9aad4c3f11575c6c79b589bb7b222 100644 --- a/recurring_events.tokens.inc +++ b/recurring_events.tokens.inc @@ -91,7 +91,7 @@ function recurring_events_tokens($type, $tokens, array $data, array $options, Bu break; case 'url': - $replacements[$original] = $event_instance->toUrl('canonical'); + $replacements[$original] = $event_instance->toUrl('canonical')->setAbsolute(TRUE)->toString(); break; } } diff --git a/src/EventSeriesAccessControlHandler.php b/src/EventSeriesAccessControlHandler.php index d686a8ecf3f5427a4c52ac82d1b0cbe5e74dfc59..4b60e0c8f3d8022ba4b6d4dd5b2838f5bf9381a3 100644 --- a/src/EventSeriesAccessControlHandler.php +++ b/src/EventSeriesAccessControlHandler.php @@ -23,6 +23,10 @@ class EventSeriesAccessControlHandler extends EntityAccessControlHandler { protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { switch ($operation) { case 'view': + $status = $entity->isPublished(); + if (!$status) { + return AccessResult::allowedIfHasPermission($account, 'view unpublished eventseries entity'); + } return AccessResult::allowedIfHasPermission($account, 'view eventseries entity'); case 'edit':