Passed
Push — master ( a01295...bde225 )
by Jodie
02:13
created

AbstractResource::isValidSerializer()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
nop 1
1
<?php
2
3
namespace Rexlabs\Smokescreen\Resource;
4
5
use Rexlabs\Smokescreen\Exception\InvalidSerializerException;
6
use Rexlabs\Smokescreen\Exception\InvalidTransformerException;
7
use Rexlabs\Smokescreen\Serializer\SerializerInterface;
8
use Rexlabs\Smokescreen\Transformer\TransformerInterface;
9
10
abstract class AbstractResource implements ResourceInterface
11
{
12
    /**
13
     * The data to process with the transformer.
14
     *
15
     * @var array|\ArrayIterator|mixed
16
     */
17
    protected $data;
18
19
    /**
20
     * Array of meta data.
21
     *
22
     * @var array
23
     */
24
    protected $meta = [];
25
26
    /**
27
     * The resource key.
28
     *
29
     * @var string
30
     */
31
    protected $resourceKey;
32
33
    /**
34
     * A transformer or callable to process the data attached to this resource.
35
     *
36
     * @var callable|TransformerInterface|null
37
     */
38
    protected $transformer;
39
40
    /**
41
     * Provide a custom serializer for this resource.
42
     *
43
     * @var callable|SerializerInterface|null
44
     */
45
    protected $serializer;
46
47
    /**
48
     * Create a new resource instance.
49
     *
50
     * @param mixed                              $data
51
     * @param callable|TransformerInterface|null $transformer
52
     * @param string                             $resourceKey
53
     *
54
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
55
     */
56
    public function __construct($data = null, $transformer = null, $resourceKey = null)
57
    {
58
        $this->setData($data);
59
        $this->setTransformer($transformer);
60
        $this->setResourceKey($resourceKey);
61
    }
62
63
    /**
64
     * Get the data.
65
     *
66
     * @return mixed
67
     */
68
    public function getData()
69
    {
70
        return $this->data;
71
    }
72
73
    /**
74
     * Set the data.
75
     *
76
     * @param mixed $data
77
     *
78
     * @return $this
79
     */
80
    public function setData($data)
81
    {
82
        $this->data = $data;
83
84
        return $this;
85
    }
86
87
    /**
88
     * Get the meta data.
89
     *
90
     * @return array
91
     */
92
    public function getMeta()
93
    {
94
        return $this->meta;
95
    }
96
97
    /**
98
     * Set the meta data.
99
     *
100
     * @param array $meta
101
     *
102
     * @return $this
103
     */
104
    public function setMeta(array $meta)
105
    {
106
        $this->meta = $meta;
107
108
        return $this;
109
    }
110
111
    /**
112
     * Get the meta data.
113
     *
114
     * @param string $metaKey
115
     *
116
     * @return array
117
     */
118
    public function getMetaValue($metaKey)
119
    {
120
        return $this->meta[$metaKey];
121
    }
122
123
    /**
124
     * Get the resource key.
125
     *
126
     * @return string|null
127
     */
128
    public function getResourceKey()
129
    {
130
        return $this->resourceKey;
131
    }
132
133
    /**
134
     * Set the resource key.
135
     *
136
     * @param string|null $resourceKey
137
     *
138
     * @return $this
139
     */
140
    public function setResourceKey($resourceKey)
141
    {
142
        $this->resourceKey = $resourceKey;
143
144
        return $this;
145
    }
146
147
    /**
148
     * Set the meta data.
149
     *
150
     * @param string $metaKey
151
     * @param mixed  $metaValue
152
     *
153
     * @return $this
154
     */
155
    public function setMetaValue(string $metaKey, $metaValue)
156
    {
157
        $this->meta[$metaKey] = $metaValue;
158
159
        return $this;
160
    }
161
162
    /**
163
     * Get a list of relationships from the transformer
164
     * Only applicable when the transformer is an instance of the TransformerInterface (eg. AbstractTransformer)
165
     * @return array
166
     */
167
    public function getRelationships(): array
168
    {
169
        $relationships = [];
170
        if ($this->hasTransformer()) {
171
            if (($transformer = $this->getTransformer()) instanceof TransformerInterface) {
172
                $relationships = $transformer->getRelationships();
173
            }
174
        }
175
176
        return $relationships;
177
    }
178
179
    /**
180
     * @return boolean
181
     */
182
    public function hasTransformer(): bool
183
    {
184
        return $this->transformer !== null;
185
    }
186
187
    /**
188
     * Get the transformer.
189
     *
190
     * @return callable|TransformerInterface|null
191
     */
192
    public function getTransformer()
193
    {
194
        return $this->transformer;
195
    }
196
197
    /**
198
     * Set the transformer.
199
     *
200
     * @param callable|TransformerInterface|null $transformer
201
     *
202
     * @return $this
203
     * @throws InvalidTransformerException
204
     */
205
    public function setTransformer($transformer)
206
    {
207
        if ($transformer !== null) {
208
            if (!$this->isValidTransformer($transformer)) {
209
                throw new InvalidTransformerException('Transformer must be a callable or implement TransformerInterface');
210
            }
211
        }
212
213
        $this->transformer = $transformer;
214
215
        return $this;
216
    }
217
218
    /**
219
     * Determines if the given argument is a valid transformer.
220
     * @param mixed $transformer
221
     *
222
     * @return bool
223
     */
224
    public function isValidTransformer($transformer): bool
225
    {
226
        if ($transformer instanceof TransformerInterface && method_exists($transformer, 'transform')) {
227
            return true;
228
        }
229
230
        if (\is_callable($transformer)) {
231
            return true;
232
        }
233
234
        return false;
235
    }
236
237
    /**
238
     * @return boolean
239
     */
240
    public function hasSerializer(): bool
241
    {
242
        return $this->serializer !== null;
243
    }
244
245
    /**
246
     * @return callable|SerializerInterface|false|null
247
     */
248
    public function getSerializer()
249
    {
250
        return $this->serializer;
251
    }
252
253
    /**
254
     * Sets a custom serializer to be used for this resource
255
     * - Usually you will set this to an instance of SerializerInterface.
256
     * - Set to false to force no serialization on this resource.
257
     * - When set to null the default serializer will be used.
258
     * - Optionally set a closure/callback to be used for serialization.
259
     *
260
     * @param callable|SerializerInterface|false|null $serializer
261
     * @throws InvalidSerializerException
262
     * @return $this
263
     */
264
    public function setSerializer($serializer)
265
    {
266
        if ($serializer !== null) {
267
            if (!$this->isValidSerializer($serializer)) {
268
                throw new InvalidSerializerException('Serializer must be one of: callable, SerializerInterface, false or null');
269
            }
270
        }
271
        $this->serializer = $serializer;
0 ignored issues
show
Documentation Bug introduced by
It seems like $serializer can also be of type false. However, the property $serializer is declared as type null|callable|Rexlabs\Sm...zer\SerializerInterface. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
272
273
        return $this;
274
    }
275
276
    /**
277
     * @param mixed $serializer
278
     *
279
     * @return bool
280
     */
281
    public function isValidSerializer($serializer): bool
282
    {
283
        if ($serializer === false) {
284
            // False is a valid value (forces serialization to be off)
285
            return true;
286
        }
287
        if ($serializer instanceof SerializerInterface) {
288
            return true;
289
        }
290
        if (\is_callable($serializer)) {
291
            return true;
292
        }
293
294
        return false;
295
    }
296
}