From: Coleman Watts Date: Wed, 22 Apr 2020 21:48:34 +0000 (-0400) Subject: APIv4 - Fix contactFieldsToRemove to work with joins and pseudoconstants X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=d818aa7b2829c516c0bbe35e6eae066a09a1d427;p=civicrm-core.git APIv4 - Fix contactFieldsToRemove to work with joins and pseudoconstants --- diff --git a/Civi/Api4/Utils/FormattingUtil.php b/Civi/Api4/Utils/FormattingUtil.php index 89f4c7c54b..818f591417 100644 --- a/Civi/Api4/Utils/FormattingUtil.php +++ b/Civi/Api4/Utils/FormattingUtil.php @@ -140,10 +140,7 @@ class FormattingUtil { public static function formatOutputValues(&$results, $fields, $entity, $action = 'get') { $fieldOptions = []; foreach ($results as &$result) { - // Remove inapplicable contact fields - if ($entity === 'Contact' && !empty($result['contact_type'])) { - \CRM_Utils_Array::remove($result, self::contactFieldsToRemove($result['contact_type'])); - } + $contactTypePaths = []; foreach ($result as $fieldExpr => $value) { $field = $fields[$fieldExpr] ?? NULL; $dataType = $field['data_type'] ?? ($fieldExpr == 'id' ? 'Integer' : NULL); @@ -163,9 +160,18 @@ class FormattingUtil { if (isset($fieldOptions[$fieldExpr])) { $value = self::replacePseudoconstant($fieldOptions[$fieldExpr], $value); } + // Keep track of contact types for self::contactFieldsToRemove + if ($value && isset($field['entity']) && $field['entity'] === 'Contact' && $field['name'] === 'contact_type') { + $prefix = strrpos($fieldExpr, '.'); + $contactTypePaths[$prefix ? substr($fieldExpr, 0, $prefix + 1) : ''] = $value; + } } $result[$fieldExpr] = self::convertDataType($value, $dataType); } + // Remove inapplicable contact fields + foreach ($contactTypePaths as $prefix => $contactType) { + \CRM_Utils_Array::remove($result, self::contactFieldsToRemove($contactType, $prefix)); + } } } @@ -257,19 +263,33 @@ class FormattingUtil { } /** + * Lists all field names (including suffixed variants) that should be removed for a given contact type. + * * @param string $contactType + * Individual|Organization|Household + * @param string $prefix + * Path at which these fields are found, e.g. "address.contact." * @return array */ - public static function contactFieldsToRemove($contactType) { + public static function contactFieldsToRemove($contactType, $prefix) { if (!isset(\Civi::$statics[__CLASS__][__FUNCTION__][$contactType])) { \Civi::$statics[__CLASS__][__FUNCTION__][$contactType] = []; foreach (\CRM_Contact_DAO_Contact::fields() as $field) { if (!empty($field['contactType']) && $field['contactType'] != $contactType) { \Civi::$statics[__CLASS__][__FUNCTION__][$contactType][] = $field['name']; + // Include suffixed variants like prefix_id:label + if (!empty($field['pseudoconstant'])) { + foreach (array_keys(self::$pseudoConstantContexts) as $suffix) { + \Civi::$statics[__CLASS__][__FUNCTION__][$contactType][] = $field['name'] . ':' . $suffix; + } + } } } } - return \Civi::$statics[__CLASS__][__FUNCTION__][$contactType]; + // Add prefix paths + return array_map(function($name) use ($prefix) { + return $prefix . $name; + }, \Civi::$statics[__CLASS__][__FUNCTION__][$contactType]); } } diff --git a/tests/phpunit/api/v4/Entity/ContactTypeTest.php b/tests/phpunit/api/v4/Entity/ContactTypeTest.php index c09e363b5c..9e7efec198 100644 --- a/tests/phpunit/api/v4/Entity/ContactTypeTest.php +++ b/tests/phpunit/api/v4/Entity/ContactTypeTest.php @@ -23,30 +23,35 @@ namespace api\v4\Entity; use Civi\Api4\Contact; use api\v4\UnitTestCase; +use Civi\Api4\Email; /** * @group headless */ class ContactTypeTest extends UnitTestCase { - public function testContactGetReturnsFieldsAppropriateToEachContactType() { + public function testGetReturnsFieldsAppropriateToEachContactType() { $indiv = Contact::create() - ->setValues(['first_name' => 'Joe', 'last_name' => 'Tester', 'contact_type' => 'Individual']) + ->setValues(['first_name' => 'Joe', 'last_name' => 'Tester', 'prefix_id:label' => 'Dr.', 'contact_type' => 'Individual']) + ->addChain('email', Email::create()->setValues(['contact_id' => '$id', 'email' => 'ind@example.com'])) ->setCheckPermissions(FALSE) ->execute()->first()['id']; $org = Contact::create() ->setValues(['organization_name' => 'Tester Org', 'contact_type' => 'Organization']) + ->addChain('email', Email::create()->setValues(['contact_id' => '$id', 'email' => 'org@example.com'])) ->setCheckPermissions(FALSE) ->execute()->first()['id']; $hh = Contact::create() ->setValues(['household_name' => 'Tester Family', 'contact_type' => 'Household']) + ->addChain('email', Email::create()->setValues(['contact_id' => '$id', 'email' => 'hh@example.com'])) ->setCheckPermissions(FALSE) ->execute()->first()['id']; $result = Contact::get() ->setCheckPermissions(FALSE) + ->addSelect('*', 'prefix_id:label') ->addWhere('id', 'IN', [$indiv, $org, $hh]) ->execute() ->indexBy('id'); @@ -55,6 +60,10 @@ class ContactTypeTest extends UnitTestCase { $this->assertArrayNotHasKey('first_name', $result[$org]); $this->assertArrayNotHasKey('first_name', $result[$hh]); + $this->assertEquals('Dr.', $result[$indiv]['prefix_id:label']); + $this->assertArrayNotHasKey('prefix_id:label', $result[$org]); + $this->assertArrayNotHasKey('prefix_id:label', $result[$hh]); + $this->assertArrayHasKey('organization_name', $result[$org]); $this->assertArrayNotHasKey('organization_name', $result[$indiv]); $this->assertArrayNotHasKey('organization_name', $result[$hh]); @@ -66,6 +75,34 @@ class ContactTypeTest extends UnitTestCase { $this->assertArrayHasKey('household_name', $result[$hh]); $this->assertArrayNotHasKey('household_name', $result[$org]); $this->assertArrayNotHasKey('household_name', $result[$indiv]); + + $emails = Email::get() + ->setCheckPermissions(FALSE) + ->addWhere('contact_id', 'IN', [$indiv, $org, $hh]) + ->addSelect('id', 'contact_id', 'contact.*', 'contact.prefix_id:label') + ->execute() + ->indexBy('contact_id'); + + $this->assertArrayHasKey('contact.first_name', $emails[$indiv]); + $this->assertArrayNotHasKey('contact.first_name', $emails[$org]); + $this->assertArrayNotHasKey('contact.first_name', $emails[$hh]); + + $this->assertEquals('Dr.', $emails[$indiv]['contact.prefix_id:label']); + $this->assertArrayNotHasKey('contact.prefix_id:label', $emails[$org]); + $this->assertArrayNotHasKey('contact.prefix_id:label', $emails[$hh]); + + $this->assertArrayHasKey('contact.organization_name', $emails[$org]); + $this->assertArrayNotHasKey('contact.organization_name', $emails[$indiv]); + $this->assertArrayNotHasKey('contact.organization_name', $emails[$hh]); + + $this->assertArrayHasKey('contact.sic_code', $emails[$org]); + $this->assertArrayNotHasKey('contact.sic_code', $emails[$indiv]); + $this->assertArrayNotHasKey('contact.sic_code', $emails[$hh]); + + $this->assertArrayHasKey('contact.household_name', $emails[$hh]); + $this->assertArrayNotHasKey('contact.household_name', $emails[$org]); + $this->assertArrayNotHasKey('contact.household_name', $emails[$indiv]); + } }