Completed
Push — master ( 465bda...34cb64 )
by Alejandro
04:17
created

ContentBasedErrorResponseGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 4
crap 1
1
<?php
2
namespace Acelaya\ExpressiveErrorHandler\ErrorHandler;
3
4
use Acelaya\ExpressiveErrorHandler\Exception\InvalidArgumentException;
5
use Acelaya\ExpressiveErrorHandler\Log\LogMessageBuilderInterface;
6
use Psr\Http\Message\ResponseInterface as Response;
7
use Psr\Http\Message\ServerRequestInterface as Request;
8
use Psr\Log\LoggerInterface;
9
10
class ContentBasedErrorResponseGenerator implements ErrorResponseGeneratorInterface
11
{
12
    /**
13
     * @deprecated Inject the default content type to be used while creating this class
14
     */
15
    const DEFAULT_CONTENT = 'text/html';
16
17
    /**
18
     * @var ErrorResponseGeneratorManagerInterface
19
     */
20
    private $errorHandlerManager;
21
    /**
22
     * @var LoggerInterface
23
     */
24
    private $logger;
25
    /**
26
     * @var LogMessageBuilderInterface
27
     */
28
    private $logMessageBuilder;
29
    /**
30
     * @var string
31
     */
32
    private $defaultContentType;
33
34
    /**
35
     * ContentBasedErrorResponseGenerator constructor.
36
     * @param ErrorResponseGeneratorManagerInterface|ErrorResponseGeneratorManager $errorHandlerManager
37
     * @param LoggerInterface $logger
38
     * @param LogMessageBuilderInterface $logMessageBuilder
39
     * @param string $defaultContentType
40
     */
41 7
    public function __construct(
42
        ErrorResponseGeneratorManagerInterface $errorHandlerManager,
43
        LoggerInterface $logger,
44
        LogMessageBuilderInterface $logMessageBuilder,
45
        $defaultContentType = 'text/html'
46
    ) {
47 7
        $this->errorHandlerManager = $errorHandlerManager;
48 7
        $this->logger = $logger;
49 7
        $this->logMessageBuilder = $logMessageBuilder;
50 7
        $this->defaultContentType = $defaultContentType;
51 7
    }
52
53
    /**
54
     * Final handler for an application.
55
     *
56
     * @param \Throwable|\Exception $e
57
     * @param Request $request
58
     * @param Response $response
59
     * @return Response
60
     */
61 5
    public function __invoke($e, Request $request, Response $response)
62
    {
63
        // Try to get an error handler for provided request accepted type
64 5
        $errorHandler = $this->resolveErrorHandlerFromAcceptHeader($request);
65 4
        $this->logger->error($this->logMessageBuilder->buildMessage($request, $response, $e));
0 ignored issues
show
Bug introduced by
It seems like $e defined by parameter $e on line 61 can also be of type object<Exception>; however, Acelaya\ExpressiveErrorH...terface::buildMessage() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
66 4
        return $errorHandler($e, $request, $response);
67
    }
68
69
    /**
70
     * Tries to resolve
71
     *
72
     * @param Request $request
73
     * @return callable
74
     * @throws InvalidArgumentException
75
     */
76 5
    protected function resolveErrorHandlerFromAcceptHeader(Request $request)
77
    {
78
        // Try to find an error handler for one of the accepted content types
79 5
        $accepts = $request->hasHeader('Accept') ? $request->getHeaderLine('Accept') : $this->defaultContentType;
80
        /** @var array $accepts */
81 5
        $accepts = explode(',', $accepts);
82 5
        foreach ($accepts as $accept) {
83 5
            if (! $this->errorHandlerManager->has($accept)) {
84 4
                continue;
85
            }
86
87 2
            return $this->errorHandlerManager->get($accept);
88
        }
89
90
        // If it wasn't possible to find an error handler for accepted content type, use default one if registered
91 3
        if ($this->errorHandlerManager->has($this->defaultContentType)) {
92 2
            return $this->errorHandlerManager->get($this->defaultContentType);
93
        }
94
95
        // It wasn't possible to find an error handler
96 1
        throw new InvalidArgumentException(sprintf(
97
            'It wasn\'t possible to find an error handler for ["%s"] content types. '
98 1
            . 'Make sure you have registered at least the default "%s" content type',
99 1
            implode('", "', $accepts),
100 1
            $this->defaultContentType
101
        ));
102
    }
103
}
104