Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEW: DBField arguments, Enum, Composite support #398

Merged
merged 14 commits into from
Sep 6, 2021
14 changes: 0 additions & 14 deletions _config/assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@ Name: graphqlassets
Only:
moduleexists: 'silverstripe/assets'
---
SilverStripe\GraphQL\Schema\Schema:
schemas:
'*':
types:
DBFile:
fields:
filename: String
hash: String
variant: String
url: String

SilverStripe\Assets\Storage\DBFile:
graphql_type: DBFile

SilverStripe\Assets\File:
allowed_extensions:
- graphql
Expand Down
18 changes: 18 additions & 0 deletions _config/dbargs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
Name: graphql-db-args
---
# For the DBFieldArgsPlugin, assign each DBField type an args factory
SilverStripe\ORM\FieldType\DBText:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBTextArgs
SilverStripe\ORM\FieldType\DBHTMLText:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBHTMLTextArgs
SilverStripe\ORM\FieldType\DBDate:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBDateArgs
SilverStripe\ORM\FieldType\DBDateTime:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBDatetimeArgs
SilverStripe\ORM\FieldType\DBTime:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBTimeArgs
SilverStripe\ORM\FieldType\DBDecimal:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBDecimalArgs
SilverStripe\ORM\FieldType\DBFloat:
graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBFloatArgs
3 changes: 3 additions & 0 deletions _config/plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ SilverStripe\Core\Injector\Injector:
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\CanViewPermission'
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\FirstResult'
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\InheritedPlugins'
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBFieldArgsPlugin'
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldTypes'
- 'SilverStripe\GraphQL\Schema\Plugin\SortPlugin'
- 'SilverStripe\GraphQL\Schema\DataObject\Plugin\ScalarDBField'
1 change: 1 addition & 0 deletions _config/schema-default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ SilverStripe\GraphQL\Schema\Schema:
config:
modelConfig:
DataObject:
parseShortcodes: true
operations:
read:
plugins:
Expand Down
9 changes: 7 additions & 2 deletions _config/schema-global.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ SilverStripe\GraphQL\Schema\Schema:
base_fields:
ID: ID!
plugins:
dbFieldArgs: true
dbFieldTypes:
ignore:
className: true
before: scalarDBField
inheritance:
useUnionQueries: false
hideAncestors:
- SilverStripe\CMS\Model\SiteTree
after: 'versioning'
scalarDBField:
after: dbFieldArgs
inheritedPlugins:
after: '*'
operations:
Expand Down
27 changes: 25 additions & 2 deletions src/Schema/DataObject/DataObjectModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use SilverStripe\GraphQL\Schema\Field\ModelQuery;
use SilverStripe\GraphQL\Schema\Interfaces\BaseFieldsProvider;
use SilverStripe\GraphQL\Schema\Interfaces\DefaultFieldsProvider;
use SilverStripe\GraphQL\Schema\Interfaces\ExtraTypeProvider;
use SilverStripe\GraphQL\Schema\Interfaces\ModelBlacklist;
use SilverStripe\GraphQL\Schema\Resolver\ResolverReference;
use SilverStripe\GraphQL\Schema\SchemaConfig;
Expand Down Expand Up @@ -114,18 +115,28 @@ public function getField(string $fieldName, array $config = []): ?ModelField
return null;
}

$hasExplicitType = isset($config['type']);

if ($result instanceof DBField) {
$fieldConfig = array_merge([
'type' => $result->config()->get('graphql_type'),
], $config);

return ModelField::create($fieldName, $fieldConfig, $this);
$modelField = ModelField::create($fieldName, $fieldConfig, $this);
if (!$hasExplicitType) {
$this->applyMetadataClass($modelField, get_class($result));
}
return $modelField;
}

$class = $this->getModelClass($result);
if (!$class) {
if ($this->isList($result)) {
return ModelField::create($fieldName, $config, $this);
$modelField = ModelField::create($fieldName, $config, $this);
if (!$hasExplicitType) {
$this->applyMetadataClass($modelField, $class);
}
return $modelField;
}
return null;
}
Expand All @@ -136,6 +147,7 @@ public function getField(string $fieldName, array $config = []): ?ModelField
], $config);
$query = ModelQuery::create($this, $fieldName, $queryConfig);
$query->setDefaultPlugins($this->getModelConfiguration()->getNestedQueryPlugins());

return $query;
}
return ModelField::create($fieldName, $type, $this);
Expand Down Expand Up @@ -399,4 +411,15 @@ private function isList($result): bool
{
return $result instanceof SS_List || $result instanceof UnsavedRelationList;
}

/**
* @param ModelField $field
* @param string | null $class
* @throws SchemaBuilderException
*/
private function applyMetadataClass(ModelField $field, ?string $class = null): void
{
$field->getMetadata()
->set('dataClass', $class);
}
}
22 changes: 20 additions & 2 deletions src/Schema/DataObject/InterfaceBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,20 @@ class InterfaceBuilder
*/
private $schema;

/**
* @var array
*/
private $hideAncestors = [];

/**
* InterfaceBuilderTest constructor.
* @param Schema $schema
* @param array $hideAncestors
*/
public function __construct(Schema $schema)
public function __construct(Schema $schema, array $hideAncestors = [])
{
$this->setSchema($schema);
$this->hideAncestors = $hideAncestors;
}

/**
Expand Down Expand Up @@ -86,7 +93,9 @@ public function createInterfaces(ModelType $modelType, array $interfaceStack = [
$interfaceStack[] = $interface;
$modelType->addInterface($interface->getName());

$chain = InheritanceChain::create($modelType->getModel()->getSourceClass());
$chain = InheritanceChain::create($modelType->getModel()->getSourceClass())
->hideAncestors($this->hideAncestors);

foreach ($chain->getDirectDescendants() as $class) {
if ($childType = $this->getSchema()->getModelByClassName($class)) {
$this->createInterfaces($childType, $interfaceStack);
Expand Down Expand Up @@ -130,6 +139,7 @@ public function applyBaseInterface(): InterfaceBuilder

/**
* @param ModelType $type
* @throws ReflectionException
* @throws SchemaBuilderException
* @return $this
*/
Expand Down Expand Up @@ -157,6 +167,14 @@ public function applyInterfacesToQueries(ModelType $type): InterfaceBuilder
$this->schema->eagerLoad($modelType->getName());
}
}
$chain = InheritanceChain::create($type->getModel()->getSourceClass())
->hideAncestors($this->hideAncestors);

foreach ($chain->getDirectDescendants() as $class) {
if ($modelType = $schema->getModelByClassName($class)) {
$this->applyInterfacesToQueries($modelType);
}
}

return $this;
}
Expand Down
92 changes: 92 additions & 0 deletions src/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php


namespace SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs;

use SilverStripe\GraphQL\Schema\Field\ModelField;
use SilverStripe\GraphQL\Schema\Type\Enum;
use SilverStripe\ORM\FieldType\DBDate;
use Exception;
use SilverStripe\ORM\FieldType\DBField;

class DBDateArgs extends DBFieldArgs
{
public function getEnum(): Enum
{
return Enum::create(
'DBDateFormattingOptions',
$this->getValues(),
'Formatting options for fields that map to DBDate data types'
);
}

public function applyToField(ModelField $field): void
{
$field
->addArg('format', [
'type' => $this->getEnum()->getName(),
'description' => 'Formatting options for this field',
])
->addArg('customFormat', [
'type' => 'String',
'description' => 'If format is CUSTOM, the format string, e.g. "y-MM-dd HH:mm:ss"',
])
->addResolverAfterware($this->getResolver());
}

/**
* @return callable
*/
protected function getResolver(): callable
{
return [static::class, 'resolve'];
emteknetnz marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @param mixed $obj
* @param array $args
* @return DBField | string
* @throws Exception
*/
public static function resolve($obj, array $args)
{
if (!$obj instanceof DBDate) {
return $obj;
}
$format = $args['format'] ?? null;
$custom = $args['customFormat'] ?? null;

if ($format === 'Format') {
if (!$custom) {
throw new Exception('The "custom" option requires a value for "customFormat"');
}
return $obj->Format($custom);
}
if ($custom) {
throw new Exception('The "customFormat" argument should not be set for formats that are not "custom"');
}

if ($obj->hasMethod($format)) {
return $obj->obj($format);
}

return $obj;
}

public function getValues(): array
{
return [
'TIMESTAMP' => 'Timestamp',
'NICE' => 'Nice',
'DAY_OF_WEEK' => 'DayOfWeek',
'MONTH' => 'Month',
'YEAR' => 'Year',
'SHORT_MONTH' => 'ShortMonth',
'DAY_OF_MONTH' => 'DayOfMonth',
'SHORT' => 'Short',
'LONG' => 'Long',
'FULL' => 'Full',
'CUSTOM' => 'Format',
];
}
}
31 changes: 31 additions & 0 deletions src/Schema/DataObject/Plugin/DBFieldArgs/DBDatetimeArgs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php


namespace SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs;

use SilverStripe\GraphQL\Schema\Type\Enum;

class DBDatetimeArgs extends DBDateArgs
{
public function getEnum(): Enum
{
return Enum::create(
'DBDatetimeFormattingOption',
$this->getValues(),
'Formatting options for fields that map to DBDatetime data types'
);
}

public function getValues(): array
{
return array_merge(
parent::getValues(),
[
'DATE' => 'Date',
emteknetnz marked this conversation as resolved.
Show resolved Hide resolved
'TIME' => 'Time',
'TIME12' => 'Time12',
'TIME24' => 'Time24',
]
);
}
}
45 changes: 45 additions & 0 deletions src/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php


namespace SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs;

use SilverStripe\GraphQL\Schema\Field\ModelField;
use SilverStripe\GraphQL\Schema\Type\Enum;

class DBDecimalArgs extends DBFieldArgs
{
public function getEnum(): Enum
{
return Enum::create(
'DBDecimalFormattingOptions',
$this->getValues(),
'Formatting options for fields that map to DBDecimal data types'
);
}

public function applyToField(ModelField $field): void
{
$field->addArg('format', [
'type' => $this->getEnum()->getName(),
'description' => 'Formatting options for this field',
])->addResolverAfterware(
$this->getResolver()
);
}

/**
* @return callable
*/
protected function getResolver(): callable
{
return [DBFieldArgs::class, 'baseFormatResolver'];
}


public function getValues(): array
{
return [
'INT' => 'Int',
emteknetnz marked this conversation as resolved.
Show resolved Hide resolved
];
}
}
Loading