diff --git a/src/core/Directus/Database/SchemaService.php b/src/core/Directus/Database/SchemaService.php index f14d889a82..e86e8ef779 100644 --- a/src/core/Directus/Database/SchemaService.php +++ b/src/core/Directus/Database/SchemaService.php @@ -352,8 +352,10 @@ public static function getRelatedCollectionName($tableName, $columnName) $tableObject = static::getCollection($tableName); $columnObject = $tableObject->getField($columnName); - - return $columnObject->getRelationship()->getCollectionOne(); + if($columnObject->getRelationship()->getType() == FieldRelationship::ONE_TO_MANY) + return $columnObject->getRelationship()->getCollectionMany(); + else + return $columnObject->getRelationship()->getCollectionOne(); } /** diff --git a/src/core/Directus/Database/TableGateway/RelationalTableGateway.php b/src/core/Directus/Database/TableGateway/RelationalTableGateway.php index a177336285..cee98b6f23 100644 --- a/src/core/Directus/Database/TableGateway/RelationalTableGateway.php +++ b/src/core/Directus/Database/TableGateway/RelationalTableGateway.php @@ -1117,7 +1117,6 @@ public function fetchItems(array $params = [], \Closure $queryCallback = null) if (ArrayUtils::get($params, 'single')) { $results = reset($results); } - return $results ? $results : []; } @@ -1198,7 +1197,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) continue; } - $columnList = $columns = explode('.', $column); + $columnList = $filterColumns = explode('.', $column); $columnsTable = [ $this->getTable() ]; @@ -1206,11 +1205,13 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $nextColumn = array_shift($columnList); $nextTable = $this->getTable(); $relational = SchemaService::hasRelationship($nextTable, $nextColumn); - + $relationalTables = []; while ($relational) { + $relationalTables[$nextColumn] = $nextTable; $nextTable = SchemaService::getRelatedCollectionName($nextTable, $nextColumn); $nextColumn = array_shift($columnList); - + if(empty($nextColumn)) + break; // Confirm the user has permission to all chained (dot) fields if ($this->acl && !$this->acl->canRead($nextTable)) { throw new Exception\ForbiddenFieldAccessException($nextColumn); @@ -1219,7 +1220,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $relational = SchemaService::hasRelationship($nextTable, $nextColumn); $columnsTable[] = $nextTable; } - + // if one of the column in the list has not relationship // it will break the loop before going over all the columns // which we will call this as column not found @@ -1230,7 +1231,23 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) // Remove the original filter column with dot-notation unset($filters[$column]); - + + //Prepare relational data for all the fields + $columnRelationalData = []; + foreach($filterColumns as $filterColumn){ + if(isset($relationalTables[$filterColumn])){ + $collection = $this->getTableSchema($relationalTables[$filterColumn]); + $fieldRelation = $collection->getField($filterColumn)->getRelationship(); + $columnRelationalData[$filterColumn] = [ + "type" => $fieldRelation->getType(), + "collection_many" => $fieldRelation->getCollectionMany(), + "field_many" => $fieldRelation->getFieldMany(), + "collection_one" => $fieldRelation->getCollectionOne(), + "field_one" => $fieldRelation->getFieldOne() + ]; + } + } + // Reverse all the columns from comments.author.id to id.author.comments // To filter from the most deep relationship to their parents $columns = explode('.', \Directus\column_identifier_reverse($column)); @@ -1246,11 +1263,23 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $query = new Builder($this->getAdapter()); $mainTableObject = $this->getTableSchema($table); - $query->columns([$mainTableObject->getPrimaryField()->getName()]); + $selectColumn = $mainTableObject->getPrimaryField()->getName(); + + //check if column type is alias and relationship is O2M + $previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:''; + if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $selectColumn = $columnRelationalData[$previousRelation]['field_many']; + } + + //get last relationship + if ($mainColumn && !empty($mainColumn) && $columnRelationalData[$mainColumn]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $mainColumn = $mainTableObject->getPrimaryField()->getName(); + } + $query->columns([$selectColumn]); + $query->from($table); $this->doFilter($query, $column, $condition, $table); - $index = 0; foreach ($columns as $key => $column) { ++$index; @@ -1261,6 +1290,11 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $field = $collection->getField($column); $selectColumn = $collection->getPrimaryField()->getName(); + //check if column type is alias and relationship is O2M + $previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:''; + if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $selectColumn = $columnRelationalData[$previousRelation]['field_many']; + } $table = $columnsTable[$key]; if ($field->isAlias()) { @@ -1279,7 +1313,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) // TODO: Make all this whereIn duplication into a function // TODO: Can we make the O2M simpler getting the parent id from itself // right now is creating one unnecessary select - if ($field->isOneToMany()) { + /*if ($field->isOneToMany()) { $mainColumn = $collection->getPrimaryField()->getName(); $oldQuery = $query; $query = new Builder($this->getAdapter()); @@ -1292,7 +1326,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $column, $oldQuery ); - } + }*/ $this->doFilter( $mainQuery,