From 5890ef9971e5f8ae8b40c8323746c9f5ba32855f Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 21 Feb 2019 16:04:26 +1300 Subject: [PATCH] NEW Use interfaces for version type Support for https://github.com/silverstripe/silverstripe-graphql/issues/209 --- .../DataObjectScaffolderExtension.php | 56 +++++------ src/GraphQL/Extensions/ManagerExtension.php | 2 + src/GraphQL/Types/VersionInterfaceType.php | 95 +++++++++++++++++++ 3 files changed, 120 insertions(+), 33 deletions(-) create mode 100644 src/GraphQL/Types/VersionInterfaceType.php diff --git a/src/GraphQL/Extensions/DataObjectScaffolderExtension.php b/src/GraphQL/Extensions/DataObjectScaffolderExtension.php index 1434eebc..f34c5993 100644 --- a/src/GraphQL/Extensions/DataObjectScaffolderExtension.php +++ b/src/GraphQL/Extensions/DataObjectScaffolderExtension.php @@ -2,18 +2,26 @@ namespace SilverStripe\Versioned\GraphQL\Extensions; +use Exception; +use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use SilverStripe\Core\Extension; use SilverStripe\GraphQL\Manager; use SilverStripe\GraphQL\Scaffolding\Scaffolders\DataObjectScaffolder; use SilverStripe\GraphQL\Scaffolding\StaticSchema; +use SilverStripe\ORM\DataObject; use SilverStripe\Security\Member; use SilverStripe\Versioned\GraphQL\Operations\ReadVersions; use SilverStripe\Versioned\Versioned; class DataObjectScaffolderExtension extends Extension { + /** + * @var string + */ + protected $versionInterfaceName = 'VersionInterface'; + /** * Adds the "Version" and "Versions" fields to any dataobject that has the Versioned extension. * @param Manager $manager @@ -28,53 +36,35 @@ public function onBeforeAddToManager(Manager $manager) if (!$instance->hasExtension(Versioned::class)) { return; } + /* @var ObjectType $rawType */ $rawType = $owner->scaffold($manager); + /** @var InterfaceType $rawVersionInterfaceType */ + $rawVersionInterfaceType = $manager->getType('VersionInterface'); + $versionName = $this->createVersionedTypeName($class); $coreFieldsFn = $rawType->config['fields']; + $versionFieldsFn = $rawVersionInterfaceType->config['fields']; + // Create the "version" type for this dataobject. Takes the original fields // and augments them with the Versioned_Version specific fields $versionType = new ObjectType([ 'name' => $versionName, - 'fields' => function () use ($coreFieldsFn, $manager, $memberType) { + 'fields' => function () use ($coreFieldsFn, $versionFieldsFn, $manager, $memberType) { $coreFields = $coreFieldsFn(); - $versionFields = [ - 'Author' => [ - 'type' => $manager->getType($memberType), - 'resolve' => function ($obj) { - return $obj->Author(); - } - ], - 'Publisher' => [ - 'type' => $manager->getType($memberType), - 'resolve' => function ($obj) { - return $obj->Publisher(); - } - ], - 'Published' => [ - 'type' => Type::boolean(), - 'resolve' => function ($obj) { - return $obj->WasPublished; - } - ], - 'LiveVersion' => [ - 'type' => Type::boolean(), - 'resolve' => function ($obj) { - return $obj->isLiveVersion(); - } - ], - 'LatestDraftVersion' => [ - 'type' => Type::boolean(), - 'resolve' => function ($obj) { - return $obj->isLatestDraftVersion(); - } - ], - ]; + $versionFields = $versionFieldsFn(); + // Remove this recursive madness. unset($coreFields['Versions']); return array_merge($coreFields, $versionFields); + }, + 'interfaces' => function() use ($rawType, $manager) { + return array_merge( + $rawType->getInterfaces(), + [$manager->getType('VersionInterface')] + ); } ]); diff --git a/src/GraphQL/Extensions/ManagerExtension.php b/src/GraphQL/Extensions/ManagerExtension.php index e55d7133..bb586a33 100644 --- a/src/GraphQL/Extensions/ManagerExtension.php +++ b/src/GraphQL/Extensions/ManagerExtension.php @@ -8,6 +8,7 @@ use SilverStripe\Versioned\GraphQL\Types\VersionedQueryMode; use SilverStripe\Versioned\GraphQL\Types\VersionedStage; use SilverStripe\Versioned\GraphQL\Types\VersionedStatus; +use SilverStripe\Versioned\GraphQL\Types\VersionInterfaceType; class ManagerExtension extends Extension { @@ -27,5 +28,6 @@ public function updateConfig(&$config) $config['types']['VersionedQueryMode'] = VersionedQueryMode::class; $config['types']['VersionedInputType'] = VersionedInputType::class; $config['types']['CopyToStageInputType'] = CopyToStageInputType::class; + $config['types']['VersionInterface'] = VersionInterfaceType::class; } } diff --git a/src/GraphQL/Types/VersionInterfaceType.php b/src/GraphQL/Types/VersionInterfaceType.php new file mode 100644 index 00000000..80f432cc --- /dev/null +++ b/src/GraphQL/Types/VersionInterfaceType.php @@ -0,0 +1,95 @@ + 'VersionInterface', + 'description' => 'Metadata fields for versioning on a DataObject' + ]; + } + + /** + * @return array + */ + public function fields() + { + $memberType = StaticSchema::inst()->typeNameForDataObject(Member::class); + return [ + 'Author' => [ + 'type' => $this->manager->getType($memberType), + 'resolve' => function ($obj) { + return $obj->Author(); + } + ], + 'Publisher' => [ + 'type' => $this->manager->getType($memberType), + 'resolve' => function ($obj) { + return $obj->Publisher(); + } + ], + 'Published' => [ + 'type' => Type::boolean(), + 'resolve' => function ($obj) { + return $obj->WasPublished; + } + ], + 'LiveVersion' => [ + 'type' => Type::boolean(), + 'resolve' => function ($obj) { + return $obj->isLiveVersion(); + } + ], + 'LatestDraftVersion' => [ + 'type' => Type::boolean(), + 'resolve' => function ($obj) { + return $obj->isLatestDraftVersion(); + } + ], + ]; + } + + /** + * @return \GraphQL\Type\Definition\Type + * @throws Exception + */ + public function resolveType() + { + if (!$obj instanceof DataObject) { + throw new Exception(sprintf( + 'Type with class %s is not a DataObject', + get_class($obj) + )); + } + $class = get_class($obj); + while ($class !== DataObject::class) { + $typeName = StaticSchema::inst()->typeNameForDataObject($class); + if ($this->manager->hasType($typeName)) { + return $this->manager->getType($typeName); + } + $class = get_parent_class($class); + } + throw new Exception(sprintf( + 'There is no type defined for %s, and none of its ancestors are defined.', + get_class($obj) + )); + } + +}