1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of EC-CUBE |
5
|
|
|
* |
6
|
|
|
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. |
7
|
|
|
* |
8
|
|
|
* http://www.ec-cube.co.jp/ |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
11
|
|
|
* file that was distributed with this source code. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Eccube\GraphQL; |
15
|
|
|
|
16
|
|
|
use Doctrine\ORM\EntityManager; |
17
|
|
|
use Doctrine\ORM\Mapping\ClassMetadata; |
18
|
|
|
use GraphQL\Type\Definition\ObjectType; |
19
|
|
|
use GraphQL\Type\Definition\Type; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* DoctrineのEntityからGraphQLのObjectTypeを変換するクラス. |
23
|
|
|
*/ |
24
|
|
|
class Types |
25
|
|
|
{ |
26
|
|
|
/** @var EntityManager */ |
27
|
|
|
private $entityManager; |
28
|
|
|
|
29
|
|
|
private $types = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Types constructor. |
33
|
|
|
* |
34
|
|
|
* @param EntityManager $entityManager |
35
|
|
|
*/ |
36
|
|
|
public function __construct(EntityManager $entityManager) |
|
|
|
|
37
|
|
|
{ |
38
|
|
|
$this->entityManager = $entityManager; |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Entityに対応するObjectTypeを返す. |
43
|
|
|
* |
44
|
|
|
* @param $className string Entityクラス名 |
45
|
|
|
* @return ObjectType |
46
|
|
|
*/ |
47
|
|
|
public function get($className) |
48
|
|
|
{ |
49
|
|
|
if (!isset($this->types[$className])) { |
50
|
|
|
$this->types[$className] = $this->createObjectType($className); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
return $this->types[$className]; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
private function createObjectType($className) |
57
|
|
|
{ |
58
|
|
|
return new ObjectType([ |
59
|
|
|
'name' => (new \ReflectionClass($className))->getShortName(), |
60
|
|
|
'fields' => function () use ($className) { |
61
|
|
|
$classMetadata = $this->entityManager->getClassMetadata($className); |
62
|
|
|
$fields = array_reduce($classMetadata->fieldMappings, function ($acc, $mapping) { |
63
|
|
|
$type = $this->convertFieldMappingToType($mapping); |
64
|
|
|
|
65
|
|
|
if ($type) { |
66
|
|
|
$acc[$mapping['fieldName']] = $type; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return $acc; |
70
|
|
|
}, []); |
71
|
|
|
|
72
|
|
|
$fields = array_reduce($classMetadata->associationMappings, function ($acc, $mapping) { |
73
|
|
|
$acc[$mapping['fieldName']] = [ |
74
|
|
|
'type' => $this->convertAssociationMappingToType($mapping), |
75
|
|
|
]; |
76
|
|
|
return $acc; |
77
|
|
|
}, $fields); |
78
|
|
|
|
79
|
|
|
return $fields; |
80
|
|
|
}, |
81
|
|
|
]); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
private function convertFieldMappingToType($fieldMapping) |
85
|
|
|
{ |
86
|
|
|
$type = $fieldMapping['id'] ? Type::id() : [ |
87
|
|
|
'string' => Type::string(), |
88
|
|
|
'text' => Type::string(), |
89
|
|
|
'integer' => Type::int(), |
90
|
|
|
'decimal' => Type::float(), |
91
|
|
|
][$fieldMapping['type']]; |
92
|
|
|
|
93
|
|
|
if ($type) { |
94
|
|
|
return $fieldMapping['nullable'] ? $type : Type::nonNull($type); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return null; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
private function convertAssociationMappingToType($mapping) |
101
|
|
|
{ |
102
|
|
|
return $this->isToManyAssociation($mapping) ? Type::listOf($this->get($mapping['targetEntity'])) : $this->get($mapping['targetEntity']); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
private function isToManyAssociation($mapping) |
106
|
|
|
{ |
107
|
|
|
return $mapping['type'] & ClassMetadata::TO_MANY; |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
|
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.