Skip to content

Commit

Permalink
Upgrade attribute type option system
Browse files Browse the repository at this point in the history
Introducing:
- NullableType: allows to overwrite nullable class types as well
- ListType: allows to define lists
  • Loading branch information
jerowork committed Jan 7, 2025
1 parent 5860c16 commit 5c0ffff
Show file tree
Hide file tree
Showing 50 changed files with 586 additions and 335 deletions.
19 changes: 8 additions & 11 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The following attributes can be used:
- `#[InputType]`
- `#[Type]`
- `#[Enum]`
- `#[EnumValue]`
- `#[EnumValue]`
- `#[Field]`
- `#[Arg]`

Expand Down Expand Up @@ -61,12 +61,11 @@ Mutations and queries:

Both `#[Mutation]` and `#[Query]` attribute can be configured:

| Option | Description |
|---------------|-------------------------------------------------------------------------------|
| `name` | Set custom name of mutation or query (instead of based on class) |
| `description` | Set description of the mutation or query, readable in the GraphQL schema |
| `type` | Set custom return type; can be either a `#[Type]` FQCN or `ScalarType` (enum) |
| `isRequired` | When a custom type is set, isRequired should be set as well |
| Option | Description |
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | Set custom name of mutation or query (instead of based on class) |
| `description` | Set description of the mutation or query, readable in the GraphQL schema |
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType:Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType:Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |

## InputType

Expand Down Expand Up @@ -276,8 +275,7 @@ final readonly class YourInputType
|---------------|----------------------------------------------------------------------------------------|
| `name` | Set custom name of field (instead of based on class) |
| `description` | Set description of the field, readable in the GraphQL schema |
| `type` | Set custom type; can be either a `#[Type]`, `#[InputType]` FQCN or `ScalarType` (enum) |
| `isRequired` | When a custom type is set, isRequired should be set as well |
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType:Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType:Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |

## Arg

Expand Down Expand Up @@ -335,5 +333,4 @@ final readonly class YourType
|---------------|------------------------------------------------------------------------|
| `name` | Set custom name of argument (instead of based on class) |
| `description` | Set description of the argument, readable in the GraphQL schema |
| `type` | Set custom type; can be either a `#[Type]` FQCN or `ScalarType` (enum) |
| `isRequired` | When a custom type is set, isRequired should be set as well |
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType:Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType:Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |
13 changes: 4 additions & 9 deletions src/Attribute/Arg.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

use Attribute;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;

#[Attribute(Attribute::TARGET_PARAMETER)]
final readonly class Arg implements BaseAttribute, TypedAttribute
{
/**
* @param class-string|ScalarType|null $type
* @param class-string|Type|ScalarType|null $type
*/
public function __construct(
public ?string $name = null,
public ?string $description = null,
public string|ScalarType|null $type = null,
public bool $isRequired = true,
public string|Type|ScalarType|null $type = null,
) {}

public function getName(): ?string
Expand All @@ -30,13 +30,8 @@ public function getDescription(): ?string
return $this->description;
}

public function getType(): string|ScalarType|null
public function getType(): string|Type|ScalarType|null
{
return $this->type;
}

public function isRequired(): bool
{
return $this->isRequired;
}
}
13 changes: 4 additions & 9 deletions src/Attribute/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

use Attribute;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;

#[Attribute(Attribute::TARGET_PROPERTY|Attribute::TARGET_METHOD)]
final readonly class Field implements BaseAttribute, TypedAttribute
{
/**
* @param class-string|ScalarType|null $type
* @param class-string|Type|ScalarType|null $type
*/
public function __construct(
public ?string $name = null,
public ?string $description = null,
public string|ScalarType|null $type = null,
public bool $isRequired = true,
public string|Type|ScalarType|null $type = null,
) {}

public function getName(): ?string
Expand All @@ -30,13 +30,8 @@ public function getDescription(): ?string
return $this->description;
}

public function getType(): string|ScalarType|null
public function getType(): string|Type|ScalarType|null
{
return $this->type;
}

public function isRequired(): bool
{
return $this->isRequired;
}
}
13 changes: 4 additions & 9 deletions src/Attribute/Mutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

use Attribute;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;

#[Attribute(Attribute::TARGET_CLASS)]
final readonly class Mutation implements BaseAttribute, TypedAttribute
{
/**
* @param class-string|ScalarType|null $type
* @param class-string|Type|ScalarType|null $type
*/
public function __construct(
public ?string $name = null,
public ?string $description = null,
public string|ScalarType|null $type = null,
public bool $isRequired = true,
public string|Type|ScalarType|null $type = null,
) {}

public function getName(): ?string
Expand All @@ -30,13 +30,8 @@ public function getDescription(): ?string
return $this->description;
}

public function getType(): string|ScalarType|null
public function getType(): string|Type|ScalarType|null
{
return $this->type;
}

public function isRequired(): bool
{
return $this->isRequired;
}
}
15 changes: 15 additions & 0 deletions src/Attribute/Option/ListType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;

final readonly class ListType implements Type
{
/**
* @param class-string|Type|ScalarType $type
*/
public function __construct(
public string|Type|ScalarType $type,
) {}
}
15 changes: 15 additions & 0 deletions src/Attribute/Option/NullableType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;

final readonly class NullableType implements Type
{
/**
* @param class-string|Type|ScalarType $type
*/
public function __construct(
public string|Type|ScalarType $type,
) {}
}
15 changes: 15 additions & 0 deletions src/Attribute/Option/ObjectType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;

final readonly class ObjectType implements Type
{
/**
* @param class-string $className
*/
public function __construct(
public string $className,
) {}
}
7 changes: 7 additions & 0 deletions src/Attribute/Option/Type.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

declare(strict_types=1);

namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;

interface Type {}
13 changes: 4 additions & 9 deletions src/Attribute/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

use Attribute;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;

#[Attribute(Attribute::TARGET_CLASS)]
final readonly class Query implements BaseAttribute, TypedAttribute
{
/**
* @param class-string|ScalarType|null $type
* @param class-string|Type|ScalarType|null $type
*/
public function __construct(
public ?string $name = null,
public ?string $description = null,
public string|ScalarType|null $type = null,
public bool $isRequired = true,
public string|Type|ScalarType|null $type = null,
) {}

public function getName(): ?string
Expand All @@ -30,13 +30,8 @@ public function getDescription(): ?string
return $this->description;
}

public function getType(): string|ScalarType|null
public function getType(): string|Type|ScalarType|null
{
return $this->type;
}

public function isRequired(): bool
{
return $this->isRequired;
}
}
7 changes: 3 additions & 4 deletions src/Attribute/TypedAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
namespace Jerowork\GraphqlAttributeSchema\Attribute;

use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;

interface TypedAttribute
{
/**
* @return class-string|ScalarType|null
* @return class-string|Type|ScalarType|null
*/
public function getType(): string|ScalarType|null;

public function isRequired(): bool;
public function getType(): string|Type|ScalarType|null;
}
1 change: 0 additions & 1 deletion src/Parser/Node/Child/ArgNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public function __construct(
public Type $type,
public string $name,
public ?string $description,
public bool $isRequired,
public string $propertyName,
) {}
}
1 change: 0 additions & 1 deletion src/Parser/Node/Child/FieldNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public function __construct(
public Type $type,
public string $name,
public ?string $description,
public bool $isRequired,
public array $argNodes,
public FieldNodeType $fieldType,
public ?string $methodName,
Expand Down
1 change: 0 additions & 1 deletion src/Parser/Node/MutationNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public function __construct(
public ?string $description,
public array $argNodes,
public Type $outputType,
public bool $isRequired,
public string $methodName,
) {}

Expand Down
1 change: 0 additions & 1 deletion src/Parser/Node/QueryNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public function __construct(
public ?string $description,
public array $argNodes,
public Type $outputType,
public bool $isRequired,
public string $methodName,
) {}

Expand Down
71 changes: 60 additions & 11 deletions src/Parser/Node/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,87 @@

namespace Jerowork\GraphqlAttributeSchema\Parser\Node;

final readonly class Type
final class Type
{
private const string SCALAR = 'scalar';
private const string OBJECT = 'object';

/**
* @param string|class-string $id
* @param class-string|string $value
*/
public function __construct(
public string $id,
public TypeType $type,
public readonly string $value,
private readonly string $type,
private bool $isValueNullable,
private bool $isList,
private bool $isListNullable,
) {}

public static function createScalar(string $name): self
public static function createScalar(string $value): self
{
return new self($value, self::SCALAR, false, false, false);
}

/**
* @param class-string $value
*/
public static function createObject(string $value): self
{
return new self($value, self::OBJECT, false, false, false);
}

public function setNullableValue(): self
{
$this->isValueNullable = true;

return $this;
}

public function setList(): self
{
return new self($name, TypeType::Scalar);
$this->isList = true;

return $this;
}

public static function createObject(string $name): self
public function setNullableList(): self
{
return new self($name, TypeType::Object);
$this->isListNullable = true;

return $this;
}

public function isScalar(): bool
{
return $this->type === TypeType::Scalar;
return $this->type === self::SCALAR;
}

public function isObject(): bool
{
return $this->type === TypeType::Object;
return $this->type === self::OBJECT;
}

public function isValueNullable(): bool
{
return $this->isValueNullable;
}

public function isList(): bool
{
return $this->isList;
}

public function isListNullable(): bool
{
return $this->isListNullable;
}

public function equals(Type $type): bool
{
return $this->id === $type->id && $this->type === $type->type;
return $this->value === $type->value
&& $this->type === $type->type
&& $this->isValueNullable === $type->isValueNullable
&& $this->isList === $type->isList
&& $this->isListNullable === $type->isListNullable;
}
}
Loading

0 comments on commit 5c0ffff

Please sign in to comment.