Skip to content

Commit

Permalink
APIv4 - Add entity metadata about class args
Browse files Browse the repository at this point in the history
The CustomValue API is a virtual API, where multiple entities all get routed to the
same class if they share the prefix "Custom_", and pass a class arg to the
php factory functions e.g. `CustomValue::get('MyCustomGroup')`.
Instead of hard-coding this idea into the  now it's part of the entity
metadata so that other APIs, notaby ECK, can use a similar pattern.
  • Loading branch information
colemanw committed Feb 27, 2022
1 parent 1f3e4c2 commit febfaa1
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 13 deletions.
5 changes: 5 additions & 0 deletions Civi/Api4/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ public static function getFields($checkPermissions = TRUE) {
'data_type' => 'String',
'description' => 'PHP class name',
],
[
'name' => 'class_args',
'data_type' => 'Array',
'description' => 'Arguments needed by php action factory functions (used when multiple entities share a class, e.g. CustomValue).',
],
[
'name' => 'bridge',
'data_type' => 'Array',
Expand Down
15 changes: 8 additions & 7 deletions Civi/Api4/Provider/CustomEntityProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,28 @@ public static function addCustomEntities(GenericHookEvent $e) {
->toSQL();
$group = \CRM_Core_DAO::executeQuery($select);
while ($group->fetch()) {
$fieldName = 'Custom_' . $group->name;
$entityName = 'Custom_' . $group->name;
$baseEntity = CoreUtil::getApiClass(CustomGroupJoinable::getEntityFromExtends($group->extends));
$e->entities[$fieldName] = [
'name' => $fieldName,
$e->entities[$entityName] = [
'name' => $entityName,
'title' => $group->title,
'title_plural' => $group->title,
'table_name' => $group->table_name,
'class_args' => [$group->name],
'description' => ts('Custom group for %1', [1 => $baseEntity::getInfo()['title_plural']]),
'paths' => [
'view' => "civicrm/contact/view/cd?reset=1&gid={$group->id}&recId=[id]&multiRecordDisplay=single",
],
] + $baseInfo;
if (!empty($group->icon)) {
$e->entities[$fieldName]['icon'] = $group->icon;
$e->entities[$entityName]['icon'] = $group->icon;
}
if (!empty($group->help_pre)) {
$e->entities[$fieldName]['comment'] = self::plainTextify($group->help_pre);
$e->entities[$entityName]['comment'] = self::plainTextify($group->help_pre);
}
if (!empty($group->help_post)) {
$pre = empty($e->entities[$fieldName]['comment']) ? '' : $e->entities[$fieldName]['comment'] . "\n\n";
$e->entities[$fieldName]['comment'] = $pre . self::plainTextify($group->help_post);
$pre = empty($e->entities[$entityName]['comment']) ? '' : $e->entities[$entityName]['comment'] . "\n\n";
$e->entities[$entityName]['comment'] = $pre . self::plainTextify($group->help_post);
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions ang/api4Explorer/Explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -688,13 +688,14 @@
var code = {},
entity = $scope.entity,
action = $scope.action,
args = getEntity(entity).class_args || [],
params = getParams(),
index = isInt($scope.index) ? +$scope.index : parseYaml($scope.index),
result = 'result';
if ($scope.entity && $scope.action) {
delete params.debug;
if (action.slice(0, 3) === 'get') {
result = entity.substr(0, 7) === 'Custom_' ? _.camelCase(entity.substr(7)) : entity;
result = args[0] ? _.camelCase(args[0]) : entity;
result = lcfirst(action.replace(/s$/, '').slice(3) || result);
}
var results = lcfirst(_.isNumber(index) ? result : pluralize(result)),
Expand Down Expand Up @@ -862,12 +863,11 @@
arrayParams = ['groupBy', 'records'],
newLine = "\n" + _.repeat(' ', indent),
code = '\\' + info.class + '::' + action + '(',
perm = params.checkPermissions === false ? 'FALSE' : '';
if (entity.substr(0, 7) !== 'Custom_') {
code += perm + ')';
} else {
code += "'" + entity.substr(7) + "'" + (perm ? ', ' : '') + perm + ")";
args = _.cloneDeep(info.class_args || []);
if (params.checkPermissions === false) {
args.push(false);
}
code += _.map(args, phpFormat).join(', ') + ')';
_.each(params, function(param, key) {
var val = '';
if (typeof objectParams[key] !== 'undefined' && key !== 'chain') {
Expand Down
11 changes: 11 additions & 0 deletions tests/phpunit/api/v4/Action/CustomValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Civi\Api4\CustomGroup;
use Civi\Api4\CustomValue;
use Civi\Api4\Contact;
use Civi\Api4\Entity;

/**
* @group headless
Expand Down Expand Up @@ -79,6 +80,16 @@ public function testCRUD() {
->execute()
->first()['id'];

// Ensure virtual api entity has been created
$entity = Entity::get(FALSE)
->addWhere('name', '=', "Custom_$group")
->execute()->single();
$this->assertEquals(['CustomValue'], $entity['type']);
$this->assertEquals(['id'], $entity['primary_key']);
$this->assertEquals('Civi\Api4\CustomValue', $entity['class']);
$this->assertEquals([$group], $entity['class_args']);
$this->assertEquals('secondary', $entity['searchable']);

// Retrieve and check the fields of CustomValue = Custom_$group
$fields = CustomValue::getFields($group)->setLoadOptions(TRUE)->setCheckPermissions(FALSE)->execute();
$expectedResult = [
Expand Down

0 comments on commit febfaa1

Please sign in to comment.