Completed
Pull Request — master (#6)
by Trevor N.
01:14
created

Processor::getHydratorFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Incoming
4
 *
5
 * @author    Trevor Suarez (Rican7)
6
 * @copyright (c) Trevor Suarez
7
 * @link      https://github.com/Rican7/incoming
8
 * @license   MIT
9
 */
10
11
declare(strict_types=1);
12
13
namespace Incoming;
14
15
use Incoming\Hydrator\Builder;
16
use Incoming\Hydrator\BuilderFactory;
17
use Incoming\Hydrator\Exception\UnresolvableBuilderException;
18
use Incoming\Hydrator\Exception\UnresolvableHydratorException;
19
use Incoming\Hydrator\Hydrator;
20
use Incoming\Hydrator\HydratorFactory;
21
use Incoming\Transformer\StructureBuilderTransformer;
22
use Incoming\Transformer\Transformer;
23
24
/**
25
 * A default implementation of both the `ModelProcessor` and `TypeProcessor`
26
 * for processing input data with an optional input transformation phase and
27
 * automatic hydrator and builder resolution
28
 */
29
class Processor implements ModelProcessor, TypeProcessor
30
{
31
32
    /**
33
     * Properties
34
     */
35
36
    /**
37
     * An input transformer to pre-process the input data before hydration
38
     *
39
     * @var Transformer
40
     */
41
    private $input_transformer;
42
43
    /**
44
     * A factory for building hydrators for a given model
45
     *
46
     * @var HydratorFactory
47
     */
48
    private $hydrator_factory;
49
50
    /**
51
     * A factory for building builders for a given model
52
     *
53
     * @var BuilderFactory
54
     */
55
    private $builder_factory;
56
57
    /**
58
     * A configuration flag that denotes whether hydration should always be run
59
     * after building a new model when processing specified types
60
     *
61
     * @var bool
62
     */
63
    private $always_hydrate_after_building = false;
64
65
66
    /**
67
     * Methods
68
     */
69
70
    /**
71
     * Constructor
72
     *
73
     * @param Transformer|null $input_transformer The input transformer
74
     * @param HydratorFactory|null $hydrator_factory A hydrator factory
75
     * @param BuilderFactory|null $builder_factory A builder factory
76
     * @param bool $always_hydrate_after_building A configuration flag that
77
     *  denotes whether hydration should always be run after building a new
78
     *  model when processing specified types
79
     */
80 39
    public function __construct(
81
        Transformer $input_transformer = null,
82
        HydratorFactory $hydrator_factory = null,
83
        BuilderFactory $builder_factory = null,
84
        bool $always_hydrate_after_building = false
85
    ) {
86 39
        $this->input_transformer = $input_transformer ?: new StructureBuilderTransformer();
87 39
        $this->hydrator_factory = $hydrator_factory;
88 39
        $this->builder_factory = $builder_factory;
89 39
        $this->always_hydrate_after_building = $always_hydrate_after_building;
90 39
    }
91
92
    /**
93
     * Get the input transformer
94
     *
95
     * @return Transformer The input transformer
96
     */
97 3
    public function getInputTransformer(): Transformer
98
    {
99 3
        return $this->input_transformer;
100
    }
101
102
    /**
103
     * Set the input transformer
104
     *
105
     * @param Transformer $input_transformer The input transformer
106
     * @return $this This instance
107
     */
108 3
    public function setInputTransformer(Transformer $input_transformer): self
109
    {
110 3
        $this->input_transformer = $input_transformer;
111
112 3
        return $this;
113
    }
114
115
    /**
116
     * Get the hydrator factory
117
     *
118
     * @return HydratorFactory|null The hydrator factory
119
     */
120 3
    public function getHydratorFactory()
121
    {
122 3
        return $this->hydrator_factory;
123
    }
124
125
    /**
126
     * Set the hydrator factory
127
     *
128
     * @param HydratorFactory|null $hydrator_factory The hydrator factory
129
     * @return $this This instance
130
     */
131 9
    public function setHydratorFactory(HydratorFactory $hydrator_factory = null): self
132
    {
133 9
        $this->hydrator_factory = $hydrator_factory;
134
135 9
        return $this;
136
    }
137
138
    /**
139
     * Get the builder factory
140
     *
141
     * @return BuilderFactory|null The builder factory
142
     */
143 3
    public function getBuilderFactory()
144
    {
145 3
        return $this->builder_factory;
146
    }
147
148
    /**
149
     * Set the builder factory
150
     *
151
     * @param BuilderFactory|null $builder_factory The builder factory
152
     * @return $this This instance
153
     */
154 6
    public function setBuilderFactory(BuilderFactory $builder_factory = null): self
155
    {
156 6
        $this->builder_factory = $builder_factory;
157
158 6
        return $this;
159
    }
160
161
    /**
162
     * Get the value of the configuration flag that denotes whether hydration
163
     * should always be run after building a new model when processing
164
     * specified types
165
     *
166
     * @return bool
167
     */
168 3
    public function getAlwaysHydrateAfterBuilding(): bool
169
    {
170 3
        return $this->always_hydrate_after_building;
171
    }
172
173
    /**
174
     * Set the value of the configuration flag that denotes whether hydration
175
     * should always be run after building a new model when processing
176
     * specified types
177
     *
178
     * @param bool $always_hydrate_after_building Whether or not to always
179
     *  hydrate after building a new model when processing types
180
     * @return $this
181
     */
182 9
    public function setAlwaysHydrateAfterBuilding(bool $always_hydrate_after_building): self
183
    {
184 9
        $this->always_hydrate_after_building = $always_hydrate_after_building;
185
186 9
        return $this;
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     *
192
     * If a hydrator isn't provided, an attempt will be made to automatically
193
     * resolve and build an appropriate hydrator from the provided factory
194
     *
195
     * @param mixed $input_data The input data
196
     * @param mixed $model The model to hydrate
197
     * @param Hydrator|null $hydrator The hydrator to use
198
     * @return mixed The hydrated model
199
     */
200 9
    public function processForModel($input_data, $model, Hydrator $hydrator = null)
201
    {
202 9
        $input_data = $this->transformInput($input_data);
203
204 9
        return $this->hydrateModel($input_data, $model, $hydrator);
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     *
210
     * If a builder isn't provided, an attempt will be made to automatically
211
     * resolve and build an appropriate builder from the provided factory
212
     *
213
     * If a hydrator is provided, it will be used to hydrate the provided type
214
     * after building via the builder
215
     *
216
     * If a hydrator isn't provided, but the "always_hydrate_after_building"
217
     * property is set to true, an attempt to hydrate the type will be made
218
     * after building via the builder, and the hydrator will be automatically
219
     * resolved from the provided factory
220
     *
221
     * @param mixed $input_data The input data
222
     * @param string $type The type to build
223
     * @param Builder $builder The builder to use in the process
0 ignored issues
show
Documentation introduced by
Should the type for parameter $builder not be null|Builder?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
224
     * @param Hydrator $hydrator An optional hydrator to use in the process,
0 ignored issues
show
Documentation introduced by
Should the type for parameter $hydrator not be null|Hydrator?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
225
     *  after the type is built, to aid in the full hydration of the resulting
226
     *  model
227
     * @return mixed The built model
228
     */
229 18
    public function processForType($input_data, string $type, Builder $builder = null, Hydrator $hydrator = null)
230
    {
231 18
        $input_data = $this->transformInput($input_data);
232
233 18
        if (null === $builder) {
234 6
            $builder = $this->getBuilderForType($type);
235
        }
236
237 15
        $model = $builder->build($input_data);
238
239 15
        if (null !== $hydrator || $this->always_hydrate_after_building) {
240 9
            $model = $this->hydrateModel($input_data, $model, $hydrator);
241
        }
242
243 12
        return $model;
244
    }
245
246
    /**
247
     * Transform the input data
248
     *
249
     * @param mixed $input_data The input data
250
     * @return mixed The resulting transformed data
251
     */
252 27
    protected function transformInput($input_data)
253
    {
254 27
        return $this->input_transformer->transform($input_data);
255
    }
256
257
    /**
258
     * Hydrate a model from incoming data
259
     *
260
     * If a hydrator isn't provided, an attempt will be made to automatically
261
     * resolve and build an appropriate hydrator from the provided factory
262
     *
263
     * @param mixed $input_data The input data
264
     * @param mixed $model The model to hydrate
265
     * @param Hydrator|null $hydrator The hydrator to use
266
     * @return mixed The hydrated model
267
     */
268 18
    protected function hydrateModel($input_data, $model, Hydrator $hydrator = null)
269
    {
270 18
        if (null === $hydrator) {
271 12
            $hydrator = $this->getHydratorForModel($model);
272
        }
273
274 12
        return $hydrator->hydrate($input_data, $model);
275
    }
276
277
    /**
278
     * Get a Hydrator for a given model
279
     *
280
     * @param mixed $model The model to get a hydrator for
281
     * @throws UnresolvableHydratorException If a hydrator can't be resolved for
282
     *  the given model
283
     * @return Hydrator The resulting hydrator
284
     */
285 12
    protected function getHydratorForModel($model): Hydrator
286
    {
287 12
        if (null === $this->hydrator_factory) {
288 6
            throw UnresolvableHydratorException::forModel($model);
289
        }
290
291 6
        return $this->hydrator_factory->buildForModel($model);
292
    }
293
294
    /**
295
     * Get a Builder for a given model
296
     *
297
     * @param string $type The type to get a builder for
298
     * @throws UnresolvableBuilderException If a builder can't be resolved for
299
     *  the given model
300
     * @return Builder The resulting builder
301
     */
302 6
    protected function getBuilderForType(string $type): Builder
303
    {
304 6
        if (null === $this->builder_factory) {
305 3
            throw UnresolvableBuilderException::forType($type);
306
        }
307
308 3
        return $this->builder_factory->buildForType($type);
309
    }
310
}
311