Skip to content

Commit 725fcf2

Browse files
committed
Finish user validation and implement exceptions
1 parent 2895cd8 commit 725fcf2

10 files changed

+298
-20
lines changed

app/Exceptions/ExceptionInterface.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PawPlanner.
5+
*
6+
* (c) Alex Broom-Roden <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace App\Exceptions;
13+
14+
/**
15+
* This is the exception interface.
16+
*
17+
* @author Alex Broom-Roden <[email protected]>
18+
*/
19+
interface ExceptionInterface
20+
{
21+
//
22+
}

app/Exceptions/Handler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace App\Exceptions;
1313

1414
use Exception;
15-
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
15+
use GrahamCampbell\Exceptions\ExceptionHandler;
1616

1717
/**
1818
* This is exception handler class.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/*
3+
* This file is part of PawPlanner.
4+
*
5+
* (c) Alex Broom-Roden <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace App\Exceptions\Http;
12+
13+
use App\Exceptions\ExceptionInterface;
14+
15+
/**
16+
* This is the http exception interface.
17+
*
18+
* @author Alex Broom-Roden <[email protected]>
19+
*/
20+
interface HttpExceptionInterface extends ExceptionInterface
21+
{
22+
//
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace App\Exceptions\Http;
4+
5+
use Exception;
6+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
7+
8+
/**
9+
* This is the missing data exception class.
10+
*
11+
* @author Alex Broom-Roden <[email protected]>
12+
*/
13+
class MissingDataException extends BadRequestHttpException implements HttpExceptionInterface
14+
{
15+
/**
16+
* Create a new missing dataexception instance.
17+
*
18+
* @param string $messages
19+
* @param \Exception $previous
20+
* @param int $code
21+
*
22+
* @return void
23+
*/
24+
public function __construct($message = null, Exception $previous, $code= 0)
25+
{
26+
if (!$message) {
27+
$message = 'Missing data.'
28+
}
29+
30+
parent::__construct($message, $previous, $code);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Exceptions\Http;
4+
5+
use Exception;
6+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
7+
8+
/**
9+
* This is the validation failure exception class.
10+
*
11+
* @author Alex Broom-Roden <[email protected]>
12+
*/
13+
class ValidationFailureException extends BadRequestHttpException implements HttpExceptionInterface
14+
{
15+
/**
16+
* Create a new validation failure exception instance.
17+
*
18+
* @param array $messages
19+
* @param \Exception $previous
20+
* @param int $code
21+
*
22+
* @return void
23+
*/
24+
public function __construct(array $messages = [], Exception $previous, $code= 0)
25+
{
26+
$errorMessage = '';
27+
if (empty($messages)) {
28+
$errorMessage = 'Validation failure.'
29+
} else {
30+
$messageCount = count($messages);
31+
32+
foreach ($messages as $key => $message) {
33+
$errorMessage =. ($key + 1) < $count ? $messages.',' : $messages;
34+
}
35+
}
36+
37+
parent::__construct($errorMessage, $previous, $code);
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Foundation\Exceptions\Http\Filters;
4+
5+
use App\Exceptions\Http\HttpExceptionInterface;
6+
use Exception;
7+
use Illuminate\Http\Request;
8+
9+
/**
10+
* This is the api filter class.
11+
*
12+
* @author Alex Broom-Roden <[email protected]>
13+
*/
14+
class HttpApiFilter
15+
{
16+
/**
17+
* Filter and return the displayers.
18+
*
19+
* @param \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[] $displayers
20+
* @param \Illuminate\Http\Request $request
21+
* @param \Exception $original
22+
* @param \Exception $transformed
23+
* @param int $code
24+
*
25+
* @return \GrahamCampbell\Exceptions\Displayers\DisplayerInterface[]
26+
*/
27+
public function filter(array $displayers, Request $request, Exception $original, Exception $transformed, $code)
28+
{
29+
if ($original instanceof HttpExceptionInterface) {
30+
foreach ($displayers as $index => $displayer) {
31+
if (!str_contains($displayer->contentType(), 'application/')) {
32+
unset($displayers[$index]);
33+
}
34+
}
35+
}
36+
37+
return array_values($displayers);
38+
}
39+
}

app/Services/User/User.php

+20-16
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,28 @@ class User implements Entity
1515
*/
1616
public function validate(array $data = [])
1717
{
18-
$validator = Validator::make([
19-
'username' => $command->username,
20-
'email' => $command->email,
21-
'password' => $command->password,
22-
'password_confirmation' => $command->confirmPassword,
23-
'plan' => (int) $command->plan,
24-
], [
25-
'username' => 'required|unique:users',
26-
'email' => 'required|unique:users',
27-
'password' => 'required|min:5|confirmed',
28-
'password_confirmation' => 'required|min:5',
29-
'plan' => 'required|integer',
30-
]);
18+
if (!empty($data)) {
19+
$validator = Validator::make([
20+
'username' => array_get($data, 'username'),
21+
'email' => array_get($data, 'email'),
22+
'password' => array_get($data, 'password'),
23+
'password_confirmation' => array_get($data, 'confirmPassword'),
24+
'plan' => array_get($data, 'plan'),
25+
], [
26+
'username' => 'required|unique:users',
27+
'email' => 'required|unique:users',
28+
'password' => 'required|min:5|confirmed',
29+
'password_confirmation' => 'required|min:5',
30+
'plan' => 'required|integer',
31+
]);
3132

32-
if ($validator->fails()) {
33-
throw new $validator->getMessageBag()->all();
33+
if ($validator->fails()) {
34+
throw new ValidationFailureException($validator->getMessageBag()->all());
35+
}
36+
37+
return true;
3438
}
3539

36-
return true;
40+
throw new MissingDataException();
3741
}
3842
}

composer.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
"license": "MIT",
66
"type": "project",
77
"require": {
8-
"php": ">=7.0.0",
8+
"alt-three/bus": "^3.0",
99
"fideloper/proxy": "~3.3",
10+
"graham-campbell/binput": "^4.0",
11+
"graham-campbell/exceptions": "^11.0",
1012
"laravel/framework": "5.5.*",
1113
"laravel/tinker": "~1.0",
12-
"mccool/laravel-auto-presenter": "^6.2"
14+
"mccool/laravel-auto-presenter": "^6.2",
15+
"php": ">=7.0.0"
1316
},
1417
"require-dev": {
1518
"filp/whoops": "~2.0",

config/app.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@
177177
* Package Service Providers...
178178
*/
179179
AltThree\Bus\BusServiceProvider::class,
180-
GrahamCampbell\Security\SecurityServiceProvider::class,
181180
GrahamCampbell\Binput\BinputServiceProvider::class,
181+
GrahamCampbell\Exceptions\ExceptionsServiceProvider::class,
182+
GrahamCampbell\Security\SecurityServiceProvider::class,
182183
McCool\LaravelAutoPresenter\AutoPresenterServiceProvider::class,
183184

184185
/*

config/exceptions.php

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of Laravel Exceptions.
7+
*
8+
* (c) Graham Campbell <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
return [
15+
16+
/*
17+
|--------------------------------------------------------------------------
18+
| Exception Transformers
19+
|--------------------------------------------------------------------------
20+
|
21+
| Here are each of the exception transformers setup for your application.
22+
|
23+
| This allows you to turn your exceptions into other exceptions such as
24+
| http exceptions for perfect results when passed to the displayers. Note
25+
| that this list is processed in order and subsequent transformers can
26+
| still modify the results of previous ones if required.
27+
|
28+
*/
29+
30+
'transformers' => [
31+
'GrahamCampbell\Exceptions\Transformers\AuthTransformer',
32+
'GrahamCampbell\Exceptions\Transformers\CsrfTransformer',
33+
'GrahamCampbell\Exceptions\Transformers\ModelTransformer',
34+
],
35+
36+
/*
37+
|--------------------------------------------------------------------------
38+
| Exception Displayers
39+
|--------------------------------------------------------------------------
40+
|
41+
| Here are each of the exception displayers setup for your application.
42+
|
43+
| These displayers are sorted by priority. Note that when we are in debug
44+
| mode, we will select the first valid displayer from the list, and when we
45+
| are not in debug mode, we'll filter out all verbose displayers, then
46+
| select the first valid displayer from the new list.
47+
|
48+
*/
49+
50+
'displayers' => [
51+
'GrahamCampbell\Exceptions\Displayers\DebugDisplayer',
52+
'GrahamCampbell\Exceptions\Displayers\ViewDisplayer',
53+
'GrahamCampbell\Exceptions\Displayers\HtmlDisplayer',
54+
'GrahamCampbell\Exceptions\Displayers\JsonDisplayer',
55+
'GrahamCampbell\Exceptions\Displayers\JsonApiDisplayer',
56+
],
57+
58+
/*
59+
|--------------------------------------------------------------------------
60+
| Displayer Filters
61+
|--------------------------------------------------------------------------
62+
|
63+
| Here are each of the filters for the displayers.
64+
|
65+
| This allows you to apply filters to your displayers in order to work out
66+
| which displayer to use for each exception. This includes things like
67+
| content type negotiation.
68+
|
69+
*/
70+
71+
'filters' => [
72+
'GrahamCampbell\Exceptions\Filters\VerboseFilter',
73+
'GrahamCampbell\Exceptions\Filters\CanDisplayFilter',
74+
'GrahamCampbell\Exceptions\Filters\ContentTypeFilter',
75+
'App\Foundation\Exceptions\Http\Filters\HttpApiFilter',
76+
],
77+
78+
/*
79+
|--------------------------------------------------------------------------
80+
| Default Displayer
81+
|--------------------------------------------------------------------------
82+
|
83+
| Here you may define the default displayer for your application.
84+
|
85+
| This displayer will be used if your filters have filtered out all the
86+
| displayers, otherwise leaving us unable to displayer the exception.
87+
|
88+
*/
89+
90+
'default' => 'GrahamCampbell\Exceptions\Displayers\HtmlDisplayer',
91+
92+
/*
93+
|--------------------------------------------------------------------------
94+
| Exception Levels
95+
|--------------------------------------------------------------------------
96+
|
97+
| Here are each of the log levels for the each exception.
98+
|
99+
| If an exception passes an instance of test for each key, then the log
100+
| level used is the value associated with each key.
101+
|
102+
*/
103+
104+
'levels' => [
105+
'Illuminate\Auth\Access\AuthorizationException' => 'warning',
106+
'Illuminate\Database\Eloquent\ModelNotFoundException' => 'warning',
107+
'Illuminate\Session\TokenMismatchException' => 'notice',
108+
'Symfony\Component\HttpKernel\Exception\NotFoundHttpException' => 'notice',
109+
'Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException' => 'error',
110+
'Symfony\Component\HttpKernel\Exception\HttpExceptionInterface' => 'warning',
111+
'Symfony\Component\Debug\Exception\FatalErrorException' => 'critical',
112+
'Exception' => 'error',
113+
],
114+
115+
];

0 commit comments

Comments
 (0)