Completed
Push — master ( 5f7cbd...b12d8e )
by Alejandro
03:03
created

ContentBasedErrorHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
cc 1
eloc 7
nc 1
nop 3
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 ContentBasedErrorHandler implements ErrorHandlerInterface
11
{
12
    const DEFAULT_CONTENT = 'text/html';
13
14
    /**
15
     * @var ErrorHandlerManagerInterface
16
     */
17
    private $errorHandlerManager;
18
    /**
19
     * @var LoggerInterface
20
     */
21
    private $logger;
22
    /**
23
     * @var LogMessageBuilderInterface
24
     */
25
    private $logMessageBuilder;
26
27
    /**
28
     * ContentBasedErrorHandler constructor.
29
     * @param ErrorHandlerManagerInterface|ErrorHandlerManager $errorHandlerManager
30
     * @param LogMessageBuilderInterface $logMessageBuilder
31
     * @param LoggerInterface $logger
32
     */
33 5
    public function __construct(
34
        ErrorHandlerManagerInterface $errorHandlerManager,
35
        LoggerInterface $logger,
36
        LogMessageBuilderInterface $logMessageBuilder
37
    ) {
38 5
        $this->errorHandlerManager = $errorHandlerManager;
39 5
        $this->logger = $logger;
40 5
        $this->logMessageBuilder = $logMessageBuilder;
41 5
    }
42
43
    /**
44
     * Final handler for an application.
45
     *
46
     * @param Request $request
47
     * @param Response $response
48
     * @param null|mixed $err
49
     * @return Response
50
     */
51 4
    public function __invoke(Request $request, Response $response, $err = null)
52
    {
53
        // Try to get an error handler for provided request accepted type
54 4
        $errorHandler = $this->resolveErrorHandlerFromAcceptHeader($request);
55 3
        $this->logger->error($this->logMessageBuilder->buildMessage($request, $response, $err));
56 3
        return $errorHandler($request, $response, $err);
57
    }
58
59
    /**
60
     * Tries to resolve
61
     *
62
     * @param Request $request
63
     * @return callable
64
     */
65 4
    protected function resolveErrorHandlerFromAcceptHeader(Request $request)
66
    {
67
        // Try to find an error handler for one of the accepted content types
68 4
        $accepts = $request->hasHeader('Accept') ? $request->getHeaderLine('Accept') : self::DEFAULT_CONTENT;
69 4
        $accepts = explode(',', $accepts);
70 4
        foreach ($accepts as $accept) {
71 4
            if (! $this->errorHandlerManager->has($accept)) {
72 3
                continue;
73
            }
74
75 2
            return $this->errorHandlerManager->get($accept);
76 2
        }
77
78
        // If it wasn't possible to find an error handler for accepted content type, use default one if registered
79 2
        if ($this->errorHandlerManager->has(self::DEFAULT_CONTENT)) {
80 1
            return $this->errorHandlerManager->get(self::DEFAULT_CONTENT);
81
        }
82
83
        // It wasn't possible to find an error handler
84 1
        throw new InvalidArgumentException(sprintf(
85
            'It wasn\'t possible to find an error handler for ["%s"] content types. '
86 1
            . 'Make sure you have registered at least the default "%s" content type',
87 1
            implode('", "', $accepts),
88
            self::DEFAULT_CONTENT
89 1
        ));
90
    }
91
}
92