Completed
Push — master ( b97c78...14a532 )
by
unknown
17:16
created

MutationHandler::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Mindtwo\DynamicMutators\Handler;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Collection;
7
use Mindtwo\DynamicMutators\Exceptions\DynamicMutatorNotCallableException;
8
use Mindtwo\DynamicMutators\Exceptions\DynamicMutatorNotDefinedException;
9
use Mindtwo\DynamicMutators\Interfaces\MutationHandlerInterface;
10
11
class MutationHandler implements MutationHandlerInterface
12
{
13
    /**
14
     * Mutator name.
15
     *
16
     * @var string
17
     */
18
    protected $name;
19
20
    /**
21
     * Related model.
22
     *
23
     * @var Model
24
     */
25
    protected $model;
26
27
    /**
28
     * Mutator settings.
29
     *
30
     * @var array
31
     */
32
    protected $mutators = [];
33
34
    /**
35
     * Mutation handler constructor.
36
     *
37
     * @param string $name
38
     */
39
    public function __construct(string $name, array $getMutator = [], array $setMutator = [])
40
    {
41
        $this->name = $name;
42
43
        if (count($getMutator) > 0) {
44
            $this->registerGetMutator(...$getMutator);
45
        }
46
47
        if (count($setMutator) > 0) {
48
            $this->registerSetMutator(...$setMutator);
49
        }
50
    }
51
52
    /**
53
     * Set related model.
54
     *
55
     * @param $model
56
     *
57
     * @return MutationHandler
58
     */
59
    public function setModel(&$model): self
60
    {
61
        $this->model = $model;
62
63
        return $this;
64
    }
65
66
    /**
67
     * Get mutation handler name.
68
     *
69
     * @return string
70
     */
71
    public function getName(): string
72
    {
73
        return $this->name;
74
    }
75
76
    /**
77
     * Get mutator config.
78
     *
79
     * @param string $operator
80
     * @param string $key
81
     *
82
     * @return mixed
83
     */
84
    protected function config(string $operator, string $key = null)
85
    {
86
        if (isset($this->mutators[$operator])) {
87
            return is_null($key) ? $this->mutators[$operator] : $this->mutators[$operator][$key];
88
        }
89
    }
90
91
    /**
92
     * Register mutator.
93
     *
94
     * @param string          $operator
95
     * @param callable|string $callable
96
     * @param bool            $stack
97
     * @param string|null     $property
98
     *
99
     * @return MutationHandler
100
     */
101
    protected function registerMutator(string $operator, $callable, bool $stack = false, string $property = null): self
102
    {
103
        $this->mutators[$operator] = [
104
            'callable' => $callable,
105
            'stack'    => $stack,
106
            'property' => $property ?? $this->name,
107
        ];
108
109
        return $this;
110
    }
111
112
    /**
113
     * Register set mutator.
114
     *
115
     * @param callable|string $callable
116
     * @param bool            $stack
117
     * @param string|null     $property
118
     *
119
     * @return MutationHandler
120
     */
121
    public function registerSetMutator($callable, bool $stack = false, string $property = null): self
122
    {
123
        return $this->registerMutator(self::OPERATOR_SET, $callable, $stack, $property);
124
    }
125
126
    /**
127
     * Register get mutator.
128
     *
129
     * @param callable|string $callable
130
     * @param bool            $stack
131
     * @param string|null     $property
132
     *
133
     * @return MutationHandler
134
     */
135
    public function registerGetMutator($callable, bool $stack = false, string $property = null): self
136
    {
137
        return $this->registerMutator(self::OPERATOR_GET, $callable, $stack, $property);
138
    }
139
140
    /**
141
     * Return a valid mutator name or throw an exceptions.
142
     *
143
     * @param string $name
144
     * @param string $operator
145
     *
146
     * @throws DynamicMutatorNotDefinedException
147
     *
148
     * @return string
149
     */
150
    protected function mutatorNameOrFail(string $name, string $operator): string
151
    {
152
        if (! $this->hasMutator($name, $operator)) {
153
            throw new DynamicMutatorNotDefinedException('Mutator not defined!', 0, null, [
154
                'name'     => $name,
155
                'operator' => $operator,
156
                'handler'  => $this->getName(),
157
            ]);
158
        }
159
160
        return $name;
161
    }
162
163
    /**
164
     * Get callable or throw an exception.
165
     *
166
     * @param $callable
167
     *
168
     * @throws DynamicMutatorNotCallableException
169
     *
170
     * @return callable
171
     */
172
    protected function callableOrFail(string $operator): callable
173
    {
174
        $callable = $this->config($operator, 'callable');
175
176
        if (is_string($callable) && method_exists($this->model, $callable)) {
177
            return [$this->model, $callable];
178
        }
179
180
        if (is_callable($callable)) {
181
            return $callable;
182
        }
183
184
        throw new DynamicMutatorNotCallableException('The given callable is invalid!', 0, null, [
185
            'callable' => $callable,
186
            'handler'  => $this->getName(),
187
        ]);
188
    }
189
190
    /**
191
     * Determinate if a mutator exists.
192
     *
193
     * @param string $name
194
     * @param string $operator
195
     *
196
     * @return bool
197
     */
198
    protected function hasMutator(string $name, string $operator): bool
199
    {
200
        return isset($this->mutators[$operator])
201
            && $this->getMutatorProperties($operator)->has($name);
202
    }
203
204
    /**
205
     * Determinate if a get mutator exists.
206
     *
207
     * @param string $name
208
     *
209
     * @return bool
210
     */
211
    public function hasGetMutator(string $name): bool
212
    {
213
        return $this->hasMutator($name, self::OPERATOR_GET);
214
    }
215
216
    /**
217
     * Determinate if a set mutator exists.
218
     *
219
     * @param string $name
220
     *
221
     * @return bool
222
     */
223
    public function hasSetMutator(string $name): bool
224
    {
225
        return $this->hasMutator($name, self::OPERATOR_SET);
226
    }
227
228
    protected function getMutatorProperties(string $operator): Collection
229
    {
230
        return collect($this->model->{$this->config($operator, 'property')} ?? []);
231
    }
232
233
    public function callGetMutator(string $name)
234
    {
235
        $name = $this->mutatorNameOrFail($name, self::OPERATOR_GET);
236
        $callable = $this->callableOrFail(self::OPERATOR_GET);
237
238
        return call_user_func_array($callable, [
239
            $name,
240
            $this->getMutatorProperties(self::OPERATOR_GET)->get($name),
241
        ]);
242
    }
243
244
    public function callSetMutator(string $name, $value)
245
    {
246
        $name = $this->mutatorNameOrFail($name, self::OPERATOR_SET);
247
        $callable = $this->callableOrFail(self::OPERATOR_SET);
248
249
        return call_user_func_array($callable, [
250
            $name,
251
            $value,
252
            $this->getMutatorProperties(self::OPERATOR_SET)->get($name),
253
        ]);
254
    }
255
256
    /**
257
     * Determinate if the next mutator should be called.
258
     *
259
     * @param $operator
260
     *
261
     * @return bool
262
     */
263
    public function shouldStack($operator): bool
264
    {
265
        return $this->config($operator, 'stack');
266
    }
267
}
268