TransformerAbstract   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 275
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 6
dl 0
loc 275
ccs 72
cts 72
cp 1
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getAvailableIncludes() 0 4 1
A getDefaultIncludes() 0 4 1
A getCurrentScope() 0 4 1
A setAvailableIncludes() 0 6 1
A setDefaultIncludes() 0 6 1
A setCurrentScope() 0 6 1
A primitive() 0 4 1
A item() 0 4 1
A collection() 0 4 1
A null() 0 4 1
A figureOutWhichIncludes() 0 18 5
A processIncludedResources() 0 17 3
A includeResourceIfAvailable() 0 18 3
A callIncludeMethod() 0 26 4
1
<?php
2
3
/*
4
 * This file is part of the League\Fractal package.
5
 *
6
 * (c) Phil Sturgeon <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace League\Fractal;
13
14
use League\Fractal\Resource\Collection;
15
use League\Fractal\Resource\Item;
16
use League\Fractal\Resource\NullResource;
17
use League\Fractal\Resource\Primitive;
18
use League\Fractal\Resource\ResourceInterface;
19
20
/**
21
 * Transformer Abstract
22
 *
23
 * All Transformer classes should extend this to utilize the convenience methods
24
 * collection() and item(), and make the self::$availableIncludes property available.
25
 * Extend it and add a `transform()` method to transform any default or included data
26
 * into a basic array.
27
 */
28
abstract class TransformerAbstract
29
{
30
    /**
31
     * Resources that can be included if requested.
32
     *
33
     * @var array
34
     */
35
    protected $availableIncludes = [];
36
37
    /**
38
     * Include resources without needing it to be requested.
39
     *
40
     * @var array
41
     */
42
    protected $defaultIncludes = [];
43
44
    /**
45
     * The transformer should know about the current scope, so we can fetch relevant params.
46
     *
47
     * @var Scope
48
     */
49
    protected $currentScope;
50
51
    /**
52
     * Getter for availableIncludes.
53
     *
54
     * @return array
55
     */
56 50
    public function getAvailableIncludes()
57
    {
58 50
        return $this->availableIncludes;
59
    }
60
61
    /**
62
     * Getter for defaultIncludes.
63
     *
64
     * @return array
65
     */
66 54
    public function getDefaultIncludes()
67
    {
68 54
        return $this->defaultIncludes;
69
    }
70
71
    /**
72
     * Getter for currentScope.
73
     *
74
     * @return \League\Fractal\Scope
75
     */
76 1
    public function getCurrentScope()
77
    {
78 1
        return $this->currentScope;
79
    }
80
81
    /**
82
     * Figure out which includes we need.
83
     *
84
     * @internal
85
     *
86
     * @param Scope $scope
87
     *
88
     * @return array
89
     */
90 50
    private function figureOutWhichIncludes(Scope $scope)
91
    {
92 50
        $includes = $this->getDefaultIncludes();
93
94 50
        foreach ($this->getAvailableIncludes() as $include) {
95 44
            if ($scope->isRequested($include)) {
96 29
                $includes[] = $include;
97 29
            }
98 50
        }
99
100 50
        foreach ($includes as $include) {
101 33
            if ($scope->isExcluded($include)) {
102 2
                $includes = array_diff($includes, [$include]);
103 2
            }
104 50
        }
105
106 50
        return $includes;
107
    }
108
109
    /**
110
     * This method is fired to loop through available includes, see if any of
111
     * them are requested and permitted for this scope.
112
     *
113
     * @internal
114
     *
115
     * @param Scope $scope
116
     * @param mixed $data
117
     *
118
     * @return array
119
     */
120 58
    public function processIncludedResources(Scope $scope, $data)
121
    {
122 58
        $includedData = [];
123
124 58
        $includes = $this->figureOutWhichIncludes($scope);
125
126 58
        foreach ($includes as $include) {
127 41
            $includedData = $this->includeResourceIfAvailable(
128 41
                $scope,
129 41
                $data,
130 41
                $includedData,
131
                $include
132 41
            );
133 56
        }
134
135 56
        return $includedData === [] ? false : $includedData;
136
    }
137
138
    /**
139
     * Include a resource only if it is available on the method.
140
     *
141
     * @internal
142
     *
143
     * @param Scope  $scope
144
     * @param mixed  $data
145
     * @param array  $includedData
146
     * @param string $include
147
     *
148
     * @return array
149
     */
150 31
    private function includeResourceIfAvailable(
151
        Scope $scope,
152
        $data,
153
        $includedData,
154
        $include
155
    ) {
156 31
        if ($resource = $this->callIncludeMethod($scope, $include, $data)) {
157 30
            $childScope = $scope->embedChildScope($include, $resource);
158
159 30
            if ($childScope->getResource() instanceof Primitive) {
160 1
                $includedData[$include] = $childScope->transformPrimitiveResource();
161 1
            } else {
162 29
                $includedData[$include] = $childScope->toArray();
163
            }
164 30
        }
165
166 31
        return $includedData;
167
    }
168
169
    /**
170
     * Call Include Method.
171
     *
172
     * @internal
173
     *
174
     * @param Scope  $scope
175
     * @param string $includeName
176
     * @param mixed  $data
177
     *
178
     * @throws \Exception
179
     *
180
     * @return \League\Fractal\Resource\ResourceInterface
181
     */
182 40
    protected function callIncludeMethod(Scope $scope, $includeName, $data)
183
    {
184 40
        $scopeIdentifier = $scope->getIdentifier($includeName);
185 40
        $params = $scope->getManager()->getIncludeParams($scopeIdentifier);
186
187
        // Check if the method name actually exists
188 40
        $methodName = 'include'.str_replace(' ', '', ucwords(str_replace('_', ' ', str_replace('-', ' ', $includeName))));
189
190 40
        $resource = call_user_func([$this, $methodName], $data, $params);
191
192 38
        if ($resource === null) {
193 3
            return false;
194
        }
195
196 35
        if (! $resource instanceof ResourceInterface) {
197 1
            throw new \Exception(sprintf(
198 1
                'Invalid return value from %s::%s(). Expected %s, received %s.',
199 1
                __CLASS__,
200 1
                $methodName,
201 1
                'League\Fractal\Resource\ResourceInterface',
202 1
                is_object($resource) ? get_class($resource) : gettype($resource)
203 1
            ));
204
        }
205
206 34
        return $resource;
207
    }
208
209
    /**
210
     * Setter for availableIncludes.
211
     *
212
     * @param array $availableIncludes
213
     *
214
     * @return $this
215
     */
216 2
    public function setAvailableIncludes($availableIncludes)
217
    {
218 2
        $this->availableIncludes = $availableIncludes;
219
220 2
        return $this;
221
    }
222
223
    /**
224
     * Setter for defaultIncludes.
225
     *
226
     * @param array $defaultIncludes
227
     *
228
     * @return $this
229
     */
230 1
    public function setDefaultIncludes($defaultIncludes)
231
    {
232 1
        $this->defaultIncludes = $defaultIncludes;
233
234 1
        return $this;
235
    }
236
237
    /**
238
     * Setter for currentScope.
239
     *
240
     * @param Scope $currentScope
241
     *
242
     * @return $this
243
     */
244 51
    public function setCurrentScope($currentScope)
245
    {
246 51
        $this->currentScope = $currentScope;
247
248 51
        return $this;
249
    }
250
251
    /**
252
     * Create a new primitive resource object.
253
     *
254
     * @param mixed                        $data
255
     * @param callable|null                $transformer
256
     * @param string                       $resourceKey
257
     *
258
     * @return Primitive
259
     */
260 1
    protected function primitive($data, $transformer = null, $resourceKey = null)
261
    {
262 1
        return new Primitive($data, $transformer, $resourceKey);
263
    }
264
265
    /**
266
     * Create a new item resource object.
267
     *
268
     * @param mixed                        $data
269
     * @param TransformerAbstract|callable $transformer
270
     * @param string                       $resourceKey
271
     *
272
     * @return Item
273
     */
274 22
    protected function item($data, $transformer, $resourceKey = null)
275
    {
276 22
        return new Item($data, $transformer, $resourceKey);
277
    }
278
279
    /**
280
     * Create a new collection resource object.
281
     *
282
     * @param mixed                        $data
283
     * @param TransformerAbstract|callable $transformer
284
     * @param string                       $resourceKey
285
     *
286
     * @return Collection
287
     */
288 14
    protected function collection($data, $transformer, $resourceKey = null)
289
    {
290 14
        return new Collection($data, $transformer, $resourceKey);
291
    }
292
293
    /**
294
     * Create a new null resource object.
295
     *
296
     * @return NullResource
297
     */
298 3
    protected function null()
299
    {
300 3
        return new NullResource();
301
    }
302
}
303