Skip to content

Commit

Permalink
Merge pull request #102 from TomHAnderson/feature/field-specific-crit…
Browse files Browse the repository at this point in the history
…eria

Added excludeCriteria to Field Attributes
  • Loading branch information
TomHAnderson authored Jan 23, 2023
2 parents e341cfc + 5b5729d commit ef25882
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 5 deletions.
8 changes: 8 additions & 0 deletions src/Attribute/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
class Field
{
/** @param string[] $excludeCriteria */
public function __construct(
protected string $group = 'default',
protected string|null $strategy = null,
protected string|null $description = null,
protected string|null $type = null,
private array $excludeCriteria = [],
) {
}

Expand All @@ -36,4 +38,10 @@ public function getType(): string|null
{
return $this->type;
}

/** @return string[] */
public function getExcludeCriteria(): array
{
return $this->excludeCriteria;
}
}
16 changes: 16 additions & 0 deletions src/Criteria/CriteriaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use function array_filter;
use function array_keys;
use function assert;
use function count;
use function in_array;

class CriteriaFactory
Expand Down Expand Up @@ -87,6 +88,21 @@ public function get(

assert($graphQLType, 'GraphQL type not found for ' . $fieldMetadata['type']);

// Limit field filters
if (
isset($entityMetadata['fields'][$fieldName]['excludeCriteria'])
&& count($entityMetadata['fields'][$fieldName]['excludeCriteria'])
) {
// Compute the difference of arrays
$fieldExcludeCriteria = $entityMetadata['fields'][$fieldName]['excludeCriteria'];
$allowedFilters = array_filter(
$allowedFilters,
static function ($value) use ($fieldExcludeCriteria) {
return ! in_array($value, $fieldExcludeCriteria);
},
);
}

$fields[$fieldName] = [
'name' => $fieldName,
'type' => new FiltersInputType($typeName, $fieldName, $graphQLType, $allowedFilters),
Expand Down
5 changes: 5 additions & 0 deletions src/Metadata/MetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ private function globalEnable(array $entityClasses): Metadata
// Set default strategy based on field type
$this->metadataConfig[$entityClass]['fields'][$fieldName]['strategy'] =
$this->getDefaultStrategy($entityClassMetadata->getTypeOfField($fieldName));

$this->metadataConfig[$entityClass]['fields'][$fieldName]['excludeCriteria'] = [];
}

// Fetch attributes for associations
Expand Down Expand Up @@ -217,6 +219,9 @@ private function buildMetadataConfigForFields(
continue;
}

$this->metadataConfig[$reflectionClass->getName()]['fields'][$fieldName]['excludeCriteria'] =
$instance->getExcludeCriteria();

// Set default strategy based on field type
$this->metadataConfig[$reflectionClass->getName()]['fields'][$fieldName]['strategy'] =
$this->getDefaultStrategy($entityClassMetadata->getTypeOfField($fieldName));
Expand Down
4 changes: 2 additions & 2 deletions test/Entity/Artist.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* Artist
*/
#[GraphQL\Entity(typeName: 'artist', description: 'Artists')]
#[GraphQL\Entity(group: 'ExcludeCriteriaTest')]
#[GraphQL\Entity(group: 'ExcludeCriteriaTest', excludeCriteria: ['neq'])]
#[GraphQL\Entity(group: 'TypeNameTest')]
#[GraphQL\Entity(group: 'DuplicateGroup')]
#[GraphQL\Entity(group: 'DuplicateGroup')]
Expand All @@ -23,7 +23,7 @@
class Artist
{
#[GraphQL\Field(description: 'Artist name')]
#[GraphQL\Field(group: 'ExcludeCriteriaTest')]
#[GraphQL\Field(group: 'ExcludeCriteriaTest', excludeCriteria: ['eq'])]
#[GraphQL\Field(group: 'TypeNameTest')]
#[GraphQL\Field(group: 'DuplicateGroup')]
#[GraphQL\Field(group: 'DuplicateGroup')]
Expand Down
20 changes: 17 additions & 3 deletions test/Feature/Criteria/ExcludeCriteriaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function testExcludeCriteria(): void
'query' => new ObjectType([
'name' => 'query',
'fields' => [
'artist' => [
'artists' => [
'type' => $driver->connection($driver->type(Artist::class)),
'args' => [
'filter' => $driver->filter(Artist::class),
Expand All @@ -36,14 +36,28 @@ public function testExcludeCriteria(): void
]),
]);

$query = '{ artist { edges { node { performances ( filter: {venue: { neq: "test"} } ) { edges { node { venue } } } } } } }';
$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 "ApiSkeletonsTest_Doctrine_GraphQL_Entity_Artist_ExcludeCriteriaTest_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 "ApiSkeletonsTest_Doctrine_GraphQL_Entity_Artist_ExcludeCriteriaTest_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 "ApiSkeletonsTest_Doctrine_GraphQL_Entity_Artist_ExcludeCriteriaTest_performances_filter_venue_filters". Did you mean "eq"?', $error->getMessage());
}

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

foreach ($result->errors as $error) {
Expand Down

0 comments on commit ef25882

Please sign in to comment.