1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Marek\Toggable\Hydrator; |
4
|
|
|
|
5
|
|
|
use ReflectionClass; |
6
|
|
|
use ReflectionProperty; |
7
|
|
|
use ArrayObject; |
8
|
|
|
use BadMethodCallException; |
9
|
|
|
use InvalidArgumentException; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Class ObjectProperty |
13
|
|
|
* @package Marek\Toggable\Hydrator |
14
|
|
|
*/ |
15
|
|
|
class ObjectProperty implements HydratorInterface, StrategyEnabledInterface |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* The list with strategies that this hydrator has. |
19
|
|
|
* |
20
|
|
|
* @var \ArrayObject |
21
|
|
|
*/ |
22
|
|
|
protected $strategies; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Initializes a new instance of this class. |
26
|
|
|
*/ |
27
|
73 |
|
public function __construct() |
28
|
|
|
{ |
29
|
73 |
|
$this->strategies = new ArrayObject(); |
30
|
73 |
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* {@inheritdoc} |
34
|
|
|
*/ |
35
|
15 |
|
public function extract($object) |
36
|
|
|
{ |
37
|
15 |
|
if (!is_object($object)) { |
38
|
1 |
|
throw new BadMethodCallException( |
39
|
1 |
|
sprintf('%s expects the provided $object to be a PHP object)', __METHOD__) |
40
|
|
|
); |
41
|
|
|
} |
42
|
|
|
|
43
|
14 |
|
$data = get_object_vars($object); |
44
|
|
|
|
45
|
14 |
|
$vars = array(); |
46
|
14 |
|
foreach ($data as $name => $value) { |
47
|
|
|
|
48
|
14 |
|
$data[$name] = $this->extractValue($name, $value); |
49
|
|
|
|
50
|
14 |
|
if (!empty($data[$name]) || $data[$name] === false) { |
51
|
14 |
|
$vars[$name] = $data[$name]; |
52
|
|
|
} |
53
|
|
|
} |
54
|
|
|
|
55
|
14 |
|
return $vars; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @inheritDoc |
60
|
|
|
*/ |
61
|
14 |
|
public function hydrate(array $data, $object) |
62
|
|
|
{ |
63
|
14 |
|
if (!is_object($object)) { |
64
|
1 |
|
throw new BadMethodCallException( |
65
|
1 |
|
sprintf('%s expects the provided $object to be a PHP object)', __METHOD__) |
66
|
|
|
); |
67
|
|
|
} |
68
|
|
|
|
69
|
13 |
|
$reflection = new ReflectionClass($object); |
70
|
|
|
|
71
|
13 |
|
$properties = $reflection->getProperties( |
72
|
|
|
ReflectionProperty::IS_PRIVATE |
73
|
|
|
+ ReflectionProperty::IS_PROTECTED |
74
|
13 |
|
+ ReflectionProperty::IS_PUBLIC |
75
|
|
|
); |
76
|
|
|
|
77
|
13 |
|
$props = array(); |
78
|
|
|
/** @var ReflectionProperty $property */ |
79
|
13 |
|
foreach ($properties as $property) { |
80
|
13 |
|
$props[$property->getName()] = true; |
81
|
|
|
} |
82
|
|
|
|
83
|
13 |
|
foreach ($data as $name => $value) { |
84
|
|
|
|
85
|
13 |
|
if (!isset($props[$name])) { |
86
|
1 |
|
continue; |
87
|
|
|
} |
88
|
|
|
|
89
|
13 |
|
$object->$name = $this->hydrateValue($name, $value); |
90
|
|
|
} |
91
|
|
|
|
92
|
13 |
|
return $object; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* @inheritDoc |
97
|
|
|
*/ |
98
|
1 |
|
public function canHydrate($object) |
99
|
|
|
{ |
100
|
1 |
|
return true; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* @inheritDoc |
105
|
|
|
*/ |
106
|
67 |
|
public function addStrategy($name, StrategyInterface $strategy) |
107
|
|
|
{ |
108
|
67 |
|
$this->strategies[$name] = $strategy; |
109
|
|
|
|
110
|
67 |
|
return $this; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @inheritDoc |
115
|
|
|
*/ |
116
|
21 |
|
public function getStrategy($name) |
117
|
|
|
{ |
118
|
21 |
|
return $this->strategies[$name]; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* @inheritDoc |
123
|
|
|
*/ |
124
|
30 |
|
public function hasStrategy($name) |
125
|
|
|
{ |
126
|
30 |
|
return array_key_exists($name, $this->strategies); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @inheritDoc |
131
|
|
|
*/ |
132
|
1 |
|
public function removeStrategy($name) |
133
|
|
|
{ |
134
|
1 |
|
unset($this->strategies[$name]); |
135
|
|
|
|
136
|
1 |
|
return $this; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Converts a value for extraction. If no strategy exists the plain value is returned. |
141
|
|
|
* |
142
|
|
|
* @param string $name The name of the strategy to use. |
143
|
|
|
* @param mixed $value The value that should be converted. |
144
|
|
|
* |
145
|
|
|
* @return mixed |
146
|
|
|
*/ |
147
|
14 |
View Code Duplication |
public function extractValue($name, $value) |
|
|
|
|
148
|
|
|
{ |
149
|
14 |
|
if ($this->hasStrategy($name)) { |
150
|
10 |
|
$strategy = $this->getStrategy($name); |
151
|
10 |
|
$value = $strategy->extract($value); |
152
|
|
|
} |
153
|
14 |
|
return $value; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Converts a value for hydration. If no strategy exists the plain value is returned. |
158
|
|
|
* |
159
|
|
|
* @param string $name The name of the strategy to use. |
160
|
|
|
* @param mixed $value The value that should be converted. |
161
|
|
|
* |
162
|
|
|
* @return mixed |
163
|
|
|
*/ |
164
|
13 |
View Code Duplication |
public function hydrateValue($name, $value) |
|
|
|
|
165
|
|
|
{ |
166
|
13 |
|
if ($this->hasStrategy($name)) { |
167
|
10 |
|
$strategy = $this->getStrategy($name); |
168
|
10 |
|
$value = $strategy->hydrate($value); |
169
|
|
|
} |
170
|
13 |
|
return $value; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
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.