*/
protected $apiVersion = 4;
- /**
- * @var array
- * Maps select fields to [<table_alias>, <column_alias>]
- */
- protected $fkSelectAliases = [];
-
/**
* @var \Civi\Api4\Service\Schema\Joinable\Joinable[]
* The joinable tables that have been joined so far
}
$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);
}
protected function buildSelectClause() {
+ // An empty select is the same as *
if (empty($this->select)) {
$this->select = $this->entityFieldNames;
}
}
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`");
+ }
}
}
$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) {
* 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);
$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) . '.' : '';
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;
}
/**
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;
+ }
+
}