|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Kaliop\eZMigrationBundle\Core\ReferenceResolver; |
|
4
|
|
|
|
|
5
|
|
|
use Kaliop\eZMigrationBundle\API\ReferenceResolverInterface; |
|
6
|
|
|
use Kaliop\eZMigrationBundle\API\ReferenceBagInterface; |
|
7
|
|
|
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface; |
|
8
|
|
|
use Kaliop\eZMigrationBundle\API\EnumerableReferenceResolverInterface; |
|
9
|
|
|
use Kaliop\eZMigrationBundle\API\EmbeddedReferenceResolverInterface; |
|
10
|
|
|
|
|
11
|
|
|
class ChainResolver implements ReferenceResolverBagInterface, EnumerableReferenceResolverInterface, EmbeddedReferenceResolverInterface |
|
12
|
|
|
{ |
|
13
|
|
|
/** @var ReferenceResolverInterface[] $resolvers */ |
|
14
|
|
|
protected $resolvers = array(); |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* @param ReferenceResolverInterface[] $resolvers |
|
18
|
73 |
|
*/ |
|
19
|
|
|
public function __construct(array $resolvers) |
|
20
|
73 |
|
{ |
|
21
|
73 |
|
$this->resolvers = $resolvers; |
|
22
|
|
|
} |
|
23
|
73 |
|
|
|
24
|
|
|
public function addResolver(ReferenceResolverInterface $resolver) |
|
25
|
73 |
|
{ |
|
26
|
73 |
|
$this->resolvers[] = $resolver; |
|
27
|
|
|
} |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* @param string $stringIdentifier |
|
31
|
|
|
* @return bool |
|
32
|
24 |
|
*/ |
|
33
|
|
|
public function isReference($stringIdentifier) |
|
34
|
24 |
|
{ |
|
35
|
24 |
|
foreach ($this->resolvers as $resolver) { |
|
36
|
24 |
|
if ($resolver->isReference($stringIdentifier)) { |
|
37
|
|
|
return true; |
|
38
|
|
|
} |
|
39
|
|
|
} |
|
40
|
20 |
|
|
|
41
|
|
|
return false; |
|
42
|
|
|
} |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* @param string $stringIdentifier |
|
46
|
|
|
* @return mixed |
|
47
|
|
|
* @throws \Exception |
|
48
|
23 |
|
*/ |
|
49
|
|
|
public function getReferenceValue($stringIdentifier) |
|
50
|
23 |
|
{ |
|
51
|
|
|
$resolvedOnce = false; |
|
52
|
23 |
|
|
|
53
|
23 |
|
foreach ($this->resolvers as $resolver) { |
|
54
|
23 |
|
if ($resolver->isReference($stringIdentifier)) { |
|
55
|
|
|
$stringIdentifier = $resolver->getReferenceValue($stringIdentifier); |
|
56
|
22 |
|
// In case of many resolvers resolving the same ref, the last one wins. Should we default to the 1st winning ? |
|
57
|
|
|
$resolvedOnce = true; |
|
58
|
|
|
} |
|
59
|
|
|
} |
|
60
|
22 |
|
|
|
61
|
|
|
if (!$resolvedOnce) { |
|
62
|
|
|
throw new \Exception("Could not resolve reference with identifier: '$stringIdentifier'"); |
|
63
|
|
|
} |
|
64
|
22 |
|
|
|
65
|
|
|
return $stringIdentifier; |
|
66
|
|
|
} |
|
67
|
24 |
|
|
|
68
|
|
|
public function resolveReference($stringIdentifier) |
|
69
|
24 |
|
{ |
|
70
|
23 |
|
if ($this->isReference($stringIdentifier)) { |
|
71
|
|
|
return $this->getReferenceValue($stringIdentifier); |
|
72
|
20 |
|
} |
|
73
|
|
|
return $stringIdentifier; |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* Tries to add the reference to one of the resolvers in the chain (the first accepting it) |
|
78
|
|
|
* |
|
79
|
|
|
* @param string $identifier |
|
80
|
|
|
* @param mixed $value |
|
81
|
|
|
* @param bool $overwrite do overwrite the existing ref if it exist without raising an exception |
|
82
|
|
|
* @return bool |
|
83
|
24 |
|
*/ |
|
84
|
|
|
public function addReference($identifier, $value, $overwrite = false) |
|
85
|
24 |
|
{ |
|
86
|
24 |
|
foreach ($this->resolvers as $resolver) { |
|
87
|
24 |
|
if ($resolver instanceof ReferenceBagInterface) { |
|
88
|
24 |
|
if ($resolver->addReference($identifier, $value, $overwrite)) { |
|
89
|
|
|
return true; |
|
90
|
|
|
} |
|
91
|
|
|
} |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
return false; |
|
95
|
|
|
} |
|
96
|
1 |
|
|
|
97
|
|
|
public function listReferences() |
|
98
|
1 |
|
{ |
|
99
|
|
|
$refs = array(); |
|
100
|
1 |
|
|
|
101
|
1 |
|
foreach ($this->resolvers as $resolver) { |
|
102
|
|
|
if (! $resolver instanceof EnumerableReferenceResolverInterface) { |
|
103
|
|
|
throw new \Exception("Could not enumerate references because of chained resolver of type: " . get_class($resolver)); |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
1 |
|
// later resolvers are stronger (see getReferenceValue) |
|
107
|
|
|
$refs = array_merge($refs, $resolver->listReferences()); |
|
108
|
|
|
} |
|
109
|
1 |
|
|
|
110
|
|
|
return $refs; |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* @param string $string |
|
115
|
|
|
* @return bool true if the given $stringIdentifier contains at least one occurrence of the reference(s) |
|
116
|
|
|
* @throws \Exception if any resolver in the chain is not an EmbeddedReferenceResolverInterface |
|
117
|
|
|
*/ |
|
118
|
|
|
public function hasEmbeddedReferences($string) |
|
119
|
|
|
{ |
|
120
|
|
View Code Duplication |
foreach ($this->resolvers as $resolver) { |
|
|
|
|
|
|
121
|
|
|
if ($resolver instanceof EmbeddedReferenceResolverInterface) { |
|
122
|
|
|
if ($resolver->hasEmbeddedReferences($string)) { |
|
123
|
|
|
return true; |
|
124
|
|
|
} |
|
125
|
|
|
} else { |
|
126
|
|
|
throw new \Exception("Could not verify embedded references because of chained resolver of type: " . get_class($resolver)); |
|
127
|
|
|
} |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
return false; |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* Returns the $string with eventual refs resolved. |
|
135
|
|
|
* Q: SHALL WE GUARANTEE THAT ALL RESOLVERS IN THE CHAIN CAN TAKE PART IN THIS? |
|
136
|
|
|
* |
|
137
|
|
|
* @param string $string |
|
138
|
|
|
* @return string |
|
139
|
|
|
* @throws \Exception if any resolver in the chain is not an EmbeddedReferenceResolverInterface |
|
140
|
|
|
*/ |
|
141
|
|
|
public function resolveEmbeddedReferences($string) |
|
142
|
|
|
{ |
|
143
|
|
View Code Duplication |
foreach ($this->resolvers as $resolver) { |
|
|
|
|
|
|
144
|
|
|
if ($resolver instanceof EmbeddedReferenceResolverInterface) { |
|
145
|
|
|
$string = $resolver->resolveEmbeddedReferences($string); |
|
146
|
|
|
} else { |
|
147
|
|
|
throw new \Exception("Could not resolve embedded references because of chained resolver of type: " . get_class($resolver)); |
|
148
|
|
|
} |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
return $string; |
|
152
|
|
|
} |
|
153
|
|
|
} |
|
154
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.