Completed
Pull Request — master (#306)
by Benoît
03:13
created

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