Issues (16)

config/handlers.php (4 issues)

1
<?php
2
3
use Awurth\Slim\Helper\Exception\AccessDeniedException;
4
use Awurth\Slim\Helper\Exception\UnauthorizedException;
5
use Slim\Exception\NotFoundException;
6
use Slim\Handlers\Strategies\RequestResponseArgs;
7
use Slim\Http\Request;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Request. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
use Slim\Http\Response;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Response. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
10
return [
11
12
    /**
13
     * Controller methods signature must be like:
14
     *
15
     * public function getCollection($request, $response, $arg1, $arg2, $args3, ...)
16
     *
17
     * https://www.slimframework.com/docs/objects/router.html#route-strategies
18
     */
19
    'foundHandler' => function ($container) {
20
        /** @var Request $request */
21
        $request = $container['request'];
22
        $container['monolog']->info(sprintf('Matched route "%s /%s"', $request->getMethod(), ltrim($request->getUri()->getPath(), '/')));
23
24
        return new RequestResponseArgs();
25
    },
26
27
    /**
28
     * Returns an error in JSON when a NotFoundException is thrown.
29
     */
30
    'notFoundHandler' => function ($container) {
31
        return function (Request $request, Response $response) use ($container) {
32
            $container['monolog']->error(sprintf('No resource found for "%s /%s"', $request->getMethod(), ltrim($request->getUri()->getPath(), '/')));
33
34
            return $response
35
                ->withStatus(404)
36
                ->withJson([
37
                    'status' => 404,
38
                    'message' => 'Resource not found.'
39
                ]);
40
        };
41
    },
42
43
    /**
44
     * Returns an error in JSON when the HTTP method is not allowed.
45
     */
46
    'notAllowedHandler' => function ($container) {
47
        return function (Request $request, Response $response, array $methods) use ($container) {
48
            $allowedMethods = implode(', ', $methods);
49
50
            $container['monolog']->error(sprintf(
51
                'No resource found for "%s /%s": Method not allowed (Allow: %s)',
52
                $request->getMethod(),
53
                ltrim($request->getUri()->getPath(), '/'),
54
                $allowedMethods
55
            ));
56
57
            if ($allowedMethods === 'OPTIONS') {
58
                throw new NotFoundException($request, $response);
59
            }
60
61
            return $response
62
                ->withStatus(405)
63
                ->withHeader('Allow', $allowedMethods)
64
                ->withJson([
65
                    'status' => 405,
66
                    'message' => 'Method must be one of: '.$allowedMethods
67
                ]);
68
        };
69
    },
70
71
    /**
72
     * Returns an error in JSON when an UnauthorizedException is thrown.
73
     */
74
    'unauthorizedHandler' => function ($container) {
75
        return function (Request $request, Response $response, Exception $exception) use ($container) {
76
            $container['monolog']->debug('Unauthorized, the user is not authenticated', [
77
                'exception' => $exception
78
            ]);
79
80
            return $response
81
                ->withStatus($exception->getCode())
82
                ->withJson([
83
                    'status' => $exception->getCode(),
84
                    'message' => $exception->getMessage()
85
                ]);
86
        };
87
    },
88
89
    /**
90
     * Returns an error in JSON when an AccessDeniedException is thrown.
91
     */
92
    'accessDeniedHandler' => function ($container) {
93
        return function (Request $request, Response $response, Exception $exception) use ($container) {
94
            $container['monolog']->debug('Access denied, the user does not have access to this section', [
95
                'exception' => $exception
96
            ]);
97
98
            return $response
99
                ->withStatus($exception->getCode())
100
                ->withJson([
101
                    'status' => $exception->getCode(),
102
                    'message' => $exception->getMessage()
103
                ]);
104
        };
105
    },
106
107
    /**
108
     * Default Slim error handler.
109
     */
110
    'errorHandler' => function ($container) {
111
        return function (Request $request, Response $response, Exception $exception) use ($container) {
112
            if ($exception instanceof AccessDeniedException) {
113
                return $container['accessDeniedHandler']($request, $response, $exception);
114
            }
115
116
            if ($exception instanceof UnauthorizedException) {
117
                return $container['unauthorizedHandler']($request, $response, $exception);
118
            }
119
120
            $container['monolog']->error('Uncaught PHP Exception '.get_class($exception), [
121
                'exception' => $exception
122
            ]);
123
124
            $message = [
125
                'status' => 500,
126
                'message' => 'Internal Server Error.'
127
            ];
128
129
            if ('dev' === $this->getEnvironment()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
130
                $message['trace'] = $exception->getTrace();
131
                $message['message'] = get_class($exception).': '.$exception->getMessage();
132
            }
133
134
            return $response
135
                ->withStatus(500)
136
                ->withJson($message);
137
        };
138
    },
139
140
    /**
141
     * PHP error handler.
142
     */
143
    'phpErrorHandler' => function ($container) {
144
        return function (Request $request, Response $response, Throwable $error) use ($container) {
145
            $container['monolog']->critical('Uncaught PHP Exception '.get_class($error), [
146
                'exception' => $error
147
            ]);
148
149
            $message = [
150
                'status' => 500,
151
                'message' => 'Internal Server Error.'
152
            ];
153
154
            if ('dev' === $this->getEnvironment()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this seems to be never defined.
Loading history...
155
                $message['trace'] = $error->getTrace();
156
                $message['message'] = get_class($error).': '.$error->getMessage();
157
            }
158
159
            return $response
160
                ->withStatus(500)
161
                ->withJson($message);
162
        };
163
    }
164
165
];
166