Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"twig/twig": "~3.21.1",
"voku/portable-ascii": "^2.0",
"web-auth/webauthn-lib": "~5.2.4",
"webonyx/graphql-php": "~14.11.10",
"webonyx/graphql-php": "~15.31.5",
"yiisoft/arrays": "^3.2",
"yiisoft/html": "^3.11",
"yiisoft/translator": "^3.2",
Expand Down
52 changes: 33 additions & 19 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 6 additions & 7 deletions src/Gql/Directives/FormatDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use DateTime;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;

Expand All @@ -32,23 +31,23 @@ public static function create(): GqlDirective
DirectiveLocation::FIELD,
],
'args' => [
new FieldArgument([
[
'name' => 'format',
'type' => Type::string(),
'defaultValue' => self::DEFAULT_FORMAT,
'description' => 'The format to use. Can be `short`, `medium`, `long`, `full`, an [ICU date format](http://userguide.icu-project.org/formatparse/datetime), or a [PHP date format](https://www.php.net/manual/en/function.date.php). Defaults to the [Atom date time format](https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.atom]).',
]),
new FieldArgument([
],
[
'name' => 'timezone',
'type' => Type::string(),
'description' => 'The full name of the timezone (e.g., America/New_York). Defaults to '.self::defaultTimeZone().' if no timezone set on the field.',
'defaultValue' => self::defaultTimeZone(),
]),
new FieldArgument([
],
[
'name' => 'locale',
'type' => Type::string(),
'description' => 'The locale to use when formatting the date. (E.g., en-US)',
]),
],
],
'description' => 'Formats a date in the desired format. Can be applied to all fields, only changes output of DateTime fields.',
]));
Expand Down
9 changes: 4 additions & 5 deletions src/Gql/Directives/Markdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use CraftCms\Cms\Support\Facades\Markdown as MarkdownFacade;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;

Expand All @@ -28,18 +27,18 @@ public static function create(): GqlDirective
DirectiveLocation::FIELD,
],
'args' => [
new FieldArgument([
[
'name' => 'flavor',
'type' => Type::string(),
'defaultValue' => self::DEFAULT_FLAVOR,
'description' => 'The “flavor” of Markdown the input should be interpreted with. Accepts the same flavor names as `CraftCms\\Cms\\Support\\Facades\\Markdown::parse()`.',
]),
new FieldArgument([
],
[
'name' => 'inlineOnly',
'type' => Type::boolean(),
'defaultValue' => self::DEFAULT_INLINE_ONLY,
'description' => 'Whether to only parse inline elements, omitting any `<p>` tags.',
]),
],
],
'description' => 'Parses the passed field value as Markdown.',
]));
Expand Down
9 changes: 4 additions & 5 deletions src/Gql/Directives/Money.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use CraftCms\Cms\Support\Money as MoneyHelper;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;

Expand All @@ -33,17 +32,17 @@ public static function create(): GqlDirective
DirectiveLocation::FIELD,
],
'args' => [
new FieldArgument([
[
'name' => 'format',
'type' => Type::string(),
'defaultValue' => self::FORMAT_STRING,
'description' => 'This specifies the format to output. This can be `amount`, `decimal`, `number`, or `string`. It defaults to the `string`.',
]),
new FieldArgument([
],
[
'name' => 'locale',
'type' => Type::string(),
'description' => 'The locale to use when formatting the money value. (e.g. `en_US`). This argument is only valid with `number` and `string` formats.',
]),
],
],
'description' => 'Formats a money object to the desired format. It can be applied to any fields, but only changes a Money field.',
]));
Expand Down
5 changes: 2 additions & 3 deletions src/Gql/Directives/StripTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use CraftCms\Cms\Gql\GqlEntityRegistry;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;

Expand All @@ -24,12 +23,12 @@ public static function create(): GqlDirective
],
'description' => 'Strips HTML tags from the field value.',
'args' => [
new FieldArgument([
[
'name' => 'allowed',
'type' => Type::listOf(Type::string()),
'defaultValue' => [],
'description' => 'List of allowed tag names.',
]),
],
],
]));
}
Expand Down
12 changes: 0 additions & 12 deletions src/Gql/Directives/Transform.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,11 @@
use CraftCms\Cms\Gql\GqlHelper as Gql;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Support\Collection;

class Transform extends Directive
{
public function __construct(array $config)
{
$args = &$config['args'];

foreach ($args as &$argument) {
$argument = new FieldArgument($argument);
}

parent::__construct($config);
}

public static function create(): GqlDirective
{
$typeName = static::name();
Expand Down
8 changes: 3 additions & 5 deletions src/Gql/ElementQueryConditionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
use GraphQL\Language\AST\ObjectValueNode;
use GraphQL\Language\AST\VariableNode;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\WrappingType;
use GraphQL\Type\Definition\Type;
use InvalidArgumentException;

class ElementQueryConditionBuilder extends Component
Expand Down Expand Up @@ -265,11 +265,9 @@ private function _prepareTransformArguments(array $arguments): array

private function _isInsideAssetQuery(): bool
{
if ($this->_resolveInfo->returnType instanceof WrappingType) {
return $this->_resolveInfo->returnType->getWrappedType()->name === AssetInterface::getName();
}
$namedType = Type::getNamedType($this->_resolveInfo->returnType);

return $this->_resolveInfo->returnType->name === AssetInterface::getName();
return $namedType !== null && $namedType->name() === AssetInterface::getName();
}

/**
Expand Down
31 changes: 23 additions & 8 deletions src/Gql/Gql.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
use CraftCms\Cms\Gql\Types\DateTime;
use CraftCms\Cms\Gql\Types\Mutation;
use CraftCms\Cms\Gql\Types\Number;
use CraftCms\Cms\Gql\Types\ObjectType;
use CraftCms\Cms\Gql\Types\Query;
use CraftCms\Cms\Gql\Types\QueryArgument;
use CraftCms\Cms\ProjectConfig\Events\ConfigEvent;
Expand Down Expand Up @@ -181,7 +182,7 @@ public function getSchemaDef(?GqlSchema $schema = null, bool $prebuildSchema = f
$this->_registerGqlMutations();

$schemaConfig = [
'typeLoader' => TypeLoader::class.'::loadType',
'typeLoader' => TypeLoader::loadType(...),
'query' => TypeLoader::loadType('Query'),
'mutation' => TypeLoader::loadType('Mutation'),
'directives' => $this->_loadGqlDirectives($schema),
Expand All @@ -191,13 +192,21 @@ public function getSchemaDef(?GqlSchema $schema = null, bool $prebuildSchema = f
// as the query is being resolved thanks to the magic of lazy-loading, so we needn't worry.
if (! $prebuildSchema) {
$this->_schemaDef = new Schema($schemaConfig);
// add default description (use schema name), or DumpSchemaCommandTest and SchemaPrinter::printSchemaDefinition() will error
// because of SchemaPrinter::hasDefaultRootOperationTypes($schema) and "Subscription"
if ($this->_schemaDef->description === null) {
$this->_schemaDef->description = $schema?->name;
}

// but we always have to add the InputObjectType mutation args
foreach ($schemaConfig['mutation']->config['fields'] as $item) {
/** @var ObjectType $mutation */
$mutation = $schemaConfig['mutation'];
foreach ($mutation->config['fields'] as $item) {
if (isset($item['args'])) {
foreach ($item['args'] as $arg) {
if ($arg instanceof InputObjectType) {
TypeInfo::extractTypes($arg);
$argType = Type::getNamedType($arg->getType());
if ($argType instanceof InputObjectType) {
TypeInfo::extractTypes($argType, $arg);
}
}
}
Expand All @@ -220,6 +229,11 @@ public function getSchemaDef(?GqlSchema $schema = null, bool $prebuildSchema = f
try {
$this->_schemaDef = new Schema($schemaConfig);
$this->_schemaDef->getTypeMap();
// add default description (use schema name), or DumpSchemaCommandTest and SchemaPrinter::printSchemaDefinition() will error
// because of SchemaPrinter::hasDefaultRootOperationTypes($schema) and "Subscription"
if ($this->_schemaDef->description === null) {
$this->_schemaDef->description = $schema?->name;
}
} catch (Throwable $exception) {
throw new GqlException('Failed to validate the GQL Schema - '.$exception->getMessage(),
previous: $exception);
Expand Down Expand Up @@ -260,7 +274,7 @@ public function getValidationRules(bool $debug = false, bool $isIntrospectionQue
}

if (! $generalConfig->enableGraphqlIntrospection && Auth::guest()) {
$validationRules[DisableIntrospection::class] = new DisableIntrospection;
$validationRules[DisableIntrospection::class] = new DisableIntrospection(0);
}

event($event = new DefineGqlValidationRules(
Expand Down Expand Up @@ -940,8 +954,9 @@ public function getContentArguments(array $contexts, string $elementType): array
}

/**
* @param Error[] $errors
* @return Error[]
* @param list<Error> $errors
* @param callable(Throwable): array{message: string, locations?: array<int, array{line: int, column: int}>, path?: array<int, int|string>, extensions?: array<string, mixed>} $formatter
* @return list<array{message: string, locations?: array<int, array{line: int, column: int}>, path?: array<int, int|string>, extensions?: array<string, mixed>}>
*/
public function handleQueryErrors(array $errors, callable $formatter): array
{
Expand Down Expand Up @@ -1126,7 +1141,7 @@ private function _loadGqlDirectives(?GqlSchema $schema): array
event($event = new RegisterGqlDirectives(directives: $directiveClasses));
$directiveClasses = $event->directives;

$directives = GraphQL::getStandardDirectives();
$directives = GqlDirective::builtInDirectives();

foreach ($directiveClasses as $class) {
/** @var class-string<Directive> $class */
Expand Down
4 changes: 2 additions & 2 deletions src/Gql/GqlHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ public static function createFullAccessSchema(): GqlSchema

public static function applyDirectives(mixed $source, ResolveInfo $resolveInfo, mixed $value): mixed
{
/** @phpstan-ignore-next-line */
if (! isset($resolveInfo->fieldNodes[0]->directives)) {
return $value;
}
Expand Down Expand Up @@ -309,7 +308,8 @@ private static function _convertArgumentValue(mixed $value, array $variableValue

public static function getFieldNameWithAlias(ResolveInfo $resolveInfo, mixed $source, ?array $context): string
{
$fieldName = is_array($resolveInfo->path) ? array_slice($resolveInfo->path, -1)[0] : $resolveInfo->fieldName;
// $resolveInfo->path is either an array or not set, so we need to check if it's set
$fieldName = isset($resolveInfo->path) ? array_slice($resolveInfo->path, -1)[0] : $resolveInfo->fieldName;
$isAlias = $fieldName !== $resolveInfo->fieldName;

/** @var ElementQueryConditionBuilder|null $conditionBuilder */
Expand Down
Loading
Loading