Last active
November 29, 2016 02:48
-
-
Save unclecheese/b56833232f521d9873781a4bc4827a2a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class GraphQLScaffolder | |
{ | |
const READ | |
const UPDATE | |
const DELETE | |
const CREATE | |
/** | |
* @var array $dataObjects | |
* ex. | |
* [ | |
* 'member' => [ | |
* 'fields' => [ | |
* 'FirstName', 'Surname', 'Email' | |
* ], | |
* 'operations' => [ | |
* 'read' => true, | |
* 'update' => true | |
* ], | |
* 'resolver' => [ | |
* // callable or instanceof GraphQLResolver | |
* ] | |
* ], | |
* 'file' => [ | |
* ... | |
* ] | |
* ] | |
* | |
*/ | |
protected $dataObjects = []; | |
public function addDataObject($name) | |
{ | |
if(dataobject_not_added) { | |
$this->dataObjects[$name] = [...defaults?] | |
} | |
} | |
public function addOperation($dataObject, $operation) | |
{ | |
if(operation_is_valid && dataobject_exists) { | |
$this->dataObjects[$dataObject]['operations'][$operation] = true; | |
} | |
} | |
public function addFieldResolver($dataObject, $resolver) | |
{ | |
if($resolver instanceof GraphQLResolver || is_callable($resolver)) { | |
$this->dataObjects[$dataObject]['field_resolver'] = $resolver; | |
} | |
} | |
public function addMutationResolver($dataObject, $mutationType, $resolver) | |
{ | |
if(($resolver instanceof GraphQLResolver || is_callable($resolver)) && is_mutation($mutationType)) { | |
$this->dataObjects[$dataObject][$mutationType.'_resolver'] = $resolver; | |
} | |
} | |
public function setFields($dataObject, $fields = []) | |
{ | |
if(dataobject_exists && is_array($fields) { | |
$this->dataObjects[$dataObject]['fields'] = $fields; | |
} | |
} | |
public function getTypeCreator($dataObject) | |
{ | |
return new DataObjectTypeCreator( | |
$dataObject, | |
$this->dataObjects[$dataObject]['fields'] | |
); | |
} | |
public function getQueryCreator($dataObject) | |
{ | |
return new DataObjectQueryCreator( | |
$dataObject, | |
$this->dataObjects[$dataObject]['field_resolver'] | |
); | |
} | |
public function getMutationCreator($dataObject, $mutation) | |
{ | |
return new DataObjectMutationCreator( | |
$dataObject, | |
$mutation, | |
$this->dataObjects[$dataObject][$mutation.'_resolver'] | |
); | |
} | |
public function addToManager(Manager $manager) | |
{ | |
foreach($this->dataObjects as $dataObjectName => $config) { | |
$manager->addType( | |
$this->getTypeCreator($dataObjectName)->getType(), | |
$type | |
); | |
if($config['operations'][self::READ]) { | |
$manager->addQuery( | |
$this->getQueryCreator($dataObjectName)->toArray(), | |
"read".ucfirst($type) | |
); | |
} | |
foreach([self::UPDATE, self::DELETE] as $mutation) { | |
if($config['operations'][$mutation]) { | |
$manager->addMutation( | |
$this->getMutationCreator($dataObjectName, $mutation)->toArray() | |
); | |
} | |
} | |
} | |
$manager->addType($this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DataObjectTypeCreator extends TypeCreator | |
{ | |
public function __construct($name, $fields = []) | |
{ | |
$this->name = $name; | |
$this->fields = $fields; | |
} | |
public function attributes() | |
{ | |
return [ | |
'name' => $this->name | |
]; | |
} | |
public function fields() | |
{ | |
$fieldMap = []; | |
foreach($this->fields as $fieldName) { | |
$graphQLType = $dataObjectInstance | |
->obj($fieldName) | |
->getGraphQLType(); // a suite of DBField extensions, maybe? | |
$fieldMap[$fieldName] = $graphQLType; | |
} | |
return $fieldMap; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DataObjectQueryCreator extends QueryCreator | |
{ | |
public function __construct($dataObject, $resolver) { } | |
public function attributes() | |
{ | |
return [ | |
'name' => "read".ucfirst($this->dataObject) | |
]; | |
} | |
public function args() | |
{ | |
// not sure how to deal with this.. search context? | |
} | |
public function type() | |
{ | |
return function() { | |
return Type::listOf( | |
$this->manager->getType($this->dataObject) | |
); | |
}; | |
} | |
public function resolve($args) | |
{ | |
if(is_callable($this->resolver)) { | |
return $this->resolver($args); | |
} | |
if($this->resolver instanceof GraphQLResolver) { | |
return $this->resolver->resolve($args); | |
} | |
return self::config()->default_resolvers['read']->resolve($args); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DataObjectMutationCreator extends MutationCreator | |
{ | |
public function __construct($dataObject, $mutationType, $resolver) {...} | |
public function attributes() | |
{ | |
return [ | |
'name' => $mutationType.ucfirst($this->dataObject) | |
]; | |
} | |
public function args() | |
{ | |
// Input types here? | |
} | |
public function type() | |
{ | |
return function() { | |
return Type::listOf( | |
$this->manager->getType($this->dataObject) | |
); | |
}; | |
} | |
public function resolve($object, array $args, $context, $info) | |
{ | |
if(is_callable($this->resolver)) { | |
return $this->resolver($args); | |
} | |
if($this->resolver instanceof GraphQLResolver) { | |
return $this->resolver->resolve($args); | |
} | |
// e.g. SimpleDeleteResolver, SimpleUpdateResolver | |
return self::config()->default_resolvers[$this->mutationType] | |
->resolve($object, $args, $context, $info); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// New stuff for the manager class | |
class Manager | |
{ | |
public static function createFromConfig($config) | |
{ | |
/** @var Manager $manager */ | |
$manager = Injector::inst()->create(Manager::class); | |
if(isset($config['scaffold_providers'])) { | |
foreach($config['scaffold_providers'] as $provider) { | |
$scaffolder = $provider->getScaffolder(); | |
$scaffolder->addToManager($manager); | |
} | |
} | |
if(isset($config['scaffolding'])) { | |
$scaffolder = new GraphQLScaffolder(); | |
foreach($config['scaffolding'] as $dataObjectName => $config) { | |
$scaffolder->addDataObject($dataObjectName); | |
$ops = ($config['operations'] === 'all') ? [... all of them] : $config['operations']; | |
foreach($ops as $op) { | |
$scaffolder->addOperation($dataObjectName, $op); | |
} | |
$scaffolder->setFields($config['fields']); | |
if(isset($config['field_resolver'])) { | |
$scaffolder->addFieldResolver($dataObjectName, $config['field_resolver']); | |
} | |
if(isset($config['mutation_resolvers'])) { | |
foreach($config['mutation_resolvers'] as $op => $resolver) { | |
$scaffolder->addMutationResolver( | |
$dataObjectName, | |
$op, | |
$resolver | |
); | |
} | |
} | |
} | |
$scaffolder->addToManager($manager); | |
} | |
// ... | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Implementation example: Add some scaffolding to the GraphQL server, procedurally | |
class MyGraqlQLScaffolder implements GraphQLScaffoldProvider | |
{ | |
public function getScaffolder() { | |
return (new GraphQLScaffolder()) | |
->addDataObject('Member') | |
->addOperation('Member', GraphQLScaffolder::READ, []) | |
->addFieldResolver('Member', function($args) { | |
$list = Member::get(); | |
// Optional filtering (could be more succinct through SearchContext) | |
if($args['Email']) | |
$list = $list->filter('Email', $args['Email']); | |
return $list; | |
}) | |
->addMutationResolver('Member', GraphQLScaffolder::UPDATE, new MySpecialMemberResolver()) | |
->setFields('Group', ['Title']); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Implementation example: a custom resolver | |
class MySpecialMemberResolver extends GraphQLResolver | |
{ | |
public function resolve($object, array $args, $context, $info) | |
{ | |
$object->FirstName = $args['FirstName']; | |
if($object->FirstName === 'UncleCheese') { | |
$object->Awesome = true; | |
} | |
$object->write(); | |
return $object; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GraphQL: | |
# procedural approach | |
scaffold_providers: [MyGraqlQLScaffolder] | |
# declarative approach | |
scaffolding: | |
Member: | |
operations: | |
- all: true # implies 'create', 'read', 'update', 'delete' | |
fields: | |
- Fullname | |
- Groups # Implicitly creates a "Group" GraphQL type | |
field_resolver: MyGraphQLMemberResolver | |
mutation_resolvers: | |
update: MySpecialMemberResolver | |
Group: | |
operations: | |
- read: true #only allow reads | |
fields: | |
Title |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment