*
* Generated from xml/schema/CRM/Contact/Contact.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:8cdd2fa476983d8770b53cc7665586cf)
+ * (GenCodeChecksum:44f607f6289003a3b6715c7b9103359b)
*/
/**
'html' => [
'type' => 'EntityRef',
'label' => ts("Current Employer"),
+ 'filter' => [
+ 'contact_type=Organization',
+ ],
],
'add' => '2.1',
],
$form->addField('job_title', ['size' => '30']);
//Current Employer Element
- $props = [
- 'api' => ['params' => ['contact_type' => 'Organization']],
- 'create' => TRUE,
- ];
- $form->addField('employer_id', $props);
+ $form->addField('employer_id', ['create' => TRUE]);
$form->addField('contact_source', ['class' => 'big']);
}
$field['html'][$htmlOption] = $this->value($htmlOption, $fieldXML->html);
}
}
+ if (isset($fieldXML->html->filter)) {
+ $field['html']['filter'] = (array) $fieldXML->html->filter;
+ }
}
// in multilingual context popup, we need extra information to create appropriate widget
$props['data-api-field'] = $props['name'];
}
}
- $props += CRM_Utils_Array::value('html', $fieldSpec, []);
+ $htmlProps = (array) ($fieldSpec['html'] ?? []);
+ CRM_Utils_Array::remove($htmlProps, 'label', 'filter');
+ $props += $htmlProps;
if (in_array($widget, ['Select', 'Select2'])
&& !array_key_exists('placeholder', $props)
&& $placeholder = self::selectOrAnyPlaceholder($props, $required, $label)) {
return $this->add('wysiwyg', $name, $label, $props, $required);
case 'EntityRef':
+ // Auto-apply filters from field metadata
+ foreach ($fieldSpec['html']['filter'] ?? [] as $filter) {
+ [$k, $v] = explode('=', $filter);
+ $props['api']['params'][$k] = $v;
+ }
return $this->addEntityRef($name, $label, $props, $required);
case 'Password':
foreach ($fieldNames as $fieldName) {
$field = $this->getField($fieldName);
$dataType = $field['data_type'] ?? NULL;
+ $operators = ($field['operators'] ?? []) ?: CoreUtil::getOperators();
// Array is either associative `OP => VAL` or sequential `IN (...)`
if (is_array($value)) {
$value = array_filter($value, [$this, 'hasValue']);
$filterClauses[] = ['AND', $andGroup];
}
}
- elseif (!empty($field['serialize'])) {
+ elseif (!empty($field['serialize']) && in_array('CONTAINS', $operators, TRUE)) {
$filterClauses[] = [$fieldName, 'CONTAINS', $value];
}
- elseif (!empty($field['options']) || in_array($dataType, ['Integer', 'Boolean', 'Date', 'Timestamp'])) {
+ elseif ((!empty($field['options']) || in_array($dataType, ['Integer', 'Boolean', 'Date', 'Timestamp'])) && in_array('=', $operators, TRUE)) {
$filterClauses[] = [$fieldName, '=', $value];
}
- elseif ($prefixWithWildcard) {
+ elseif ($prefixWithWildcard && in_array('CONTAINS', $operators, TRUE)) {
$filterClauses[] = [$fieldName, 'CONTAINS', $value];
}
- else {
+ elseif (in_array('LIKE', $operators, TRUE)) {
$filterClauses[] = [$fieldName, 'LIKE', $value . '%'];
}
+ elseif (in_array('IN', $operators, TRUE)) {
+ $filterClauses[] = [$fieldName, 'IN', (array) $value];
+ }
+ else {
+ $filterClauses[] = [$fieldName, '=', $value];
+ }
}
// Single field
if (count($filterClauses) === 1) {
$inputType = $data['html']['type'] ?? $data['html_type'] ?? NULL;
$inputAttrs = $data['html'] ?? [];
unset($inputAttrs['type']);
+ // Custom field contact ref filters
+ if (is_string($data['filter'] ?? NULL) && strpos($data['filter'], '=')) {
+ $filters = explode('&', $data['filter']);
+ $inputAttrs['filter'] = $filters;
+ }
$map = [
'Select Date' => 'Date',
foreach ($inputAttrs as $key => $val) {
if ($key !== strtolower($key)) {
unset($inputAttrs[$key]);
- $key = strtolower(preg_replace('/(?=[A-Z])/', '_$0', $key));
+ $key = \CRM_Utils_String::convertStringToSnakeCase($key);
$inputAttrs[$key] = $val;
}
+ // Format EntityRef filter property (core and custom fields)
+ if ($key === 'filter' && is_array($val)) {
+ $filters = [];
+ foreach ($val as $filter) {
+ [$k, $v] = explode('=', $filter);
+ $filters[$k] = $v;
+ }
+ // Legacy APIv3 custom field stuff
+ if ($dataTypeName === 'ContactReference') {
+ if (!empty($filters['group'])) {
+ $filters['groups'] = $filters['group'];
+ }
+ unset($filters['action'], $filters['group']);
+ }
+ $inputAttrs['filter'] = $filters;
+ }
}
$fieldSpec
->setInputType($inputType)
$formDataModel = new FormDataModel($afform['layout']);
$entity = $formDataModel->getEntity($entityName);
$isId = $fieldName === CoreUtil::getIdFieldName($entity['type']);
+ $field = civicrm_api4($entity['type'], 'getFields', [
+ 'checkPermissions' => FALSE,
+ 'where' => [['name', '=', $fieldName]],
+ ])->single();
// For the "Existing Entity" selector,
// Look up the "type" fields (e.g. contact_type, activity_type_id, case_type_id, etc)
// And apply it as a filter if specified on the form.
if ($isId) {
- $typeFields = [];
if ($entity['type'] === 'Contact') {
$typeFields = ['contact_type', 'contact_sub_type'];
}
}
}
}
+ foreach ($field['input_attrs']['filter'] ?? [] as $key => $value) {
+ $apiRequest->addFilter($key, $value);
+ }
$apiRequest->setCheckPermissions($entity['security'] !== 'FBAC');
$apiRequest->setSavedSearch($entity['fields'][$fieldName]['defn']['saved_search'] ?? NULL);
<?php
use Civi\Api4\Contact;
+use Civi\Api4\GroupContact;
/**
* Test case for Afform with autocomplete.
$this->assertEquals('B ' . $lastName, $result[1]['label']);
}
+ public function testCustomContactRefFieldWithGroupsFilter(): void {
+ $lastName = uniqid(__FUNCTION__);
+
+ $sampleData = [
+ ['last_name' => $lastName, 'first_name' => 'A'],
+ ['last_name' => $lastName, 'first_name' => 'B'],
+ ['last_name' => $lastName, 'first_name' => 'C'],
+ ];
+
+ $contacts = Contact::save(FALSE)
+ ->setRecords($sampleData)
+ ->execute();
+
+ $group = \Civi\Api4\Group::create(FALSE)
+ ->addValue('name', $lastName)
+ ->addValue('title', $lastName)
+ ->addChain('A', GroupContact::create()->addValue('group_id', '$id')->addValue('contact_id', $contacts[0]['id']))
+ ->addChain('B', GroupContact::create()->addValue('group_id', '$id')->addValue('contact_id', $contacts[1]['id']))
+ ->execute()->single();
+
+ \Civi\Api4\CustomGroup::create(FALSE)
+ ->addValue('title', 'test_af_fields')
+ ->addValue('extends', 'Contact')
+ ->addChain('fields', \Civi\Api4\CustomField::save()
+ ->addDefault('custom_group_id', '$id')
+ ->setRecords([
+ ['label' => 'contact_ref', 'data_type' => 'ContactReference', 'html_type' => 'Autocomplete', 'filter' => 'action=get&group=' . $group['id']],
+ ])
+ )
+ ->execute();
+
+ $layout = <<<EOHTML
+<af-form ctrl="afform">
+ <af-entity data="{contact_type: 'Individual'}" type="Contact" name="Individual1" label="Individual 1" actions="{create: true, update: true}" security="RBAC" />
+ <fieldset af-fieldset="Individual1" class="af-container" af-title="Individual 1">
+ <div class="af-container">
+ <af-field name="test_af_fields.contact_ref" />
+ </div>
+ </fieldset>
+</af-form>
+EOHTML;
+
+ $this->useValues([
+ 'layout' => $layout,
+ 'permission' => CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION,
+ ]);
+
+ $result = Contact::autocomplete()
+ ->setFormName('afform:' . $this->formName)
+ ->setFieldName('Individual1:test_af_fields.contact_ref')
+ ->setInput($lastName)
+ ->execute();
+
+ $this->assertCount(2, $result);
+ $this->assertEquals('A ' . $lastName, $result[0]['label']);
+ $this->assertEquals('B ' . $lastName, $result[1]['label']);
+ }
+
}
$this->assertEquals('Contact', $tagFields['entity_id']['fk_entity']);
}
+ public function testFiltersAreReturned(): void {
+ $field = Contact::getFields(FALSE)
+ ->addWhere('name', '=', 'employer_id')
+ ->execute()->single();
+ $this->assertEquals(['contact_type' => 'Organization'], $field['input_attrs']['filter']);
+ }
+
}
$this->assertArrayHasKey('always.on', $participant3Fields);
}
+ public function testFiltersAreReturnedForContactRefFields(): void {
+ $grp = CustomGroup::create(FALSE)
+ ->addValue('extends', 'Activity')
+ ->addValue('title', 'act_test_grp2')
+ ->execute()->single();
+ $field = $this->createTestRecord('CustomField', [
+ 'data_type' => 'ContactReference',
+ 'html_type' => 'Autocomplete-Select',
+ 'custom_group_id' => $grp['id'],
+ 'filter' => 'action=get&contact_type=Household&group=2',
+ ]);
+ $getField = Activity::getFields(FALSE)
+ ->addWhere('custom_field_id', '=', $field['id'])
+ ->execute()->single();
+ $this->assertEquals(['contact_type' => 'Household', 'groups' => 2], $getField['input_attrs']['filter']);
+ }
+
}
<html>
<type>EntityRef</type>
<label>Current Employer</label>
+ <filter>contact_type=Organization</filter>
</html>
<contactType>Individual</contactType>
</field>
{if $field.html}
'html' => array(
{foreach from=$field.html item=val key=key}
- '{$key}' => {if $key eq 'label'}{$tsFunctionName}("{$val}"){else}'{$val}'{/if},
+ '{$key}' => {if $key eq 'label'}{$tsFunctionName}("{$val}"){elseif is_array($val)}{$val|@print_array}{else}'{$val}'{/if},
{/foreach}
),
{/if}