Scope::includeDefinitionFor()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Rexlabs\Smokescreen\Transformer;
4
5
use Rexlabs\Smokescreen\Includes\Includes;
6
use Rexlabs\Smokescreen\Resource\ResourceInterface;
7
8
class Scope
9
{
10
    /** @var mixed|ResourceInterface */
11
    protected $resource;
12
13
    /** @var Includes */
14
    protected $includes;
15
16
    /** @var Scope|null */
17
    protected $parent;
18
19
    /**
20
     * Scope constructor.
21
     *
22
     * @param ResourceInterface|mixed $resource
23
     * @param Includes                $includes
24
     * @param Scope|null              $parent
25
     */
26 16
    public function __construct($resource, Includes $includes, self $parent = null)
27
    {
28 16
        $this->resource = $resource;
29 16
        $this->includes = $includes;
30 16
        $this->parent = $parent;
31
    }
32
33
    /**
34
     * @return TransformerInterface|mixed|null
35
     */
36 14
    public function transformer()
37
    {
38 14
        return $this->resource instanceof ResourceInterface ?
39 14
           $this->resource->getTransformer() : null;
40
    }
41
42
    /**
43
     * @return Includes
44
     */
45 14
    public function includes(): Includes
46
    {
47 14
        return $this->includes;
48
    }
49
50
    /**
51
     * @param Includes $includes
52
     */
53
    public function setIncludes(Includes $includes)
54
    {
55
        $this->includes = $includes;
56
    }
57
58
    /**
59
     * @return mixed|ResourceInterface
60
     */
61 16
    public function resource()
62
    {
63 16
        return $this->resource;
64
    }
65
66
    /**
67
     * @param mixed|ResourceInterface $resource
68
     */
69
    public function setResource($resource)
70
    {
71
        $this->resource = $resource;
72
    }
73
74 12
    public function defaultIncludeKeys(): array
75
    {
76 12
        $defaultIncludeKeys = [];
77 12
        if (($transformer = $this->transformer()) !== null && ($transformer instanceof  TransformerInterface)) {
78 2
            $defaultIncludeKeys = $transformer->getDefaultIncludes();
79
        }
80
81 12
        return $defaultIncludeKeys;
82
    }
83
84
    /**
85
     * List of array keys identifying the available includes for this resource.
86
     *
87
     * @return array
88
     */
89 14
    public function availableIncludeKeys(): array
90
    {
91 14
        $availableKeys = [];
92 14
        if (($transformer = $this->transformer()) !== null && ($transformer instanceof  TransformerInterface)) {
93 7
            $availableKeys = $transformer->getAvailableIncludes();
94
        }
95
96 14
        return $availableKeys;
97
    }
98
99
    /**
100
     * The include keys that were requested.
101
     *
102
     * @return array
103
     */
104 14
    public function requestedIncludeKeys(): array
105
    {
106 14
        return $this->includes()->baseKeys();
107
    }
108
109
    /**
110
     * The include keys that were either requested or (if empty) the ones
111
     * that are are enabled by default.
112
     *
113
     * @return array
114
     */
115 14
    public function includeKeys(): array
116
    {
117
        // Wanted includes is a either the explicit includes requested, or the defaults for the transformer.
118 14
        return $this->requestedIncludeKeys() ?: $this->defaultIncludeKeys();
119
    }
120
121 14
    public function includeMap(): array
122
    {
123 14
        $map = [];
124 14
        if (($transformer = $this->transformer()) !== null && ($transformer instanceof  TransformerInterface)) {
125 7
            $map = $transformer->getIncludeMap();
126
        }
127
128 14
        return $map;
129
    }
130
131
    /**
132
     * @param $key
133
     *
134
     * @return array|null
135
     */
136
    public function includeDefinitionFor($key): ?array
137
    {
138
        return $this->includeMap()[$key] ?? null;
139
    }
140
141
    /**
142
     * A list of include keys that were requested and are available for
143
     * usage (eg. they are declared in the transformer).
144
     *
145
     * @return array
146
     */
147 14
    public function resolvedIncludeKeys(): array
148
    {
149 14
        $availableIncludeKeys = $this->availableIncludeKeys();
150
151 14
        return array_filter($this->includeKeys(), function ($includeKey) use ($availableIncludeKeys) {
152 7
            return \in_array($includeKey, $availableIncludeKeys, true);
153 14
        });
154
    }
155
156
    /**
157
     * Get a list of relationship keys for all of the includes which
158
     * have been resolved.
159
     *
160
     * @return array
161
     */
162 14
    public function resolvedRelationshipKeys(): array
163
    {
164 14
        $includeMap = $this->includeMap();
165
166 14
        $keys = [];
167 14
        foreach ($this->resolvedIncludeKeys() as $includeKey) {
168 6
            $relations = $includeMap[$includeKey]['relation'] ?? [];
169 6
            if (\count($relations) > 0) {
170 1
                array_push($keys, ...$relations);
171
            }
172
        }
173
174 14
        return array_unique($keys);
175
    }
176
177 7
    public function filterProps(): array
178
    {
179
        // We can consider our props anything that has not been mapped.
180 7
        $resolvedIncludeKeys = $this->resolvedIncludeKeys();
181 7
        $keys = array_filter($this->includeKeys(), function ($includeKey) use ($resolvedIncludeKeys) {
182 7
            return !\in_array($includeKey, $resolvedIncludeKeys, true);
183 7
        });
184
185
        // Were any filter props explicitly provided?
186
        // If not, see if defaults were provided from the transformer.
187 7
        if (empty($keys) && ($transformer = $this->transformer()) !== null) {
188
            // No explicit props provided
189 7
            $defaultProps = $transformer->getDefaultProps();
190 7
            if (!empty($defaultProps)) {
191 1
                $keys = $defaultProps;
192
            }
193
        }
194
195 7
        return $keys;
196
    }
197
198
    /**
199
     * @return null|Scope
200
     */
201
    public function parent()
202
    {
203
        return $this->parent;
204
    }
205
206
    /**
207
     * Apply the scope's sparse field-set to the given data.
208
     *
209
     * @param array $data
210
     *
211
     * @return array
212
     */
213 7
    public function filterData(array $data)
214
    {
215
        // Filter the sparse field-set if we have a specific list of properties
216
        // defined that we want.
217 7
        $filterProps = $this->filterProps();
218 7
        if (!empty($filterProps)) {
219 1
            $filteredData = array_filter($data, function ($key) use ($filterProps) {
220 1
                return \in_array($key, $filterProps, true);
221 1
            }, ARRAY_FILTER_USE_KEY);
222
223
            // We must always have some data after filtering, so if our filtered
224
            // data is empty, we should just ignore it ...
225 1
            if (!empty($filteredData)) {
226 1
                $data = $filteredData;
227
            }
228
        }
229
230 7
        return $data;
231
    }
232
}
233