Skip to content

Commit

Permalink
IBX-1565: Refactor schema's types' names validation (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
barw4 authored Dec 28, 2021
1 parent 165337e commit acb2428
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace spec\EzSystems\EzPlatformGraphQL\Schema\Builder;

use EzSystems\EzPlatformGraphQL\Schema\Builder\Input;
use EzSystems\EzPlatformGraphQL\Schema\Builder\SchemaBuilder;
use Ibexa\GraphQL\Schema\Domain\NameValidator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class SchemaBuilderSpec extends ObjectBehavior
{
Expand All @@ -17,13 +23,20 @@ class SchemaBuilderSpec extends ObjectBehavior
const ARG = 'arg';
const ARG_TYPE = 'Boolean';

function it_is_initializable()
public function let(NameValidator $nameValidator)
{
$this->beConstructedWith($nameValidator);
}

public function it_is_initializable()
{
$this->shouldHaveType(SchemaBuilder::class);
}

function it_adds_a_type_to_the_schema()
public function it_adds_a_type_to_the_schema(NameValidator $nameValidator)
{
$nameValidator->isValidName(Argument::any())->willReturn(true);

$this->addType($this->inputType('Parent', 'Interface'));

$schema = $this->getSchema();
Expand All @@ -33,8 +46,10 @@ function it_adds_a_type_to_the_schema()
$schema->shouldHaveGraphQLTypeThatImplements('Interface');
}

function it_adds_a_field_to_an_existing_type()
public function it_adds_a_field_to_an_existing_type(NameValidator $nameValidator)
{
$nameValidator->isValidName(Argument::any())->willReturn(true);

$this->addType($this->inputType());
$this->addFieldToType(self::TYPE,
$this->inputField('Description', '@=resolver("myresolver")')
Expand All @@ -47,8 +62,10 @@ function it_adds_a_field_to_an_existing_type()
$schema->shouldHaveGraphQLTypeFieldWithResolve('@=resolver("myresolver")');
}

function it_adds_an_argument_to_an_existing_type_field()
public function it_adds_an_argument_to_an_existing_type_field(NameValidator $nameValidator)
{
$nameValidator->isValidName(Argument::any())->willReturn(true);

$this->addType($this->inputType());
$this->addFieldToType(self::TYPE, $this->inputField());
$this->addArgToField(self::TYPE, self::FIELD, $this->inputArg('Description'));
Expand Down Expand Up @@ -112,7 +129,7 @@ protected function inputType($inherits = [], $interfaces = []): Input\Type
self::TYPE, self::TYPE_TYPE,
[
'inherits' => $inherits,
'interfaces' => $interfaces
'interfaces' => $interfaces,
]
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php
namespace spec\EzSystems\EzPlatformGraphQL\Schema\Domain\Content;

use Ibexa\GraphQL\Schema\Domain\NameValidator;
use spec\EzSystems\EzPlatformGraphQL\Tools\TypeArgument;
use eZ\Publish\API\Repository\ContentTypeService;
use eZ\Publish\Core\Repository\Values\ContentType\ContentType;
Expand All @@ -14,11 +13,9 @@

class ContentDomainIteratorSpec extends ObjectBehavior
{
public function let(
ContentTypeService $contentTypeService,
NameValidator $nameValidator
) {
$this->beConstructedWith($contentTypeService, $nameValidator);
public function let(ContentTypeService $contentTypeService)
{
$this->beConstructedWith($contentTypeService);
}

function it_is_initializable()
Expand All @@ -38,10 +35,8 @@ function it_initializes_the_schema_with_the_Platform_root_type(Builder $schema)
)->shouldHaveBeenCalled();
}

function it_yields_content_type_groups(ContentTypeService $contentTypeService, NameValidator $nameValidator)
function it_yields_content_type_groups(ContentTypeService $contentTypeService)
{
$nameValidator->isValidName(Argument::any())->willReturn(true);

$contentTypeService->loadContentTypeGroups()->willReturn([
$group1 = new ContentTypeGroup(['identifier' => 'Group 1']),
$group2 = new ContentTypeGroup(['identifier' => 'Group 2']),
Expand All @@ -59,11 +54,8 @@ function it_yields_content_type_groups(ContentTypeService $contentTypeService, N
}

function it_yields_content_types_with_their_group_from_a_content_type_group(
ContentTypeService $contentTypeService,
NameValidator $nameValidator
ContentTypeService $contentTypeService
) {
$nameValidator->isValidName(Argument::any())->willReturn(true);

$contentTypeService->loadContentTypeGroups()->willReturn([
$group = new ContentTypeGroup(['identifier' => 'Group']),
]);
Expand All @@ -84,11 +76,8 @@ function it_yields_content_types_with_their_group_from_a_content_type_group(
}

function it_yields_fields_definitions_with_their_content_types_and_group_from_a_content_type(
ContentTypeService $contentTypeService,
NameValidator $nameValidator
ContentTypeService $contentTypeService
) {
$nameValidator->isValidName(Argument::any())->willReturn(true);

$contentTypeService->loadContentTypeGroups()->willReturn([
$group = new ContentTypeGroup(['identifier' => 'Group']),
]);
Expand All @@ -115,11 +104,8 @@ function it_yields_fields_definitions_with_their_content_types_and_group_from_a_
}

function it_only_yields_fields_definitions_from_the_current_content_type(
ContentTypeService $contentTypeService,
NameValidator $nameValidator
ContentTypeService $contentTypeService
) {
$nameValidator->isValidName(Argument::any())->willReturn(true);

$contentTypeService->loadContentTypeGroups()->willReturn([
$group = new ContentTypeGroup([
'identifier' => 'group'
Expand Down
20 changes: 9 additions & 11 deletions src/Resources/config/services/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ services:
tags:
- {name: 'ezplatform_graphql.schema_domain_iterator'}

EzSystems\EzPlatformGraphQL\Schema\Builder\SchemaBuilder: ~
EzSystems\EzPlatformGraphQL\Schema\Builder\SchemaBuilder:
arguments:
- '@Ibexa\GraphQL\Schema\Domain\NameValidator'
calls:
- method: setLogger
arguments:
- '@logger'

EzSystems\EzPlatformGraphQL\Schema\Domain\Content\Mapper\FieldDefinition\FieldDefinitionMapper:
alias: EzSystems\EzPlatformGraphQL\Schema\Domain\Content\Mapper\FieldDefinition\DefaultFieldDefinitionMapper
Expand Down Expand Up @@ -83,17 +89,9 @@ services:

Ibexa\GraphQL\Schema\Domain\NameValidator: ~

EzSystems\EzPlatformGraphQL\Schema\Domain\ImageVariationDomain:
calls:
- method: setLogger
arguments:
- '@logger'
EzSystems\EzPlatformGraphQL\Schema\Domain\ImageVariationDomain: ~

EzSystems\EzPlatformGraphQL\Schema\Domain\Content\ContentDomainIterator:
calls:
- method: setLogger
arguments:
- '@logger'
EzSystems\EzPlatformGraphQL\Schema\Domain\Content\ContentDomainIterator: ~

EzSystems\EzPlatformGraphQL\Schema\Builder:
alias: 'EzSystems\EzPlatformGraphQL\Schema\Builder\SchemaBuilder'
Expand Down
37 changes: 36 additions & 1 deletion src/Schema/Builder/SchemaBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,39 @@
namespace EzSystems\EzPlatformGraphQL\Schema\Builder;

use EzSystems\EzPlatformGraphQL\Schema\Builder as SchemaBuilderInterface;
use Ibexa\GraphQL\Schema\Domain\NameValidator;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;

class SchemaBuilder implements SchemaBuilderInterface
class SchemaBuilder implements SchemaBuilderInterface, LoggerAwareInterface
{
use LoggerAwareTrait;

private $schema = [];

/** @var \Ibexa\GraphQL\Schema\Domain\NameValidator */
private $nameValidator;

public function __construct(NameValidator $nameValidator)
{
$this->nameValidator = $nameValidator;
$this->logger = new NullLogger();
}

public function getSchema(): array
{
return $this->schema;
}

public function addType(Input\Type $typeInput)
{
if (!$this->nameValidator->isValidName($typeInput->name)) {
$this->generateInvalidGraphQLNameWarning($typeInput->type, $typeInput->name);

return;
}

if ($this->hasType($typeInput->name)) {
throw new \Exception("The type $typeInput->name is already defined");
}
Expand All @@ -43,6 +64,12 @@ public function addType(Input\Type $typeInput)

public function addFieldToType($type, Input\Field $fieldInput)
{
if (!$this->nameValidator->isValidName($fieldInput->name)) {
$this->generateInvalidGraphQLNameWarning($fieldInput->type, $fieldInput->name);

return;
}

if (!$this->hasType($type)) {
throw new \Exception("Expected type $type to be defined, but it was not");
}
Expand Down Expand Up @@ -150,4 +177,12 @@ public function hasEnum($enum): bool
{
return $this->hasType($enum);
}

private function generateInvalidGraphQLNameWarning(string $type, string $name): void
{
$message = "Skipping schema generation for %s with identifier '%s' as it stands against GraphQL specification. "
. 'For more details see http://spec.graphql.org/[latest-release]/#sec-Names.';

$this->logger->warning(sprintf($message, $type, $name));
}
}
39 changes: 2 additions & 37 deletions src/Schema/Domain/Content/ContentDomainIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,15 @@
use EzSystems\EzPlatformGraphQL\Schema\Builder\Input;
use EzSystems\EzPlatformGraphQL\Schema\Domain\Iterator;
use Generator;
use Ibexa\GraphQL\Schema\Domain\NameValidator;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;

class ContentDomainIterator implements Iterator, LoggerAwareInterface
class ContentDomainIterator implements Iterator
{
use LoggerAwareTrait;

/** @var \eZ\Publish\API\Repository\ContentTypeService */
private $contentTypeService;

/** @var \Ibexa\GraphQL\Schema\Domain\NameValidator */
private $nameValidator;

public function __construct(ContentTypeService $contentTypeService, NameValidator $nameValidator)
public function __construct(ContentTypeService $contentTypeService)
{
$this->contentTypeService = $contentTypeService;
$this->nameValidator = $nameValidator;
$this->logger = new NullLogger();
}

public function init(Builder $schema)
Expand All @@ -43,42 +32,18 @@ public function init(Builder $schema)
public function iterate(): Generator
{
foreach ($this->contentTypeService->loadContentTypeGroups() as $contentTypeGroup) {
if (!$this->nameValidator->isValidName($contentTypeGroup->identifier)) {
$this->generateInvalidGraphQLNameWarning('Content Type Group', $contentTypeGroup->identifier);
continue;
}

yield ['ContentTypeGroup' => $contentTypeGroup];

foreach ($this->contentTypeService->loadContentTypes($contentTypeGroup) as $contentType) {
if (!$this->nameValidator->isValidName($contentType->identifier)) {
$this->generateInvalidGraphQLNameWarning('Content Type', $contentType->identifier);
continue;
}

yield ['ContentTypeGroup' => $contentTypeGroup]
+ ['ContentType' => $contentType];

foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
if (!$this->nameValidator->isValidName($fieldDefinition->identifier)) {
$this->generateInvalidGraphQLNameWarning('Field Definition', $fieldDefinition->identifier);
continue;
}

yield ['ContentTypeGroup' => $contentTypeGroup]
+ ['ContentType' => $contentType]
+ ['FieldDefinition' => $fieldDefinition];
}
}
}
}

private function generateInvalidGraphQLNameWarning(string $type, string $name): void
{
$message = "Skipped schema generation for %s with identifier '%s'. "
. 'Please rename given %s according to GraphQL specification '
. '(http://spec.graphql.org/June2018/#sec-Names)';

$this->logger->warning(sprintf($message, $type, $name, $type));
}
}
28 changes: 3 additions & 25 deletions src/Schema/Domain/ImageVariationDomain.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,26 @@
use EzSystems\EzPlatformGraphQL\Schema\Builder;
use EzSystems\EzPlatformGraphQL\Schema\Domain;
use Generator;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;
use Ibexa\GraphQL\Schema\Domain\NameValidator;

/**
* Adds configured image variations to the ImageVariationIdentifier type.
*/
class ImageVariationDomain implements Domain\Iterator, Schema\Worker, LoggerAwareInterface
class ImageVariationDomain implements Domain\Iterator, Schema\Worker
{
use LoggerAwareTrait;

const TYPE = 'ImageVariationIdentifier';
const ARG = 'ImageVariation';

/** @var \eZ\Publish\Core\MVC\ConfigResolverInterface */
private $configResolver;

/** @var \Ibexa\GraphQL\Schema\Domain\NameValidator */
private $nameValidator;

public function __construct(
ConfigResolverInterface $configResolver,
NameValidator $nameValidator
) {
public function __construct(ConfigResolverInterface $configResolver)
{
$this->configResolver = $configResolver;
$this->nameValidator = $nameValidator;
$this->logger = new NullLogger();
}

public function iterate(): Generator
{
foreach ($this->configResolver->getParameter('image_variations') as $identifier => $variation) {
if (!$this->nameValidator->isValidName($identifier)) {
$message = "Skipped schema generation for Image Variation with identifier '%s'. "
. 'Please rename given image variation according to GraphQL specification '
. '(http://spec.graphql.org/June2018/#sec-Names)';

$this->logger->warning(sprintf($message, $identifier));
continue;
}

yield [self::ARG => ['identifier' => $identifier, 'variation' => $variation]];
}
}
Expand Down

0 comments on commit acb2428

Please sign in to comment.