Completed
Push — master ( 605dcd...eeb8ed )
by Nate
02:13
created

Scope::transform()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * @author    Flipbox Factory
5
 * @copyright Copyright (c) 2017, Flipbox Digital
6
 * @link      https://github.com/flipbox/transform/releases/latest
7
 * @license   https://github.com/flipbox/transform/blob/master/LICENSE
8
 */
9
10
namespace Flipbox\Transform;
11
12
use Flipbox\Transform\Transformers\TransformerInterface;
13
14
/**
15
 * @author Flipbox Factory <[email protected]>
16
 * @since 1.0.0
17
 */
18
class Scope
19
{
20
    /**
21
     * @var string
22
     */
23
    protected $scopeIdentifier;
24
25
    /**
26
     * @var Transform
27
     */
28
    protected $transform;
29
30
    /**
31
     * @var array
32
     */
33
    protected $parentScopes = [];
34
35
    /**
36
     * Scope constructor.
37
     * @param Transform $transform
38
     * @param string|null $scopeIdentifier
39
     * @param array $parentScopes
40
     */
41
    public function __construct(
42
        Transform $transform,
43
        string $scopeIdentifier = null,
44
        array $parentScopes = []
45
    ) {
46
        $this->transform = $transform;
47
        $this->scopeIdentifier = $scopeIdentifier;
48
        $this->parentScopes = $parentScopes;
49
    }
50
51
    /**
52
     * @return Transform
53
     */
54
    public function getTransform(): Transform
55
    {
56
        return $this->transform;
57
    }
58
59
    /**
60
     * @param $key
61
     * @return ParamBag
62
     */
63
    public function getParams(string $key = null): ParamBag
64
    {
65
        return $this->getTransform()->getParams(
66
            $this->getIdentifier($key)
67
        );
68
    }
69
70
    /**
71
     * Get the current identifier.
72
     *
73
     * @return string|null
74
     */
75
    public function getScopeIdentifier()
76
    {
77
        return $this->scopeIdentifier;
78
    }
79
80
    /**
81
     * Get the unique identifier for this scope.
82
     *
83
     * @param string $appendIdentifier
84
     *
85
     * @return string
86
     */
87
    public function getIdentifier(string $appendIdentifier = null): string
88
    {
89
        return implode(
90
            '.',
91
            array_filter(array_merge(
92
                $this->parentScopes,
93
                [
94
                    $this->scopeIdentifier,
95
                    $appendIdentifier
96
                ]
97
            ))
98
        );
99
    }
100
101
    /**
102
     * Getter for parentScopes.
103
     *
104
     * @return array
105
     */
106
    public function getParentScopes(): array
107
    {
108
        return $this->parentScopes;
109
    }
110
111
    /**
112
     * Is Requested.
113
     *
114
     * Check if - in relation to the current scope - this specific segment is allowed.
115
     * That means, if a.b.c is requested and the current scope is a.b, then c is allowed. If the current
116
     * scope is a then c is not allowed, even if it is there and potentially transformable.
117
     *
118
     * @internal
119
     *
120
     * @param string $checkScopeSegment
121
     *
122
     * @return bool Returns the new number of elements in the array.
123
     */
124
    public function isRequested($checkScopeSegment): bool
125
    {
126
        return in_array(
127
            $this->scopeString($checkScopeSegment),
128
            $this->transform->getIncludes()
129
        );
130
    }
131
132
    /**
133
     * Is Excluded.
134
     *
135
     * Check if - in relation to the current scope - this specific segment should
136
     * be excluded. That means, if a.b.c is excluded and the current scope is a.b,
137
     * then c will not be allowed in the transformation whether it appears in
138
     * the list of default or available, requested includes.
139
     *
140
     * @internal
141
     *
142
     * @param string $checkScopeSegment
143
     *
144
     * @return bool
145
     */
146
    public function isExcluded($checkScopeSegment): bool
147
    {
148
        return in_array(
149
            $this->scopeString($checkScopeSegment),
150
            $this->transform->getExcludes()
151
        );
152
    }
153
154
    /**
155
     * @param TransformerInterface|callable $transformer
156
     * @param mixed $data
157
     * @return mixed
158
     */
159
    public function transform(callable $transformer, $data)
160
    {
161
        return $this->parseValue($transformer, $data);
162
    }
163
164
    /**
165
     * @param callable $transformer
166
     * @param string $key
167
     * @return bool
168
     */
169
    public function includeValue(callable $transformer, string $key): bool
170
    {
171
        // Ignore optional (that have not been explicitly requested)
172
        if ($transformer instanceof TransformerInterface &&
173
            in_array($key, $transformer->getIncludes(), true) &&
174
            !$this->isRequested($key)
175
        ) {
176
            return false;
177
        }
178
179
        // Ignore excludes
180
        if ($this->isExcluded($key)) {
181
            return false;
182
        }
183
184
        return true;
185
    }
186
187
    /**
188
     * @param $val
189
     * @param $data
190
     * @param string|null $key
191
     * @return mixed
192
     */
193
    public function parseValue($val, $data, string $key = null)
194
    {
195
        if (is_callable($val)) {
196
            return call_user_func_array($val, [$data, $this, $key]);
197
        }
198
199
        return $val;
200
    }
201
202
    /**
203
     * @param string $identifier
204
     * @return Scope
205
     */
206
    public function childScope(string $identifier): Scope
207
    {
208
        $parentScopes = $this->getParentScopes();
209
        $parentScopes[] = $this->getScopeIdentifier();
210
211
        return new static(
212
            $this->getTransform(),
213
            $identifier,
214
            $parentScopes
215
        );
216
    }
217
218
    /**
219
     * Check, if this is the root scope.
220
     *
221
     * @return bool
222
     */
223
    protected function isRootScope(): bool
224
    {
225
        return empty($this->parentScopes);
226
    }
227
228
    /**
229
     * Filter the provided data with the requested filter fields for
230
     * the scope resource
231
     *
232
     * @param array $data
233
     *
234
     * @return array
235
     */
236
    public function filterFields(array $data): array
237
    {
238
        $fields = $this->getFilterFields();
239
240
        if ($fields === null) {
241
            return $data;
242
        }
243
244
        return array_intersect_key(
245
            $data,
246
            array_flip(
247
                iterator_to_array($fields)
248
            )
249
        );
250
    }
251
252
    /**
253
     * Return the requested filter fields for the scope resource
254
     *
255
     * @internal
256
     *
257
     * @return ParamBag|null
258
     */
259
    protected function getFilterFields()
260
    {
261
        return $this->transform->getField(
262
            $this->getScopeIdentifier()
263
        );
264
    }
265
266
    /**
267
     * @param string $checkScopeSegment
268
     * @return string
269
     */
270
    private function scopeString(string $checkScopeSegment): string
271
    {
272
        if ($this->parentScopes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->parentScopes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
273
            $scopeArray = array_slice($this->parentScopes, 1);
274
            array_push($scopeArray, $this->scopeIdentifier, $checkScopeSegment);
275
        } else {
276
            $scopeArray = [$checkScopeSegment];
277
        }
278
279
        return implode('.', (array)$scopeArray);
280
    }
281
}
282