Skip to content

Commit

Permalink
Afform - Support implicit joins in SearchDisplay filter fields
Browse files Browse the repository at this point in the history
  • Loading branch information
colemanw committed Jul 6, 2021
1 parent 84b531d commit 96ff473
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
22 changes: 21 additions & 1 deletion ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Civi\AfformAdmin;

use Civi\Api4\Utils\CoreUtil;
use CRM_AfformAdmin_ExtensionUtil as E;

class AfformAdminMeta {
Expand Down Expand Up @@ -104,7 +105,26 @@ public static function getFields($entityName, $params = []) {
}
$params['values']['state_province_id'] = \Civi::settings()->get('defaultContactStateProvince');
}
return (array) civicrm_api4($entityName, 'getFields', $params, 'name');
$fields = (array) civicrm_api4($entityName, 'getFields', $params);

// Add implicit joins to search fields
if ($params['action'] === 'search') {
foreach (array_reverse($fields, TRUE) as $index => $field) {
if (!empty($field['fk_entity']) && !$field['options']) {
$fkLabelField = CoreUtil::getInfoItem($field['fk_entity'], 'label_field');
if ($fkLabelField) {
// Add the label field from the other entity to this entity's list of fields
$newField = civicrm_api4($field['fk_entity'], 'getFields', [
'where' => [['name', '=', $fkLabelField]],
])->first();
$newField['name'] = $field['name'] . '.' . $newField['name'];
$newField['label'] = $field['label'] . ' ' . $newField['label'];
array_splice($fields, $index, 0, [$newField]);
}
}
}
}
return array_column($fields, NULL, 'name');
}

/**
Expand Down
61 changes: 43 additions & 18 deletions ext/afform/core/Civi/Afform/AfformMetadataInjector.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,7 @@ public static function preprocess($e) {
*/
private static function fillFieldMetadata($entityName, $action, \DOMElement $afField) {
$fieldName = $afField->getAttribute('name');
// For explicit joins, strip the alias off the field name
if (strpos($entityName, ' AS ')) {
[$entityName, $alias] = explode(' AS ', $entityName);
$fieldName = preg_replace('/^' . preg_quote($alias . '.', '/') . '/', '', $fieldName);
}
$params = [
'action' => $action,
'where' => [['name', '=', $fieldName]],
'select' => ['label', 'input_type', 'input_attrs', 'help_pre', 'help_post', 'options', 'fk_entity'],
'loadOptions' => ['id', 'label'],
// If the admin included this field on the form, then it's OK to get metadata about the field regardless of user permissions.
'checkPermissions' => FALSE,
];
if (in_array($entityName, \CRM_Contact_BAO_ContactType::basicTypes(TRUE))) {
$params['values'] = ['contact_type' => $entityName];
$entityName = 'Contact';
}
$fieldInfo = civicrm_api4($entityName, 'getFields', $params)->first();
$fieldInfo = self::getField($entityName, $fieldName, $action);
// Merge field definition data with whatever's already in the markup.
$deep = ['input_attrs'];
if ($fieldInfo) {
Expand Down Expand Up @@ -160,6 +143,48 @@ private static function fillFieldMetadata($entityName, $action, \DOMElement $afF
}
}

/**
* @param string $entityName
* @param string $fieldName
* @param string $action
* @return array|NULL
*/
private static function getField(string $entityName, string $fieldName, string $action):? array {
// For explicit joins, strip the alias off the field name
if (strpos($entityName, ' AS ')) {
[$entityName, $alias] = explode(' AS ', $entityName);
$fieldName = preg_replace('/^' . preg_quote($alias . '.', '/') . '/', '', $fieldName);
}
$namesToMatch = [$fieldName];
// Also match base field if this is an implicit join
if ($action === 'get' && strpos($fieldName, '.')) {
$namesToMatch[] = substr($fieldName, 0, strrpos($fieldName, '.'));
}
$params = [
'action' => $action,
'where' => [['name', 'IN', $namesToMatch]],
'select' => ['name', 'label', 'input_type', 'input_attrs', 'help_pre', 'help_post', 'options', 'fk_entity'],
'loadOptions' => ['id', 'label'],
// If the admin included this field on the form, then it's OK to get metadata about the field regardless of user permissions.
'checkPermissions' => FALSE,
];
if (in_array($entityName, \CRM_Contact_BAO_ContactType::basicTypes(TRUE))) {
$params['values'] = ['contact_type' => $entityName];
$entityName = 'Contact';
}
$fields = civicrm_api4($entityName, 'getFields', $params);
$field = $originalField = $fields->first();
// If this is an implicit join, get new field from fk entity
if ($field['name'] !== $fieldName && $field['fk_entity']) {
$params['where'] = [['name', '=', substr($fieldName, 1 + strrpos($fieldName, '.'))]];
$field = civicrm_api4($field['fk_entity'], 'getFields', $params)->first();
if ($field) {
$field['label'] = $originalField['label'] . ' ' . $field['label'];
}
}
return $field;
}

/**
* Determines name of the api entity based on the field name prefix
*
Expand Down

0 comments on commit 96ff473

Please sign in to comment.