From 9b06167d3c8dc54bb51e22e3583b18799a46c930 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 30 Mar 2020 12:22:43 -0400 Subject: [PATCH] Api4SelectQuery - add more metadata to apiFieldSpec --- Civi/Api4/Query/Api4SelectQuery.php | 69 ++++++++++++++++++----------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/Civi/Api4/Query/Api4SelectQuery.php b/Civi/Api4/Query/Api4SelectQuery.php index 4e7082a4dc..38c46ad887 100644 --- a/Civi/Api4/Query/Api4SelectQuery.php +++ b/Civi/Api4/Query/Api4SelectQuery.php @@ -41,12 +41,6 @@ class Api4SelectQuery extends SelectQuery { */ protected $apiVersion = 4; - /** - * @var array - * Maps select fields to [, ] - */ - protected $fkSelectAliases = []; - /** * @var \Civi\Api4\Service\Schema\Joinable\Joinable[] * The joinable tables that have been joined so far @@ -82,9 +76,9 @@ class Api4SelectQuery extends SelectQuery { } $baoName = CoreUtil::getBAOFromApiName($this->entity); $this->entityFieldNames = array_column($baoName::fields(), 'name'); - $this->apiFieldSpec = $apiGet->entityFields(); - foreach ($this->apiFieldSpec as $key => $field) { - $this->apiFieldSpec[$key]['sql_name'] = '`' . self::MAIN_TABLE_ALIAS . '`.`' . $field['column_name'] . '`'; + foreach ($apiGet->entityFields() as $path => $field) { + $field['sql_name'] = '`' . self::MAIN_TABLE_ALIAS . '`.`' . $field['column_name'] . '`'; + $this->addSpecField($path, $field); } $this->constructQueryObject($baoName); @@ -145,6 +139,7 @@ class Api4SelectQuery extends SelectQuery { } protected function buildSelectClause() { + // An empty select is the same as * if (empty($this->select)) { $this->select = $this->entityFieldNames; } @@ -172,19 +167,19 @@ class Api4SelectQuery extends SelectQuery { } foreach ($this->select as $fieldName) { $field = $this->getField($fieldName); - if (!$this->isOneToOneField($fieldName)) { - continue; - } - elseif ($field) { - $this->query->select($field['sql_name'] . " AS `$fieldName`"); - } // Remove unknown fields without raising an error - else { + if (!$field) { $this->select = array_diff($this->select, [$fieldName]); if (is_array($this->debugOutput)) { $this->debugOutput['undefined_fields'][] = $fieldName; } } + elseif ($field['is_many']) { + continue; + } + elseif ($field) { + $this->query->select($field['sql_name'] . " AS `$fieldName`"); + } } } @@ -315,8 +310,7 @@ class Api4SelectQuery extends SelectQuery { $this->joinFK($fieldName); } $field = $this->apiFieldSpec[$fieldName] ?? NULL; - // Check if field exists and we have permission to view it - if ($field && (!$this->checkPermissions || empty($field['permission']) || \CRM_Core_Permission::check($field['permission']))) { + if ($field) { return $field; } elseif ($strict) { @@ -329,13 +323,12 @@ class Api4SelectQuery extends SelectQuery { * Joins a path and adds all fields in the joined eneity to apiFieldSpec * * @param $key - * @return bool * @throws \API_Exception * @throws \Exception */ protected function joinFK($key) { if (isset($this->apiFieldSpec[$key])) { - return TRUE; + return; } $pathArray = explode('.', $key); @@ -347,15 +340,24 @@ class Api4SelectQuery extends SelectQuery { $pathString = implode('.', $pathArray); if (!$joiner->canJoin($this, $pathString)) { - return FALSE; + return; } $joinPath = $joiner->join($this, $pathString); + + $isMany = FALSE; + foreach ($joinPath as $joinable) { + if ($joinable->getJoinType() === Joinable::JOIN_TYPE_ONE_TO_MANY) { + $isMany = TRUE; + } + } + /** @var \Civi\Api4\Service\Schema\Joinable\Joinable $lastLink */ $lastLink = array_pop($joinPath); // Custom field names are already prefixed - if ($lastLink instanceof CustomGroupJoinable) { + $isCustom = $lastLink instanceof CustomGroupJoinable; + if ($isCustom) { array_pop($pathArray); } $prefix = $pathArray ? implode('.', $pathArray) . '.' : ''; @@ -364,10 +366,11 @@ class Api4SelectQuery extends SelectQuery { foreach ($lastLink->getEntityFields() as $fieldObject) { $fieldArray = ['entity' => $joinEntity] + $fieldObject->toArray(); $fieldArray['sql_name'] = '`' . $lastLink->getAlias() . '`.`' . $fieldArray['column_name'] . '`'; - $this->apiFieldSpec[$prefix . $fieldArray['name']] = $fieldArray; + $fieldArray['is_custom'] = $isCustom; + $fieldArray['is_join'] = TRUE; + $fieldArray['is_many'] = $isMany; + $this->addSpecField($prefix . $fieldArray['name'], $fieldArray); } - - return TRUE; } /** @@ -574,4 +577,20 @@ class Api4SelectQuery extends SelectQuery { return $path; } + /** + * @param $path + * @param $field + */ + private function addSpecField($path, $field) { + // Only add field to spec if we have permission + if ($this->checkPermissions && !empty($field['permission']) && !\CRM_Core_Permission::check($field['permission'])) { + $this->apiFieldSpec[$path] = FALSE; + return; + } + $defaults = []; + $defaults['is_custom'] = $defaults['is_join'] = $defaults['is_many'] = FALSE; + $field += $defaults; + $this->apiFieldSpec[$path] = $field; + } + } -- 2.25.1