diff --git a/registration.tokens.inc b/registration.tokens.inc new file mode 100644 index 0000000000000000000000000000000000000000..8c6940b6e25c2ebd34852d0b6b66b27e1e063125 --- /dev/null +++ b/registration.tokens.inc @@ -0,0 +1,221 @@ +<?php + +/** + * @file + * Builds placeholder replacement tokens for registration-related data. + */ + +use Drupal\Core\Datetime\Entity\DateFormat; +use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\user\Entity\User; + +/** + * Implements hook_token_info(). + */ +function registration_token_info() { + $types['registration'] = [ + 'name' => t('Registration'), + 'description' => t('Tokens related to registrations.'), + 'needs-data' => 'registration', + ]; + $registration['id'] = [ + 'name' => t('ID'), + 'description' => t('The unique identifier for the registration.'), + ]; + $registration['count'] = [ + 'name' => t('Spaces'), + 'description' => t('The number of spaces reserved by the registration.'), + ]; + $registration['label'] = [ + 'name' => t('Label'), + 'description' => t('The registration label.'), + ]; + $registration['mail'] = [ + 'name' => t('Email'), + 'description' => t('The email address for the registration.'), + ]; + $registration['state'] = [ + 'name' => t('Status'), + 'description' => t('The registration state.'), + ]; + $registration['type'] = [ + 'name' => t('Type'), + 'description' => t('The registration type ID.'), + ]; + $registration['type-name'] = [ + 'name' => t('Type name'), + 'description' => t('The registration type name.'), + ]; + + // Chained tokens for registrations. + $registration['author'] = [ + 'name' => t('Author'), + 'type' => 'user', + ]; + $node['created'] = [ + 'name' => t("Date created"), + 'type' => 'date', + ]; + $node['changed'] = [ + 'name' => t("Date changed"), + 'description' => t("The date the registration was most recently updated."), + 'type' => 'date', + ]; + $node['completed'] = [ + 'name' => t("Date completed"), + 'description' => t("The date the registration was completed."), + 'type' => 'date', + ]; + $registration['entity'] = [ + 'name' => t('Host entity'), + 'description' => t('The host entity for the registration.'), + ]; + $registration['user'] = [ + 'name' => t('User'), + 'type' => 'user', + ]; + + return [ + 'types' => $types, + 'tokens' => ['registration' => $registration], + ]; +} + +/** + * Implements hook_tokens(). + */ +function registration_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) { + + $token_service = \Drupal::token(); + + if (isset($options['langcode'])) { + $url_options['language'] = \Drupal::languageManager()->getLanguage($options['langcode']); + $langcode = $options['langcode']; + } + else { + $langcode = LanguageInterface::LANGCODE_DEFAULT; + } + + $replacements = []; + + // The registration tokens. + if ($type == 'registration' && !empty($data['registration'])) { + /** @var \Drupal\registration\Entity\RegistrationInterface $registration */ + $registration = $data['registration']; + + // Simple tokens. + foreach ($tokens as $name => $original) { + switch ($name) { + case 'id': + $replacements[$original] = $registration->id(); + break; + + case 'count': + $replacements[$original] = $registration->getSpacesReserved(); + break; + + case 'label': + $replacements[$original] = $registration->label(); + break; + + case 'mail': + $replacements[$original] = $registration->getEmail(); + break; + + case 'state': + $replacements[$original] = $registration->getState()?->label(); + break; + + case 'type': + $replacements[$original] = $registration->getType()->id(); + break; + + case 'type-name': + $replacements[$original] = $registration->getType()->label(); + break; + + // Default values for the chained tokens handled below. + case 'author': + $account = $registration->getAuthor() ? $registration->getAuthor() : User::load(0); + $bubbleable_metadata->addCacheableDependency($account); + $replacements[$original] = $account->label(); + break; + + case 'created': + $date_format = DateFormat::load('medium'); + $bubbleable_metadata->addCacheableDependency($date_format); + $replacements[$original] = \Drupal::service('date.formatter')->format($registration->getCreatedTime(), 'medium', '', NULL, $langcode); + break; + + case 'changed': + $date_format = DateFormat::load('medium'); + $bubbleable_metadata->addCacheableDependency($date_format); + $replacements[$original] = \Drupal::service('date.formatter')->format($registration->getChangedTime(), 'medium', '', NULL, $langcode); + break; + + case 'completed': + if ($registration->isComplete()) { + $date_format = DateFormat::load('medium'); + $bubbleable_metadata->addCacheableDependency($date_format); + $replacements[$original] = \Drupal::service('date.formatter')->format($registration->getCompletedTime(), 'medium', '', NULL, $langcode); + } + break; + + case 'entity': + if ($entity = $registration->getHostEntity()?->getEntity()) { + $bubbleable_metadata->addCacheableDependency($entity); + $replacements[$original] = $entity->label(); + } + break; + + case 'user': + $account = $registration->getUser() ? $registration->getUser() : User::load(0); + $bubbleable_metadata->addCacheableDependency($account); + $replacements[$original] = $account->label(); + break; + } + } + + // Author tokens at [registration:author:*]. + if ($author_tokens = $token_service->findWithPrefix($tokens, 'author')) { + $data = ['user' => $registration->getAuthor()]; + $replacements += $token_service->generate('user', $author_tokens, $data, $options, $bubbleable_metadata); + } + + // Date created tokens at [registration:created:*]. + if ($created_tokens = $token_service->findWithPrefix($tokens, 'created')) { + $data = ['date' => $registration->getCreatedTime()]; + $replacements += $token_service->generate('date', $created_tokens, $data, $options, $bubbleable_metadata); + } + + // Date changed tokens at [registration:changed:*]. + if ($changed_tokens = $token_service->findWithPrefix($tokens, 'changed')) { + $data = ['date' => $registration->getChangedTime()]; + $replacements += $token_service->generate('date', $changed_tokens, $data, $options, $bubbleable_metadata); + } + + // Date completed tokens at [registration:completed:*]. + if ($completed_tokens = $token_service->findWithPrefix($tokens, 'completed')) { + $data = ['date' => $registration->getCompletedTime()]; + $replacements += $token_service->generate('date', $completed_tokens, $data, $options, $bubbleable_metadata); + } + + // Host entity tokens at [registration:entity:*]. + if ($entity_tokens = $token_service->findWithPrefix($tokens, 'entity')) { + if ($entity = $registration->getHostEntity()?->getEntity()) { + $entity_type_id = $entity->getEntityTypeId(); + $data = [$entity_type_id => $entity]; + $replacements += $token_service->generate($entity_type_id, $entity_tokens, $data, $options, $bubbleable_metadata); + } + } + + // User tokens at [registration:user:*]. + if ($user_tokens = $token_service->findWithPrefix($tokens, 'user')) { + $data = ['user' => $registration->getUser()]; + $replacements += $token_service->generate('user', $user_tokens, $data, $options, $bubbleable_metadata); + } + } + + return $replacements; +} diff --git a/tests/src/Kernel/RegistrationTokensTest.php b/tests/src/Kernel/RegistrationTokensTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9c7caba7032086862578be881da97d9f9ae9303d --- /dev/null +++ b/tests/src/Kernel/RegistrationTokensTest.php @@ -0,0 +1,77 @@ +<?php + +namespace Drupal\Tests\registration\Kernel; + +use Drupal\Core\Utility\Token; +use Drupal\Tests\registration\Traits\NodeCreationTrait; +use Drupal\Tests\registration\Traits\RegistrationCreationTrait; + +/** + * Tests registration tokens. + * + * @group registration + */ +class RegistrationTokensTest extends RegistrationKernelTestBase { + + use NodeCreationTrait; + use RegistrationCreationTrait; + + /** + * The token service. + */ + protected Token $tokenService; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->tokenService = $this->container->get('token'); + } + + /** + * Tests token generation and chaining. + */ + public function testRegistrationTokens() { + $node = $this->createAndSaveNode(); + $registration = $this->createRegistration($node); + $registration->set('anon_mail', 'test@example.org'); + $registration->save(); + + // Simple tokens. + $test_data = [ + '[registration:id]' => '1', + '[registration:count]' => '1', + '[registration:label]' => 'Registration #1 for My event', + '[registration:mail]' => 'test@example.org', + '[registration:state]' => 'Pending', + '[registration:type]' => 'conference', + '[registration:type-name]' => 'Conference', + ]; + + $token_data = [ + 'registration' => $registration, + ]; + + foreach ($test_data as $token => $expected_value) { + $token_replaced = $this->tokenService->replace($token, $token_data); + $this->assertEquals($token_replaced, $expected_value); + } + + // Chained host entity tokens. + $test_data = [ + '[registration:entity]' => 'My event', + '[registration:entity:nid]' => '1', + '[registration:entity:title]' => 'My event', + '[registration:entity:type]' => 'event', + '[registration:entity:type-name]' => 'Event', + ]; + + foreach ($test_data as $token => $expected_value) { + $token_replaced = $this->tokenService->replace($token, $token_data); + $this->assertEquals($token_replaced, $expected_value); + } + } + +}