FormRequest   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 225
rs 10
c 0
b 0
f 0
wmc 18

14 Methods

Rating   Name   Duplication   Size   Complexity  
A createDefaultValidator() 0 7 1
A attributes() 0 3 1
A messages() 0 3 1
A setRedirector() 0 5 1
A setContainer() 0 5 1
A formatErrors() 0 3 1
A response() 0 3 1
A getValidatorInstance() 0 15 3
A failedAuthorization() 0 3 1
A validationData() 0 3 1
A forbiddenResponse() 0 3 1
A validated() 0 7 2
A passesAuthorization() 0 7 2
A failedValidation() 0 4 1
1
<?php
2
3
namespace Noitran\Form\Http;
4
5
use Illuminate\Http\JsonResponse;
6
use Illuminate\Http\Request;
7
use Laravel\Lumen\Http\Redirector;
8
use Illuminate\Contracts\Container\Container;
9
use Illuminate\Contracts\Validation\Validator;
10
use Illuminate\Http\Exceptions\HttpResponseException;
11
use Illuminate\Auth\Access\AuthorizationException;
12
use Illuminate\Validation\ValidatesWhenResolvedTrait;
13
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
14
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
15
use Illuminate\Support\Str;
16
17
/**
18
 * Class FormRequest
19
 */
20
class FormRequest extends Request implements ValidatesWhenResolved
21
{
22
    use ValidatesWhenResolvedTrait;
23
24
    /**
25
     * The container instance.
26
     *
27
     * @var \Illuminate\Contracts\Container\Container
28
     */
29
    protected $container;
30
31
    /**
32
     * The redirector instance.
33
     *
34
     * @var \Laravel\Lumen\Http\Redirector
35
     */
36
    protected $redirector;
37
38
    /**
39
     * The URI to redirect to if validation fails.
40
     *
41
     * @var string
42
     */
43
    protected $redirect;
44
45
    /**
46
     * The route to redirect to if validation fails.
47
     *
48
     * @var string
49
     */
50
    protected $redirectRoute;
51
52
    /**
53
     * The controller action to redirect to if validation fails.
54
     *
55
     * @var string
56
     */
57
    protected $redirectAction;
58
59
    /**
60
     * The key to be used for the view error bag.
61
     *
62
     * @var string
63
     */
64
    protected $errorBag = 'default';
65
66
    /**
67
     * Get the validator instance for the request.
68
     *
69
     * @return \Illuminate\Contracts\Validation\Validator
70
     */
71
    protected function getValidatorInstance(): Validator
72
    {
73
        $factory = $this->container->make(ValidationFactory::class);
74
75
        if (method_exists($this, 'validator')) {
76
            $validator = $this->container->call([$this, 'validator'], compact('factory'));
77
        } else {
78
            $validator = $this->createDefaultValidator($factory);
79
        }
80
81
        if (method_exists($this, 'withValidator')) {
82
            $this->withValidator($validator);
0 ignored issues
show
Bug introduced by
The method withValidator() does not exist on Noitran\Form\Http\FormRequest. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

82
            $this->/** @scrutinizer ignore-call */ 
83
                   withValidator($validator);
Loading history...
83
        }
84
85
        return $validator;
86
    }
87
88
    /**
89
     * Create the default validator instance.
90
     *
91
     * @param  \Illuminate\Contracts\Validation\Factory  $factory
92
     * @return \Illuminate\Contracts\Validation\Validator
93
     */
94
    protected function createDefaultValidator(ValidationFactory $factory): Validator
95
    {
96
        return $factory->make(
97
            $this->validationData(),
98
            $this->container->call([$this, 'rules']),
0 ignored issues
show
Bug introduced by
It seems like $this->container->call(array($this, 'rules')) can also be of type callable; however, parameter $rules of Illuminate\Validation\Factory::make() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

98
            /** @scrutinizer ignore-type */ $this->container->call([$this, 'rules']),
Loading history...
99
            $this->messages(),
100
            $this->attributes()
101
        );
102
    }
103
104
    /**
105
     * Get data to be validated from the request.
106
     *
107
     * @return array
108
     */
109
    protected function validationData(): array
110
    {
111
        return $this->all();
112
    }
113
114
    /**
115
     * Handle a failed validation attempt.
116
     *
117
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
118
     * @throws HttpResponseException
119
     * @return void
120
     *
121
     */
122
    protected function failedValidation(Validator $validator): void
123
    {
124
        throw new HttpResponseException($this->response(
125
            $this->formatErrors($validator)
126
        ));
127
    }
128
129
    /**
130
     * Determine if the request passes the authorization check.
131
     *
132
     * @return bool
133
     */
134
    protected function passesAuthorization(): bool
135
    {
136
        if (method_exists($this, 'authorize')) {
137
            return $this->container->call([$this, 'authorize']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->container-...ay($this, 'authorize')) could return the type callable which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
138
        }
139
140
        return false;
141
    }
142
143
    /**
144
     * Handle a failed authorization attempt.
145
     *
146
     * @throws \Illuminate\Auth\Access\AuthorizationException
147
     * @return void
148
     *
149
     */
150
    protected function failedAuthorization(): void
151
    {
152
        throw new AuthorizationException($this->forbiddenResponse());
153
    }
154
155
    /**
156
     * Get the proper failed validation response for the request.
157
     *
158
     * @param  array  $errors
159
     * @return \Illuminate\Http\JsonResponse
160
     */
161
    public function response(array $errors): JsonResponse
162
    {
163
        return new JsonResponse($errors, 422);
164
    }
165
166
    /**
167
     * Get the response for a forbidden operation.
168
     *
169
     * @return JsonResponse
170
     */
171
    public function forbiddenResponse(): JsonResponse
172
    {
173
        return new JsonResponse('Forbidden', 403);
174
    }
175
176
    /**
177
     * Format the errors from the given Validator instance.
178
     *
179
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
180
     * @return array
181
     */
182
    protected function formatErrors(Validator $validator): array
183
    {
184
        return $validator->getMessageBag()->toArray();
185
    }
186
187
    /**
188
     * Get the validated data from the request.
189
     *
190
     * @return array
191
     */
192
    public function validated(): array
193
    {
194
        $rules = $this->container->call([$this, 'rules']);
195
196
        return $this->only(collect($rules)->keys()->map(function ($rule) {
197
            return Str::contains($rule, '.') ? explode('.', $rule)[0] : $rule;
198
        })->unique()->toArray());
199
    }
200
201
    /**
202
     * Get custom messages for validator errors.
203
     *
204
     * @return array
205
     */
206
    public function messages(): array
207
    {
208
        return [];
209
    }
210
211
    /**
212
     * Get custom attributes for validator errors.
213
     *
214
     * @return array
215
     */
216
    public function attributes(): array
217
    {
218
        return [];
219
    }
220
221
    /**
222
     * Set the Redirector instance.
223
     *
224
     * @param  \Laravel\Lumen\Http\Redirector $redirector
225
     * @return $this
226
     */
227
    public function setRedirector(Redirector $redirector): self
228
    {
229
        $this->redirector = $redirector;
230
231
        return $this;
232
    }
233
234
    /**
235
     * Set the container implementation.
236
     *
237
     * @param  \Illuminate\Contracts\Container\Container  $container
238
     * @return $this
239
     */
240
    public function setContainer(Container $container): self
241
    {
242
        $this->container = $container;
243
244
        return $this;
245
    }
246
}
247