Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
/**
4
 * Slim Framework (https://slimframework.com)
5
 *
6
 * @license https://github.com/slimphp/Slim/blob/4.x/LICENSE.md (MIT License)
7
 */
8
 
9
declare(strict_types=1);
10
 
11
namespace Slim\Middleware;
12
 
13
use Psr\Http\Message\ResponseFactoryInterface;
14
use Psr\Http\Message\ResponseInterface;
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Http\Server\MiddlewareInterface;
17
use Psr\Http\Server\RequestHandlerInterface;
18
use Psr\Log\LoggerInterface;
19
use Slim\Exception\HttpException;
20
use Slim\Handlers\ErrorHandler;
21
use Slim\Interfaces\CallableResolverInterface;
22
use Slim\Interfaces\ErrorHandlerInterface;
23
use Throwable;
24
 
25
use function get_class;
26
use function is_subclass_of;
27
 
28
class ErrorMiddleware implements MiddlewareInterface
29
{
30
    protected CallableResolverInterface $callableResolver;
31
 
32
    protected ResponseFactoryInterface $responseFactory;
33
 
34
    protected bool $displayErrorDetails;
35
 
36
    protected bool $logErrors;
37
 
38
    protected bool $logErrorDetails;
39
 
40
    protected ?LoggerInterface $logger = null;
41
 
42
    /**
43
     * @var ErrorHandlerInterface[]|callable[]|string[]
44
     */
45
    protected array $handlers = [];
46
 
47
    /**
48
     * @var ErrorHandlerInterface[]|callable[]|string[]
49
     */
50
    protected array $subClassHandlers = [];
51
 
52
    /**
53
     * @var ErrorHandlerInterface|callable|string|null
54
     */
55
    protected $defaultErrorHandler;
56
 
57
    public function __construct(
58
        CallableResolverInterface $callableResolver,
59
        ResponseFactoryInterface $responseFactory,
60
        bool $displayErrorDetails,
61
        bool $logErrors,
62
        bool $logErrorDetails,
63
        ?LoggerInterface $logger = null
64
    ) {
65
        $this->callableResolver = $callableResolver;
66
        $this->responseFactory = $responseFactory;
67
        $this->displayErrorDetails = $displayErrorDetails;
68
        $this->logErrors = $logErrors;
69
        $this->logErrorDetails = $logErrorDetails;
70
        $this->logger = $logger;
71
    }
72
 
73
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
74
    {
75
        try {
76
            return $handler->handle($request);
77
        } catch (Throwable $e) {
78
            return $this->handleException($request, $e);
79
        }
80
    }
81
 
82
    public function handleException(ServerRequestInterface $request, Throwable $exception): ResponseInterface
83
    {
84
        if ($exception instanceof HttpException) {
85
            $request = $exception->getRequest();
86
        }
87
 
88
        $exceptionType = get_class($exception);
89
        $handler = $this->getErrorHandler($exceptionType);
90
 
91
        return $handler($request, $exception, $this->displayErrorDetails, $this->logErrors, $this->logErrorDetails);
92
    }
93
 
94
    /**
95
     * Get callable to handle scenarios where an error
96
     * occurs when processing the current request.
97
     *
98
     * @param string $type Exception/Throwable name. ie: RuntimeException::class
99
     * @return callable|ErrorHandler
100
     */
101
    public function getErrorHandler(string $type)
102
    {
103
        if (isset($this->handlers[$type])) {
104
            return $this->callableResolver->resolve($this->handlers[$type]);
105
        }
106
 
107
        if (isset($this->subClassHandlers[$type])) {
108
            return $this->callableResolver->resolve($this->subClassHandlers[$type]);
109
        }
110
 
111
        foreach ($this->subClassHandlers as $class => $handler) {
112
            if (is_subclass_of($type, $class)) {
113
                return $this->callableResolver->resolve($handler);
114
            }
115
        }
116
 
117
        return $this->getDefaultErrorHandler();
118
    }
119
 
120
    /**
121
     * Get default error handler
122
     *
123
     * @return ErrorHandler|callable
124
     */
125
    public function getDefaultErrorHandler()
126
    {
127
        if ($this->defaultErrorHandler === null) {
128
            $this->defaultErrorHandler = new ErrorHandler(
129
                $this->callableResolver,
130
                $this->responseFactory,
131
                $this->logger
132
            );
133
        }
134
 
135
        return $this->callableResolver->resolve($this->defaultErrorHandler);
136
    }
137
 
138
    /**
139
     * Set callable as the default Slim application error handler.
140
     *
141
     * The callable signature MUST match the ErrorHandlerInterface
142
     *
143
     * @see \Slim\Interfaces\ErrorHandlerInterface
144
     *
145
     * 1. Instance of \Psr\Http\Message\ServerRequestInterface
146
     * 2. Instance of \Throwable
147
     * 3. Boolean $displayErrorDetails
148
     * 4. Boolean $logErrors
149
     * 5. Boolean $logErrorDetails
150
     *
151
     * The callable MUST return an instance of
152
     * \Psr\Http\Message\ResponseInterface.
153
     *
154
     * @param string|callable|ErrorHandler $handler
155
     */
156
    public function setDefaultErrorHandler($handler): self
157
    {
158
        $this->defaultErrorHandler = $handler;
159
        return $this;
160
    }
161
 
162
    /**
163
     * Set callable to handle scenarios where an error
164
     * occurs when processing the current request.
165
     *
166
     * The callable signature MUST match the ErrorHandlerInterface
167
     *
168
     * Pass true to $handleSubclasses to make the handler handle all subclasses of
169
     * the type as well. Pass an array of classes to make the same function handle multiple exceptions.
170
     *
171
     * @see \Slim\Interfaces\ErrorHandlerInterface
172
     *
173
     * 1. Instance of \Psr\Http\Message\ServerRequestInterface
174
     * 2. Instance of \Throwable
175
     * 3. Boolean $displayErrorDetails
176
     * 4. Boolean $logErrors
177
     * 5. Boolean $logErrorDetails
178
     *
179
     * The callable MUST return an instance of
180
     * \Psr\Http\Message\ResponseInterface.
181
     *
182
     * @param string|string[] $typeOrTypes Exception/Throwable name.
183
     * ie: RuntimeException::class or an array of classes
184
     * ie: [HttpNotFoundException::class, HttpMethodNotAllowedException::class]
185
     * @param string|callable|ErrorHandlerInterface $handler
186
     */
187
    public function setErrorHandler($typeOrTypes, $handler, bool $handleSubclasses = false): self
188
    {
189
        if (is_array($typeOrTypes)) {
190
            foreach ($typeOrTypes as $type) {
191
                $this->addErrorHandler($type, $handler, $handleSubclasses);
192
            }
193
        } else {
194
            $this->addErrorHandler($typeOrTypes, $handler, $handleSubclasses);
195
        }
196
 
197
        return $this;
198
    }
199
 
200
    /**
201
     * Used internally to avoid code repetition when passing multiple exceptions to setErrorHandler().
202
     * @param string|callable|ErrorHandlerInterface $handler
203
     */
204
    private function addErrorHandler(string $type, $handler, bool $handleSubclasses): void
205
    {
206
        if ($handleSubclasses) {
207
            $this->subClassHandlers[$type] = $handler;
208
        } else {
209
            $this->handlers[$type] = $handler;
210
        }
211
    }
212
}