Completed
Push — master ( 7b85f5...35d881 )
by Arthur
02:39
created

ResolvesValidation::parentRules()   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 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
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 50
    public function parentRules(){
28 50
        return [];
29
    }
30
31 50
    public function buildRules()
32
    {
33 50
        $rules = [];
34 50
        foreach (array_merge($this->parentRules(), $this->rules()) as $key => $rule) {
35 19
            if ($rule instanceof Attribute) {
36 6
                $rule = $rule->getRules();
37
            }
38 19
            $rules[$key] = $rule;
39
        }
40
41 50
        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

41
        foreach ($this->/** @scrutinizer ignore-call */ includes() as $key => $included) {
Loading history...
42 2
            if (! array_key_exists($key, $rules)) {
43 1
                $rules[$key] = 'required';
44
            }
45
        }
46
47 50
        return $rules;
48
    }
49
50 50
    public function passesValidation()
51
    {
52 50
        return $this->getValidatorInstance()->passes();
53
    }
54
55 50
    public function setValidator(Validator $validator)
56
    {
57 50
        $this->validator = $validator;
58
59 50
        return $this;
60
    }
61
62 45
    public function validated(bool $recursive = true)
63
    {
64 45
        return $recursive ? $this->filterRulesRecursively($this->validator->validated()) : $this->validator->validated();
65
    }
66
67 45
    protected function filterRulesRecursively(array $data)
68
    {
69
        //Dot notation makes it possible to parse nested values without recursion
70 45
        $original = Arr::dot($data);
71
72 45
        $filtered = [];
73 45
        $rules = collect($this->buildRules());
74 45
        $keys = $rules->keys();
75
        $rules->each(function ($rules, $key) use ($original, $keys, &$filtered) {
76
            //Allow for array or pipe-delimited rule-sets
77 15
            if (is_string($rules)) {
78 10
                $rules = explode('|', $rules);
79
            }
80
            //In case a rule requires an element to be an array, look for nested rules
81
            $nestedRules = $keys->filter(function ($otherKey) use ($key) {
82 15
                return strpos($otherKey, "$key.") === 0;
83 15
            });
84
            //If the input must be an array, default missing nested rules to a wildcard
85 15
            if (in_array('array', $rules) && $nestedRules->isEmpty()) {
86
                $key .= '.*';
87
            }
88
89 15
            foreach ($original as $dotIndex => $element) {
90
                //fnmatch respects wildcard asterisks
91 12
                if (fnmatch($key, $dotIndex)) {
92
                    //array_set respects dot-notation, building out a normal array
93 12
                    array_set($filtered, $dotIndex, $element);
0 ignored issues
show
Deprecated Code introduced by
The function array_set() has been deprecated: Arr::set() should be used directly instead. Will be removed in Laravel 5.9. ( Ignorable by Annotation )

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

93
                    /** @scrutinizer ignore-deprecated */ array_set($filtered, $dotIndex, $element);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
94
                }
95
            }
96 45
        });
97
98 45
        return $filtered;
99
    }
100
101 38
    public function rules()
102
    {
103 38
        return [];
104
    }
105
106 49
    public function messages()
107
    {
108 49
        return [];
109
    }
110
111 49
    public function attributes()
112
    {
113 49
        return [];
114
    }
115
116 48
    protected function resolveValidation()
117
    {
118 48
        if (! $this->passesValidation()) {
119 5
            $this->failedValidation();
120
        }
121
122 44
        return $this;
123
    }
124
125 50
    protected function getValidatorInstance()
126
    {
127 50
        if ($this->validator) {
128 3
            return $this->validator;
129
        }
130
131 50
        $factory = app(ValidationFactory::class);
132
133 50
        $validator = method_exists($this, 'validator')
134 1
            ? $this->validator($factory)
135 50
            : $this->createDefaultValidator($factory);
136
137 50
        if (method_exists($this, 'withValidator')) {
138 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

138
            $this->/** @scrutinizer ignore-call */ 
139
                   resolveAndCall($this, 'withValidator', compact('validator'));
Loading history...
139
        }
140
141 50
        if (method_exists($this, 'afterValidator')) {
142
            $validator->after(function ($validator) {
143 1
                $this->resolveAndCall($this, 'afterValidator', compact('validator'));
144 1
            });
145
        }
146
147 50
        $this->setValidator($validator);
148
149 50
        return $this->validator;
150
    }
151
152 49
    protected function createDefaultValidator(ValidationFactory $factory)
153
    {
154 49
        return $factory->make(
155 49
            $this->validationData(), $this->buildRules(),
156 49
            $this->messages(), $this->attributes()
157
        );
158
    }
159
160 5
    protected function failedValidation()
161
    {
162 5
        throw (new ValidationException($this->validator))
163 5
            ->errorBag($this->errorBag)
164 5
            ->redirectTo($this->getRedirectUrl());
165
    }
166
167 5
    protected function getRedirectUrl()
168
    {
169 5
        return redirect()->getUrlGenerator()->previous();
170
    }
171
172 49
    protected function validationData()
173
    {
174 49
        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

174
        return $this->/** @scrutinizer ignore-call */ all();
Loading history...
175
    }
176
}
177