Passed
Push — master ( 2915de...908b7b )
by Arthur
03:36
created

ResolvesValidation::setValidatorInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 2
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Larapie\Actions\Concerns;
4
5
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
6
use Illuminate\Support\Arr;
7
use Illuminate\Validation\ValidationException;
8
use Illuminate\Validation\Validator;
9
use Larapie\Actions\Attribute;
10
11
trait ResolvesValidation
12
{
13
    protected $errorBag = 'default';
14
15
    /**
16
     * @var Validator
17
     */
18
    protected $validator;
19
20 1
    public function validate($rules = [], $messages = [], $customAttributes = [])
21
    {
22 1
        return app(ValidationFactory::class)
23 1
            ->make($this->validationData(), $rules, $messages, $customAttributes)
24 1
            ->validate();
25
    }
26
27 53
    public function parentRules()
28
    {
29 53
        return [];
30
    }
31
32 53
    public function buildRules()
33
    {
34 53
        $rules = [];
35 53
        foreach (array_merge($this->parentRules(), $this->rules()) as $key => $rule) {
36 22
            if ($rule instanceof Attribute) {
37 9
                $rule = $rule->getRules();
38
            }
39 22
            $rules[$key] = $rule;
40
        }
41
42 53
        foreach ($this->includes() as $key => $included) {
0 ignored issues
show
Bug introduced by
It seems like includes() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

42
        foreach ($this->/** @scrutinizer ignore-call */ includes() as $key => $included) {
Loading history...
43 2
            if (! array_key_exists($key, $rules)) {
44 1
                $rules[$key] = 'required';
45
            }
46
        }
47
48 53
        return $rules;
49
    }
50
51 53
    public function passesValidation()
52
    {
53 53
        return $this->getValidatorInstance()->passes();
54
    }
55
56 53
    public function setValidator(Validator $validator)
57
    {
58 53
        $this->validator = $validator;
59
60 53
        return $this;
61
    }
62
63 12
    public function validated(bool $recursive = true)
64
    {
65 12
        $data = $this->validator->validated();
66
67 12
        return array_merge($recursive ? $this->filterRulesRecursively($data) : $data, $this->includes());
68
    }
69
70 11
    protected function filterRulesRecursively(array $data)
71
    {
72
        //Dot notation makes it possible to parse nested values without recursion
73 11
        $original = Arr::dot($data);
74
75 11
        $filtered = [];
76 11
        $rules = collect($this->buildRules());
77 11
        $keys = $rules->keys();
78
        $rules->each(function ($rules, $key) use ($original, $keys, &$filtered) {
79
            //Allow for array or pipe-delimited rule-sets
80 11
            if (is_string($rules)) {
81 3
                $rules = explode('|', $rules);
82
            }
83
            //In case a rule requires an element to be an array, look for nested rules
84
            $nestedRules = $keys->filter(function ($otherKey) use ($key) {
85 11
                return strpos($otherKey, "$key.") === 0;
86 11
            });
87
            //If the input must be an array, default missing nested rules to a wildcard
88 11
            if (in_array('array', $rules) && $nestedRules->isEmpty()) {
89 1
                $key .= '.*';
90
            }
91
92 11
            foreach ($original as $dotIndex => $element) {
93
                //fnmatch respects wildcard asterisks
94 11
                if (fnmatch($key, $dotIndex)) {
95
                    //array_set respects dot-notation, building out a normal array
96 11
                    Arr::set($filtered, $dotIndex, $element);
97
                }
98
            }
99 11
        });
100
101 11
        return $filtered;
102
    }
103
104 51
    public function rules()
105
    {
106 51
        return [];
107
    }
108
109 52
    public function messages()
110
    {
111 52
        return [];
112
    }
113
114 52
    public function attributes()
115
    {
116 52
        return [];
117
    }
118
119 51
    protected function resolveValidation()
120
    {
121 51
        if (! $this->passesValidation()) {
122 6
            $this->failedValidation();
123
        }
124
125 47
        return $this;
126
    }
127
128 51
    protected function setValidatorInstance($validator){
129 51
        $this->validator = $validator;
130 51
    }
131
132 53
    protected function getValidatorInstance()
133
    {
134 53
        if ($this->validator) {
135
            return $this->validator;
136
        }
137
138 53
        $factory = app(ValidationFactory::class);
139
140 53
        $validator = method_exists($this, 'validator')
141 1
            ? $this->validator($factory)
142 53
            : $this->createDefaultValidator($factory);
143
144 53
        if (method_exists($this, 'withValidator')) {
145 1
            $this->resolveAndCall($this, 'withValidator', compact('validator'));
0 ignored issues
show
Bug introduced by
It seems like resolveAndCall() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

145
            $this->/** @scrutinizer ignore-call */ 
146
                   resolveAndCall($this, 'withValidator', compact('validator'));
Loading history...
146
        }
147
148 53
        if (method_exists($this, 'afterValidator')) {
149
            $validator->after(function ($validator) {
150 1
                $this->resolveAndCall($this, 'afterValidator', compact('validator'));
151 1
            });
152
        }
153
154 53
        $this->setValidator($validator);
155
156 53
        return $this->validator;
157
    }
158
159 52
    protected function createDefaultValidator(ValidationFactory $factory)
160
    {
161 52
        return $factory->make(
162 52
            $this->validationData(), $this->buildRules(),
163 52
            $this->messages(), $this->attributes()
164
        );
165
    }
166
167 6
    protected function failedValidation()
168
    {
169 6
        throw (new ValidationException($this->validator))
170 6
            ->errorBag($this->errorBag)
171 6
            ->redirectTo($this->getRedirectUrl());
172
    }
173
174 6
    protected function getRedirectUrl()
175
    {
176 6
        return redirect()->getUrlGenerator()->previous();
177
    }
178
179 52
    protected function validationData()
180
    {
181 52
        return $this->all();
0 ignored issues
show
Bug introduced by
It seems like all() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

181
        return $this->/** @scrutinizer ignore-call */ all();
Loading history...
182
    }
183
}
184