Skip to content

Commit

Permalink
Added excludeCritiera to Config
Browse files Browse the repository at this point in the history
  • Loading branch information
TomHAnderson committed Oct 15, 2023
1 parent 1ee1d1e commit 46d5806
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 11 deletions.
21 changes: 21 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ class Config
*/
protected bool|null $sortFields = null;

/**
* @var string[] An array of filters to exclude from
* available filters for all fields and
* associations in every entity
*/
protected array $excludeCriteria = [];

/** @param mixed[] $config */
public function __construct(array $config = [])
{
Expand Down Expand Up @@ -189,4 +196,18 @@ public function getSortFields(): bool|null
{
return $this->sortFields;
}

/** @param string[] $excludeCriteria */
public function setExcludeCriteria(array $excludeCriteria): self
{
$this->excludeCriteria = $excludeCriteria;

return $this;
}

/** @return string[] */
public function getExcludeCriteria(): array
{
return $this->excludeCriteria;
}
}
28 changes: 17 additions & 11 deletions src/Criteria/CriteriaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@
use GraphQL\Type\Definition\Type;
use League\Event\EventDispatcher;

use function array_diff;
use function array_filter;
use function array_keys;
use function array_merge;
use function array_unique;
use function count;
use function in_array;

use const SORT_REGULAR;

class CriteriaFactory
{
public function __construct(
Expand All @@ -44,17 +49,18 @@ public function get(
return $this->typeManager->get($typeName);
}

$fields = [];
$entityMetadata = $targetEntity->getMetadata();
$allowedFilters = Filters::toArray();

// Limit entity filters
if ($entityMetadata['excludeCriteria']) {
$excludeCriteria = $entityMetadata['excludeCriteria'];
$allowedFilters = array_filter($allowedFilters, static function ($value) use ($excludeCriteria) {
return ! in_array($value, $excludeCriteria);
});
}
$fields = [];
$entityMetadata = $targetEntity->getMetadata();
$excludedFilters = array_unique(
array_merge(
$entityMetadata['excludeCriteria'],
$this->config->getExcludeCriteria(),
),
SORT_REGULAR,
);

// Limit filters
$allowedFilters = array_diff(Filters::toArray(), $excludedFilters);

// Limit association filters
if ($associationName) {
Expand Down
67 changes: 67 additions & 0 deletions test/Feature/Criteria/ConfigExcludeCriteriaTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace ApiSkeletonsTest\Doctrine\GraphQL\Feature\Criteria;

use ApiSkeletons\Doctrine\GraphQL\Config;
use ApiSkeletons\Doctrine\GraphQL\Driver;
use ApiSkeletonsTest\Doctrine\GraphQL\AbstractTest;
use ApiSkeletonsTest\Doctrine\GraphQL\Entity\Artist;
use GraphQL\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Schema;

class ConfigExcludeCriteriaTest extends AbstractTest
{
public function testConfigExcludeCriteria(): void
{
$config = new Config(['excludeCriteria' => ['eq', 'neq', 'contains']]);

$driver = new Driver($this->getEntityManager(), $config);

$schema = new Schema([
'query' => new ObjectType([
'name' => 'query',
'fields' => [
'artists' => [
'type' => $driver->connection($driver->type(Artist::class)),
'args' => [
'filter' => $driver->filter(Artist::class),
'pagination' => $driver->pagination(),
],
'resolve' => $driver->resolve(Artist::class),
],
],
]),
]);

$query = '{ artists (filter: { name: { eq: "Grateful Dead" } } ) { edges { node { name } } } }';
$result = GraphQL::executeQuery($schema, $query);

foreach ($result->errors as $error) {
$this->assertEquals('Field "eq" is not defined by type "artist_default_filter_name_filters".', $error->getMessage());
}

$query = '{ artists (filter: { name: { neq: "Grateful Dead" } } ) { edges { node { name } } } }';
$result = GraphQL::executeQuery($schema, $query);

foreach ($result->errors as $error) {
$this->assertEquals('Field "neq" is not defined by type "artist_default_filter_name_filters".', $error->getMessage());
}

$query = '{ artists { edges { node { performances ( filter: {venue: { neq: "test"} } ) { edges { node { venue } } } } } } }';
$result = GraphQL::executeQuery($schema, $query);

foreach ($result->errors as $error) {
$this->assertEquals('Field "neq" is not defined by type "artist_default_performances_filter_venue_filters".', $error->getMessage());
}

$query = '{ artists { edges { node { performances ( filter: {venue: { contains: "test" } } ) { edges { node { venue } } } } } } }';
$result = GraphQL::executeQuery($schema, $query);

foreach ($result->errors as $error) {
$this->assertEquals('Field "contains" is not defined by type "artist_default_performances_filter_venue_filters". Did you mean "notin"?', $error->getMessage());
}
}
}

0 comments on commit 46d5806

Please sign in to comment.