Skip to content

Commit c7559ab

Browse files
authored
Merge pull request #138 from TomHAnderson/feature/sort-fields
Added sortFields config option
2 parents f44a496 + 8b0206d commit c7559ab

3 files changed

Lines changed: 77 additions & 0 deletions

File tree

src/Config.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ class Config
6161
*/
6262
protected string|null $entityPrefix = null;
6363

64+
/**
65+
* @var bool|null When set to true entity fields will be
66+
* sorted alphabetically
67+
*/
68+
protected bool|null $sortFields = null;
69+
6470
/** @param mixed[] $config */
6571
public function __construct(array $config = [])
6672
{
@@ -171,4 +177,16 @@ public function getEntityPrefix(): string|null
171177
{
172178
return $this->entityPrefix;
173179
}
180+
181+
public function setSortFields(bool|null $sortFields): self
182+
{
183+
$this->sortFields = $sortFields;
184+
185+
return $this;
186+
}
187+
188+
public function getSortFields(): bool|null
189+
{
190+
return $this->sortFields;
191+
}
174192
}

src/Type/Entity.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66

77
use ApiSkeletons\Doctrine\GraphQL\AbstractContainer;
88
use ApiSkeletons\Doctrine\GraphQL\Buildable;
9+
use ApiSkeletons\Doctrine\GraphQL\Config;
910
use ApiSkeletons\Doctrine\GraphQL\Criteria\CriteriaFactory;
1011
use ApiSkeletons\Doctrine\GraphQL\Event\EntityDefinition;
1112
use ApiSkeletons\Doctrine\GraphQL\Hydrator\HydratorFactory;
1213
use ApiSkeletons\Doctrine\GraphQL\Resolve\FieldResolver;
1314
use ApiSkeletons\Doctrine\GraphQL\Resolve\ResolveCollectionFactory;
1415
use ArrayObject;
16+
use Closure;
1517
use Doctrine\ORM\EntityManager;
1618
use Doctrine\ORM\Mapping\ClassMetadataInfo;
1719
use Doctrine\ORM\Mapping\MappingException;
@@ -23,12 +25,17 @@
2325
use function array_keys;
2426
use function assert;
2527
use function in_array;
28+
use function ksort;
29+
30+
use const SORT_REGULAR;
2631

2732
class Entity implements Buildable
2833
{
2934
/** @var mixed[] */
3035
protected array $metadata;
3136

37+
protected Config $config;
38+
3239
protected CriteriaFactory $criteriaFactory;
3340

3441
protected EntityManager $entityManager;
@@ -50,6 +57,7 @@ public function __construct(AbstractContainer $container, string $typeName, arra
5057
$container = $container->getContainer();
5158

5259
$this->collectionFactory = $container->get(ResolveCollectionFactory::class);
60+
$this->config = $container->get(Config::class);
5361
$this->criteriaFactory = $container->get(CriteriaFactory::class);
5462
$this->entityManager = $container->get(EntityManager::class);
5563
$this->eventDispatcher = $container->get(EventDispatcher::class);
@@ -127,6 +135,17 @@ protected function getGraphQLType(): ObjectType
127135
new EntityDefinition($arrayObject, $this->getEntityClass() . '.definition'),
128136
);
129137

138+
/**
139+
* If sortFields then resolve the fiels and sort them
140+
*/
141+
if ($this->config->getSortFields()) {
142+
if ($arrayObject['fields'] instanceof Closure) {
143+
$arrayObject['fields'] = $arrayObject['fields']();
144+
}
145+
146+
ksort($arrayObject['fields'], SORT_REGULAR);
147+
}
148+
130149
/** @psalm-suppress InvalidArgument */
131150
$objectType = new ObjectType($arrayObject->getArrayCopy());
132151
$this->typeManager->set($this->getTypeName(), $objectType);

test/Feature/Type/EntityTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@
66

77
use ApiSkeletons\Doctrine\GraphQL\Config;
88
use ApiSkeletons\Doctrine\GraphQL\Driver;
9+
use ApiSkeletons\Doctrine\GraphQL\Event\EntityDefinition;
910
use ApiSkeletons\Doctrine\GraphQL\Hydrator\Strategy\AssociationDefault;
1011
use ApiSkeletons\Doctrine\GraphQL\Hydrator\Strategy\FieldDefault;
1112
use ApiSkeletons\Doctrine\GraphQL\Hydrator\Strategy\ToInteger;
1213
use ApiSkeletons\Doctrine\GraphQL\Type\Entity;
1314
use ApiSkeletons\Doctrine\GraphQL\Type\TypeManager;
1415
use ApiSkeletonsTest\Doctrine\GraphQL\AbstractTest;
1516
use ApiSkeletonsTest\Doctrine\GraphQL\Entity\Recording;
17+
use ApiSkeletonsTest\Doctrine\GraphQL\Entity\User;
18+
use ArrayObject;
19+
use League\Event\EventDispatcher;
20+
21+
use function array_keys;
22+
use function array_values;
23+
use function sort;
1624

1725
class EntityTest extends AbstractTest
1826
{
@@ -58,4 +66,36 @@ public function testEntityMetadata(): void
5866

5967
$this->assertEquals('entitytestrecording_entityTest', $metadata['typeName']);
6068
}
69+
70+
public function testSortFields(): void
71+
{
72+
$unsortedFields = new ArrayObject();
73+
$unsortedFields['fields'] = [];
74+
75+
$config = new Config(['sortFields' => true]);
76+
77+
$driver = new Driver($this->getEntityManager(), $config);
78+
79+
// Fields are only sorted after this event is fired
80+
$driver->get(EventDispatcher::class)->subscribeTo(
81+
User::class . '.definition',
82+
static function (EntityDefinition $event) use ($unsortedFields): void {
83+
$fields = $event->getDefinition()['fields']();
84+
85+
$unsortedFields['fields'] = array_keys($fields);
86+
},
87+
);
88+
89+
$graphQLType = $driver->get(TypeManager::class)
90+
->build(Entity::class, User::class)();
91+
$fields = array_keys($graphQLType->getFields());
92+
$fieldsSorted = $fields;
93+
sort($fieldsSorted);
94+
$unsortedFieldsSorted = $unsortedFields['fields'];
95+
sort($unsortedFieldsSorted);
96+
97+
$this->assertNotEquals(array_values($unsortedFields['fields']), $fields);
98+
$this->assertEquals($fields, $fieldsSorted);
99+
$this->assertEquals($fields, $unsortedFieldsSorted);
100+
}
61101
}

0 commit comments

Comments
 (0)