Completed
Branch develop (01c1b0)
by Pavel
02:03
created

Caster::cast()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 1
1
<?php
2
3
namespace Koch\Casters;
4
5
use Closure;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Collection;
8
use Koch\Casters\Behavior\BuildsCastQueries;
9
use Koch\Casters\Contracts\Caster as CasterContract;
10
11
abstract class Caster implements CasterContract
12
{
13
    use BuildsCastQueries;
14
15
    /**
16
     * Determines the function sign.
17
     *
18
     * @var string
19
     */
20
    private $functionSign = '@';
21
22
    /**
23
     * Determines the query sign.
24
     *
25
     * @var string
26
     */
27
    private $querySign = '!';
28
29
    /**
30
     * Casts collection fields.
31
     *
32
     * @param  mixed  $model
33
     * @return array
34
     */
35
    public function cast($model)
36
    {
37
        if ($model instanceof Collection) {
38
            return $model->map([$this, 'cast'])->toArray();
39
        }
40
41
        if (empty($model)) {
42
            return;
43
        }
44
45
        $transformed = [];
46
        
47
        foreach ($this->castRules() as $old => $desired) {
48
            $this->resolveCast($old, $desired, $model, $transformed);
49
        }
50
51
        return $transformed;
52
    }
53
54
    /**
55
     * Resolves casts based on supplied array of arguments.
56
     *
57
     * @param  string  $old
58
     * @param  string|Closure  $desired
59
     * @param  \Illuminate\Database\Eloquent\Model  $model
60
     * @param  array  &$transformed
61
     * @return array
62
     */
63
    private function resolveCast($old, $desired, Model $model, &$transformed)
64
    {
65
        // If there was a closure provided as a value of the array
66
        // run that closure and return it as a result of casting.
67
        if ($desired instanceof Closure) {
68
            return $transformed[$old] = call_user_func($desired, $model);
69
        }
70
71
        // If the value was prefixed with the function sign, which
72
        // is '@' by default, call desired method on this class.
73
        if (is_string($desired) && strpos($desired, $this->functionSign) !== false) {
74
            return $transformed[$old] = call_user_func([$this, substr($desired, 1)], $model);
75
        }
76
77
        // If it was prefixed with the query sign, which
78
        // is '!' by default, make use of the CastBuilder instance
79
        // and resolve the cast there.
80
        if (is_string($desired) && strpos($desired, $this->querySign) !== false) {
81
            return $this->parse($old, substr($desired, 1), $model, $transformed);
82
        }
83
84
        // If they specified simple key - value string pairs, simply
85
        // rename the column, retaining the contents.
86
        if (is_string($old)) {
87
            return $transformed[$desired] = $model->$old;
88
        }
89
90
        // Otherwise keep unchanged.
91
        return $transformed[$desired] = $model->$desired;
92
    }
93
94
    /**
95
     * Returns the cast rules.
96
     *
97
     * @return array
98
     */
99
    abstract protected function castRules();
100
}
101