Passed
Push — master ( e68f99...117087 )
by Ben
07:39
created

SetReference::parameters()   B

Complexity

Conditions 8
Paths 33

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 8.048

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 23
ccs 10
cts 11
cp 0.9091
rs 8.4444
cc 8
nc 33
nop 3
crap 8.048
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Thinktomorrow\Chief\Sets;
6
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Str;
9
use Illuminate\Support\Collection;
10
use Thinktomorrow\Chief\FlatReferences\FlatReference;
11
use Thinktomorrow\Chief\FlatReferences\ProvidesFlatReference;
12
use Thinktomorrow\Chief\Relations\ActsAsParent;
13
14
class SetReference implements ProvidesFlatReference
15
{
16
    /** @var string */
17
    private $key;
18
19
    /** @var string */
20
    private $action;
21
22
    /** @var array */
23
    private $parameters;
24
25
    /** @var string */
26 16
    private $label;
27
28 16
    public function __construct(string $key, string $action, array $parameters = [], string $label = null)
29 16
    {
30 16
        $this->key = $key;
31 16
        $this->action = $action;
32 16
        $this->parameters = $parameters;
33
        $this->label = $label;
34 8
    }
35
36
    public static function fromArray(string $key, array $values): SetReference
37 8
    {
38
        // Constraints
39
        if (!isset($values['action'])) {
40
            throw new \InvalidArgumentException('Set reference array is missing required values for the "action" keys. Given: ' . print_r($values, true));
41 8
        }
42 8
43 8
        return new static(
44 8
            $key,
45 8
            $values['action'],
46
            $values['parameters'] ?? [],
47
            $values['label'] ?? null
48
        );
49 54
    }
50
51 54
    public static function all(): Collection
52
    {
53
        $sets = config('thinktomorrow.chief.sets', []);
54 8
55 54
        return collect($sets)->map(function ($set, $key) {
56
            return SetReference::fromArray($key, $set);
57
        });
58 3
    }
59
60
    public static function find($key): ?SetReference
61 3
    {
62 3
        return static::all()->filter(function ($ref) use ($key) {
63
            return $ref->key() == $key;
64
        })->first();
65
    }
66
67
    /**
68
     * Run the query and collect the resulting items into a GenericSet object.
69
     *
70 8
     * @return Set
71
     */
72
    public function toSet(ActsAsParent $parent): Set
73 8
    {
74
        // Reconstitute the action - optional @ ->defaults to the name of the set e.g. @upcoming
75 8
        list($class, $method) = $this->parseAction($this->action, Str::camel($this->key));
76
77 6
        $this->validateAction($class, $method);
78
79 6
        $result = call_user_func_array([app($class),$method], $this->parameters($class, $method, $parent));
80
81
        if (! $result instanceof Set && $result instanceof Collection) {
82
            return new Set($result->all(), $this->key);
83 6
        }
84
85
        return $result;
86 9
    }
87
88 9
    /**
89 9
     * Only pass the extra parameters when they are expected, otherwise this will conflict with any
90 9
     * base eloquent methods such as all() which have a fixed columns parameter.
91 9
     *
92
     * @param ActsAsParent $parent
93
     */
94
    protected function parameters(string $class, string $method, ActsAsParent $parent): array
95 8
    {
96
        try{
97 8
            $parameters = $this->parameters;
98
99
            $reflection = new \ReflectionClass($class);
100 8
            foreach($reflection->getMethod($method)->getParameters() as $parameter){
101
                if($parameter->getType() && $parameter->getType()->getName() == ActsAsParent::class){
102 8
                    $parameters[] = $parent;
103 8
                }
104
                if($parameter->getType() && $parameter->getType()->getName() == Request::class){
105
                    $parameters[] = request();
106
                }
107
            }
108
109 8
            return $parameters;
110
        }
111 8
        catch(\Exception $e) {
112 1
            if (config('thinktomorrow.chief.strict')) {
113
                throw $e;
114
            }
115 7
116 1
            return $this->parameters;
117
        }
118 6
    }
119
120 1
    public function store()
121
    {
122 1
        return StoredSetReference::create([
123
            'key'        => $this->key,
124
            'action'     => $this->action,
125 4
            'parameters' => $this->parameters,
126
        ]);
127 4
    }
128
129
    public function key()
130 3
    {
131
        return $this->key;
132 3
    }
133
134
    private static function parseAction($action, $default_method = '__invoke'): array
135
    {
136
        if (false !== strpos($action, '@')) {
137
            return explode('@', $action);
138
        }
139
140
        return [$action, $default_method];
141
    }
142
143
    private static function validateAction($class, $method)
144
    {
145
        if (! class_exists($class)) {
146
            throw new \InvalidArgumentException('The class ['.$class.'] isn\'t a valid class reference or does not exist in the chief-settings.sets config entry.');
147
        }
148
149
        if (!method_exists($class, $method)) {
150
            throw new \InvalidArgumentException('The method ['.$method.'] does not exist on the class ['.$class.']. Make sure you provide a valid method to the action value in the chief-settings.sets config entry.');
151
        }
152
    }
153
154
    public function flatReference(): FlatReference
155
    {
156
        return new FlatReference(static::class, $this->key);
157
    }
158
159
    public function flatReferenceLabel(): string
160
    {
161
        return $this->label ?? $this->key;
162
    }
163
164
    public function flatReferenceGroup(): string
165
    {
166
        return 'set';
167
    }
168
}
169