Skip to content

Commit

Permalink
Merge pull request #577 from kinglozzer/571-sort-warning
Browse files Browse the repository at this point in the history
FIX: Don't attempt to correct sort when passed as an argument (closes #571)
  • Loading branch information
GuySartorelli authored May 23, 2024
2 parents 2aabfb0 + d6e7735 commit f4587b2
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
6 changes: 6 additions & 0 deletions _config/logging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ after: '#logging'
---

SilverStripe\Core\Injector\Injector:
# Omits the HTTPOutputHandler from the logger so errors won't appear in output
Psr\Log\LoggerInterface.graphql-quiet:
type: singleton
class: Monolog\Logger
constructor:
- 'graphql'
# This will occasionally be overridden with SilverStripe\GraphQL\Schema\Logger to provide a nicer output on schema build task
Psr\Log\LoggerInterface.graphql-build: '%$Psr\Log\LoggerInterface.errorhandler'
11 changes: 11 additions & 0 deletions src/Schema/Traits/SortTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

namespace SilverStripe\GraphQL\Schema\Traits;

use GraphQL\Language\AST\ObjectValueNode;
use GraphQL\Type\Definition\ResolveInfo;
use Psr\Log\LoggerInterface;
use SilverStripe\Core\Injector\Injector;

trait SortTrait
{
Expand Down Expand Up @@ -44,6 +47,14 @@ private static function getSortOrder(ResolveInfo $info, string $fieldName)
continue;
}

// If the sort has been passed as a variable, we can't attempt to fix it
// See https://github.com/silverstripe/silverstripe-graphql/issues/573
if (!$arg->value instanceof ObjectValueNode) {
$logger = Injector::inst()->get(LoggerInterface::class . '.graphql-quiet');
$logger->warning('Unable to adjust sort order, sort fields may be applied in incorrect order.');
continue;
}

// Get the sort order from the query
$sortOrder = [];
foreach ($arg->value->fields as $field) {
Expand Down
106 changes: 106 additions & 0 deletions tests/Schema/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,112 @@ public function testFilterAndSortOnlyRead(string $fixture, string $query, array
$this->assertResults($expected, $records);
}

public function provideFilterAndSortWithArgsOnlyRead(): array
{
return [
'read with sort - with sort arg' => [
'fixture' => '_QuerySort',
'query' => <<<GRAPHQL
query (\$sort: DataObjectFakeSortFields) {
readDataObjectFakes(sort: \$sort) {
nodes {
myField
author {
firstName
}
}
}
}
GRAPHQL,
'args' => [
'sort' => ['author' => ['id' => 'DESC'], 'myField' => 'ASC']
],
'expected' => [
["myField" => "test2", "author" => ["firstName" => "tester2"]],
["myField" => "test3", "author" => ["firstName" => "tester2"]],
["myField" => "test1", "author" => ["firstName" => "tester1"]],
],
],
'read with sorter files ParentID DESC, name ASC - with sort args' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query (\$sort: DataObjectFakeSortFields, \$fileSort: FilesSimpleSortFields) {
readDataObjectFakes(sort: \$sort) {
nodes {
myField
files(sort: \$fileSort) {
title
}
}
}
}
GRAPHQL,
'args' => [
'sort' => ['myField' => 'ASC'],
'fileSort' => ['ParentID' => 'DESC', 'name' => 'ASC'],
],
'expected' => [
["myField" => "test1", "files" => [["title" => "file2"], ["title" => "file4"], ["title" => "file1"], ["title" => "file3"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
];
}

/**
* @dataProvider provideFilterAndSortWithArgsOnlyRead
*/
public function testFilterAndSortWithArgsOnlyRead(string $fixture, string $query, array $args, array $expected)
{
$author = Member::create(['FirstName' => 'tester1']);
$author->write();

$author2 = Member::create(['FirstName' => 'tester2']);
$author2->write();

$dataObject1 = DataObjectFake::create(['MyField' => 'test1', 'AuthorID' => $author->ID]);
$dataObject1->write();

$dataObject2 = DataObjectFake::create(['MyField' => 'test2', 'AuthorID' => $author2->ID]);
$dataObject2->write();

$dataObject3 = DataObjectFake::create(['MyField' => 'test3', 'AuthorID' => $author2->ID]);
$dataObject3->write();

$file1 = File::create(['Title' => 'file1', 'Name' => 'asc_name']);
$file1->ParentID = 1;
$file1->write();

$file2 = File::create(['Title' => 'file2', 'Name' => 'desc_name']);
$file2->ParentID = 1;
$file2->write();

$file3 = File::create(['Title' => 'file3', 'Name' => 'asc_name']);
$file3->ParentID = 2;
$file3->write();

$file4 = File::create(['Title' => 'file4', 'Name' => 'desc_name']);
$file4->ParentID = 2;
$file4->write();

$dataObject1->Files()->add($file1);
$dataObject1->Files()->add($file2);
$dataObject1->Files()->add($file3);
$dataObject1->Files()->add($file4);

$factory = new TestSchemaBuilder(['_' . __FUNCTION__ . $fixture]);
$schema = $this->createSchema($factory);

$result = $this->querySchema($schema, $query, $args);
$this->assertSuccess($result);
$records = $result['data']['readDataObjectFakes']['nodes'] ?? [];

// We intentionally don't check the sort order, as it's expected it may not match:
// See https://github.com/silverstripe/silverstripe-graphql/issues/573
$this->assertEqualsCanonicalizing($expected, $records);
}

public function testAggregateProperties()
{
$file1 = File::create(['Title' => '1']);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
SilverStripe\GraphQL\Tests\Fake\DataObjectFake:
operations:
read:
plugins:
sort:
before: paginateList
fields:
myField: true
author:
fields:
id: true
firstName: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
SilverStripe\GraphQL\Tests\Fake\DataObjectFake:
operations:
read:
plugins:
sort:
before: paginateList
fields:
myField: true
AuthorID: true
author:
fields:
firstName: true
files:
fields:
title: true
plugins:
sorter:
fields:
id: true
title: true
name: true
ParentID: true

0 comments on commit f4587b2

Please sign in to comment.