Passed
Push — ft/mediagallery-existing-asset... ( d90314...381209 )
by Philippe
08:44
created

SetReference::parameters()   B

Complexity

Conditions 8
Paths 33

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 8.064

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 13
dl 0
loc 22
ccs 9
cts 10
cp 0.9
rs 8.4444
c 2
b 1
f 0
cc 8
nc 33
nop 3
crap 8.064
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Thinktomorrow\Chief\Sets;
6
7
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
8
use Illuminate\Contracts\Pagination\Paginator;
9
use Illuminate\Http\Request;
10
use Illuminate\Support\Str;
11
use Illuminate\Support\Collection;
12
use Thinktomorrow\Chief\FlatReferences\FlatReference;
13
use Thinktomorrow\Chief\FlatReferences\ProvidesFlatReference;
14
use Thinktomorrow\Chief\Relations\ActsAsParent;
15
16
class SetReference implements ProvidesFlatReference
17
{
18
    /** @var string */
19
    private $key;
20
21
    /** @var string */
22
    private $action;
23
24
    /** @var array */
25
    private $parameters;
26 16
27
    /** @var string */
28 16
    private $label;
29 16
30 16
    public function __construct(string $key, string $action, array $parameters = [], string $label = null)
31 16
    {
32 16
        $this->key = $key;
33
        $this->action = $action;
34 8
        $this->parameters = $parameters;
35
        $this->label = $label;
36
    }
37 8
38
    public static function fromArray(string $key, array $values): SetReference
39
    {
40
        // Constraints
41 8
        if (!isset($values['action'])) {
42 8
            throw new \InvalidArgumentException('Set reference array is missing required values for the "action" keys. Given: ' . print_r($values, true));
43 8
        }
44 8
45 8
        return new static(
46
            $key,
47
            $values['action'],
48
            $values['parameters'] ?? [],
49 54
            $values['label'] ?? null
50
        );
51 54
    }
52
53
    public static function all(): Collection
54 8
    {
55 54
        $sets = config('thinktomorrow.chief.sets', []);
56
57
        return collect($sets)->map(function ($set, $key) {
58 3
            return SetReference::fromArray($key, $set);
59
        });
60
    }
61 3
62 3
    public static function find($key): ?SetReference
63
    {
64
        return static::all()->filter(function ($ref) use ($key) {
65
            return $ref->key() == $key;
66
        })->first();
67
    }
68
69
    /**
70 8
     * Run the query and collect the resulting items into a GenericSet object.
71
     *
72
     * @return Set
73 8
     */
74
    public function toSet(ActsAsParent $parent): Set
75 8
    {
76
        // Reconstitute the action - optional @ ->defaults to the name of the set e.g. @upcoming
77 6
        list($class, $method) = $this->parseAction($this->action, Str::camel($this->key));
78
79 6
        $this->validateAction($class, $method);
80
81
        $result = call_user_func_array([app($class),$method], $this->parameters($class, $method, $parent));
82
83 6
        if (! $result instanceof Set && $result instanceof Collection) {
84
            return new Set($result->all(), $this->key);
85
        }
86 9
87
        if (! $result instanceof Set && $result instanceof Paginator) {
88 9
            return new Set($result->all(), $this->key, [
0 ignored issues
show
Bug introduced by
The method all() does not exist on Illuminate\Contracts\Pagination\Paginator. It seems like you code against a sub-type of said class. However, the method does not exist in Illuminate\Contracts\Pag...on\LengthAwarePaginator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
            return new Set($result->/** @scrutinizer ignore-call */ all(), $this->key, [
Loading history...
89 9
                'paginate' => [
90 9
                    'total' => $result->total(),
91 9
                    'perPage' => $result->perPage(),
92
                ]
93
            ]);
94
        }
95 8
96
        return $result;
97 8
    }
98
99
    /**
100 8
     * Only pass the extra parameters when they are expected, otherwise this will conflict with any
101
     * base eloquent methods such as all() which have a fixed columns parameter.
102 8
     *
103 8
     * @param ActsAsParent $parent
104
     */
105
    protected function parameters(string $class, string $method, ActsAsParent $parent): array
106
    {
107
        try {
108
            $parameters = $this->parameters;
109 8
110
            $reflection = new \ReflectionClass($class);
111 8
            foreach ($reflection->getMethod($method)->getParameters() as $parameter) {
112 1
                if ($parameter->getType() && $parameter->getType()->getName() == ActsAsParent::class) {
113
                    $parameters[] = $parent;
114
                }
115 7
                if ($parameter->getType() && $parameter->getType()->getName() == Request::class) {
116 1
                    $parameters[] = request();
117
                }
118 6
            }
119
120 1
            return $parameters;
121
        } catch (\Exception $e) {
122 1
            if (config('thinktomorrow.chief.strict')) {
123
                throw $e;
124
            }
125 4
126
            return $this->parameters;
127 4
        }
128
    }
129
130 3
    public function store()
131
    {
132 3
        return StoredSetReference::create([
133
            'key'        => $this->key,
134
            'action'     => $this->action,
135
            'parameters' => $this->parameters,
136
        ]);
137
    }
138
139
    public function key()
140
    {
141
        return $this->key;
142
    }
143
144
    private static function parseAction($action, $default_method = '__invoke'): array
145
    {
146
        if (false !== strpos($action, '@')) {
147
            return explode('@', $action);
148
        }
149
150
        return [$action, $default_method];
151
    }
152
153
    private static function validateAction($class, $method)
154
    {
155
        if (! class_exists($class)) {
156
            throw new \InvalidArgumentException('The class ['.$class.'] isn\'t a valid class reference or does not exist in the chief-settings.sets config entry.');
157
        }
158
159
        if (!method_exists($class, $method)) {
160
            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.');
161
        }
162
    }
163
164
    public function flatReference(): FlatReference
165
    {
166
        return new FlatReference(static::class, $this->key);
167
    }
168
169
    public function flatReferenceLabel(): string
170
    {
171
        return $this->label ?? $this->key;
172
    }
173
174
    public function flatReferenceGroup(): string
175
    {
176
        return 'set';
177
    }
178
}
179