don't try to convert blanks
authordemeritcowboy <demeritcowboy@hotmail.com>
Tue, 2 Mar 2021 21:32:32 +0000 (16:32 -0500)
committerdemeritcowboy <demeritcowboy@hotmail.com>
Tue, 2 Mar 2021 21:32:32 +0000 (16:32 -0500)
CRM/Case/Form/CustomData.php
api/v3/CustomValue.php
tests/phpunit/CRM/Case/Form/CustomDataTest.php [new file with mode: 0644]

index ec2f6ddb04ce0807e4f73d7133ef8071cc6bd82d..f77fadb5c770bc208956117c6d92ed7bb63fea79 100644 (file)
@@ -146,7 +146,7 @@ class CRM_Case_Form_CustomData extends CRM_Core_Form {
     $formattedDetails = [];
     foreach ($params as $customField => $newCustomValue) {
       if (substr($customField, 0, 7) == 'custom_') {
-        if ($this->_defaults[$customField] == $newCustomValue) {
+        if (($this->_defaults[$customField] ?? '') === $newCustomValue) {
           // Don't show values that did not change
           continue;
         }
index 34f96a9f2daa350e2c3115255a74d9a0b3ccaf27..7c2a5a790b040fdff9bbfb1b918d1a2b99bcadf9 100644 (file)
@@ -399,7 +399,7 @@ function _civicrm_api3_custom_value_getdisplayvalue_spec(&$spec) {
   ];
   $spec['custom_field_value'] = [
     'title' => 'Custom Field value',
-    'description' => 'Specify the value of the custom field to return as displayed value',
+    'description' => 'Specify the value of the custom field to return as displayed value, or omit to use the current value.',
     'type' => CRM_Utils_Type::T_STRING,
     'api.required' => 0,
   ];
@@ -414,14 +414,15 @@ function _civicrm_api3_custom_value_getdisplayvalue_spec(&$spec) {
  * @throws \CiviCRM_API3_Exception
  */
 function civicrm_api3_custom_value_getdisplayvalue($params) {
-  if (empty($params['custom_field_value'])) {
+  // Null or missing means use the current db value, but treat '0', 0, and '' as legitimate values to look up.
+  if (($params['custom_field_value'] ?? NULL) === NULL) {
     $params['custom_field_value'] = civicrm_api3('CustomValue', 'getsingle', [
       'return' => ["custom_{$params['custom_field_id']}"],
       'entity_id' => $params['entity_id'],
     ]);
     $params['custom_field_value'] = $params['custom_field_value']['latest'];
   }
-  $values[$params['custom_field_id']]['display'] = CRM_Core_BAO_CustomField::displayValue($params['custom_field_value'], $params['custom_field_id'], CRM_Utils_Array::value('entity_id', $params));
+  $values[$params['custom_field_id']]['display'] = CRM_Core_BAO_CustomField::displayValue($params['custom_field_value'], $params['custom_field_id'], $params['entity_id'] ?? NULL);
   $values[$params['custom_field_id']]['raw'] = $params['custom_field_value'];
   return civicrm_api3_create_success($values, $params, 'CustomValue', 'getdisplayvalue');
 }
diff --git a/tests/phpunit/CRM/Case/Form/CustomDataTest.php b/tests/phpunit/CRM/Case/Form/CustomDataTest.php
new file mode 100644 (file)
index 0000000..112de1e
--- /dev/null
@@ -0,0 +1,333 @@
+<?php
+require_once 'CiviTest/CiviCaseTestCase.php';
+
+/**
+ * Class CRM_Case_Form_CustomDataTest
+ * @group headless
+ */
+class CRM_Case_Form_CustomDataTest extends CiviCaseTestCase {
+
+  protected $custom_group;
+
+  public function setUp() {
+    parent::setUp();
+    $this->custom_group = $this->customGroupCreate(['extends' => 'Case']);
+    $this->custom_group = $this->custom_group['values'][$this->custom_group['id']];
+  }
+
+  /**
+   * Test that changes to custom fields on cases generate the correct details
+   * body for ChangeCustomData.
+   *
+   * @dataProvider customDataProvider
+   *
+   * @param array $input
+   * @param array $expected
+   */
+  public function testChangeCustomDataFormattedDetails(array $input, array $expected) {
+    // set up custom field, with any overrides from input params
+    $custom_field = $this->callAPISuccess('custom_field', 'create', array_merge([
+      'custom_group_id' => $this->custom_group['id'],
+      'label' => 'What?',
+      'data_type' => 'String',
+      'html_type' => 'Text',
+      'is_active' => 1,
+    ], $input['custom_field_params']));
+    $custom_field = $custom_field['values'][$custom_field['id']];
+
+    // set up case and set the custom field initial value
+    $client_id = $this->individualCreate([], 0, TRUE);
+    $caseObj = $this->createCase($client_id, $this->_loggedInUser);
+    if (isset($input['custom_field_oldvalue'])) {
+      $this->callAPISuccess('CustomValue', 'create', [
+        "custom_{$custom_field['id']}" => $input['custom_field_oldvalue'],
+        'entity_id' => $caseObj->id,
+      ]);
+    }
+
+    // set up form
+    $form = $this->getFormObject('CRM_Case_Form_CustomData');
+    $form->set('groupID', $this->custom_group['id']);
+    $form->set('entityID', $caseObj->id);
+    $form->set('subType', $this->caseTypeId);
+    $form->set('cid', $client_id);
+    $form->preProcess();
+
+    // We need to do money conversion here because to do the creation above it
+    // needs to be in machine format, but then for the form stuff it needs to
+    // be in user format.
+    if (($input['custom_field_params']['data_type'] ?? '') === 'Money' && CRM_Core_I18n::singleton()->getLocale() !== 'en_US') {
+      $expected['string'] = $this->convertCurrency($expected['string']);
+      if (isset($input['custom_field_oldvalue'])) {
+        $input['custom_field_oldvalue'] = $this->convertCurrency($input['custom_field_oldvalue']);
+      }
+      $input['custom_field_newvalue'] = $this->convertCurrency($input['custom_field_newvalue']);
+    }
+
+    // Simulate an edit with formValues.
+    // The suffix is always going to be '1' since we created it above and it's
+    // the first entry in the custom_value_XX table. If it doesn't exist yet
+    // then our new entry will still be the first and will have suffix 1.
+    $custom_field_name = "custom_{$custom_field['id']}_1";
+    $formValues = [$custom_field_name => $input['custom_field_newvalue']];
+
+    // compute and compare
+    $output = $form->formatCustomDataChangesForDetail($formValues);
+    $this->assertEquals($expected['string'], $output);
+  }
+
+  /**
+   * Same as testChangeCustomDataFormattedDetails but in a different locale.
+   *
+   * @dataProvider customDataProvider
+   *
+   * @param array $input
+   * @param array $expected
+   */
+  public function testChangeCustomDataFormattedDetailsLocale(array $input, array $expected) {
+    CRM_Core_I18n::singleton()->setLocale('it_IT');
+    CRM_Core_Config::singleton()->defaultCurrency = 'EUR';
+    CRM_Core_Config::singleton()->monetaryThousandSeparator = ' ';
+    CRM_Core_Config::singleton()->monetaryDecimalPoint = ',';
+
+    $this->testChangeCustomDataFormattedDetails($input, $expected);
+
+    CRM_Core_Config::singleton()->defaultCurrency = 'USD';
+    CRM_Core_Config::singleton()->monetaryThousandSeparator = ',';
+    CRM_Core_Config::singleton()->monetaryDecimalPoint = '.';
+    CRM_Core_I18n::singleton()->setLocale('en_US');
+  }
+
+  /**
+   * data provider for testChangeCustomDataFormattedDetails
+   *
+   * @return array
+   */
+  public function customDataProvider(): array {
+    return [
+      0 => [
+        'input' => [
+          'custom_field_params' => [
+            'html_type' => 'Select',
+            'option_values' => [
+              [
+                'name' => 'Red',
+                'label' => 'Red',
+                'value' => '1',
+                'is_active' => 1,
+                'weight' => 1,
+              ],
+              [
+                'name' => 'Green',
+                'label' => 'Green',
+                'value' => '2',
+                'is_active' => 1,
+                'weight' => 2,
+              ],
+            ],
+          ],
+          'custom_field_oldvalue' => '1',
+          'custom_field_newvalue' => '2',
+        ],
+        'expected' => [
+          'string' => 'What?: Red => Green',
+        ],
+      ],
+
+      1 => [
+        'input' => [
+          'custom_field_params' => [
+            'html_type' => 'Select',
+            'option_values' => [
+              [
+                'name' => 'Red',
+                'label' => 'Red',
+                'value' => '1',
+                'is_active' => 1,
+                'weight' => 1,
+              ],
+              [
+                'name' => 'Green',
+                'label' => 'Green',
+                'value' => '2',
+                'is_active' => 1,
+                'weight' => 2,
+              ],
+            ],
+          ],
+          'custom_field_oldvalue' => '',
+          'custom_field_newvalue' => '2',
+        ],
+        'expected' => [
+          'string' => 'What?:  => Green',
+        ],
+      ],
+
+      2 => [
+        'input' => [
+          'custom_field_params' => [
+            'html_type' => 'Select',
+            'option_values' => [
+              [
+                'name' => 'Red',
+                'label' => 'Red',
+                'value' => '1',
+                'is_active' => 1,
+                'weight' => 1,
+              ],
+              [
+                'name' => 'Green',
+                'label' => 'Green',
+                'value' => '2',
+                'is_active' => 1,
+                'weight' => 2,
+              ],
+            ],
+          ],
+          'custom_field_oldvalue' => '1',
+          'custom_field_newvalue' => '',
+        ],
+        'expected' => [
+          'string' => 'What?: Red => ',
+        ],
+      ],
+
+      3 => [
+        'input' => [
+          'custom_field_params' => [
+            'html_type' => 'Select',
+            'option_values' => [
+              [
+                'name' => 'Red',
+                'label' => 'Red',
+                'value' => '1',
+                'is_active' => 1,
+                'weight' => 1,
+              ],
+              [
+                'name' => 'Green',
+                'label' => 'Green',
+                'value' => '2',
+                'is_active' => 1,
+                'weight' => 2,
+              ],
+            ],
+          ],
+          // Note no old value, simulating as if we already have existing cases, but just added the field definition now.
+          'custom_field_newvalue' => '2',
+        ],
+        'expected' => [
+          'string' => 'What?:  => Green',
+        ],
+      ],
+
+      4 => [
+        'input' => [
+          'custom_field_params' => [
+            'data_type' => 'Money',
+          ],
+          'custom_field_oldvalue' => '1.23',
+          'custom_field_newvalue' => '2.34',
+        ],
+        'expected' => [
+          'string' => 'What?: 1.23 => 2.34',
+        ],
+      ],
+
+      5 => [
+        'input' => [
+          'custom_field_params' => [
+            'data_type' => 'Money',
+          ],
+          'custom_field_oldvalue' => '',
+          'custom_field_newvalue' => '2.34',
+        ],
+        'expected' => [
+          'string' => 'What?: 0.00 => 2.34',
+        ],
+      ],
+
+      6 => [
+        'input' => [
+          'custom_field_params' => [
+            'data_type' => 'Money',
+          ],
+          'custom_field_oldvalue' => '1.23',
+          'custom_field_newvalue' => '',
+        ],
+        'expected' => [
+          'string' => 'What?: 1.23 => ',
+        ],
+      ],
+
+      7 => [
+        'input' => [
+          'custom_field_params' => [
+            'data_type' => 'Money',
+          ],
+          'custom_field_newvalue' => '2.34',
+        ],
+        'expected' => [
+          'string' => 'What?:  => 2.34',
+        ],
+      ],
+
+      8 => [
+        'input' => [
+          'custom_field_params' => [],
+          'custom_field_oldvalue' => 'some text',
+          'custom_field_newvalue' => 'some new text',
+        ],
+        'expected' => [
+          'string' => 'What?: some text => some new text',
+        ],
+      ],
+
+      9 => [
+        'input' => [
+          'custom_field_params' => [],
+          'custom_field_oldvalue' => '',
+          'custom_field_newvalue' => 'some new text',
+        ],
+        'expected' => [
+          'string' => 'What?:  => some new text',
+        ],
+      ],
+
+      10 => [
+        'input' => [
+          'custom_field_params' => [],
+          'custom_field_oldvalue' => 'some text',
+          'custom_field_newvalue' => '',
+        ],
+        'expected' => [
+          'string' => 'What?: some text => ',
+        ],
+      ],
+
+      11 => [
+        'input' => [
+          'custom_field_params' => [],
+          'custom_field_newvalue' => 'some new text',
+        ],
+        'expected' => [
+          'string' => 'What?:  => some new text',
+        ],
+      ],
+    ];
+  }
+
+  /**
+   * Convert to locale currency format for purposes of these tests
+   * @param string $input
+   * @return string
+   */
+  private function convertCurrency(string $input): string {
+    $conversion_table = [
+      ',' => CRM_Core_Config::singleton()->monetaryThousandSeparator,
+      '.' => CRM_Core_Config::singleton()->monetaryDecimalPoint,
+    ];
+    return strtr($input, $conversion_table);
+  }
+
+}