Completed
Push — ft/states ( d9d02a...d4f7ca )
by Ben
45:58 queued 35:27
created

SetReference   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Test Coverage

Coverage 83.82%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 28
eloc 61
dl 0
loc 161
ccs 57
cts 68
cp 0.8382
rs 10
c 3
b 1
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A all() 0 6 1
A fromArray() 0 12 2
A flatReferenceGroup() 0 3 1
A parseAction() 0 7 2
A flatReference() 0 3 1
A store() 0 6 1
A validateAction() 0 8 3
A key() 0 3 1
A flatReferenceLabel() 0 3 1
A __construct() 0 6 1
A toSet() 0 23 5
B parameters() 0 22 8
A find() 0 5 1
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
27
    /** @var string */
28
    private $label;
29
30 16
    public function __construct(string $key, string $action, array $parameters = [], string $label = null)
31
    {
32 16
        $this->key = $key;
33 16
        $this->action = $action;
34 16
        $this->parameters = $parameters;
35 16
        $this->label = $label;
36 16
    }
37
38 8
    public static function fromArray(string $key, array $values): SetReference
39
    {
40
        // Constraints
41 8
        if (!isset($values['action'])) {
42
            throw new \InvalidArgumentException('Set reference array is missing required values for the "action" keys. Given: ' . print_r($values, true));
43
        }
44
45 8
        return new static(
46 8
            $key,
47 8
            $values['action'],
48 8
            $values['parameters'] ?? [],
49 8
            $values['label'] ?? null
50
        );
51
    }
52
53 54
    public static function all(): Collection
54
    {
55 54
        $sets = config('thinktomorrow.chief.sets', []);
56
57
        return collect($sets)->map(function ($set, $key) {
58 8
            return SetReference::fromArray($key, $set);
59 54
        });
60
    }
61
62 3
    public static function find($key): ?SetReference
63
    {
64
        return static::all()->filter(function ($ref) use ($key) {
65 3
            return $ref->key() == $key;
66 3
        })->first();
67
    }
68
69
    /**
70
     * Run the query and collect the resulting items into a GenericSet object.
71
     *
72
     * @return Set
73
     */
74 8
    public function toSet(ActsAsParent $parent): Set
75
    {
76
        // Reconstitute the action - optional @ ->defaults to the name of the set e.g. @upcoming
77 8
        list($class, $method) = $this->parseAction($this->action, Str::camel($this->key));
78
79 8
        $this->validateAction($class, $method);
80
81 6
        $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
87 6
        if (! $result instanceof Set && $result instanceof Paginator) {
88
            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
                'paginate' => [
90
                    'total' => $result->total(),
91
                    'perPage' => $result->perPage(),
92
                ]
93
            ]);
94
        }
95
96 6
        return $result;
97
    }
98
99
    /**
100
     * 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
     *
103
     * @param ActsAsParent $parent
104
     */
105 6
    protected function parameters(string $class, string $method, ActsAsParent $parent): array
106
    {
107
        try {
108 6
            $parameters = $this->parameters;
109
110 6
            $reflection = new \ReflectionClass($class);
111 6
            foreach ($reflection->getMethod($method)->getParameters() as $parameter) {
112 6
                if ($parameter->getType() && $parameter->getType()->getName() == ActsAsParent::class) {
113
                    $parameters[] = $parent;
114
                }
115 6
                if ($parameter->getType() && $parameter->getType()->getName() == Request::class) {
116 6
                    $parameters[] = request();
117
                }
118
            }
119
120 6
            return $parameters;
121
        } catch (\Exception $e) {
122
            if (config('thinktomorrow.chief.strict')) {
123
                throw $e;
124
            }
125
126
            return $this->parameters;
127
        }
128
    }
129
130 9
    public function store()
131
    {
132 9
        return StoredSetReference::create([
133 9
            'key'        => $this->key,
134 9
            'action'     => $this->action,
135 9
            'parameters' => $this->parameters,
136
        ]);
137
    }
138
139 8
    public function key()
140
    {
141 8
        return $this->key;
142
    }
143
144 8
    private static function parseAction($action, $default_method = '__invoke'): array
145
    {
146 8
        if (false !== strpos($action, '@')) {
147 8
            return explode('@', $action);
148
        }
149
150
        return [$action, $default_method];
151
    }
152
153 8
    private static function validateAction($class, $method)
154
    {
155 8
        if (! class_exists($class)) {
156 1
            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 7
        if (!method_exists($class, $method)) {
160 1
            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 6
    }
163
164 1
    public function flatReference(): FlatReference
165
    {
166 1
        return new FlatReference(static::class, $this->key);
167
    }
168
169 4
    public function flatReferenceLabel(): string
170
    {
171 4
        return $this->label ?? $this->key;
172
    }
173
174 3
    public function flatReferenceGroup(): string
175
    {
176 3
        return 'set';
177
    }
178
}
179