diff --git a/CRM/Api4/Page/Api4Explorer.php b/CRM/Api4/Page/Api4Explorer.php index 655800bfe596..af188f313609 100644 --- a/CRM/Api4/Page/Api4Explorer.php +++ b/CRM/Api4/Page/Api4Explorer.php @@ -40,9 +40,7 @@ public function run() { 'groupOptions' => array_column((array) $groupOptions, 'options', 'name'), ]; Civi::resources() - ->addBundle('bootstrap3') ->addVars('api4', $vars) - ->addPermissions(['access debug output', 'edit groups', 'administer reserved groups']) ->addScriptFile('civicrm', 'bower_components/js-yaml/dist/js-yaml.min.js') ->addScriptFile('civicrm', 'bower_components/marked/marked.min.js') ->addScriptFile('civicrm', 'bower_components/google-code-prettify/bin/prettify.min.js') diff --git a/ang/api4Explorer.ang.php b/ang/api4Explorer.ang.php index 2eec108aaf14..d0ac2be6ecfe 100644 --- a/ang/api4Explorer.ang.php +++ b/ang/api4Explorer.ang.php @@ -1,5 +1,5 @@ 'civicrm', 'js' => [ @@ -13,5 +13,7 @@ 'ang/api4Explorer', ], 'basePages' => [], + 'bundles' => ['bootstrap3'], + 'permissions' => ['access debug output', 'edit groups', 'administer reserved groups'], 'requires' => ['crmUi', 'crmUtil', 'ngRoute', 'crmRouteBinder', 'ui.sortable', 'api4', 'ngSanitize', 'dialogService', 'checklist-model'], ]; diff --git a/ang/api4Explorer/Explorer.js b/ang/api4Explorer/Explorer.js index 50e793565757..c51793b3a241 100644 --- a/ang/api4Explorer/Explorer.js +++ b/ang/api4Explorer/Explorer.js @@ -122,12 +122,15 @@ } // Replaces contents of fieldList array with current fields formatted for select2 - function getFieldList(fieldList, action, addPseudoconstant) { + function getFieldList(fieldList, action, addPseudoconstant, addWriteJoins) { var fieldInfo = _.cloneDeep(_.findWhere(getEntity().actions, {name: action}).fields); fieldList.length = 0; if (addPseudoconstant) { addPseudoconstants(fieldInfo, addPseudoconstant); } + if (addWriteJoins) { + addWriteJoinFields(fieldInfo); + } formatForSelect2(fieldInfo, fieldList, 'name', ['description', 'required', 'default_value']); } @@ -194,6 +197,19 @@ }); } + // Adds join fields for create actions + // Note: this function transforms a raw list a-la getFields; not a select2-formatted list + function addWriteJoinFields(fieldList) { + _.eachRight(fieldList, function(field, pos) { + var fkNameField = field.fk_entity && getField('name', field.fk_entity, $scope.action); + if (fkNameField) { + var newField = _.cloneDeep(fkNameField); + newField.name = field.name + '.' + newField.name; + fieldList.splice(pos, 0, newField); + } + }); + } + $scope.help = function(title, content) { if (!content) { $scope.helpTitle = helpTitle; @@ -263,12 +279,13 @@ $scope.fieldList = function(param) { return function() { var fields = []; - getFieldList(fields, $scope.action === 'getFields' ? ($scope.params.action || 'get') : $scope.action, ['name']); + getFieldList(fields, $scope.action === 'getFields' ? ($scope.params.action || 'get') : $scope.action, ['name'], true); // Disable fields that are already in use _.each($scope.params[param] || [], function(val) { - var usedField = val[0].replace(':name', ''); + var usedField = val[0].replace(/[:.]name/, ''); (_.findWhere(fields, {id: usedField}) || {}).disabled = true; (_.findWhere(fields, {id: usedField + ':name'}) || {}).disabled = true; + (_.findWhere(fields, {id: usedField + '.name'}) || {}).disabled = true; }); return {results: fields}; }; @@ -1194,7 +1211,8 @@ $el.removeClass('loading').crmSelect2({data: options, multiple: multi}); }); } else if (field.fk_entity) { - $el.crmEntityRef({entity: field.fk_entity, select:{multiple: multi}, static: field.fk_entity === 'Contact' ? ['user_contact_id'] : []}); + var apiParams = field.id_field ? {id_field: field.id_field} : {}; + $el.crmEntityRef({entity: field.fk_entity, api: apiParams, select: {multiple: multi}, static: field.fk_entity === 'Contact' ? ['user_contact_id'] : []}); } else if (dataType === 'Boolean') { $el.attr('placeholder', ts('- select -')).crmSelect2({allowClear: false, multiple: multi, placeholder: ts('- select -'), data: [ {id: 'true', text: ts('Yes')}, @@ -1374,10 +1392,15 @@ var suffix = fieldName.split(':')[1]; fieldName = fieldName.split(':')[0]; var fieldNames = fieldName.split('.'); - var field = get(entity, fieldNames); + var field = _.cloneDeep(get(entity, fieldNames)); if (field && suffix) { field.pseudoconstant = suffix; } + // When joining to a 'name' field, value fields should render an appropriate entityRef + if (field && field.type === 'Field' && field.name === 'name' && _.includes(fieldName, '.')) { + field.fk_entity = field.entity; + field.id_field = 'name'; + } return field; function get(entity, fieldNames) { diff --git a/api/v3/Activity.php b/api/v3/Activity.php index 422ebff5905d..d6dc51b7ffab 100644 --- a/api/v3/Activity.php +++ b/api/v3/Activity.php @@ -744,6 +744,8 @@ function _civicrm_api3_activity_getlist_params(&$request) { 'activity_type_id', 'subject', 'source_contact_id', + $request['id_field'], + $request['label_field'], ]; $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra'])); $request['params']['options']['sort'] = 'activity_date_time DESC'; diff --git a/api/v3/Campaign.php b/api/v3/Campaign.php index 3ea11481d9b8..3a39dd3bc03a 100644 --- a/api/v3/Campaign.php +++ b/api/v3/Campaign.php @@ -81,7 +81,15 @@ function civicrm_api3_campaign_delete($params) { * @param array $request */ function _civicrm_api3_campaign_getlist_params(&$request) { - $fieldsToReturn = ['title', 'campaign_type_id', 'status_id', 'start_date', 'end_date']; + $fieldsToReturn = [ + 'title', + 'campaign_type_id', + 'status_id', + 'start_date', + 'end_date', + $request['id_field'], + $request['label_field'], + ]; $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra'])); if (empty($request['params']['id'])) { $request['params']['options']['sort'] = 'start_date DESC, title'; diff --git a/api/v3/Event.php b/api/v3/Event.php index 324bb9775b27..f20d6702cf81 100644 --- a/api/v3/Event.php +++ b/api/v3/Event.php @@ -204,7 +204,14 @@ function _civicrm_api3_event_getisfull(&$event, $event_id) { * @param array $request */ function _civicrm_api3_event_getlist_params(&$request) { - $fieldsToReturn = ['start_date', 'event_type_id', 'title', 'summary']; + $fieldsToReturn = [ + 'start_date', + 'event_type_id', + 'title', + 'summary', + $request['id_field'], + $request['label_field'], + ]; $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra'])); $request['params']['options']['sort'] = 'start_date DESC'; if (empty($request['params']['id'])) { diff --git a/api/v3/MembershipType.php b/api/v3/MembershipType.php index 9dd682e0a9fb..595b18046a23 100644 --- a/api/v3/MembershipType.php +++ b/api/v3/MembershipType.php @@ -106,6 +106,7 @@ function _civicrm_api3_membership_type_get_spec(&$params) { * Array of parameters determined by getfields. */ function _civicrm_api3_membership_type_getlist_params(&$request) { + _civicrm_api3_generic_getlist_params($request); if (!isset($request['params']['is_active']) && empty($request['params']['id'])) { $request['params']['is_active'] = 1; } diff --git a/ext/afform/core/api/v3/Afform.php b/ext/afform/core/api/v3/Afform.php index 41c20c63a487..fda6038cb506 100644 --- a/ext/afform/core/api/v3/Afform.php +++ b/ext/afform/core/api/v3/Afform.php @@ -88,7 +88,14 @@ function _civicrm_api3_afform_get_spec(&$fields) { * API request. */ function _civicrm_api3_afform_getlist_params(&$request) { - $fieldsToReturn = ['name', 'title', 'type', 'description']; + $fieldsToReturn = [ + 'name', + 'title', + 'type', + 'description', + $request['id_field'], + $request['label_field'], + ]; $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra'])); }