Skip to content

Commit

Permalink
Merge pull request #83 from moufmouf/fix_cache_issue
Browse files Browse the repository at this point in the history
Fixing a cachng issue with sub-types
  • Loading branch information
moufmouf committed Jan 16, 2019
2 parents d80d23d + 9b29527 commit dbf644a
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 9 deletions.
24 changes: 16 additions & 8 deletions src/Mappers/RecursiveTypeMapper.php
Expand Up @@ -107,8 +107,12 @@ public function canMapClassToType(string $className): bool
*/
public function mapClassToType(string $className, ?OutputType $subType): MutableObjectType
{
if (isset($this->classToTypeCache[$className])) {
return $this->classToTypeCache[$className];
$cacheKey = $className;
if ($subType !== null) {
$cacheKey .= '__`__'.$subType->name;
}
if (isset($this->classToTypeCache[$cacheKey])) {
return $this->classToTypeCache[$cacheKey];
}

$closestClassName = $this->findClosestMatchingParent($className);
Expand All @@ -129,7 +133,7 @@ public function mapClassToType(string $className, ?OutputType $subType): Mutable
}

$this->typeRegistry->registerType($type);
$this->classToTypeCache[$className] = $type;
$this->classToTypeCache[$cacheKey] = $type;

$this->extendType($className, $type);

Expand Down Expand Up @@ -192,19 +196,23 @@ public function mapClassToInterfaceOrType(string $className, ?OutputType $subTyp
if ($closestClassName === null) {
throw CannotMapTypeException::createForType($className);
}
if (!isset($this->interfaces[$closestClassName])) {
$cacheKey = $closestClassName;
if ($subType !== null) {
$cacheKey .= '__`__'.$subType->name;
}
if (!isset($this->interfaces[$cacheKey])) {
$objectType = $this->mapClassToType($className, $subType);

$supportedClasses = $this->getClassTree();
if (isset($supportedClasses[$closestClassName]) && !empty($supportedClasses[$closestClassName]->getChildren())) {
// Cast as an interface
$this->interfaces[$closestClassName] = new InterfaceFromObjectType($this->namingStrategy->getInterfaceNameFromConcreteName($objectType->name), $objectType, $subType, $this);
$this->typeRegistry->registerType($this->interfaces[$closestClassName]);
$this->interfaces[$cacheKey] = new InterfaceFromObjectType($this->namingStrategy->getInterfaceNameFromConcreteName($objectType->name), $objectType, $subType, $this);
$this->typeRegistry->registerType($this->interfaces[$cacheKey]);
} else {
$this->interfaces[$closestClassName] = $objectType;
$this->interfaces[$cacheKey] = $objectType;
}
}
return $this->interfaces[$closestClassName];
return $this->interfaces[$cacheKey];
}

/**
Expand Down
27 changes: 27 additions & 0 deletions tests/Fixtures/Integration/Controllers/ProductController.php
@@ -0,0 +1,27 @@
<?php


namespace TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Controllers;


use Porpaginas\Arrays\ArrayResult;
use Psr\Http\Message\UploadedFileInterface;
use TheCodingMachine\GraphQL\Controllers\Annotations\Mutation;
use TheCodingMachine\GraphQL\Controllers\Annotations\Query;
use TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Models\Contact;
use TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Models\Product;
use TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Models\User;

class ProductController
{
/**
* @Query()
* @return Product[]
*/
public function getProducts(): ArrayResult
{
return new ArrayResult([
new Product('Foo', 42.0),
]);
}
}
54 changes: 54 additions & 0 deletions tests/Fixtures/Integration/Models/Product.php
@@ -0,0 +1,54 @@
<?php


namespace TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Models;


use DateTimeInterface;
use Psr\Http\Message\UploadedFileInterface;
use TheCodingMachine\GraphQL\Controllers\Annotations\Field;
use TheCodingMachine\GraphQL\Controllers\Annotations\Type;

/**
* @Type()
*/
class Product
{
/**
* @var string
*/
private $name;
/**
* @var float
*/
private $price;

/**
* Product constructor.
* @param string $name
* @param float $price
*/
public function __construct(string $name, float $price)
{
$this->name = $name;
$this->price = $price;
}

/**
* @Field(name="name")
* @return string
*/
public function getName(): string
{
return $this->name;
}

/**
* @Field(name="price")
* @return float
*/
public function getPrice(): float
{
return $this->price;
}
}
66 changes: 65 additions & 1 deletion tests/Integration/EndToEndTest.php
Expand Up @@ -44,6 +44,7 @@
use TheCodingMachine\GraphQL\Controllers\TypeGenerator;
use TheCodingMachine\GraphQL\Controllers\TypeRegistry;
use TheCodingMachine\GraphQL\Controllers\Types\TypeResolver;
use function var_dump;
use function var_export;

class EndToEndTest extends TestCase
Expand Down Expand Up @@ -394,5 +395,68 @@ public function testEndToEndPorpaginas()
],
'count' => 2
]
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']); }
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
}

/**
* This tests is used to be sure that the PorpaginasIterator types are not mixed up when cached (because it has a subtype)
*/
public function testEndToEnd2Iterators()
{
/**
* @var Schema $schema
*/
$schema = $this->mainContainer->get(Schema::class);

$queryString = '
query {
getContactsIterator {
items(limit: 1, offset: 1) {
name
uppercaseName
... on User {
email
}
}
count
}
getProducts {
items {
name
price
}
count
}
}
';

$result = GraphQL::executeQuery(
$schema,
$queryString
);

$this->assertSame([
'getContactsIterator' => [
'items' => [
[
'name' => 'Bill',
'uppercaseName' => 'BILL',
'email' => 'bill@example.com'
]
],
'count' => 2
],
'getProducts' => [
'items' => [
[
'name' => 'Foo',
'price' => 42.0,
]
],
'count' => 1
]
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);

}
}

0 comments on commit dbf644a

Please sign in to comment.