Smokescreen::transform()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 10
cc 3
nc 4
nop 0
crap 3
1
<?php
2
3
namespace Rexlabs\Smokescreen;
4
5
use Rexlabs\Smokescreen\Exception\MissingResourceException;
6
use Rexlabs\Smokescreen\Helpers\JsonHelper;
7
use Rexlabs\Smokescreen\Includes\IncludeParser;
8
use Rexlabs\Smokescreen\Includes\IncludeParserInterface;
9
use Rexlabs\Smokescreen\Includes\Includes;
10
use Rexlabs\Smokescreen\Relations\RelationLoaderInterface;
11
use Rexlabs\Smokescreen\Resource\Collection;
12
use Rexlabs\Smokescreen\Resource\Item;
13
use Rexlabs\Smokescreen\Resource\ResourceInterface;
14
use Rexlabs\Smokescreen\Serializer\DefaultSerializer;
15
use Rexlabs\Smokescreen\Serializer\SerializerInterface;
16
use Rexlabs\Smokescreen\Transformer\Pipeline;
17
use Rexlabs\Smokescreen\Transformer\Scope;
18
use Rexlabs\Smokescreen\Transformer\TransformerInterface;
19
use Rexlabs\Smokescreen\Transformer\TransformerResolverInterface;
20
21
/**
22
 * Smokescreen is a library for transforming and serializing data - typically RESTful API output.
23
 */
24
class Smokescreen implements \JsonSerializable
25
{
26
    /** @var ResourceInterface Item or Collection to be transformed */
27
    protected $resource;
28
29
    /** @var SerializerInterface */
30
    protected $serializer;
31
32
    /** @var IncludeParserInterface */
33
    protected $includeParser;
34
35
    /** @var RelationLoaderInterface */
36
    protected $relationLoader;
37
38
    /** @var Includes */
39
    protected $includes;
40
41
    /** @var TransformerResolverInterface */
42
    protected $transformerResolver;
43
44
    /**
45
     * Return the current resource.
46
     *
47
     * @return ResourceInterface|mixed|null
48
     */
49 6
    public function getResource()
50
    {
51 6
        return $this->resource;
52
    }
53
54
    /**
55
     * Set the resource to be transformed.
56
     *
57
     * @param ResourceInterface|mixed|null $resource
58
     *
59
     * @return $this
60
     */
61 21
    public function setResource($resource)
62
    {
63 21
        $this->resource = $resource;
64
65 21
        return $this;
66
    }
67
68
    /**
69
     * Set the resource item to be transformed.
70
     *
71
     * @param mixed                           $data
72
     * @param TransformerInterface|mixed|null $transformer
73
     * @param string|null                     $key
74
     *
75
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
76
     *
77
     * @return $this
78
     */
79 14
    public function item($data, $transformer = null, $key = null)
80
    {
81 14
        $this->setResource(new Item($data, $transformer, $key));
82
83 13
        return $this;
84
    }
85
86
    /**
87
     * Set the resource collection to be transformed.
88
     *
89
     * @param mixed                           $data
90
     * @param TransformerInterface|mixed|null $transformer
91
     * @param string|null                     $key
92
     * @param callable|null                   $callback
93
     *
94
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
95
     *
96
     * @return $this
97
     */
98 8
    public function collection($data, TransformerInterface $transformer = null, $key = null, callable $callback = null)
99
    {
100 8
        $this->setResource(new Collection($data, $transformer, $key));
101 8
        if ($callback !== null) {
102 1
            $callback($this->resource);
103
        }
104
105 8
        return $this;
106
    }
107
108
    /**
109
     * Sets the transformer to be used to transform the resource ... later.
110
     *
111
     * @throws MissingResourceException
112
     *
113
     * @return TransformerInterface|mixed|null
114
     */
115 5
    public function getTransformer()
116
    {
117 5
        if (!$this->resource) {
118 1
            throw new MissingResourceException('Resource must be specified before setting a transformer');
119
        }
120
121 4
        return $this->resource->getTransformer();
122
    }
123
124
    /**
125
     * Sets the transformer to be used to transform the resource ... later.
126
     *
127
     * @param TransformerInterface|mixed|null $transformer
128
     *
129
     * @throws MissingResourceException
130
     *
131
     * @return $this
132
     */
133 2
    public function setTransformer($transformer = null)
134
    {
135 2
        if (!$this->resource) {
136 1
            throw new MissingResourceException('Resource must be specified before setting a transformer');
137
        }
138 1
        $this->resource->setTransformer($transformer);
139
140 1
        return $this;
141
    }
142
143
    /**
144
     * Returns an object (stdClass) representation of the transformed/serialized data.
145
     *
146
     * @throws \Rexlabs\Smokescreen\Exception\InvalidSerializerException
147
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
148
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
149
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
150
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
151
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
152
     *
153
     * @return \stdClass
154
     */
155 1
    public function toObject(): \stdClass
156
    {
157 1
        return (object) json_decode($this->toJson());
158
    }
159
160
    /**
161
     * Outputs a JSON string of the resulting transformed and serialized data.
162
     *
163
     * @param int $options
164
     *
165
     * @throws \Rexlabs\Smokescreen\Exception\InvalidSerializerException
166
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
167
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
168
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
169
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
170
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
171
     *
172
     * @return string
173
     */
174 2
    public function toJson($options = 0): string
175
    {
176 2
        return JsonHelper::encode($this->jsonSerialize(), $options);
177
    }
178
179
    /**
180
     * Output the transformed and serialized data as an array.
181
     * Implements PHP's JsonSerializable interface.
182
     *
183
     * @throws \Rexlabs\Smokescreen\Exception\InvalidSerializerException
184
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
185
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
186
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
187
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
188
     *
189
     * @return array
190
     *
191
     * @see Smokescreen::toArray()
192
     */
193 2
    public function jsonSerialize(): array
194
    {
195 2
        return $this->toArray();
196
    }
197
198
    /**
199
     * Return the transformed data as an array.
200
     *
201
     * @throws \Rexlabs\Smokescreen\Exception\InvalidSerializerException
202
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
203
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
204
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
205
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
206
     *
207
     * @return array
208
     */
209 17
    public function toArray(): array
210
    {
211 17
        if (!$this->resource) {
212 1
            throw new MissingResourceException('No resource has been defined to transform');
213
        }
214
215 16
        return (array) $this->transform();
216
    }
217
218
    /**
219
     * @throws Exception\IncludeException
220
     *
221
     * @return array
222
     */
223 16
    protected function transform()
224
    {
225 16
        $scope = new Scope($this->resource, $this->getIncludes());
226 16
        $pipeline = new Pipeline();
227 16
        $pipeline->setSerializer($this->getSerializer());
228
229 16
        if (($transformerResolver = $this->getTransformerResolver()) !== null) {
230 2
            $pipeline->setTransformerResolver($transformerResolver);
231
        }
232
233 16
        if (($relationLoader = $this->getRelationLoader()) !== null) {
234 1
            $pipeline->setRelationLoader($relationLoader);
235
        }
236
237 16
        return $pipeline->transform($scope);
238
    }
239
240
    /**
241
     * @return SerializerInterface
242
     */
243 17
    public function getSerializer(): SerializerInterface
244
    {
245 17
        return $this->serializer ?? new DefaultSerializer();
246
    }
247
248
    /**
249
     * Set the serializer which will be used to output the transformed resource.
250
     *
251
     * @param SerializerInterface|null $serializer
252
     *
253
     * @return $this
254
     */
255 1
    public function setSerializer(SerializerInterface $serializer = null)
256
    {
257 1
        $this->serializer = $serializer;
258
259 1
        return $this;
260
    }
261
262
    /**
263
     * Get the current includes object.
264
     *
265
     * @return Includes
266
     */
267 18
    public function getIncludes(): Includes
268
    {
269 18
        return $this->includes ?? new Includes();
270
    }
271
272
    /**
273
     * Set the Includes object used for determining included resources.
274
     *
275
     * @param Includes $includes
276
     *
277
     * @return $this
278
     */
279 1
    public function setIncludes(Includes $includes)
280
    {
281 1
        $this->includes = $includes;
282
283 1
        return $this;
284
    }
285
286
    /**
287
     * Parse the given string to generate a new Includes object.
288
     *
289
     * @param string $str
290
     *
291
     * @return $this
292
     */
293 8
    public function parseIncludes($str)
294
    {
295 8
        $this->includes = $this->getIncludeParser()->parse(!empty($str) ? $str : '');
296
297 8
        return $this;
298
    }
299
300
    /**
301
     * Return the include parser object.
302
     * If not set explicitly via setIncludeParser(), it will return the default IncludeParser object.
303
     *
304
     * @return IncludeParserInterface
305
     *
306
     * @see Smokescreen::setIncludeParser()
307
     */
308 8
    public function getIncludeParser(): IncludeParserInterface
309
    {
310 8
        return $this->includeParser ?? new IncludeParser();
311
    }
312
313
    /**
314
     * Set the include parser to handle converting a string to an Includes object.
315
     *
316
     * @param IncludeParserInterface $includeParser
317
     *
318
     * @return $this
319
     */
320 1
    public function setIncludeParser(IncludeParserInterface $includeParser)
321
    {
322 1
        $this->includeParser = $includeParser;
323
324 1
        return $this;
325
    }
326
327
    /**
328
     * Get the current relation loader.
329
     *
330
     * @return RelationLoaderInterface|null
331
     */
332 16
    public function getRelationLoader()
333
    {
334 16
        return $this->relationLoader;
335
    }
336
337
    /**
338
     * Set the relationship loader.
339
     *
340
     * @param RelationLoaderInterface $relationLoader
341
     *
342
     * @return $this
343
     */
344 1
    public function setRelationLoader(RelationLoaderInterface $relationLoader)
345
    {
346 1
        $this->relationLoader = $relationLoader;
347
348 1
        return $this;
349
    }
350
351
    /**
352
     * Returns true if a RelationLoaderInterface object has been defined.
353
     *
354
     * @return bool
355
     */
356 1
    public function hasRelationLoader(): bool
357
    {
358 1
        return $this->relationLoader !== null;
359
    }
360
361
    /**
362
     * @return TransformerResolverInterface|null
363
     */
364 17
    public function getTransformerResolver()
365
    {
366 17
        return $this->transformerResolver;
367
    }
368
369
    /**
370
     * Set the transformer resolve to user.
371
     *
372
     * @param TransformerResolverInterface|null $transformerResolver
373
     *
374
     * @return $this
375
     */
376 3
    public function setTransformerResolver(TransformerResolverInterface $transformerResolver = null)
377
    {
378 3
        $this->transformerResolver = $transformerResolver;
379
380 3
        return $this;
381
    }
382
}
383