From dcc03544bd8e5ddefe24a650b6ff3415ecab68b8 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Sat, 11 Jan 2020 12:33:45 -0500 Subject: [PATCH] Api4 - Filter returned fields by contact type --- .../Subscriber/PostSelectQuerySubscriber.php | 29 +++++++- .../phpunit/api/v4/Entity/ContactTypeTest.php | 71 +++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 tests/phpunit/api/v4/Entity/ContactTypeTest.php diff --git a/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php b/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php index 2101231cd6..6d7cd949f0 100644 --- a/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php +++ b/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php @@ -32,6 +32,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; */ class PostSelectQuerySubscriber implements EventSubscriberInterface { + private $contactFieldsToRemove = []; + /** * @inheritdoc */ @@ -60,7 +62,7 @@ class PostSelectQuerySubscriber implements EventSubscriberInterface { return $results; } - $this->formatFieldValues($results, $query->getApiFieldSpec()); + $this->formatFieldValues($results, $query->getApiFieldSpec(), $query->getEntity()); // Group the selects to avoid queries for each field $groupedSelects = $this->getNtoManyJoinSelects($query); @@ -97,7 +99,7 @@ class PostSelectQuerySubscriber implements EventSubscriberInterface { $fields[array_pop($name)] = $field->toArray(); } if ($fields) { - $this->formatFieldValues($joinResults, $fields); + $this->formatFieldValues($joinResults, $fields, $join->getEntity()); } } @@ -106,9 +108,14 @@ class PostSelectQuerySubscriber implements EventSubscriberInterface { * * @param array $results * @param array $fields + * @param string $entity */ - protected function formatFieldValues(&$results, $fields = []) { + protected function formatFieldValues(&$results, $fields, $entity) { foreach ($results as &$result) { + // Remove inapplicable contact fields + if ($entity === 'Contact' && !empty($result['contact_type'])) { + \CRM_Utils_Array::remove($result, $this->contactFieldsToRemove($result['contact_type'])); + } foreach ($result as $field => $value) { $dataType = $fields[$field]['data_type'] ?? NULL; if (!empty($fields[$field]['serialize'])) { @@ -375,4 +382,20 @@ class PostSelectQuerySubscriber implements EventSubscriberInterface { return $subResults; } + /** + * @param string $contactType + * @return array + */ + private function contactFieldsToRemove($contactType) { + if (!isset($this->contactFieldsToRemove[$contactType])) { + $this->contactFieldsToRemove[$contactType] = []; + foreach (\CRM_Contact_DAO_Contact::fields() as $field) { + if (!empty($field['contactType']) && $field['contactType'] != $contactType) { + $this->contactFieldsToRemove[$contactType][] = $field['name']; + } + } + } + return $this->contactFieldsToRemove[$contactType]; + } + } diff --git a/tests/phpunit/api/v4/Entity/ContactTypeTest.php b/tests/phpunit/api/v4/Entity/ContactTypeTest.php new file mode 100644 index 0000000000..c09e363b5c --- /dev/null +++ b/tests/phpunit/api/v4/Entity/ContactTypeTest.php @@ -0,0 +1,71 @@ +setValues(['first_name' => 'Joe', 'last_name' => 'Tester', 'contact_type' => 'Individual']) + ->setCheckPermissions(FALSE) + ->execute()->first()['id']; + + $org = Contact::create() + ->setValues(['organization_name' => 'Tester Org', 'contact_type' => 'Organization']) + ->setCheckPermissions(FALSE) + ->execute()->first()['id']; + + $hh = Contact::create() + ->setValues(['household_name' => 'Tester Family', 'contact_type' => 'Household']) + ->setCheckPermissions(FALSE) + ->execute()->first()['id']; + + $result = Contact::get() + ->setCheckPermissions(FALSE) + ->addWhere('id', 'IN', [$indiv, $org, $hh]) + ->execute() + ->indexBy('id'); + + $this->assertArrayHasKey('first_name', $result[$indiv]); + $this->assertArrayNotHasKey('first_name', $result[$org]); + $this->assertArrayNotHasKey('first_name', $result[$hh]); + + $this->assertArrayHasKey('organization_name', $result[$org]); + $this->assertArrayNotHasKey('organization_name', $result[$indiv]); + $this->assertArrayNotHasKey('organization_name', $result[$hh]); + + $this->assertArrayHasKey('sic_code', $result[$org]); + $this->assertArrayNotHasKey('sic_code', $result[$indiv]); + $this->assertArrayNotHasKey('sic_code', $result[$hh]); + + $this->assertArrayHasKey('household_name', $result[$hh]); + $this->assertArrayNotHasKey('household_name', $result[$org]); + $this->assertArrayNotHasKey('household_name', $result[$indiv]); + } + +} -- 2.25.1