Skip to content

Commit

Permalink
API Standardise OperationResolver::resolve() (#28)
Browse files Browse the repository at this point in the history
API PaginatedQueryCreator is abstract
PSR2 cleanup
PHPDoc cleanup
  • Loading branch information
Damian Mooyman authored and Uncle Cheese committed Jan 20, 2017
1 parent 4de64d7 commit eb35ad4
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 67 deletions.
21 changes: 3 additions & 18 deletions src/InterfaceTypeCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,18 @@

namespace SilverStripe\GraphQL;

use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\InterfaceType as BaseInterfaceType;

/**
* Base type creator for interface type generation.
*
* @link https://github.com/webonyx/graphql-php#interfaces
*/
class InterfaceTypeCreator extends TypeCreator
{
/**
* Returns a callback to the type resolver for this interface
*
* @return callable
*/

protected function getTypeResolver()
{
if (!method_exists($this, 'resolveType')) {
return null;
}

$resolver = array($this, 'resolveType');

return function () use ($resolver) {
$args = func_get_args();
return call_user_func_array($resolver, $args);
Expand All @@ -47,13 +37,8 @@ public function getAttributes()
return $attributes;
}

/**
* Generates the interface type from its configuration
*
* @return InterfaceType
*/
public function toType()
{
return new InterfaceType($this->toArray());
return new BaseInterfaceType($this->toArray());
}
}
54 changes: 24 additions & 30 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@
use GraphQL\Schema;
use GraphQL\GraphQL;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Injector\Injectable;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Error;
use GraphQL\Type\Definition\Type;
use SilverStripe\Security\Member;
use SilverStripe\GraphQL\Scaffolding\ScaffoldingProvider;
use SilverStripe\GraphQL\Scaffolding\Scaffolders\GraphQLScaffolder;

class Manager
{
use Injectable;

/**
* @var array Map of named {@link Type}
*/
Expand Down Expand Up @@ -45,39 +41,38 @@ class Manager

/**
* @param array $config An array with optional 'types' and 'queries' keys
*
* @return Manager
*/
public static function createFromConfig($config)
{
/** @var Manager $manager */
$manager = Injector::inst()->create(self::class);
$manager = Injector::inst()->create(Manager::class);

if (isset($config['scaffolding'])) {
$scaffolder = GraphQLScaffolder::createFromConfig($config['scaffolding']);
if(isset($config['scaffolding'])) {
$scaffolder = GraphQLScaffolder::createFromConfig($config['scaffolding']);
} else {
$scaffolder = new GraphQLScaffolder();
$scaffolder = new GraphQLScaffolder();
}

if (isset($config['scaffolding_providers'])) {
foreach ($config['scaffolding_providers'] as $provider) {
if (!class_exists($provider)) {
if(isset($config['scaffolding_providers'])) {
foreach($config['scaffolding_providers'] as $provider) {
if(!class_exists($provider)) {
throw new InvalidArgumentException(sprintf(
'Scaffolding provider %s does not exist.',
$provider
));
}
));
}

$provider = Injector::inst()->create($provider);

$provider = Injector::inst()->create($provider);

if (!$provider instanceof ScaffoldingProvider) {
if(!$provider instanceof ScaffoldingProvider) {
throw new InvalidArgumentException(sprintf(
'All scaffolding providers must implement the %s interface',
ScaffoldingProvider::class
));
}
$scaffolder = $provider->provideGraphQLScaffolding($scaffolder);
}
));
}
$scaffolder = $provider->provideGraphQLScaffolding($scaffolder);
}
}

$scaffolder->addToManager($manager);
Expand All @@ -88,7 +83,7 @@ public static function createFromConfig($config)
$typeCreator = Injector::inst()->create($typeCreatorClass, $manager);
if (!($typeCreator instanceof TypeCreator)) {
throw new InvalidArgumentException(sprintf(
'The type named "%s" needs to be a class extending '.TypeCreator::class,
'The type named "%s" needs to be a class extending ' . TypeCreator::class,
$name
));
}
Expand All @@ -104,7 +99,7 @@ public static function createFromConfig($config)
$queryCreator = Injector::inst()->create($queryCreatorClass, $manager);
if (!($queryCreator instanceof QueryCreator)) {
throw new InvalidArgumentException(sprintf(
'The type named "%s" needs to be a class extending '.QueryCreator::class,
'The type named "%s" needs to be a class extending ' . QueryCreator::class,
$name
));
}
Expand All @@ -120,7 +115,7 @@ public static function createFromConfig($config)
$mutationCreator = Injector::inst()->create($mutationCreatorClass, $manager);
if (!($mutationCreator instanceof MutationCreator)) {
throw new InvalidArgumentException(sprintf(
'The mutation named "%s" needs to be a class extending '.MutationCreator::class,
'The mutation named "%s" needs to be a class extending ' . MutationCreator::class,
$name
));
}
Expand Down Expand Up @@ -189,21 +184,20 @@ public function query($query, $params = [], $schema = null)
public function queryAndReturnResult($query, $params = [], $schema = null)
{
$schema = $this->schema($schema);
$context = $this->getContext();
$result = GraphQL::executeAndReturnResult($schema, $query, null, $context, $params);
$result = GraphQL::executeAndReturnResult($schema, $query, null, null, $params);

return $result;
}

/**
* @param Type $type
* @param string $name An optional identifier for this type (defaults to 'name' attribute in type definition).
* Needs to be unique in schema
* Needs to be unique in schema.
*/
public function addType(Type $type, $name = '')
{
if (!$name) {
$name = (string) $type;
$name = (string)$type;
}
$this->types[$name] = $type;
}
Expand Down Expand Up @@ -234,7 +228,7 @@ public function hasType($name)

/**
* @param array $query
* @param string $name Identifier for this query (unique in schema)
* @param string $name Identifier for this query (unique in schema)
*/
public function addQuery($query, $name)
{
Expand All @@ -253,7 +247,7 @@ public function getQuery($name)

/**
* @param array $mutation
* @param string $name Identifier for this mutation (unique in schema)
* @param string $name Identifier for this mutation (unique in schema)
*/
public function addMutation($mutation, $name)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Pagination/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace SilverStripe\GraphQL\Pagination;

use SilverStripe\Core\Object;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\GraphQL\OperationResolver;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\Limitable;
use SilverStripe\ORM\Sortable;
Expand Down Expand Up @@ -32,10 +32,8 @@
* }
* </code>
*/
class Connection implements OperationResolver
class Connection extends Object implements OperationResolver
{
use Injectable;

/**
* @var string
*/
Expand Down Expand Up @@ -89,6 +87,8 @@ class Connection implements OperationResolver
public function __construct($connectionName)
{
$this->connectionName = $connectionName;

parent::__construct();
}

/**
Expand Down
40 changes: 40 additions & 0 deletions src/Pagination/SortDirectionType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace SilverStripe\GraphQL\Pagination;

use SilverStripe\Core\Object;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\ObjectType;

class SortDirectionType extends Object
{
/**
* @var ObjectType
*/
private $type;

/**
* @return ObjectType
*/
public function toType()
{
if (!$this->type) {
$this->type = new EnumType([
'name' => 'SortDirection',
'description' => 'Set order order to either ASC or DESC',
'values' => [
'ASC' => [
'value' => 'ASC',
'description' => 'Lowest value to highest.'
],
'DESC' => [
'value' => 'DESC',
'description' => 'Highest value to lowest.'
]
]
]);
}

return $this->type;
}
}
91 changes: 91 additions & 0 deletions src/Pagination/SortInputType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace SilverStripe\GraphQL\Pagination;

use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectType;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Injector\Injectable;
use GraphQL\Type\Definition\EnumType;

class SortInputType
{
use Injectable;

/**
* @var InputObjectType
*/
private $type;

/**
* @var string
*/
private $inputName;


/**
* @var array Keyed by field argument name, values as DataObject column names.
* Does not support in-memory sorting for composite values (getters).
*/
protected $sortableFields = [];

/**
*
*/
public function __construct($name)
{
parent::__construct();
$this->inputName = $name;
}

/**
* @param array $sortableFields
*
* @return $this
*/
public function setSortableFields($sortableFields)
{
$this->sortableFields = $sortableFields;

return $this;
}

/**
* @return Type
*/
public function toType()
{
$values = [];

foreach ($this->sortableFields as $fieldAlias => $fieldName) {
$values[$fieldAlias] = [
'value' => $fieldAlias
];
}

$sortableField = new EnumType([
'name' => ucfirst($this->inputName) . 'SortFieldType',
'description' => 'Field name to sort by.',
'values' => $values
]);

if (!$this->type) {
$this->type = new InputObjectType([
'name' => ucfirst($this->inputName) .'SortInputType',
'description' => 'Define the sorting',
'fields' => [
'field' => [
'type' => Type::nonNull($sortableField),
'description' => 'Sort field name.'
],
'direction' => [
'type' => Injector::inst()->get(SortDirectionType::class)->toType(),
'description' => 'Sort direction (ASC / DESC)'
]
]
]);
}

return $this->type;
}
}
22 changes: 7 additions & 15 deletions src/Util/CaseInsensitiveFieldAccessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ public function getValue(ViewableData $object, $fieldName, $opts = [])
public function setValue(ViewableData $object, $fieldName, $value, $opts = [])
{
$opts = $opts ?: [];
$opts = array_merge([
self::HAS_METHOD => true,
self::HAS_FIELD => true,
self::HAS_SETTER => true,
self::DATAOBJECT => true,
], $opts);
$opts = [
self::HAS_METHOD => true,
self::HAS_FIELD => true,
self::HAS_SETTER => true,
self::DATAOBJECT => true,
] + $opts;

$objectFieldName = $this->getObjectFieldName($object, $fieldName, $opts);

Expand Down Expand Up @@ -118,16 +118,8 @@ public function setValue(ViewableData $object, $fieldName, $value, $opts = [])
* Example: [ViewableDataCaseInsensitiveFieldMapper::HAS_METHOD => true]
* @return null|string Name in actual casing on $object
*/
public function getObjectFieldName(ViewableData $object, $fieldName, $opts = [])
protected function getObjectFieldName(ViewableData $object, $fieldName, $opts = [])
{
$opts = $opts ?: [];
$opts = array_merge([
self::HAS_METHOD => true,
self::HAS_FIELD => true,
self::HAS_SETTER => true,
self::DATAOBJECT => true,
], $opts);

$optFn = function ($type) use (&$opts) {
return (in_array($type, $opts) && $opts[$type] === true);
};
Expand Down

0 comments on commit eb35ad4

Please sign in to comment.