From 465bc32a8c9bb7135ccea1ea10aadd5d62407703 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 20 Nov 2020 21:53:30 -0500 Subject: [PATCH] Use trait instead of class for Entity Bridges; add OptionList trait Traits allow each entity to have > 1 type This excludes both EntityBridge and OptionList types from the main search dropdown. --- Civi/Api4/ActivityContact.php | 3 ++- Civi/Api4/Country.php | 1 + Civi/Api4/DashboardContact.php | 3 ++- Civi/Api4/Entity.php | 9 +++++++- Civi/Api4/EntityTag.php | 3 ++- Civi/Api4/Generic/AbstractEntity.php | 5 ++++- Civi/Api4/Generic/DAOGetAction.php | 4 ++-- .../EntityBridge.php} | 6 +++--- Civi/Api4/Generic/Traits/OptionList.php | 21 +++++++++++++++++++ Civi/Api4/GroupContact.php | 3 ++- Civi/Api4/LocationType.php | 1 + Civi/Api4/MembershipType.php | 1 + Civi/Api4/OptionValue.php | 1 + Civi/Api4/PaymentProcessorType.php | 1 + Civi/Api4/Query/Api4SelectQuery.php | 8 ++++--- Civi/Api4/RelationshipCache.php | 1 + Civi/Api4/RelationshipType.php | 1 + Civi/Api4/StateProvince.php | 1 + Civi/Api4/UFJoin.php | 1 + Civi/Api4/UFMatch.php | 3 ++- ang/api4Explorer/Explorer.js | 3 ++- ext/search/Civi/Search/Admin.php | 2 +- .../crmSearchAdmin.component.js | 7 ++++++- 23 files changed, 71 insertions(+), 18 deletions(-) rename Civi/Api4/Generic/{BridgeEntity.php => Traits/EntityBridge.php} (80%) create mode 100644 Civi/Api4/Generic/Traits/OptionList.php diff --git a/Civi/Api4/ActivityContact.php b/Civi/Api4/ActivityContact.php index e0d39cfb27..1af0de36ff 100644 --- a/Civi/Api4/ActivityContact.php +++ b/Civi/Api4/ActivityContact.php @@ -29,6 +29,7 @@ namespace Civi\Api4; * @see \Civi\Api4\Activity * @package Civi\Api4 */ -class ActivityContact extends Generic\BridgeEntity { +class ActivityContact extends Generic\DAOEntity { + use Generic\Traits\EntityBridge; } diff --git a/Civi/Api4/Country.php b/Civi/Api4/Country.php index c1845d7ba0..ccc9442789 100644 --- a/Civi/Api4/Country.php +++ b/Civi/Api4/Country.php @@ -24,5 +24,6 @@ namespace Civi\Api4; * @package Civi\Api4 */ class Country extends Generic\DAOEntity { + use Generic\Traits\OptionList; } diff --git a/Civi/Api4/DashboardContact.php b/Civi/Api4/DashboardContact.php index 3133272041..4ca8b6ecf6 100644 --- a/Civi/Api4/DashboardContact.php +++ b/Civi/Api4/DashboardContact.php @@ -26,6 +26,7 @@ namespace Civi\Api4; * @see \Civi\Api4\Dashboard * @package Civi\Api4 */ -class DashboardContact extends Generic\BridgeEntity { +class DashboardContact extends Generic\DAOEntity { + use Generic\Traits\EntityBridge; } diff --git a/Civi/Api4/Entity.php b/Civi/Api4/Entity.php index 883e80dc5c..e326df3830 100644 --- a/Civi/Api4/Entity.php +++ b/Civi/Api4/Entity.php @@ -58,8 +58,15 @@ class Entity extends Generic\AbstractEntity { ], [ 'name' => 'type', + 'data_type' => 'Array', 'description' => 'Base class for this entity', - 'options' => ['DAOEntity' => 'DAOEntity', 'BasicEntity' => 'BasicEntity', 'BridgeEntity' => 'BridgeEntity', 'AbstractEntity' => 'AbstractEntity'], + 'options' => [ + 'AbstractEntity' => 'AbstractEntity', + 'DAOEntity' => 'DAOEntity', + 'BasicEntity' => 'BasicEntity', + 'EntityBridge' => 'EntityBridge', + 'OptionList' => 'OptionList', + ], ], [ 'name' => 'description', diff --git a/Civi/Api4/EntityTag.php b/Civi/Api4/EntityTag.php index aeefb3d747..2febe72254 100644 --- a/Civi/Api4/EntityTag.php +++ b/Civi/Api4/EntityTag.php @@ -25,6 +25,7 @@ namespace Civi\Api4; * * @package Civi\Api4 */ -class EntityTag extends Generic\BridgeEntity { +class EntityTag extends Generic\DAOEntity { + use Generic\Traits\EntityBridge; } diff --git a/Civi/Api4/Generic/AbstractEntity.php b/Civi/Api4/Generic/AbstractEntity.php index 443a7f186c..a07dc847d1 100644 --- a/Civi/Api4/Generic/AbstractEntity.php +++ b/Civi/Api4/Generic/AbstractEntity.php @@ -133,9 +133,12 @@ abstract class AbstractEntity { 'name' => static::getEntityName(), 'title' => static::getEntityTitle(), 'title_plural' => static::getEntityTitle(TRUE), - 'type' => self::stripNamespace(get_parent_class(static::class)), + 'type' => [self::stripNamespace(get_parent_class(static::class))], 'paths' => static::getEntityPaths(), ]; + foreach (ReflectionUtils::getTraits(static::class) as $trait) { + $info['type'][] = self::stripNamespace($trait); + } $reflection = new \ReflectionClass(static::class); $info += ReflectionUtils::getCodeDocs($reflection, NULL, ['entity' => $info['name']]); unset($info['package'], $info['method']); diff --git a/Civi/Api4/Generic/DAOGetAction.php b/Civi/Api4/Generic/DAOGetAction.php index 852a333ccf..055eb72370 100644 --- a/Civi/Api4/Generic/DAOGetAction.php +++ b/Civi/Api4/Generic/DAOGetAction.php @@ -59,13 +59,13 @@ class DAOGetAction extends AbstractGetAction { * * - `Entity`: the name of the api entity to join onto. * - `Required`: `TRUE` for an `INNER JOIN`, `FALSE` for a `LEFT JOIN`. - * - `Bridge` (optional): Name of a BridgeEntity to incorporate into the join. + * - `Bridge` (optional): Name of a Bridge to incorporate into the join. * - `[field, op, value]...`: zero or more conditions for the ON clause, using the same nested format as WHERE and HAVING * but with the difference that "value" is interpreted as an expression (e.g. can be the name of a field). * Enclose literal values with quotes. * * @var array - * @see \Civi\Api4\Generic\BridgeEntity + * @see \Civi\Api4\Generic\Traits\EntityBridge */ protected $join = []; diff --git a/Civi/Api4/Generic/BridgeEntity.php b/Civi/Api4/Generic/Traits/EntityBridge.php similarity index 80% rename from Civi/Api4/Generic/BridgeEntity.php rename to Civi/Api4/Generic/Traits/EntityBridge.php index 32faea1aa5..1123021dba 100644 --- a/Civi/Api4/Generic/BridgeEntity.php +++ b/Civi/Api4/Generic/Traits/EntityBridge.php @@ -9,13 +9,13 @@ +--------------------------------------------------------------------+ */ -namespace Civi\Api4\Generic; +namespace Civi\Api4\Generic\Traits; /** * A bridge is a small table that provides an intermediary link between two other tables. * - * The API can automatically incorporate a bridgeEntity into a join expression. + * The API can automatically incorporate a Bridge into a join expression. */ -class BridgeEntity extends DAOEntity { +trait EntityBridge { } diff --git a/Civi/Api4/Generic/Traits/OptionList.php b/Civi/Api4/Generic/Traits/OptionList.php new file mode 100644 index 0000000000..fb400cc55e --- /dev/null +++ b/Civi/Api4/Generic/Traits/OptionList.php @@ -0,0 +1,21 @@ + 4, 'checkPermissions' => $this->getCheckPermissions()]); + $bridgeEntityGet = $bridgeEntityClass::get($this->getCheckPermissions()); $fkToJoinField = $fkToBaseField = NULL; // Find the bridge field that links to the joinEntity (either an explicit FK or an entity_id/entity_table combo) foreach ($bridgeEntityGet->entityFields() as $name => $field) { diff --git a/Civi/Api4/RelationshipCache.php b/Civi/Api4/RelationshipCache.php index 4030d33180..a206cd2c27 100644 --- a/Civi/Api4/RelationshipCache.php +++ b/Civi/Api4/RelationshipCache.php @@ -27,6 +27,7 @@ namespace Civi\Api4; * @package Civi\Api4 */ class RelationshipCache extends Generic\AbstractEntity { + use Generic\Traits\EntityBridge; /** * @param bool $checkPermissions diff --git a/Civi/Api4/RelationshipType.php b/Civi/Api4/RelationshipType.php index 5032e947fb..883a7c48b4 100644 --- a/Civi/Api4/RelationshipType.php +++ b/Civi/Api4/RelationshipType.php @@ -27,5 +27,6 @@ namespace Civi\Api4; * @package Civi\Api4 */ class RelationshipType extends Generic\DAOEntity { + use Generic\Traits\OptionList; } diff --git a/Civi/Api4/StateProvince.php b/Civi/Api4/StateProvince.php index 1b0eb9efe9..97ec5e5259 100644 --- a/Civi/Api4/StateProvince.php +++ b/Civi/Api4/StateProvince.php @@ -24,5 +24,6 @@ namespace Civi\Api4; * @package Civi\Api4 */ class StateProvince extends Generic\DAOEntity { + use Generic\Traits\OptionList; } diff --git a/Civi/Api4/UFJoin.php b/Civi/Api4/UFJoin.php index 7e6369de58..a5c8ce9008 100644 --- a/Civi/Api4/UFJoin.php +++ b/Civi/Api4/UFJoin.php @@ -26,5 +26,6 @@ namespace Civi\Api4; * @package Civi\Api4 */ class UFJoin extends Generic\DAOEntity { + use Generic\Traits\EntityBridge; } diff --git a/Civi/Api4/UFMatch.php b/Civi/Api4/UFMatch.php index 6cc1c4ee59..c7956c9d88 100644 --- a/Civi/Api4/UFMatch.php +++ b/Civi/Api4/UFMatch.php @@ -24,6 +24,7 @@ namespace Civi\Api4; * * @package Civi\Api4 */ -class UFMatch extends Generic\BridgeEntity { +class UFMatch extends Generic\DAOEntity { + use Generic\Traits\EntityBridge; } diff --git a/ang/api4Explorer/Explorer.js b/ang/api4Explorer/Explorer.js index 4b8c0257d9..82bce19045 100644 --- a/ang/api4Explorer/Explorer.js +++ b/ang/api4Explorer/Explorer.js @@ -57,7 +57,7 @@ $scope.controls = {}; $scope.langs = ['php', 'js', 'ang', 'cli']; $scope.joinTypes = [{k: false, v: 'FALSE (LEFT JOIN)'}, {k: true, v: 'TRUE (INNER JOIN)'}]; - $scope.bridgeEntities = _.filter(schema, {type: 'BridgeEntity'}); + $scope.bridgeEntities = _.filter(schema, function(entity) {return _.includes(entity.type, 'EntityBridge');}); $scope.code = { php: [ {name: 'oop', label: ts('OOP Style'), code: ''}, @@ -873,6 +873,7 @@ setHelp($scope.entity, { description: entityInfo.description, comment: entityInfo.comment, + type: entityInfo.type, see: entityInfo.see }); } diff --git a/ext/search/Civi/Search/Admin.php b/ext/search/Civi/Search/Admin.php index bf392c57b0..ab90e7f02e 100644 --- a/ext/search/Civi/Search/Admin.php +++ b/ext/search/Civi/Search/Admin.php @@ -58,7 +58,7 @@ class Admin { public static function getSchema() { $schema = []; $entities = \Civi\Api4\Entity::get() - ->addSelect('name', 'title', 'title_plural', 'description', 'icon', 'paths') + ->addSelect('name', 'title', 'type', 'title_plural', 'description', 'icon', 'paths') ->addWhere('name', '!=', 'Entity') ->addOrderBy('title_plural') ->setChain([ diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdmin.component.js b/ext/search/ang/crmSearchAdmin/crmSearchAdmin.component.js index a62dc05a2c..1b29fe45c6 100644 --- a/ext/search/ang/crmSearchAdmin/crmSearchAdmin.component.js +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdmin.component.js @@ -27,7 +27,12 @@ $scope.controls = {tab: 'compose'}; $scope.joinTypes = [{k: false, v: ts('Optional')}, {k: true, v: ts('Required')}]; $scope.groupOptions = CRM.crmSearchActions.groupOptions; - $scope.entities = formatForSelect2(CRM.vars.search.schema, 'name', 'title_plural', ['description', 'icon']); + // Try to create a sensible list of entities one might want to search for, + // excluding those whos primary purpose is to provide joins or option lists to other entities + var primaryEntities = _.filter(CRM.vars.search.schema, function(entity) { + return !_.includes(entity.type, 'EntityBridge') && !_.includes(entity.type, 'OptionList'); + }); + $scope.entities = formatForSelect2(primaryEntities, 'name', 'title_plural', ['description', 'icon']); this.perm = { editGroups: CRM.checkPerm('edit groups') }; -- 2.25.1