From d568dbe080f3affbe88f216a28ab01b3107aadcd Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 13 Sep 2021 18:23:47 +1200 Subject: [PATCH] dev/core#2832 Extend Membership tokens to 'listen' and add test cover --- CRM/Core/EntityTokens.php | 32 +++++++++++++++- CRM/Member/BAO/MembershipType.php | 4 +- CRM/Member/Tokens.php | 37 ++++++------------- .../CRM/Utils/TokenConsistencyTest.php | 26 +++++++++++-- 4 files changed, 67 insertions(+), 32 deletions(-) diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php index 5226f5e9fe4a..d879efdc73c7 100644 --- a/CRM/Core/EntityTokens.php +++ b/CRM/Core/EntityTokens.php @@ -444,8 +444,38 @@ public function getCurrency($row): string { return CRM_Core_Config::singleton()->defaultCurrency; } + /** + * Get the fields required to prefetch the entity. + * + * @param \Civi\Token\Event\TokenValueEvent $e + * + * @return array + * @throws \API_Exception + */ public function getPrefetchFields(TokenValueEvent $e): array { - return array_intersect(array_merge($this->getActiveTokens($e), $this->getCurrencyFieldName(), ['id']), array_keys($this->getAllTokens())); + $allTokens = array_keys($this->getAllTokens()); + $requiredFields = array_intersect($this->getActiveTokens($e), $allTokens); + if (empty($requiredFields)) { + return []; + } + $requiredFields = array_merge($requiredFields, array_intersect($allTokens, array_merge(['id'], $this->getCurrencyFieldName()))); + foreach ($this->getDependencies() as $field => $required) { + if (in_array($field, $this->getActiveTokens($e), TRUE)) { + foreach ((array) $required as $key) { + $requiredFields[] = $key; + } + } + } + return $requiredFields; + } + + /** + * Get fields which need to be returned to render another token. + * + * @return array + */ + public function getDependencies(): array { + return []; } } diff --git a/CRM/Member/BAO/MembershipType.php b/CRM/Member/BAO/MembershipType.php index a0b599f282a0..1ec67d2e16a5 100644 --- a/CRM/Member/BAO/MembershipType.php +++ b/CRM/Member/BAO/MembershipType.php @@ -818,8 +818,8 @@ public static function updateAllPriceFieldValue($membershipTypeId, $params) { * List of membershipType details keyed by membershipTypeID * @throws \CiviCRM_API3_Exception */ - public static function getAllMembershipTypes() { - $cacheString = __CLASS__ . __FUNCTION__ . CRM_Core_Config::domainID(); + public static function getAllMembershipTypes(): array { + $cacheString = __CLASS__ . __FUNCTION__ . CRM_Core_Config::domainID() . '_' . CRM_Core_I18n::getLocale(); if (!Civi::cache('metadata')->has($cacheString)) { $types = civicrm_api3('MembershipType', 'get', ['options' => ['limit' => 0, 'sort' => 'weight']])['values']; $taxRates = CRM_Core_PseudoConstant::getTaxRates(); diff --git a/CRM/Member/Tokens.php b/CRM/Member/Tokens.php index 9db8a15420ae..ff18e93ce067 100644 --- a/CRM/Member/Tokens.php +++ b/CRM/Member/Tokens.php @@ -55,38 +55,25 @@ public function getAllTokens(): array { /** * @inheritDoc - */ - public function checkActive(\Civi\Token\TokenProcessor $processor) { - // Extracted from scheduled-reminders code. See the class description. - return !empty($processor->context['actionMapping']) - && $processor->context['actionMapping']->getEntity() === 'civicrm_membership'; - } - - /** - * Alter action schedule query. - * - * @param \Civi\ActionSchedule\Event\MailingQueryEvent $e - */ - public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent $e): void { - if ($e->mapping->getEntity() !== 'civicrm_membership') { - return; - } - parent::alterActionScheduleQuery($e); - $e->query - ->select('mt.minimum_fee as ' . $this->getEntityAlias() . 'fee') - ->join('mt', '!casMailingJoinType civicrm_membership_type mt ON e.membership_type_id = mt.id'); - } - - /** - * @inheritDoc + * @throws \CiviCRM_API3_Exception */ public function evaluateToken(\Civi\Token\TokenRow $row, $entity, $field, $prefetch = NULL) { if ($field === 'fee') { - $row->tokens($entity, $field, \CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($this->getFieldValue($row, $field))); + $membershipType = CRM_Member_BAO_MembershipType::getMembershipType($this->getFieldValue($row, 'membership_type_id')); + $row->tokens($entity, $field, \CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($membershipType['minimum_fee'])); } else { parent::evaluateToken($row, $entity, $field, $prefetch); } } + /** + * Get fields which need to be returned to render another token. + * + * @return array + */ + public function getDependencies(): array { + return ['fee' => 'membership_type_id']; + } + } diff --git a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php index f1ff7b67c0d4..6e7e5cfc0ee1 100644 --- a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php +++ b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php @@ -45,14 +45,13 @@ class CRM_Utils_TokenConsistencyTest extends CiviUnitTestCase { * @throws \CRM_Core_Exception */ public function tearDown(): void { - $this->quickCleanup(['civicrm_case', 'civicrm_case_type']); + $this->quickCleanup(['civicrm_case', 'civicrm_case_type'], TRUE); parent::tearDown(); } /** * Test that case tokens are consistently rendered. * - * @throws \API_Exception * @throws \CiviCRM_API3_Exception */ public function testCaseTokenConsistency(): void { @@ -367,7 +366,8 @@ public function testMembershipTokenConsistency(): void { $this->restoreMembershipTypes(); $this->createCustomGroupWithFieldOfType(['extends' => 'Membership']); $tokens = CRM_Core_SelectValues::membershipTokens(); - $this->assertEquals($this->getMembershipTokens(), $tokens); + $expectedTokens = $this->getMembershipTokens(); + $this->assertEquals($expectedTokens, $tokens); $newStyleTokens = "\n{membership.status_id:label}\n{membership.membership_type_id:label}\n"; $tokenString = $newStyleTokens . implode("\n", array_keys($this->getMembershipTokens())); @@ -393,7 +393,25 @@ public function testMembershipTokenConsistency(): void { 'body_html' => $tokenString, ]); $this->callAPISuccess('job', 'send_reminder', []); - $mut->checkMailLog([$this->getExpectedMembershipTokenOutput() . "\nmy field"]); + $expected = $this->getExpectedMembershipTokenOutput(); + // Unlike the legacy method custom fields are resolved by the processor. + $expected .= "\nmy field"; + $mut->checkMailLog([$expected]); + + $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [ + 'controller' => __CLASS__, + 'smarty' => FALSE, + 'schema' => ['membershipId'], + ]); + $tokens = $tokenProcessor->listTokens(); + // Add in custom tokens as token processor supports these. + $expectedTokens['{membership.custom_1}'] = 'Enter text here :: Group with field text'; + $this->assertEquals($expectedTokens, $tokens); + $tokenProcessor->addMessage('html', $tokenString, 'text/plain'); + $tokenProcessor->addRow(['membershipId' => $this->getMembershipID()]); + $tokenProcessor->evaluate(); + $this->assertEquals($expected, $tokenProcessor->getRow(0)->render('html')); + } /**