APIv4 - CiviCase API: Fix openening a case with current user as creator
authorColeman Watts <coleman@civicrm.org>
Wed, 5 May 2021 21:33:28 +0000 (17:33 -0400)
committerColeman Watts <coleman@civicrm.org>
Thu, 6 May 2021 12:51:01 +0000 (08:51 -0400)
The DAOActionTrait::writeObjects function was formatting values but not by reference,
so the CiviCase writeObjects function was using unformatted values to open the case,
which would contain the raw string `user_contact_id` instead of the processed value.

12 files changed:
Civi/Api4/Action/Address/AddressSaveTrait.php
Civi/Api4/Action/CiviCase/CiviCaseSaveTrait.php
Civi/Api4/Action/GroupContact/GroupContactSaveTrait.php
Civi/Api4/Generic/DAOCreateAction.php
Civi/Api4/Generic/DAOUpdateAction.php
Civi/Api4/Generic/Traits/CustomValueActionTrait.php
Civi/Api4/Generic/Traits/DAOActionTrait.php
Civi/Api4/Service/Spec/Provider/CaseCreationSpecProvider.php
tests/phpunit/api/v4/DataSets/CaseType.json [new file with mode: 0644]
tests/phpunit/api/v4/DataSets/ConformanceTest.json
tests/phpunit/api/v4/Entity/CaseTest.php [new file with mode: 0644]
tests/phpunit/api/v4/Entity/ConformanceTest.php

index af121c42b9b987f0108a3b0099b1ce394d53ad3a..2f966d97e1ef3c7d9bba00c67c981452761dc340 100644 (file)
@@ -54,7 +54,7 @@ trait AddressSaveTrait {
   /**
    * @inheritDoc
    */
-  protected function writeObjects($items) {
+  protected function writeObjects(&$items) {
     foreach ($items as &$item) {
       if ($this->streetParsing && !empty($item['street_address'])) {
         $item = array_merge($item, \CRM_Core_BAO_Address::parseStreetAddress($item['street_address']));
index 8f83c11206c7ee2b7fabd2d678779fc9d79a73de..33d2d1514120d6a0ebe2b008fa8453434d7c3568 100644 (file)
@@ -28,7 +28,7 @@ trait CiviCaseSaveTrait {
    * @param array $cases
    * @return array
    */
-  protected function writeObjects($cases) {
+  protected function writeObjects(&$cases) {
     $cases = array_values($cases);
     $result = parent::writeObjects($cases);
 
index 85492afdb486d8c2466241ab71d623ad9ef67bda..546a94458f7944622dd57ad364d6fe0bff7a16b0 100644 (file)
@@ -46,7 +46,7 @@ trait GroupContactSaveTrait {
   /**
    * @inheritDoc
    */
-  protected function writeObjects($items) {
+  protected function writeObjects(&$items) {
     foreach ($items as &$item) {
       $item['method'] = $this->method;
       $item['tracking'] = $this->tracking;
index d2371d3180f473f8c9a076989d888fd11d4c2c2a..336b26be7502b3be4d25eaca381ba3178b0d46c4 100644 (file)
@@ -36,10 +36,9 @@ class DAOCreateAction extends AbstractCreateAction {
     $this->validateValues();
     $params = $this->values;
     $this->fillDefaults($params);
+    $items = [$params];
 
-    $resultArray = $this->writeObjects([$params]);
-
-    $result->exchangeArray($resultArray);
+    $result->exchangeArray($this->writeObjects($items));
   }
 
   /**
index 0d4bf17551157b82610da514c5eb62ecff4810d8..a3c86dbfe6226229f87aceb26bbd7332316b19b7 100644 (file)
@@ -60,7 +60,8 @@ class DAOUpdateAction extends AbstractUpdateAction {
     // Update a single record by ID unless select requires more than id
     if ($this->getSelect() === ['id'] && count($this->where) === 1 && $this->where[0][0] === 'id' && $this->where[0][1] === '=' && !empty($this->where[0][2])) {
       $this->values['id'] = $this->where[0][2];
-      $result->exchangeArray($this->writeObjects([$this->values]));
+      $items = [$this->values];
+      $result->exchangeArray($this->writeObjects($items));
       return;
     }
 
index 5a7a0e33127607b914774beb577f54b6af635ce9..6d595b04ae2b34841fb99883978a5ce01379addd 100644 (file)
@@ -51,7 +51,7 @@ trait CustomValueActionTrait {
   /**
    * @inheritDoc
    */
-  protected function writeObjects($items) {
+  protected function writeObjects(&$items) {
     $fields = $this->entityFields();
     foreach ($items as $idx => $item) {
       FormattingUtil::formatWriteParams($item, $fields);
index 2a94bfbe4f2c3c1a89071effcf8127949348a3e7..197e8936ac76affd0180a9f7d022b66fe366fc25 100644 (file)
@@ -103,7 +103,7 @@ trait DAOActionTrait {
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  protected function writeObjects($items) {
+  protected function writeObjects(&$items) {
     $baoName = $this->getBaoName();
 
     // Some BAOs are weird and don't support a straightforward "create" method.
@@ -118,7 +118,7 @@ trait DAOActionTrait {
 
     $result = [];
 
-    foreach ($items as $item) {
+    foreach ($items as &$item) {
       $entityId = $item['id'] ?? NULL;
       FormattingUtil::formatWriteParams($item, $this->entityFields());
       $this->formatCustomParams($item, $entityId);
index ce0dcf726fa6d108b749c0e77f696840ca9577d5..1e768dfd4606f5c21adebbd80c3fff85d5d6f82c 100644 (file)
@@ -59,6 +59,16 @@ class CaseCreationSpecProvider implements Generic\SpecProviderInterface {
     $duration->setInputType('Number');
     $duration->setDescription('Open Case activity duration (minutes).');
     $spec->addFieldSpec($duration);
+
+    $defaultStatus = \CRM_Core_DAO::singleValueQuery('SELECT value FROM civicrm_option_value
+      WHERE is_default
+        AND domain_id = ' . \CRM_Core_BAO_Domain::getDomain()->id . '
+        AND option_group_id = (SELECT id FROM civicrm_option_group WHERE name = "case_status")
+      LIMIT 1');
+    if ($defaultStatus) {
+      $status = $spec->getFieldByName('status_id');
+      $status->setDefaultValue((int) $defaultStatus);
+    }
   }
 
   /**
diff --git a/tests/phpunit/api/v4/DataSets/CaseType.json b/tests/phpunit/api/v4/DataSets/CaseType.json
new file mode 100644 (file)
index 0000000..dd1c084
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "CaseType": [
+    {
+      "name": "test_case_type",
+      "title": "Test Case Type",
+      "definition": {
+        "activityTypes": [
+          {
+            "name": "Open Case",
+            "max_instances": "1"
+          },
+          {
+            "name": "Follow up"
+          }
+        ],
+        "activitySets": [
+          {
+            "name": "standard_timeline",
+            "label": "Standard Timeline",
+            "timeline": 1,
+            "activityTypes": [
+              {
+                "name": "Open Case",
+                "status": "Completed"
+              },
+              {
+                "name": "Follow up",
+                "reference_activity": "Open Case",
+                "reference_offset": "3",
+                "reference_select": "newest"
+              }
+            ]
+          }
+        ],
+        "timelineActivityTypes": [
+          {
+            "name": "Open Case",
+            "status": "Completed"
+          },
+          {
+            "name": "Follow up",
+            "reference_activity": "Open Case",
+            "reference_offset": "3",
+            "reference_select": "newest"
+          }
+        ],
+        "caseRoles": [
+          {
+            "name": "Parent of",
+            "creator": "1",
+            "manager": "1"
+          }
+        ]
+      },
+      "@ref": "test_case_type_1"
+    }
+  ]
+}
index 217138e077b385ec5046886077e94b96591a2fcc..78a3b72aaa8dcda0edcde5597969dc12c2d8a49b 100644 (file)
       "@ref": "test_contact_2"
     }
   ],
-  "CaseType": [
-    {
-      "name": "test_case_type",
-      "title": "Test Case Type",
-      "definition": {
-        "activityTypes": [
-          {
-            "name": "Open Case",
-            "max_instances": "1"
-          },
-          {
-            "name": "Follow up"
-          }
-        ],
-        "activitySets": [
-          {
-            "name": "standard_timeline",
-            "label": "Standard Timeline",
-            "timeline": 1,
-            "activityTypes": [
-              {
-                "name": "Open Case",
-                "status": "Completed"
-              },
-              {
-                "name": "Follow up",
-                "reference_activity": "Open Case",
-                "reference_offset": "3",
-                "reference_select": "newest"
-              }
-            ]
-          }
-        ],
-        "timelineActivityTypes": [
-          {
-            "name": "Open Case",
-            "status": "Completed"
-          },
-          {
-            "name": "Follow up",
-            "reference_activity": "Open Case",
-            "reference_offset": "3",
-            "reference_select": "newest"
-          }
-        ],
-        "caseRoles": [
-          {
-            "name": "Parent of",
-            "creator": "1",
-            "manager": "1"
-          }
-        ]
-      },
-      "@ref": "test_case_type_1"
-    }
-  ],
   "Case": [
     {
       "case_type_id": "@ref test_case_type_1.id",
diff --git a/tests/phpunit/api/v4/Entity/CaseTest.php b/tests/phpunit/api/v4/Entity/CaseTest.php
new file mode 100644 (file)
index 0000000..9145bd8
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+
+namespace api\v4\Entity;
+
+use Civi\Api4\CiviCase;
+use api\v4\UnitTestCase;
+
+/**
+ * @group headless
+ */
+class CaseTest extends UnitTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    \CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
+    $this->loadDataSet('CaseType');
+  }
+
+  public function testCreateUsingLoggedInUser() {
+    $this->createLoggedInUser();
+
+    $contactID = $this->createEntity(['type' => 'Individual'])['id'];
+
+    $result = CiviCase::create(FALSE)
+      ->addValue('case_type_id', $this->getReference('test_case_type_1')['id'])
+      ->addValue('creator_id', 'user_contact_id')
+      ->addValue('status_id', 1)
+      ->addValue('contact_id', $contactID)
+      ->execute()
+      ->first();
+
+  }
+
+}
index a523447fb5d8a4ea2847e1c39be8aed21d7f1390..6af37e8e1378a6b07fb56af281d779c3797e99be 100644 (file)
@@ -53,6 +53,7 @@ class ConformanceTest extends UnitTestCase {
     $this->dropByPrefix('civicrm_value_myfavorite');
     $this->cleanup(['tablesToTruncate' => $tablesToTruncate]);
     $this->setUpOptionCleanup();
+    $this->loadDataSet('CaseType');
     $this->loadDataSet('ConformanceTest');
     $this->creationParamProvider = \Civi::container()->get('test.param_provider');
     parent::setUp();