Completed
Push — master ( b5fb47...8bb9d4 )
by Nate
02:22
created

ArrayScope::includeValue()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 0
cts 13
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 8
nc 3
nop 2
crap 30
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\Scope;
11
12
use Flipbox\Transform\Transformers\TransformerInterface;
13
use Flipbox\Transform\Transform\ArrayTransform as ConfigurableTransform;
14
use Flipbox\Transform\ParamBag;
15
16
/**
17
 * @author Flipbox Factory <[email protected]>
18
 * @since 1.0.0
19
 *
20
 * @property ConfigurableTransform $transform
21
 */
22
class ArrayScope extends AbstractScope
23
{
24
25
    /**
26
     * Scope constructor.
27
     * @param ConfigurableTransform $transform
28
     * @param string|null $scopeIdentifier
29
     * @param array $parentScopes
30
     */
31
    public function __construct(
32
        ConfigurableTransform $transform,
33
        string $scopeIdentifier = null,
34
        array $parentScopes = []
35
    ) {
36
        parent::__construct($transform, $scopeIdentifier, $parentScopes);
37
    }
38
39
    /**
40
     * Is Requested.
41
     *
42
     * Check if - in relation to the current scope - this specific segment is allowed.
43
     * That means, if a.b.c is requested and the current scope is a.b, then c is allowed. If the current
44
     * scope is a then c is not allowed, even if it is there and potentially transformable.
45
     *
46
     * @internal
47
     *
48
     * @param string $checkScopeSegment
49
     *
50
     * @return bool Returns the new number of elements in the array.
51
     */
52
    protected function isRequested($checkScopeSegment): bool
53
    {
54
        return in_array(
55
            $this->scopeString($checkScopeSegment),
56
            $this->transform->getIncludes()
57
        );
58
    }
59
60
    /**
61
     * Is Excluded.
62
     *
63
     * Check if - in relation to the current scope - this specific segment should
64
     * be excluded. That means, if a.b.c is excluded and the current scope is a.b,
65
     * then c will not be allowed in the transformation whether it appears in
66
     * the list of default or available, requested includes.
67
     *
68
     * @internal
69
     *
70
     * @param string $checkScopeSegment
71
     *
72
     * @return bool
73
     */
74
    protected function isExcluded($checkScopeSegment): bool
75
    {
76
        return in_array(
77
            $this->scopeString($checkScopeSegment),
78
            $this->transform->getExcludes()
79
        );
80
    }
81
82
    /**
83
     * @param TransformerInterface|callable $transformer
84
     * @param mixed $data
85
     * @return array
86
     */
87
    public function transform(callable $transformer, $data): array
88
    {
89
        $includedData = [];
90
91
        // Transform data
92
        $transformedData = parent::transform($transformer, $data);
93
94
        // Bail now
95
        if (null === $transformedData) {
96
            return $includedData;
97
        }
98
99
        if (is_string($transformedData)) {
100
            $transformedData = [$transformedData];
101
        }
102
103
        foreach ($transformedData as $key => $val) {
104
            if (!$this->includeValue($transformer, $key)) {
105
                continue;
106
            }
107
            $includedData[$key] = $this->parseValue($val, $data, $key);
108
        }
109
110
        // Return only the requested fields
111
        $includedData = $this->filterFields($includedData);
112
113
        return $includedData;
114
    }
115
116
    /**
117
     * @param callable $transformer
118
     * @param string $key
119
     * @return bool
120
     */
121
    protected function includeValue(callable $transformer, string $key): bool
122
    {
123
        // Ignore optional (that have not been explicitly requested)
124
        if ($transformer instanceof TransformerInterface &&
125
            in_array($key, $transformer->getIncludes(), true) &&
126
            !$this->isRequested($key)
127
        ) {
128
            return false;
129
        }
130
131
        // Ignore excludes
132
        if ($this->isExcluded($key)) {
133
            return false;
134
        }
135
136
        return true;
137
    }
138
139
    /**
140
     * Filter the provided data with the requested filter fields for
141
     * the scope resource
142
     *
143
     * @internal
144
     *
145
     * @param array $data
146
     *
147
     * @return array
148
     */
149
    protected function filterFields(array $data): array
150
    {
151
        $fields = $this->getFilterFields();
152
153
        if ($fields === null) {
154
            return $data;
155
        }
156
157
        return array_intersect_key(
158
            $data,
159
            array_flip(
160
                iterator_to_array($fields)
161
            )
162
        );
163
    }
164
165
    /**
166
     * Return the requested filter fields for the scope resource
167
     *
168
     * @internal
169
     *
170
     * @return ParamBag|null
171
     */
172
    protected function getFilterFields()
173
    {
174
        return $this->transform->getField(
175
            $this->getScopeIdentifier()
176
        );
177
    }
178
179
    /**
180
     * @param string $checkScopeSegment
181
     * @return string
182
     */
183
    private function scopeString(string $checkScopeSegment): string
184
    {
185
        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...
186
            $scopeArray = array_slice($this->parentScopes, 1);
187
            array_push($scopeArray, $this->scopeIdentifier, $checkScopeSegment);
188
        } else {
189
            $scopeArray = [$checkScopeSegment];
190
        }
191
192
        return implode('.', (array)$scopeArray);
193
    }
194
}
195