From: Coleman Watts <coleman@civicrm.org> Date: Sat, 15 Sep 2018 02:46:43 +0000 (-0400) Subject: Fix api profile.submit to work with tag & note fields X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=9c473adf6e9a7399984e806fb5eeecd77f2676b2;p=civicrm-core.git Fix api profile.submit to work with tag & note fields --- diff --git a/api/v3/EntityTag.php b/api/v3/EntityTag.php index a3098bea85..6b0bd7033e 100644 --- a/api/v3/EntityTag.php +++ b/api/v3/EntityTag.php @@ -101,7 +101,7 @@ function _civicrm_api3_entity_tag_delete_spec(&$params) { */ function _civicrm_api3_entity_tag_common($params, $op = 'add') { - $entityIDs = array(); + $entityIDs = $tagIDs = array(); $entityTable = 'civicrm_contact'; if (is_array($params)) { foreach ($params as $n => $v) { @@ -109,7 +109,12 @@ function _civicrm_api3_entity_tag_common($params, $op = 'add') { $entityIDs[] = $v; } elseif (substr($n, 0, 6) == 'tag_id') { - $tagIDs[] = $v; + if (is_array($v)) { + $tagIDs = array_merge($tagIDs, $v); + } + else { + $tagIDs[] = $v; + } } elseif (substr($n, 0, 12) == 'entity_table') { $entityTable = $v; @@ -156,3 +161,38 @@ function _civicrm_api3_entity_tag_common($params, $op = 'add') { } return $values; } + +/** + * Replace tags for an entity + */ +function civicrm_api3_entity_tag_replace($params) { + $transaction = new CRM_Core_Transaction(); + try { + civicrm_api3_verify_one_mandatory($params, NULL, ['values', 'tag_id']); + + $baseParams = _civicrm_api3_generic_replace_base_params($params); + unset($baseParams['tag_id']); + + // Lookup pre-existing records + $preexisting = civicrm_api3('entity_tag', 'get', $baseParams); + $preexisting = array_column($preexisting['values'], 'tag_id'); + $toAdd = isset($params['tag_id']) ? $params['tag_id'] : array_column($params['values'], 'tag_id'); + $toRemove = array_diff($preexisting, $toAdd); + + $result = []; + if ($toAdd) { + $result = _civicrm_api3_entity_tag_common(array_merge($baseParams, ['tag_id' => $toAdd]), 'add'); + } + if ($toRemove) { + $result += _civicrm_api3_entity_tag_common(array_merge($baseParams, ['tag_id' => $toRemove]), 'remove'); + } + // Not really errors + unset($result['is_error'], $result['error_message']); + + return civicrm_api3_create_success($result, $params, 'EntityTag', 'replace'); + } + catch(Exception $e) { + $transaction->rollback(); + return civicrm_api3_create_error($e->getMessage()); + } +} diff --git a/api/v3/Profile.php b/api/v3/Profile.php index 2951c8d65c..22a26becab 100644 --- a/api/v3/Profile.php +++ b/api/v3/Profile.php @@ -202,14 +202,35 @@ function civicrm_api3_profile_submit($params) { $entity = strtolower(CRM_Utils_Array::value('entity', $field)); if ($entity && !in_array($entity, array_merge($contactEntities, $locationEntities))) { - $contactParams['api.' . $entity . '.create'][$fieldName] = $value; - //@todo we are not currently declaring this option - if (isset($params['batch_id']) && strtolower($entity) == 'contribution') { - $contactParams['api.' . $entity . '.create']['batch_id'] = $params['batch_id']; - } - if (isset($params[$entity . '_id'])) { - //todo possibly declare $entity_id in getfields ? - $contactParams['api.' . $entity . '.create']['id'] = $params[$entity . '_id']; + switch ($entity) { + case 'note': + if ($value) { + $contactParams['api.Note.create'] = [ + 'note' => $value, + 'contact_id' => 'user_contact_id', + ]; + } + break; + + case 'entity_tag': + if (!is_array($value)) { + $value = $value ? explode(',', $value) : []; + } + $contactParams['api.entity_tag.replace'] = [ + 'tag_id' => $value, + ]; + break; + + default: + $contactParams['api.' . $entity . '.create'][$fieldName] = $value; + //@todo we are not currently declaring this option + if (isset($params['batch_id']) && strtolower($entity) == 'contribution') { + $contactParams['api.' . $entity . '.create']['batch_id'] = $params['batch_id']; + } + if (isset($params[$entity . '_id'])) { + //todo possibly declare $entity_id in getfields ? + $contactParams['api.' . $entity . '.create']['id'] = $params[$entity . '_id']; + } } } else { @@ -230,7 +251,7 @@ function civicrm_api3_profile_submit($params) { ); } - $contactParams['contact_id'] = CRM_Utils_Array::value('contact_id', $params); + $contactParams['contact_id'] = empty($params['contact_id']) ? CRM_Utils_Array::value('id', $params) : $params['contact_id']; $contactParams['profile_id'] = $profileID; $contactParams['skip_custom'] = 1; @@ -291,6 +312,11 @@ function _civicrm_api3_profile_submit_spec(&$params, $apirequest) { } $params['profile_id']['api.required'] = TRUE; $params['profile_id']['title'] = 'Profile ID'; + // Profile forms submit tag values as a string; hack to get past api wrapper validation + if (!empty($params['tag_id'])) { + unset($params['tag_id']['pseudoconstant']); + $params['tag_id']['type'] = CRM_Utils_Type::T_STRING; + } } /** @@ -663,6 +689,7 @@ function _civicrm_api3_map_profile_fields_to_entity(&$field) { 'soft_credit_type' => 'contribution_soft', 'group' => 'group_contact', 'tag' => 'entity_tag', + 'note' => 'note', ); if (array_key_exists($fieldName, $hardCodedEntityMappings)) { $entity = $hardCodedEntityMappings[$fieldName]; diff --git a/tests/phpunit/api/v3/ProfileTest.php b/tests/phpunit/api/v3/ProfileTest.php index e09abecfb0..1ceee078b7 100644 --- a/tests/phpunit/api/v3/ProfileTest.php +++ b/tests/phpunit/api/v3/ProfileTest.php @@ -85,7 +85,7 @@ class api_v3_ProfileTest extends CiviUnitTestCase { */ public function testProfileGet() { $profileFieldValues = $this->_createIndividualContact(); - $expected = current($profileFieldValues); + $expected = reset($profileFieldValues); $contactId = key($profileFieldValues); $params = array( 'profile_id' => $this->_profileID, @@ -99,7 +99,7 @@ class api_v3_ProfileTest extends CiviUnitTestCase { public function testProfileGetMultiple() { $profileFieldValues = $this->_createIndividualContact(); - $expected = current($profileFieldValues); + $expected = reset($profileFieldValues); $contactId = key($profileFieldValues); $params = array( 'profile_id' => array($this->_profileID, 1, 'Billing'), @@ -382,9 +382,8 @@ class api_v3_ProfileTest extends CiviUnitTestCase { * Check with missing required field in profile. */ public function testProfileSubmitCheckProfileRequired() { - $pofileFieldValues = $this->_createIndividualContact(); - current($pofileFieldValues); - $contactId = key($pofileFieldValues); + $profileFieldValues = $this->_createIndividualContact(); + $contactId = key($profileFieldValues); $updateParams = array( 'first_name' => 'abc2', 'last_name' => 'xyz2', @@ -406,9 +405,8 @@ class api_v3_ProfileTest extends CiviUnitTestCase { * Check with success. */ public function testProfileSubmit() { - $pofileFieldValues = $this->_createIndividualContact(); - current($pofileFieldValues); - $contactId = key($pofileFieldValues); + $profileFieldValues = $this->_createIndividualContact(); + $contactId = key($profileFieldValues); $updateParams = array( 'first_name' => 'abc2', @@ -505,9 +503,8 @@ class api_v3_ProfileTest extends CiviUnitTestCase { * Set is deprecated but we need to ensure it still works. */ public function testLegacySet() { - $pofileFieldValues = $this->_createIndividualContact(); - current($pofileFieldValues); - $contactId = key($pofileFieldValues); + $profileFieldValues = $this->_createIndividualContact(); + $contactId = key($profileFieldValues); $updateParams = array( 'first_name' => 'abc2', @@ -706,6 +703,65 @@ class api_v3_ProfileTest extends CiviUnitTestCase { } } + /** + * Check success with tags. + */ + public function testSubmitWithTags() { + $profileFieldValues = $this->_createIndividualContact(); + $params = reset($profileFieldValues); + $contactId = key($profileFieldValues); + $params['profile_id'] = $this->_profileID; + $params['contact_id'] = $contactId; + + $this->callAPISuccess('ufField', 'create', array( + 'uf_group_id' => $this->_profileID, + 'field_name' => 'tag', + 'visibility' => 'Public Pages and Listings', + 'field_type' => 'Contact', + 'label' => 'Tags', + )); + + $tag_1 = $this->callAPISuccess('tag', 'create', ['name' => 'abc'])['id']; + $tag_2 = $this->callAPISuccess('tag', 'create', ['name' => 'def'])['id']; + + $params['tag'] = "$tag_1,$tag_2"; + $result = $this->callAPISuccess('profile', 'submit', $params); + + $tags = $this->callAPISuccess('entityTag', 'get', ['entity_id' => $contactId]); + $this->assertEquals(2, $tags['count']); + + $params['tag'] = [$tag_1]; + $result = $this->callAPISuccess('profile', 'submit', $params); + + $tags = $this->callAPISuccess('entityTag', 'get', ['entity_id' => $contactId]); + $this->assertEquals(1, $tags['count']); + } + + /** + * Check success with a note. + */ + public function testSubmitWithNote() { + $profileFieldValues = $this->_createIndividualContact(); + $params = reset($profileFieldValues); + $contactId = key($profileFieldValues); + $params['profile_id'] = $this->_profileID; + $params['contact_id'] = $contactId; + + $this->callAPISuccess('ufField', 'create', array( + 'uf_group_id' => $this->_profileID, + 'field_name' => 'note', + 'visibility' => 'Public Pages and Listings', + 'field_type' => 'Contact', + 'label' => 'Note', + )); + + $params['note'] = "Hello 123"; + $this->callAPISuccess('profile', 'submit', $params); + + $note = $this->callAPISuccessGetSingle('note', ['entity_id' => $contactId]); + $this->assertEquals("Hello 123", $note['note']); + } + /** * Helper function to create an Individual with address/email/phone info. Import UF Group and UF Fields * @param array $params