Completed
Pull Request — master (#11)
by Jodie
02:41
created

AbstractTransformer   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 90.48%

Importance

Changes 0
Metric Value
wmc 26
dl 0
loc 184
ccs 57
cts 63
cp 0.9048
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getCachedIncludeMap() 0 7 2
A getAvailableIncludes() 0 3 1
A item() 0 3 1
A getDefaultIncludes() 0 4 1
A collection() 0 3 1
A getDefaultProps() 0 3 1
A getRelationships() 0 7 2
C getIncludeMap() 0 62 17
1
<?php
2
3
namespace Rexlabs\Smokescreen\Transformer;
4
5
use Rexlabs\Smokescreen\Exception\ParseDefinitionException;
6
use Rexlabs\Smokescreen\Helpers\StrHelper;
7
use Rexlabs\Smokescreen\Resource\Collection;
8
use Rexlabs\Smokescreen\Resource\Item;
9
10
class AbstractTransformer implements TransformerInterface
11
{
12
//    protected $autoIncludes = true;
13
14
    /** @var array The list of available includes */
15
    protected $includes = [];
16
17
    /** @var array The default properties to return (if blank, all props from transform() are returned) */
18
    protected $defaultProps = [];
19
20
    /** @var null|array The $includes property is processed and turned into a map */
21
    protected $cachedIncludeMap;
22
23
//    protected $scope;
24
25
    /**
26
     * {@inheritdoc}
27
     *
28
     * @throws ParseDefinitionException
29
     */
30 8
    public function getAvailableIncludes(): array
31
    {
32 8
        return array_keys($this->getCachedIncludeMap());
33
    }
34
35
    /**
36
     * Return a cached version of the include map.
37
     *
38
     * @see AbstractTransformer::getIncludeMap()
39
     *
40
     * @throws ParseDefinitionException
41
     *
42
     * @return array
43
     */
44 9
    protected function getCachedIncludeMap(): array
45
    {
46 9
        if ($this->cachedIncludeMap === null) {
47 9
            $this->cachedIncludeMap = $this->getIncludeMap();
48
        }
49
50 9
        return $this->cachedIncludeMap;
51
    }
52
53
    /**
54
     * Process the $includes property and convert the directives into a map
55
     * indexed by the include key, and specifying: default, relation, method.
56
     *
57
     * @throws ParseDefinitionException
58
     *
59
     * @return array
60
     */
61 10
    public function getIncludeMap(): array
62
    {
63 10
        $map = [];
64
65 10
        foreach ($this->includes as $includeKey => $definition) {
66 9
            if (\is_int($includeKey)) {
67 5
                $includeKey = $definition;
68 5
                $definition = null;
69
            }
70
71 9
            $settings = [];
72 9
            if (!empty($definition)) {
73 6
                $parts = preg_split('/\s*\|\s*/', $definition);
74 6
                foreach ($parts as $part) {
75 6
                    if (!preg_match('/^([^:]+)(:(.+))?$/', $part, $match)) {
76 1
                        throw new ParseDefinitionException("Unable to parse field definition for '{$includeKey}''");
77
                    }
78
                    // If only list() was viable ...
79 5
                    $directive = $match[1];
80 5
                    $val = $match[3] ?? null;
81
                    switch ($directive) {
82 5
                        case 'default':
83 1
                            $settings['default'] = true;
84 1
                            break;
85 4
                        case 'relation':
86 2
                            $settings['relation'] = !empty($val) ?
87 2
                                preg_split('/s*,\s*/', $val) : [$includeKey];
88 2
                            break;
89 2
                        case 'method':
90 2
                            if (!empty($val)) {
91 2
                                $settings['method'] = $val;
92
                            }
93 2
                            break;
94
                        case 'item':
95
                            $settings['resource_type'] = 'item';
96
                            break;
97
                        case 'collection':
98
                            $settings['resource_type'] = 'collection';
99
                            break;
100
                        default:
101 5
                            throw new ParseDefinitionException("Invalid key '{$directive}' for {$includeKey}");
102
                    }
103
                }
104
            }
105
106 9
            if (!isset($settings['relation'])) {
107 7
                $settings['relation'] = [];
108
            }
109 9
            if (!isset($settings['method'])) {
110 7
                $settings['method'] = 'include'.StrHelper::studlyCase($includeKey);
111
            }
112 9
            if (!isset($settings['default'])) {
113 9
                $settings['default'] = false;
114
            }
115 9
            if (!isset($settings['resource_type'])) {
116 9
                $settings['resource_type'] = null;
117
            }
118
119 9
            $map[$includeKey] = $settings;
120
        }
121
122 9
        return $map;
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     *
128
     * @throws ParseDefinitionException
129
     */
130
    public function getDefaultIncludes(): array
131
    {
132 4
        return array_values(array_filter(array_keys($this->getCachedIncludeMap()), function ($includeKey) {
133 2
            return $this->getCachedIncludeMap()[$includeKey]['default'];
134 4
        }));
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     *
140
     * @throws ParseDefinitionException
141
     */
142 1
    public function getRelationships(): array
143
    {
144 1
        return array_column(
145 1
            array_filter(array_map(function ($includeKey, $settings) {
146 1
                return $settings['relation'] ? [$includeKey, $settings['relation']] : null;
147 1
            }, array_keys($this->getCachedIncludeMap()), array_values($this->getCachedIncludeMap()))),
148 1
            1, 0
149
        );
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 5
    public function getDefaultProps(): array
156
    {
157 5
        return $this->defaultProps;
158
    }
159
160
//    /**
161
//     * @inheritdoc
162
//     */
163
//    public function getScope(): Scope
164
//    {
165
//        return $this->scope;
166
//    }
167
168
    /**
169
     * Create a new Item resource.
170
     *
171
     * @param mixed       $data
172
     * @param mixed|null  $transformer
173
     * @param string|null $resourceKey
174
     *
175
     * @return Item
176
     */
177 1
    public function item($data, $transformer = null, $resourceKey = null): Item
178
    {
179 1
        return new Item($data, $transformer, $resourceKey);
180
    }
181
182
    /**
183
     * Create new Collection resource.
184
     *
185
     * @param mixed       $data
186
     * @param mixed|null  $transformer
187
     * @param string|null $resourceKey
188
     *
189
     * @return Collection
190
     */
191 1
    public function collection($data, $transformer = null, $resourceKey = null): Collection
192
    {
193 1
        return new Collection($data, $transformer, $resourceKey);
194
    }
195
}
196