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

ContentBasedErrorHandler   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 5
dl 0
loc 82
ccs 23
cts 23
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A __invoke() 0 7 1
B resolveErrorHandlerFromAcceptHeader() 0 26 5
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