Regression fix - be tolerant with smarty money
authorEileen McNaughton <emcnaughton@wikimedia.org>
Tue, 8 Feb 2022 03:38:05 +0000 (16:38 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Tue, 8 Feb 2022 03:39:11 +0000 (16:39 +1300)
I've seen issues in extended reports and in core where already-formatted money from
custom fields is formatted again in the smarty layer and, with recent changes
, throwing an exception when the money is greater than 1000
(because the presence of a comma makes it invalid). This adds tolerance
that seems consistent with prior code

CRM/Core/Smarty/plugins/modifier.crmMoney.php
Civi/Core/Format.php

index ec5a6a93b6f485d4ef0d9f19ddf0d39689c28869..4a764b9669baf62df3bd23987b75fdc02500a245 100644 (file)
  *
  * @return string
  *   formatted monetary amount
- *
- * @throws \CRM_Core_Exception
  */
 function smarty_modifier_crmMoney($amount, ?string $currency = NULL): string {
-  return Civi::format()->money($amount, $currency);
+  try {
+    return Civi::format()->money($amount, $currency);
+  }
+  catch (CRM_Core_Exception $e) {
+    // @todo escalate this to a deprecation notice. It turns out to be depressingly
+    // common for us to double process amount strings - if they are > 1000 then
+    // they wind up throwing an exception in the money function.
+    // It would be more correct to format in the smarty layer, only.
+    Civi::log()->warning('Invalid amount passed in as money - {money}', ['money' => $amount]);
+    return $amount;
+  }
 }
index 57bdea8c542148d1e93b087c67f6e1b42880a999..582727cce57a1dfa81fd04bf16e7f2d52b038d35 100644 (file)
@@ -30,6 +30,8 @@ class Format {
    *
    * @return string
    *
+   * @throws \CRM_Core_Exception
+   *
    * @noinspection PhpDocMissingThrowsInspection
    * @noinspection PhpUnhandledExceptionInspection
    */
@@ -61,6 +63,7 @@ class Format {
    *   add any padding.
    *
    * @return string
+   * @throws \CRM_Core_Exception
    */
   public function number($amount, ?string $locale = NULL, array $attributes = [
     NumberFormatter::MIN_FRACTION_DIGITS => 0,
@@ -214,7 +217,7 @@ class Format {
     }
     // Verify the amount is a number or numeric string/object.
     // We cast to string because it can be a BigDecimal object.
-    elseif ($amount === TRUE || !is_numeric((string) $amount)) {
+    if ($amount === TRUE || !is_numeric((string) $amount)) {
       throw new \CRM_Core_Exception('Invalid value for type money');
     }
     return (string) $amount;