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);
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));
+ }
}
}
}
/**
+ * 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]);
}
}
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');
$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]);
$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]);
+
}
}