Skip to content

Commit

Permalink
Allow ignore enum, prevent duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Carlino committed Aug 1, 2021
1 parent 01f8c23 commit 781e981
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 12 deletions.
2 changes: 2 additions & 0 deletions _config/schema-global.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ SilverStripe\GraphQL\Schema\Schema:
plugins:
dbFieldArgs: true
dbFieldTypes:
ignore:
className: true
before: scalarDBField
inheritance:
useUnionQueries: false
Expand Down
50 changes: 42 additions & 8 deletions src/Schema/DataObject/Plugin/DBFieldTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,20 @@ public function getIdentifier(): string
*/
public function apply(ModelType $type, Schema $schema, array $config = []): void
{
$ignore = $config['ignore'] ?? [];
$mapping = $config['enumTypeMapping'] ?? [];
foreach ($type->getFields() as $field) {
if ($field instanceof ModelField && $field->getModel() instanceof DataObjectModel) {
if (($ignore[$field->getName()] ?? null)) {
continue;
}
$dataClass = $field->getMetadata()->get('dataClass');
if (!$dataClass) {
continue;
}
if ($dataClass === DBEnum::class || is_subclass_of($dataClass, DBEnum::class)) {
$this->applyEnum($type, $field, $schema);
$customName = $mapping[$type->getName()][$field->getName()] ?? null;
$this->applyEnum($type, $field, $schema, $customName);
} elseif ($dataClass === DBComposite::class || is_subclass_of($dataClass, DBComposite::class)) {
$this->applyComposite($field, $schema);
}
Expand All @@ -56,10 +62,15 @@ public function apply(ModelType $type, Schema $schema, array $config = []): void
* @param ModelType $type
* @param ModelField $field
* @param Schema $schema
* @param string | null $customName
* @throws SchemaBuilderException
*/
private function applyEnum(ModelType $type, ModelField $field, Schema $schema): void
{
private function applyEnum(
ModelType $type,
ModelField $field,
Schema $schema,
?string $customName = null
): void {
$sng = Injector::inst()->get($field->getModel()->getSourceClass());
/* @var DBEnum $enumField */
$enumField = $sng->dbObject($field->getPropertyName());
Expand All @@ -68,11 +79,34 @@ private function applyEnum(ModelType $type, ModelField $field, Schema $schema):
}

$values = $enumField->enumValues();
$enum = Enum::create(
sprintf('%s%sEnum', $type->getName(), $field->getName()),
$values
);
$schema->addEnum($enum);

// If another enum exists with the same values, recycle it.
$hash = md5(json_encode($values));
$enum = null;
foreach ($schema->getEnums() as $candidate) {
$candidateHash = md5(json_encode($candidate->getValues()));
if ($candidateHash === $hash) {
$enum = $candidate;
break;
}
}

if (!$enum) {
$enum = Enum::create(
$customName ?: sprintf('%sEnum', $field->getName()),
$values
);

// Name collision detection. If already exists, prefix with type.
$enums = $schema->getEnums();
$existing = $enums[$enum->getName()] ?? null;
if ($existing) {
$enum->setName($type->getName() . $enum->getName());
}

$schema->addEnum($enum);
}

$field->setType($enum->getName());
}

Expand Down
13 changes: 9 additions & 4 deletions src/Schema/Plugin/PaginationPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use SilverStripe\GraphQL\Schema\Schema;
use SilverStripe\GraphQL\Schema\Type\Type;
use Countable;
use SilverStripe\GraphQL\Schema\Type\TypeReference;

/**
* Generic pagination functionality for a query that can be customised in subclasses
Expand Down Expand Up @@ -104,22 +105,26 @@ 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);

$connectionName = ucfirst($connectionName) . 'Connection';
$field->setType($connectionName, true);
$connectionTypeStr = $ref->isRequired() ? $connectionName . '!' : $connectionName;
$field->setType($connectionTypeStr);

// Create the edge type for this query
$edgeType = Type::create($connectionName . 'Edge')
->setDescription('The collections edge')
->addField('node', $plainType, function (Field $field) {
->addField('node', "$plainType!", function (Field $field) {
$field->setResolver([static::class, 'noop'])
->setDescription('The node at the end of the collections edge');
});
$schema->addType($edgeType);

// Create the connection type for this query
$connectionType = Type::create($connectionName)
->addField('edges', "[{$edgeType->getName()}!]!")
->addField('nodes', "[{$plainType}!]!")
->addField('edges', "[{$edgeType->getName()}]!")
->addField('nodes', $fullType)
->addField('pageInfo', 'PageInfo!');

$schema->addType($connectionType);
Expand Down

0 comments on commit 781e981

Please sign in to comment.