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

ArrayTransform::setFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 8
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 6
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\Transform;
11
12
use Flipbox\Transform\ParamBag;
13
14
/**
15
 * @author Flipbox Factory <[email protected]>
16
 * @since 1.0.0
17
 */
18
class ArrayTransform extends AbstractTransform
19
{
20
    /**
21
     * Scope identifiers that resources can optionally include.
22
     *
23
     * @var array
24
     */
25
    protected $includes = [];
26
27
    /**
28
     * Scope identifiers that resources must exclude.
29
     *
30
     * @var array
31
     */
32
    protected $excludes = [];
33
34
    /**
35
     * Scope identifiers that resources must return.
36
     *
37
     * @var array
38
     */
39
    protected $fields = [];
40
41
    /**
42
     * Auto-include Parents
43
     *
44
     * Look at the requested includes and automatically include the parents if they
45
     * are not explicitly requested. E.g: [foo, bar.baz] becomes [foo, bar, bar.baz]
46
     *
47
     * @internal
48
     *
49
     * @return void
50
     */
51
    protected function autoIncludeParents()
52
    {
53
        $parsed = [];
54
55
        foreach ($this->includes as $include) {
56
            $nested = explode('.', $include);
57
58
            $part = array_shift($nested);
59
            $parsed[] = $part;
60
61
            while (count($nested) > 0) {
62
                $part .= '.' . array_shift($nested);
63
                $parsed[] = $part;
64
            }
65
        }
66
67
        $this->includes = array_values(array_unique($parsed));
68
    }
69
70
    /*******************************************
71
     * INCLUDES
72
     *******************************************/
73
74
    /**
75
     * Get Requested Includes.
76
     *
77
     * @return array
78
     */
79
    public function getIncludes(): array
80
    {
81
        return $this->includes;
82
    }
83
84
    /**
85
     * Parse Include String.
86
     *
87
     * @param array|string $includes Array or csv string of resources to include
88
     *
89
     * @return $this
90
     */
91
    public function setIncludes($includes)
92
    {
93
        // Wipe these before we go again
94
        $this->includes = $this->params = [];
95
96
        if (is_string($includes)) {
97
            $includes = explode(',', $includes);
98
        }
99
100
        if (!is_array($includes)) {
101
            throw new \InvalidArgumentException(
102
                'The parseIncludes() method expects a string or an array. ' . gettype($includes) . ' given'
103
            );
104
        }
105
106
        foreach ($includes as $include) {
107
            list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, null);
108
109
            // Trim it down to a cool level of recursion
110
            $includeName = $this->trimToAcceptableRecursionLevel($includeName);
111
112
            if (in_array($includeName, $this->includes)) {
113
                continue;
114
            }
115
            $this->includes[] = $includeName;
116
117
            // No Params? Bored
118
            if ($allModifiersStr === null) {
119
                continue;
120
            }
121
122
            // Matches multiple instances of 'something(foo|bar|baz)' in the string
123
            // I guess it ignores : so you could use anything, but probably don't do that
124
            preg_match_all('/([\w]+)(\(([^\)]+)\))?/', $allModifiersStr, $allModifiersArr);
125
126
            // [0] is full matched strings...
127
            $modifierCount = count($allModifiersArr[0]);
128
129
            $modifierArr = [];
130
131
            for ($modifierIt = 0; $modifierIt < $modifierCount; $modifierIt++) {
132
                // [1] is the modifier
133
                $modifierName = $allModifiersArr[1][$modifierIt];
134
135
                // and [3] is delimited params
136
                $modifierParamStr = $allModifiersArr[3][$modifierIt];
137
138
                // Make modifier array key with an array of params as the value
139
                $modifierArr[$modifierName] = explode($this->paramDelimiter, $modifierParamStr);
140
            }
141
142
            $this->params[$includeName] = $modifierArr;
143
        }
144
145
        // This should be optional and public someday, but without it includes would never show up
146
        $this->autoIncludeParents();
147
148
        return $this;
149
    }
150
151
    /*******************************************
152
     * EXCLUDES
153
     *******************************************/
154
155
    /**
156
     * Get Requested Excludes.
157
     *
158
     * @return array
159
     */
160
    public function getExcludes(): array
161
    {
162
        return $this->excludes;
163
    }
164
165
    /**
166
     * Parse Exclude String.
167
     *
168
     * @param array|string $excludes Array or csv string of resources to exclude
169
     *
170
     * @return $this
171
     */
172
    public function setExcludes($excludes)
173
    {
174
        $this->excludes = [];
175
176
        if (is_string($excludes)) {
177
            $excludes = explode(',', $excludes);
178
        }
179
180
        if (!is_array($excludes)) {
181
            throw new \InvalidArgumentException(
182
                'The parseExcludes() method expects a string or an array. ' . gettype($excludes) . ' given'
183
            );
184
        }
185
186
        foreach ($excludes as $excludeName) {
187
            $excludeName = $this->trimToAcceptableRecursionLevel($excludeName);
188
189
            if (in_array($excludeName, $this->excludes)) {
190
                continue;
191
            }
192
193
            $this->excludes[] = $excludeName;
194
        }
195
196
        return $this;
197
    }
198
199
    /*******************************************
200
     * FIELDS
201
     *******************************************/
202
203
    /**
204
     * Parse field parameter.
205
     *
206
     * @param array $fields Array of fields to include. It must be an array
207
     *                         whose keys are resource types and values a string
208
     *                         of the fields to return, separated by a comma
209
     *
210
     * @return $this
211
     */
212
    public function setFields(array $fields)
213
    {
214
        $this->fields = [];
215
216
        foreach ($fields as $type => $field) {
217
            //Remove empty and repeated fields
218
            $this->fields[$type] = array_unique(array_filter(explode(',', $field)));
219
        }
220
221
        return $this;
222
    }
223
224
    /**
225
     * Get requested fields.
226
     *
227
     * @return array
228
     */
229
    public function getFields(): array
230
    {
231
        return $this->fields;
232
    }
233
234
    /**
235
     * Get field params for the specified type.
236
     *
237
     * @param string $type
238
     *
239
     * @return ParamBag|null
240
     */
241
    public function getField($type)
242
    {
243
        return !isset($this->fields[$type]) ?
244
            null :
245
            new ParamBag($this->fields[$type]);
246
    }
247
}
248