if ($fkClass) {
$tableName = AllCoreTables::getTableForClass($fkClass);
$fkKey = $data['FKKeyColumn'] ?? 'id';
+ // Fixme: Clumsy string manipulation to transform e.g. "contact_id" to "contact" - we never should have done this
$alias = str_replace('_id', '', $field);
$joinable = new Joinable($tableName, $fkKey, $alias);
$joinable->setJoinType($joinable::JOIN_TYPE_MANY_TO_ONE);
}
$fieldData = \CRM_Utils_SQL_Select::from('civicrm_custom_field f')
->join('custom_group', 'INNER JOIN civicrm_custom_group g ON g.id = f.custom_group_id')
- ->select(['g.name as custom_group_name', 'g.table_name', 'g.is_multiple', 'f.name', 'label', 'column_name', 'option_group_id'])
+ ->select(['g.name as custom_group_name', 'g.table_name', 'g.is_multiple', 'f.name', 'f.data_type', 'label', 'column_name', 'option_group_id'])
->where('g.extends IN (@entity)', ['@entity' => $customInfo['extends']])
->where('g.is_active')
->where('f.is_active')
$joinable = new Joinable($baseTable->getName(), $customInfo['column'], AllCoreTables::convertEntityNameToLower($entityName));
$customTable->addTableLink('entity_id', $joinable);
}
+
+ if ($fieldData->data_type === 'ContactReference') {
+ $joinable = new Joinable('civicrm_contact', 'id', $fieldData->name);
+ $customTable->addTableLink($fieldData->column_name, $joinable);
+ }
}
foreach ($links as $alias => $link) {
if (in_array('DAOEntity', $entity['type'], TRUE) && !in_array('EntityBridge', $entity['type'], TRUE)) {
foreach (array_reverse($entity['fields'], TRUE) as $index => $field) {
if (!empty($field['fk_entity']) && !$field['options'] && !empty($schema[$field['fk_entity']]['label_field'])) {
- // The original field will get title instead of label since it represents the id (title usually ends in ID but label does not)
- $entity['fields'][$index]['label'] = $field['title'];
+ $isCustom = strpos($field['name'], '.');
+ // Custom fields: append "ID" to original field label
+ if ($isCustom) {
+ $entity['fields'][$index]['label'] .= ' ' . E::ts('Contact ID');
+ }
+ // DAO fields: use title instead of label since it represents the id (title usually ends in ID but label does not)
+ else {
+ $entity['fields'][$index]['label'] = $field['title'];
+ }
// Add the label field from the other entity to this entity's list of fields
$newField = \CRM_Utils_Array::findAll($schema[$field['fk_entity']]['fields'], ['name' => $schema[$field['fk_entity']]['label_field']])[0];
- $newField['name'] = str_replace('_id', '', $field['name']) . '.' . $schema[$field['fk_entity']]['label_field'];
+ // Due to string manipulation in \Civi\Api4\Service\Schema\SchemaMapBuilder::addJoins()
+ $alias = $isCustom ? $field['name'] : str_replace('_id', '', $field['name']);
+ $newField['name'] = $alias . '.' . $schema[$field['fk_entity']]['label_field'];
$newField['label'] = $field['label'] . ' ' . $newField['label'];
array_splice($entity['fields'], $index, 0, [$newField]);
}
return new RegExp('^' + join.alias + '_\\d\\d').test(path);
});
if (!join) {
- console.warn( 'Join ' + fullNameOrAlias + ' not found.');
return;
}
path = path.replace(join.alias + '_', '');
return result;
}
function getFieldAndJoin(fieldName, entityName) {
- var dotSplit = fieldName.split('.'),
- joinEntity = dotSplit.length > 1 ? dotSplit[0] : null,
- name = _.last(dotSplit).split(':')[0],
+ var fieldPath = fieldName.split(':')[0],
+ dotSplit = fieldPath.split('.'),
+ name,
join,
field;
- // Custom fields contain a dot in their fieldname
- // If 3 segments, the first is the joinEntity and the last 2 are the custom field
- if (dotSplit.length === 3) {
- name = dotSplit[1] + '.' + name;
- }
- // If 2 segments, it's ambiguous whether this is a custom field or joined field. Search the main entity first.
- if (dotSplit.length === 2) {
- field = _.find(getEntity(entityName).fields, {name: dotSplit[0] + '.' + name});
- if (field) {
- field.baseEntity = entityName;
- return {field: field};
+ // If 2 or more segments, the first might be the name of a join
+ if (dotSplit.length > 1) {
+ join = getJoin(dotSplit[0]);
+ if (join) {
+ dotSplit.shift();
+ entityName = join.entity;
}
}
- if (joinEntity) {
- join = getJoin(joinEntity);
- entityName = getJoin(joinEntity).entity;
- }
+ name = dotSplit.join('.');
field = _.find(getEntity(entityName).fields, {name: name});
if (!field && join && join.bridge) {
field = _.find(getEntity(join.bridge).fields, {name: name});
--- /dev/null
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+
+namespace api\v4\Action;
+
+use Civi\Api4\Contact;
+use Civi\Api4\CustomField;
+use Civi\Api4\CustomGroup;
+
+/**
+ * @group headless
+ */
+class CustomJoinTest extends BaseCustomValueTest {
+
+ public function testGetWithJoin() {
+
+ $customGroup = CustomGroup::create(FALSE)
+ ->addValue('name', 'MyContactRef')
+ ->addValue('extends', 'Individual')
+ ->execute()
+ ->first();
+
+ CustomField::create(FALSE)
+ ->addValue('label', 'FavPerson')
+ ->addValue('custom_group_id', $customGroup['id'])
+ ->addValue('html_type', 'Autocomplete-Select')
+ ->addValue('data_type', 'ContactReference')
+ ->execute();
+
+ $favPersonId = Contact::create(FALSE)
+ ->addValue('first_name', 'Favorite')
+ ->addValue('last_name', 'Person')
+ ->addValue('contact_type', 'Individual')
+ ->execute()
+ ->first()['id'];
+
+ $contactId = Contact::create(FALSE)
+ ->addValue('first_name', 'Mya')
+ ->addValue('last_name', 'Tester')
+ ->addValue('contact_type', 'Individual')
+ ->addValue('MyContactRef.FavPerson', $favPersonId)
+ ->execute()
+ ->first()['id'];
+
+ $contact = Contact::get(FALSE)
+ ->addSelect('display_name')
+ ->addSelect('MyContactRef.FavPerson.first_name')
+ ->addSelect('MyContactRef.FavPerson.last_name')
+ ->addWhere('id', '=', $contactId)
+ ->execute()
+ ->first();
+
+ $this->assertEquals('Favorite', $contact['MyContactRef.FavPerson.first_name']);
+ $this->assertEquals('Person', $contact['MyContactRef.FavPerson.last_name']);
+ }
+
+}
* @copyright CiviCRM LLC https://civicrm.org/licensing
*/
-// vim: set si ai expandtab tabstop=4 shiftwidth=4 softtabstop=4:
-
-/**
- * File for the api_v4_AllTests class
- *
- * (PHP 5)
- *
- * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
- * @copyright Copyright CiviCRM LLC (C) 2009
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
- * GNU Affero General Public License version 3
- * @version $Id: AllTests.php 40328 2012-05-11 23:06:13Z allen $
- * @package CiviCRM
- *
- * This file is part of CiviCRM
- *
- * CiviCRM is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
- *
- * CiviCRM is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
/**
* Class containing the APIv4 test suite
*
}
}
-// class AllTests
-
-// -- set Emacs parameters --
-// Local variables:
-// mode: php;
-// tab-width: 4
-// c-basic-offset: 4
-// c-hanging-comment-ender-p: nil
-// indent-tabs-mode: nil
-// End: