From d82914fcb2c50c881cf3ad8d5452ca360ad04a43 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 11 Oct 2021 11:25:58 +1300 Subject: [PATCH] Use money formatting for currency --- CRM/Core/EntityTokens.php | 10 ++++++- Civi/Token/TokenCompatSubscriber.php | 6 ++++- Civi/Token/TokenProcessor.php | 12 ++++++++- Civi/Token/TokenRow.php | 5 +++- .../Contribute/ActionMapping/ByTypeTest.php | 16 ++++++------ .../CRM/Contribute/Form/Task/EmailTest.php | 4 +-- .../Form/Task/PDFLetterCommonTest.php | 9 +++---- .../Form/UpdateSubscriptionTest.php | 2 +- .../CRM/Utils/TokenConsistencyTest.php | 26 +++++++++++++++++-- 9 files changed, 68 insertions(+), 22 deletions(-) diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php index c1cb2fcbc414..f995bc365050 100644 --- a/CRM/Core/EntityTokens.php +++ b/CRM/Core/EntityTokens.php @@ -16,6 +16,7 @@ use Civi\Token\TokenRow; use Civi\ActionSchedule\Event\MailingQueryEvent; use Civi\Token\TokenProcessor; +use Brick\Money\Money; /** * Class CRM_Core_EntityTokens @@ -123,8 +124,15 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) return $row->customToken($entity, \CRM_Core_BAO_CustomField::getKeyID($field), $this->getFieldValue($row, 'id')); } if ($this->isMoneyField($field)) { + $currency = $this->getCurrency($row); + if (!$currency) { + // too hard basket for now - just do what we always did. + return $row->format('text/plain')->tokens($entity, $field, + \CRM_Utils_Money::format($fieldValue, $currency)); + } return $row->format('text/plain')->tokens($entity, $field, - \CRM_Utils_Money::format($fieldValue, $this->getCurrency($row))); + Money::of($fieldValue, $currency)); + } if ($this->isDateField($field)) { try { diff --git a/Civi/Token/TokenCompatSubscriber.php b/Civi/Token/TokenCompatSubscriber.php index 33e394f3cdfc..6274d8f29c39 100644 --- a/Civi/Token/TokenCompatSubscriber.php +++ b/Civi/Token/TokenCompatSubscriber.php @@ -3,6 +3,7 @@ use Civi\Token\Event\TokenRenderEvent; use Civi\Token\Event\TokenValueEvent; +use Money\Money; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -69,7 +70,10 @@ public function onRender(TokenRenderEvent $e): void { if ($useSmarty) { $smartyVars = []; foreach ($e->context['smartyTokenAlias'] ?? [] as $smartyName => $tokenName) { - $smartyVars[$smartyName] = \CRM_Utils_Array::pathGet($e->row->tokens, explode('.', $tokenName)); + $smartyVars[$smartyName] = \CRM_Utils_Array::pathGet($e->row->tokens, explode('.', $tokenName), $e->context['locale'] ?? NULL); + if ($smartyVars[$smartyName] instanceof \Brick\Money\Money) { + $smartyVars[$smartyName] = \Civi::format()->money($smartyVars[$smartyName]->getAmount(), $smartyVars[$smartyName]->getCurrency()); + } } \CRM_Core_Smarty::singleton()->pushScope($smartyVars); try { diff --git a/Civi/Token/TokenProcessor.php b/Civi/Token/TokenProcessor.php index f2e32add9168..0451b2ae531e 100644 --- a/Civi/Token/TokenProcessor.php +++ b/Civi/Token/TokenProcessor.php @@ -1,6 +1,7 @@ $enqueue, ], $m[3]); if ($unmatched) { - throw new \CRM_Core_Exception("Malformed token parameters (" . $m[0] . ")"); + throw new \CRM_Core_Exception('Malformed token parameters (' . $m[0] . ')'); } } return $callback($m[0] ?? NULL, $m[1] ?? NULL, $m[2] ?? NULL, $filterParts); @@ -458,6 +459,10 @@ private function filterTokenValue($value, ?array $filter, TokenRow $row) { } } + if ($value instanceof Money && $filter === NULL) { + $filter = ['crmMoney']; + } + switch ($filter[0] ?? NULL) { case NULL: return $value; @@ -468,6 +473,11 @@ private function filterTokenValue($value, ?array $filter, TokenRow $row) { case 'lower': return mb_strtolower($value); + case 'crmMoney': + if ($value instanceof Money) { + return \Civi::format()->money($value->getAmount(), $value->getCurrency()); + } + case 'crmDate': if ($value instanceof \DateTime) { // @todo cludgey. diff --git a/Civi/Token/TokenRow.php b/Civi/Token/TokenRow.php index 680e7c0e3693..11be3a3ba1ff 100644 --- a/Civi/Token/TokenRow.php +++ b/Civi/Token/TokenRow.php @@ -1,8 +1,11 @@ Plain. foreach ($htmlTokens as $entity => $values) { foreach ($values as $field => $value) { - if (!$value instanceof \DateTime) { + if (!$value instanceof \DateTime && !$value instanceof Money) { $value = html_entity_decode(strip_tags($value)); } if (!isset($textTokens[$entity][$field])) { diff --git a/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php b/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php index fa2a50b8dbc9..52f74d502f9a 100644 --- a/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php +++ b/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php @@ -311,10 +311,10 @@ public function testTokenRendering(): void { 'payment instrument id = 4', 'payment instrument name = Check', 'payment instrument label = Check', - 'non_deductible_amount = € 10.00', - 'total_amount = € 100.00', - 'net_amount = € 95.00', - 'fee_amount = € 5.00', + 'non_deductible_amount = €10.00', + 'total_amount = €100.00', + 'net_amount = €95.00', + 'fee_amount = €5.00', 'campaign_id = 1', 'campaign name = big_campaign', 'campaign label = Campaign', @@ -362,10 +362,10 @@ public function testTokenRendering(): void { 'payment instrument label = Check', 'legacy source SSF', 'source SSF', - 'non_deductible_amount = € 10.00', - 'total_amount = € 100.00', - 'net_amount = € 95.00', - 'fee_amount = € 5.00', + 'non_deductible_amount = €10.00', + 'total_amount = €100.00', + 'net_amount = €95.00', + 'fee_amount = €5.00', 'campaign_id = 1', 'campaign name = big_campaign', 'campaign label = Campaign', diff --git a/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php b/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php index e3cdc9ffc7ef..8211eae5a628 100644 --- a/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php +++ b/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php @@ -70,10 +70,10 @@ public function testEmailTokens(): void { $form->buildForm(); $this->assertEquals('

--Benny, Benny', $form->_defaultValues['html_message']); $form->postProcess(); - $mut->assertSubjects(['Mr. Anthony Anderson II $ 999.00', 'Mr. Elton Anderson II $ 100.00']); + $mut->assertSubjects(['Mr. Anthony Anderson II $999.00', 'Mr. Elton Anderson II $100.00']); $mut->checkAllMailLog([ 'Subject: Mr. Anthony Anderson II', - '$ 999.0', + '$999.0', 'Default Domain Name', 'Donation soy', 'Donation ranch', diff --git a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php index 54250b806d73..bfc2573b06d5 100644 --- a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php +++ b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php @@ -198,7 +198,6 @@ public function testPostProcess(): void { $this->createLoggedInUser();; foreach (['docx', 'odt'] as $docType) { $formValues = [ - 'is_unit_test' => TRUE, 'group_by' => NULL, 'document_file' => [ 'name' => __DIR__ . "/sample_documents/Template.$docType", @@ -297,10 +296,10 @@ public function testAllContributionTokens(): void {
id : 1 -total_amount : € 9,999.99 -fee_amount : € 1,111.11 -net_amount : € 7,777.78 -non_deductible_amount : € 2,222.22 +total_amount : €9,999.99 +fee_amount : €1,111.11 +net_amount : €7,777.78 +non_deductible_amount : €2,222.22 receive_date : July 20th, 2018 payment_instrument_id:label : Check trxn_id : 1234 diff --git a/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php b/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php index d758acedfe47..7cb3d3ee529f 100644 --- a/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php +++ b/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php @@ -50,7 +50,7 @@ public function getExpectedMailStrings(): array { 'Return-Path: bob@example.org', 'Dear Anthony,', 'Your recurring contribution has been updated as requested:', - 'Recurring contribution is for $ 10.00, every 1 month(s) for 12 installments.', + 'Recurring contribution is for $10.00, every 1 month(s) for 12 installments.', 'If you have questions please contact us at "Bob" .', ]; } diff --git a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php index e5878ab7848e..50176589f047 100644 --- a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php +++ b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php @@ -206,6 +206,28 @@ public function testContributionRecurTokenConsistency(): void { $this->assertEquals($this->getExpectedContributionRecurTokenOutPut(), $tokenProcessor->getRow(0)->render('html')); } + /** + * Test money format tokens can respect passed in locale. + */ + public function testMoneyFormat(): void { + // Our 'migration' off configured thousand separators at the moment is a define. + putenv('IGNORE_SEPARATOR_CONFIG=1'); + $this->createLoggedInUser(); + $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [ + 'controller' => __CLASS__, + 'smarty' => FALSE, + 'schema' => ['contribution_recurId'], + ]); + $tokenString = '{contribution_recur.amount}'; + $tokenProcessor->addMessage('html', $tokenString, 'text/plain'); + $tokenProcessor->addRow([ + 'contribution_recurId' => $this->getContributionRecurID(), + 'locale' => 'nb_NO', + ]); + $tokenProcessor->evaluate(); + $this->assertEquals('€ 5 990,99', $tokenProcessor->getRow(0)->render('html')); + } + /** * Get tokens that are not advertised via listTokens. * @@ -379,7 +401,7 @@ protected function getContributionRecurID(): int { */ protected function getExpectedContributionRecurTokenOutPut(): string { return 'contribution_recur.id :' . $this->getContributionRecurID() . ' -contribution_recur.amount :€ 5,990.99 +contribution_recur.amount :€5,990.99 contribution_recur.currency :EUR contribution_recur.frequency_unit :year contribution_recur.frequency_interval :2 @@ -533,7 +555,7 @@ protected function getExpectedParticipantTokenOutput(): string { participant.register_date :February 19th, 2007 participant.source :Wimbeldon participant.fee_level :steep -participant.fee_amount :$ 50.00 +participant.fee_amount :$50.00 participant.registered_by_id : participant.transferred_to_contact_id : participant.role_id:label :Attendee