From 6e56de0706df4050cb011c72f674fee556c2cdf1 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Wed, 30 Aug 2023 12:50:17 +1200 Subject: [PATCH] Add contribution page tokens to contribution tokens --- CRM/Contact/Tokens.php | 4 ++ CRM/Contribute/DAO/ContributionPage.php | 7 +++- CRM/Contribute/Tokens.php | 21 +++++++++- CRM/Core/EntityTokens.php | 14 +++++++ CRM/Core/I18n/SchemaStructure.php | 4 +- .../CRM/Utils/TokenConsistencyTest.php | 39 ++++++++++++++++++- xml/schema/Contribute/ContributionPage.xml | 5 +++ 7 files changed, 90 insertions(+), 4 deletions(-) diff --git a/CRM/Contact/Tokens.php b/CRM/Contact/Tokens.php index 97d87b2d93b1..232f8661a138 100644 --- a/CRM/Contact/Tokens.php +++ b/CRM/Contact/Tokens.php @@ -641,6 +641,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => 'String', + 'input_type' => NULL, 'audience' => 'user', ], 'employer_id.display_name' => [ @@ -659,6 +660,7 @@ protected function getBespokeTokens(): array { 'api_v3' => 'world_region', 'options' => NULL, 'data_type' => 'String', + 'input_type' => 'Text', 'advertised_name' => 'world_region', 'audience' => 'user', ], @@ -669,6 +671,7 @@ protected function getBespokeTokens(): array { 'type' => 'Field', 'options' => NULL, 'data_type' => 'String', + 'input_type' => 'Text', 'audience' => 'sysadmin', ], // this gets forced out if we specify individual fields @@ -678,6 +681,7 @@ protected function getBespokeTokens(): array { 'type' => 'Field', 'options' => NULL, 'data_type' => 'String', + 'input_type' => 'Text', 'audience' => 'sysadmin', ], ]; diff --git a/CRM/Contribute/DAO/ContributionPage.php b/CRM/Contribute/DAO/ContributionPage.php index 6cc64df78af1..7ce4c8cc8511 100644 --- a/CRM/Contribute/DAO/ContributionPage.php +++ b/CRM/Contribute/DAO/ContributionPage.php @@ -6,7 +6,7 @@ * * Generated from xml/schema/CRM/Contribute/ContributionPage.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:765f5bf08dbacf12c3d292837d718c39) + * (GenCodeChecksum:84e81e764d43c0d0116ae54d90a18a84) */ /** @@ -904,6 +904,8 @@ public static function &fields() { 'type' => CRM_Utils_Type::T_TEXT, 'title' => ts('Pay Later Receipt'), 'description' => ts('The receipt sent to the user instead of the normal receipt text'), + 'rows' => 8, + 'cols' => 60, 'usage' => [ 'import' => FALSE, 'export' => FALSE, @@ -915,6 +917,9 @@ public static function &fields() { 'entity' => 'ContributionPage', 'bao' => 'CRM_Contribute_BAO_ContributionPage', 'localizable' => 1, + 'html' => [ + 'type' => 'RichTextEditor', + ], 'add' => '2.0', ], 'is_partial_payment' => [ diff --git a/CRM/Contribute/Tokens.php b/CRM/Contribute/Tokens.php index 39f87b123100..5af208998fcd 100644 --- a/CRM/Contribute/Tokens.php +++ b/CRM/Contribute/Tokens.php @@ -10,6 +10,7 @@ +--------------------------------------------------------------------+ */ +use Civi\Api4\ContributionPage; use Civi\Api4\ContributionRecur; /** @@ -55,9 +56,26 @@ public function getCurrencyFieldName() { */ protected function getRelatedTokens(): array { $tokens = []; - if (!in_array('ContributionRecur', array_keys(\Civi::service('action_object_provider')->getEntities()))) { + // Check to make sure CiviContribute is enabled, just in case it remains registered. Eventually this will be moved to the CiviContribute extension + // and this check can hopefully be removed (as long as caching on enable / disable doesn't explode our brains and / or crash the site). + if (!array_key_exists('Contribution', \Civi::service('action_object_provider')->getEntities())) { return $tokens; } + // Ideally we would derive this from 'usage' - but it looks like adding the usage data + // was quite a bit of work & didn't leave the energy to implement - esp expose for + // where clauses (also, it feels like 'hidden+token' would be a good usage. + $tokenList = ['frontend_title', 'pay_later_text', 'pay_later_receipt', 'is_share', 'receipt_text']; + $contributionPageTokens = ContributionPage::getFields(FALSE)->addWhere('name', 'IN', $tokenList)->execute(); + foreach ($contributionPageTokens as $contributionPageToken) { + $tokens['contribution_page_id.' . $contributionPageToken['name']] = [ + 'title' => $contributionPageToken['title'], + 'name' => 'contribution_page_id.' . $contributionPageToken['name'], + 'type' => 'mapped', + 'data_type' => $contributionPageToken['data_type'], + 'input_type' => $contributionPageToken['input_type'], + 'audience' => $contributionPageToken['name'] === 'is_share' ? 'hidden' : 'user', + ]; + } $hiddenTokens = ['modified_date', 'create_date', 'trxn_id', 'invoice_id', 'is_test', 'payment_token_id', 'payment_processor_id', 'payment_instrument_id', 'cycle_day', 'installments', 'processor_id', 'next_sched_contribution_date', 'failure_count', 'failure_retry_date', 'auto_renew', 'is_email_receipt', 'contribution_status_id']; $contributionRecurFields = ContributionRecur::getFields(FALSE)->setLoadOptions(TRUE)->execute(); foreach ($contributionRecurFields as $contributionRecurField) { @@ -67,6 +85,7 @@ protected function getRelatedTokens(): array { 'type' => 'mapped', 'options' => $contributionRecurField['options'] ?? NULL, 'data_type' => $contributionRecurField['data_type'], + 'input_type' => $contributionRecurField['input_type'], 'audience' => in_array($contributionRecurField['name'], $hiddenTokens) ? 'hidden' : 'user', ]; } diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php index a5e80be22394..d2917f960f93 100644 --- a/CRM/Core/EntityTokens.php +++ b/CRM/Core/EntityTokens.php @@ -138,9 +138,23 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) Civi::log()->info('invalid date token'); } } + if ($this->isHTMLTextField($field)) { + return $row->format('text/html')->tokens($entity, $field, (string) $fieldValue); + } $row->format('text/plain')->tokens($entity, $field, (string) $fieldValue); } + /** + * Is the text stored in html format. + * + * @param string $fieldName + * + * @return bool + */ + public function isHTMLTextField(string $fieldName): bool { + return $this->getMetadataForField($fieldName)['input_type'] === 'RichTextEditor'; + } + /** * Metadata about the entity fields. * diff --git a/CRM/Core/I18n/SchemaStructure.php b/CRM/Core/I18n/SchemaStructure.php index cd0b0939f5ea..3dc519a76770 100644 --- a/CRM/Core/I18n/SchemaStructure.php +++ b/CRM/Core/I18n/SchemaStructure.php @@ -447,7 +447,9 @@ public static function &widgets() { 'type' => "Text", ], 'pay_later_receipt' => [ - 'type' => "Text", + 'type' => "RichTextEditor", + 'rows' => "8", + 'cols' => "60", ], 'initial_amount_label' => [ 'label' => "Initial Amount Label", diff --git a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php index d33bb0a979fe..3714f772777a 100644 --- a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php +++ b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php @@ -195,11 +195,48 @@ public function testContributionRecurTokenConsistency(): void { $tokenString = $this->getTokenString(array_keys($this->getContributionRecurTokens())); $tokenProcessor->addMessage('html', $tokenString, 'text/plain'); - $tokenProcessor->addRow(['contribution_recurId' => $this->getContributionRecurID()]); $tokenProcessor->evaluate(); $this->assertEquals($this->getExpectedContributionRecurTokenOutPut(), $tokenProcessor->getRow(0)->render('html')); } + /** + * Test contribution tokens pulled from the contribution page. + */ + public function testContributionPageTokens(): void { + $tokenValues = [ + 'frontend_title' => 'public title', + 'pay_later_text' => 'pay later text', + 'pay_later_receipt' => '

first line

second line

', + 'is_share' => TRUE, + 'receipt_text' => "Text in\n non html", + ]; + $tokens = []; + foreach (array_keys($tokenValues) as $token) { + $tokens[] = '{contribution.contribution_page_id.' . $token . '}'; + } + $tokenString = trim($this->getTokenString($tokens)); + $this->contributionPageCreate($tokenValues); + + $tokenProcessor = $this->getTokenProcessor(['schema' => ['contributionId']]); + $tokenProcessor->addMessage('text', $tokenString, 'text/plain'); + $tokenProcessor->addMessage('html', $tokenString, 'text/html'); + $tokenProcessor->addRow(['contributionId' => $this->contributionCreate(['contribution_page_id' => $this->ids['ContributionPage']['test'], 'contact_id' => $this->individualCreate()])]); + $tokenProcessor->evaluate(); + $this->assertEquals('contribution.contribution_page_id.frontend_title :public title +contribution.contribution_page_id.pay_later_text :pay later text +contribution.contribution_page_id.pay_later_receipt :

first line

second line

+contribution.contribution_page_id.is_share :1 +contribution.contribution_page_id.receipt_text :Text in + non html', $tokenProcessor->getRow(0)->render('html')); + $this->assertEquals('contribution.contribution_page_id.frontend_title :public title +contribution.contribution_page_id.pay_later_text :pay later text +contribution.contribution_page_id.pay_later_receipt :first linesecond line +contribution.contribution_page_id.is_share :1 +contribution.contribution_page_id.receipt_text :Text in + non html', $tokenProcessor->getRow(0)->render('text')); + + } + /** * Test that contribution recur tokens are consistently rendered. */ diff --git a/xml/schema/Contribute/ContributionPage.xml b/xml/schema/Contribute/ContributionPage.xml index c0532859bf6e..c0e030b048f2 100644 --- a/xml/schema/Contribute/ContributionPage.xml +++ b/xml/schema/Contribute/ContributionPage.xml @@ -222,6 +222,11 @@ Pay Later Receipt text true + + RichTextEditor + 8 + 60 + The receipt sent to the user instead of the normal receipt text 2.0