diff --git a/CRM/Api4/Page/Api4Explorer.php b/CRM/Api4/Page/Api4Explorer.php index af188f313609..0f1125f5ca2c 100644 --- a/CRM/Api4/Page/Api4Explorer.php +++ b/CRM/Api4/Page/Api4Explorer.php @@ -10,7 +10,6 @@ +--------------------------------------------------------------------+ */ -use Civi\Api4\Service\Schema\Joinable\Joinable; use Civi\Api4\Utils\CoreUtil; /** @@ -23,18 +22,11 @@ class CRM_Api4_Page_Api4Explorer extends CRM_Core_Page { public function run() { $apiDoc = new ReflectionFunction('civicrm_api4'); $groupOptions = civicrm_api4('Group', 'getFields', ['loadOptions' => TRUE, 'select' => ['options', 'name'], 'where' => [['name', 'IN', ['visibility', 'group_type']]]]); - // Don't show n-to-many joins in Explorer - $entityLinks = (array) civicrm_api4('Entity', 'getLinks', [], ['entity' => 'links']); - foreach ($entityLinks as $entity => $links) { - $entityLinks[$entity] = array_filter($links, function($link) { - return $link['joinType'] != Joinable::JOIN_TYPE_ONE_TO_MANY; - }); - } + $vars = [ 'operators' => CoreUtil::getOperators(), 'basePath' => Civi::resources()->getUrl('civicrm'), 'schema' => (array) \Civi\Api4\Entity::get()->setChain(['fields' => ['$name', 'getFields']])->execute(), - 'links' => $entityLinks, 'docs' => \Civi\Api4\Utils\ReflectionUtils::parseDocBlock($apiDoc->getDocComment()), 'functions' => self::getSqlFunctions(), 'groupOptions' => array_column((array) $groupOptions, 'options', 'name'), diff --git a/Civi/Api4/Action/Entity/GetLinks.php b/Civi/Api4/Action/Entity/GetLinks.php index 8ae38eead3d2..e0458b56b599 100644 --- a/Civi/Api4/Action/Entity/GetLinks.php +++ b/Civi/Api4/Action/Entity/GetLinks.php @@ -15,11 +15,15 @@ use Civi\Api4\Utils\CoreUtil; /** - * Get a list of FK links between entities + * Get a list of FK links between entities. + * + * This action is deprecated; the API no longer uses these links to determine available joins. + * @deprecated */ class GetLinks extends \Civi\Api4\Generic\BasicGetAction { public function getRecords() { + \CRM_Core_Error::deprecatedWarning('APIv4 Entity::getLinks is deprecated.'); $result = []; /** @var \Civi\Api4\Service\Schema\SchemaMap $schema */ $schema = \Civi::container()->get('schema_map'); diff --git a/Civi/Api4/Entity.php b/Civi/Api4/Entity.php index b693895572c2..1660d74d8cb0 100644 --- a/Civi/Api4/Entity.php +++ b/Civi/Api4/Entity.php @@ -128,6 +128,7 @@ public static function getFields($checkPermissions = TRUE) { /** * @param bool $checkPermissions + * @deprecated * @return Action\Entity\GetLinks */ public static function getLinks($checkPermissions = TRUE) { diff --git a/Civi/Api4/Service/Schema/SchemaMapBuilder.php b/Civi/Api4/Service/Schema/SchemaMapBuilder.php index e89b7c359ada..7db2ac0d5bc7 100644 --- a/Civi/Api4/Service/Schema/SchemaMapBuilder.php +++ b/Civi/Api4/Service/Schema/SchemaMapBuilder.php @@ -68,8 +68,6 @@ private function loadTables(SchemaMap $map) { $this->addCustomFields($map, $table, $data['name']); } } - - $this->addBackReferences($map); } /** @@ -98,49 +96,6 @@ private function addJoins(Table $table, $field, array $data) { } } - /** - * Loop through existing links and provide link from the other side - * - * @param SchemaMap $map - */ - private function addBackReferences(SchemaMap $map) { - foreach ($map->getTables() as $table) { - foreach ($table->getTableLinks() as $link) { - $target = $map->getTableByName($link->getTargetTable()); - $tableName = $link->getBaseTable(); - // Exclude custom field tables - if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0 && strpos($link->getBaseTable(), 'civicrm_value_') !== 0) { - $plural = str_replace('civicrm_', '', $this->getPlural($tableName)); - $joinable = new Joinable($tableName, $link->getBaseColumn(), $plural); - $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY); - $target->addTableLink($link->getTargetColumn(), $joinable); - } - } - } - } - - /** - * Simple implementation of pluralization. - * Could be replaced with symfony/inflector - * - * @param string $singular - * - * @return string - */ - private function getPlural($singular) { - $last_letter = substr($singular, -1); - switch ($last_letter) { - case 'y': - return substr($singular, 0, -1) . 'ies'; - - case 's': - return $singular . 'es'; - - default: - return $singular . 's'; - } - } - /** * @param \Civi\Api4\Service\Schema\SchemaMap $map * @param \Civi\Api4\Service\Schema\Table $baseTable diff --git a/ang/api4Explorer/Explorer.html b/ang/api4Explorer/Explorer.html index f28cec6dbe9b..3d800559426b 100644 --- a/ang/api4Explorer/Explorer.html +++ b/ang/api4Explorer/Explorer.html @@ -10,10 +10,10 @@

- + - + diff --git a/ang/api4Explorer/Explorer.js b/ang/api4Explorer/Explorer.js index c51793b3a241..a0cdc38ac82e 100644 --- a/ang/api4Explorer/Explorer.js +++ b/ang/api4Explorer/Explorer.js @@ -2,8 +2,6 @@ // Schema metadata var schema = CRM.vars.api4.schema; - // FK schema data - var links = CRM.vars.api4.links; // Cache list of entities var entities = []; // Cache list of actions @@ -13,7 +11,6 @@ // Api params var params; - angular.module('api4Explorer').config(function($routeProvider) { $routeProvider.when('/explorer/:api4entity?/:api4action?', { controller: 'Api4Explorer', @@ -168,17 +165,17 @@ } }); // Add implicit joins based on schema links - _.each(links[$scope.entity], function(link) { - var linkFields = _.cloneDeep(entityFields(link.entity)), - wildCard = addWildcard ? [{id: link.alias + '.*', text: link.alias + '.*', 'description': 'All core ' + link.entity + ' fields'}] : []; - if (linkFields) { + _.each(entityFields($scope.entity, $scope.action), function(field) { + if (field.fk_entity) { + var linkFields = _.cloneDeep(entityFields(field.fk_entity)), + wildCard = addWildcard ? [{id: field.name + '.*', text: field.name + '.*', 'description': 'All core ' + field.fk_entity + ' fields'}] : []; if (addPseudoconstant) { addPseudoconstants(linkFields, addPseudoconstant); } fieldList.push({ - text: link.alias, - description: 'Implicit join to ' + link.entity, - children: wildCard.concat(formatForSelect2(linkFields, [], 'name', ['description'], link.alias + '.')) + text: field.name, + description: 'Implicit join to ' + field.fk_entity, + children: wildCard.concat(formatForSelect2(linkFields, [], 'name', ['description'], field.name + '.')) }); } }); @@ -361,13 +358,13 @@ if (joins[alias]) { return joins[alias].entity; } - // Then lookup implicit links + // Then lookup implicit joins _.each(path, function(node) { - var link = _.find(links[entity], {alias: node}); - if (!link) { + var field = getField(node, entity, $scope.action); + if (!field || !field.fk_entity) { return false; } - entity = link.entity; + entity = field.fk_entity; }); return entity; } @@ -476,10 +473,15 @@ $scope.fieldsAndJoinsAndFunctionsAndWildcards.unshift({id: '*', text: '*', 'description': 'All core ' + $scope.entity + ' fields'}); }; + // Select2 formatter: Add 'strikethrough' class to deprecated items + $scope.formatResultCssClass = function(result) { + return result.deprecated ? 'strikethrough' : ''; + }; + function selectAction() { $scope.action = $routeParams.api4action; if (!actions.length) { - formatForSelect2(getEntity().actions, actions, 'name', ['description', 'params']); + formatForSelect2(getEntity().actions, actions, 'name', ['description', 'params', 'deprecated']); } if ($scope.action) { var actionInfo = _.findWhere(actions, {id: $scope.action}); @@ -958,7 +960,7 @@ if ($scope.entity && $routeParams.api4action !== newVal && !_.isUndefined(newVal)) { $location.url('/explorer/' + $scope.entity + '/' + newVal); } else if (newVal) { - setHelp($scope.entity + '::' + newVal, _.pick(_.findWhere(getEntity().actions, {name: newVal}), ['description', 'comment', 'see'])); + setHelp($scope.entity + '::' + newVal, _.pick(_.findWhere(getEntity().actions, {name: newVal}), ['description', 'comment', 'see', 'deprecated'])); } }); @@ -1413,7 +1415,7 @@ } var linkName = fieldNames.shift(), join = getExplicitJoins()[linkName], - newEntity = join ? join.entity : _.findWhere(links[entity], {alias: linkName}).entity; + newEntity = join ? join.entity : _.findWhere(entityFields(entity, action), {name: linkName}).fk_entity; return get(newEntity, fieldNames); } } diff --git a/tests/phpunit/api/v4/Service/Schema/SchemaMapRealTableTest.php b/tests/phpunit/api/v4/Service/Schema/SchemaMapRealTableTest.php deleted file mode 100644 index 6a7b2598da1a..000000000000 --- a/tests/phpunit/api/v4/Service/Schema/SchemaMapRealTableTest.php +++ /dev/null @@ -1,40 +0,0 @@ -get('schema_map'); - $this->assertNotEmpty($map->getTables()); - } - - public function testSimplePathWillExist() { - $map = \Civi::container()->get('schema_map'); - $path = $map->getPath('civicrm_contact', 'emails'); - $this->assertCount(1, $path); - } - -}