From af729742eba718f79d79f66abb73d0cce79f6573 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Mon, 2 Aug 2021 17:16:19 +1200 Subject: [PATCH] Nullable fixes, duplication protection --- _config/schema-default.yml | 2 +- .../Plugin/DBFieldArgs/DBDateArgs.php | 7 ++-- .../Plugin/DBFieldArgs/DBFieldArgs.php | 8 +++-- .../Plugin/DBFieldArgs/DBHTMLTextArgs.php | 23 ++++++++---- .../Plugin/DBFieldArgs/DBTextArgs.php | 10 ++++-- .../Plugin/DBFieldArgs/DBTimeArgs.php | 8 +++-- .../DataObject/Plugin/ScalarDBField.php | 5 ++- src/Schema/DataObject/ReadCreator.php | 2 +- src/Schema/Plugin/PaginationPlugin.php | 36 ++++++++++++++----- 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/_config/schema-default.yml b/_config/schema-default.yml index 6181c4954..1d3dfd7e2 100644 --- a/_config/schema-default.yml +++ b/_config/schema-default.yml @@ -14,9 +14,9 @@ SilverStripe\GraphQL\Schema\Schema: schemas: default: config: - parseShortcodes: true modelConfig: DataObject: + parseShortcodes: true operations: read: plugins: diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgs.php index 88e9fdff1..fffd648bd 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgs.php @@ -43,13 +43,16 @@ protected function getResolver(): callable } /** - * @param DBDate $obj + * @param mixed $obj * @param array $args * @return DBField | string * @throws Exception */ - public static function resolve(DBDate $obj, array $args) + public static function resolve($obj, array $args) { + if (!$obj instanceof DBDate) { + return $obj; + } $format = $args['format'] ?? null; $custom = $args['customFormat'] ?? null; diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgs.php index 9e7ff4ff9..1ff096525 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgs.php @@ -3,7 +3,6 @@ namespace SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs; -use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Injector\Injectable; use SilverStripe\GraphQL\Schema\Field\ModelField; use SilverStripe\GraphQL\Schema\Type\Enum; @@ -28,12 +27,15 @@ abstract public function getEnum(): Enum; abstract public function applyToField(ModelField $field): void; /** - * @param DBField $obj + * @param mixed $obj * @param array $args * @return mixed */ - public static function baseFormatResolver(DBField $obj, array $args) + public static function baseFormatResolver($obj, array $args) { + if (!$obj instanceof DBField) { + return $obj; + } $format = $args['format'] ?? null; if ($format) { if ($obj->hasMethod($format)) { diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgs.php index 9c65f7077..6e96f7b53 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgs.php @@ -3,11 +3,12 @@ namespace SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs; +use SilverStripe\Control\HTTP; +use SilverStripe\GraphQL\QueryHandler\SchemaConfigProvider; use SilverStripe\GraphQL\Schema\Field\ModelField; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBHTMLText; use Exception; -use SilverStripe\ORM\FieldType\DBString; class DBHTMLTextArgs extends DBTextArgs { @@ -22,19 +23,29 @@ public function applyToField(ModelField $field): void } /** - * @param DBString $obj + * @param mixed $obj * @param array $args + * @param array $context * @return DBField * @throws Exception */ - public static function resolve(DBString $obj, array $args) + public static function resolve($obj, array $args, array $context) { + $result = parent::resolve($obj, $args, $context); + if (!$result instanceof DBHTMLText) { + return $result; + } + /* @var DBHTMLText $obj */ $parse = $args['parseShortcodes'] ?? null; - if ($parse !== null) { - $obj->setProcessShortcodes($parse); + if ($parse === null) { + $config = SchemaConfigProvider::get($context); + if ($config) { + $parse = $config->getModelConfiguration('DataObject')->get('parseShortcodes', true); + } } + $obj->setProcessShortcodes($parse); - return parent::resolve($obj, $args); + return $obj->RAW(); } } diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php index 84bfb607e..4523330e3 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php @@ -5,8 +5,8 @@ use SilverStripe\GraphQL\Schema\Field\ModelField; use SilverStripe\GraphQL\Schema\Type\Enum; -use SilverStripe\ORM\FieldType\DBString; use Exception; +use SilverStripe\ORM\FieldType\DBText; class DBTextArgs extends DBFieldArgs { @@ -54,11 +54,15 @@ protected function getResolver(): callable } /** - * @param DBString $obj + * @param mixed $obj * @param array $args + * @param array $context */ - public static function resolve(DBString $obj, array $args) + public static function resolve($obj, array $args, array $context) { + if (!$obj instanceof DBText) { + return $obj; + } $format = $args['format'] ?? null; $limit = $args['limit'] ?? null; diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php index 6512fb39f..e4045b52e 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php @@ -5,7 +5,6 @@ use SilverStripe\GraphQL\Schema\Field\ModelField; use SilverStripe\GraphQL\Schema\Type\Enum; -use SilverStripe\ORM\FieldType\DBDate; use SilverStripe\ORM\FieldType\DBField; use Exception; use SilverStripe\ORM\FieldType\DBTime; @@ -42,13 +41,16 @@ protected function getResolver(): callable } /** - * @param DBTime $obj + * @param mixed $obj * @param array $args * @return DBField | string * @throws Exception */ - public static function resolve(DBTime $obj, array $args) + public static function resolve($obj, array $args) { + if (!$obj instanceof DBTime) { + return $obj; + } $format = $args['format'] ?? null; $custom = $args['customFormat'] ?? null; diff --git a/src/Schema/DataObject/Plugin/ScalarDBField.php b/src/Schema/DataObject/Plugin/ScalarDBField.php index c07385160..7574393b5 100644 --- a/src/Schema/DataObject/Plugin/ScalarDBField.php +++ b/src/Schema/DataObject/Plugin/ScalarDBField.php @@ -32,8 +32,7 @@ public function apply(ModelType $type, Schema $schema, array $config = []): void { foreach ($type->getFields() as $field) { if ($field instanceof ModelField && $field->getModel() instanceof DataObjectModel) { - $dataClass = $field->getMetadata()->get('dataClass'); - if (is_subclass_of($dataClass, DBField::class)) { + if (!$field->isList()) { $field->addResolverAfterware([static::class, 'resolve']); } } @@ -47,7 +46,7 @@ public function apply(ModelType $type, Schema $schema, array $config = []): void public static function resolve($obj) { if ($obj instanceof DBField) { - return $obj->forTemplate(); + return $obj->getValue(); } return $obj; diff --git a/src/Schema/DataObject/ReadCreator.php b/src/Schema/DataObject/ReadCreator.php index fd68a42dd..545450604 100644 --- a/src/Schema/DataObject/ReadCreator.php +++ b/src/Schema/DataObject/ReadCreator.php @@ -44,7 +44,7 @@ public function createOperation( } $query = ModelQuery::create($model, $queryName) - ->setType("[$typeName]") + ->setType("[$typeName!]!") ->setPlugins($plugins) ->setResolver([static::class, 'resolve']) ->setResolverContext([ diff --git a/src/Schema/Plugin/PaginationPlugin.php b/src/Schema/Plugin/PaginationPlugin.php index bfecbfdb6..ca53088d1 100644 --- a/src/Schema/Plugin/PaginationPlugin.php +++ b/src/Schema/Plugin/PaginationPlugin.php @@ -92,8 +92,13 @@ public static function updateSchema(Schema $schema): void */ public function apply(Field $field, Schema $schema, array $config = []): void { + // Set the new return type + $plainType = $field->getNamedType(); + $fullType = $field->getType(); + $ref = TypeReference::create($fullType); + $defaultLimit = $config['defaultLimit'] ?? $this->config()->get('default_limit'); - $connectionName = $config['connection'] ?? $field->getName(); + $connectionName = $config['connection'] ?? $plainType; $max = $this->config()->get('max_limit'); $limit = min($defaultLimit, $max); $field->addArg('limit', "Int = $limit") @@ -103,14 +108,26 @@ public function apply(Field $field, Schema $schema, array $config = []): void ['maxLimit' => $max] ); - // Set the new return type - $plainType = $field->getNamedType(); - $fullType = $field->getType(); - $ref = TypeReference::create($fullType); + $existing = $schema->getState()->get(['connections', $fullType]); + if ($existing) { + $field->setType($existing, $ref->isRequired()); + return; + } $connectionName = ucfirst($connectionName) . 'Connection'; - $connectionTypeStr = $ref->isRequired() ? $connectionName . '!' : $connectionName; - $field->setType($connectionTypeStr); + + // Dedupe. If the connection exists for the same type + // (possibly with different wrapper type, e.g. not required) + if ($existing = $schema->getType($connectionName)) { + $i = 1; + $rootConnectionName = $connectionName; + while ($schema->getType($connectionName)) { + $connectionName = $rootConnectionName . $i; + $i++; + } + } + + $field->setType($connectionName, $ref->isRequired()); // Create the edge type for this query $edgeType = Type::create($connectionName . 'Edge') @@ -123,11 +140,14 @@ public function apply(Field $field, Schema $schema, array $config = []): void // Create the connection type for this query $connectionType = Type::create($connectionName) - ->addField('edges', "[{$edgeType->getName()}]!") + ->addField('edges', "[{$edgeType->getName()}!]!") ->addField('nodes', $fullType) ->addField('pageInfo', 'PageInfo!'); $schema->addType($connectionType); + + // Cache the connection for this type so it can be reused + $schema->getState()->set(['connections', $fullType], $connectionType->getName()); } /**