Completed
Push — master ( 52e56e...044348 )
by Cedric
03:57
created

ExceptionWrapper::create401ErrorMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
/*
3
 * This file is part of the Adlogix package.
4
 *
5
 * (c) Allan Segebarth <[email protected]>
6
 * (c) Jean-Jacques Courtens <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Adlogix\ConfluenceClient\Exception;
13
14
15
use GuzzleHttp\Exception\RequestException;
16
use JMS\Serializer\SerializerInterface;
17
use Psr\Http\Message\RequestInterface;
18
use Psr\Http\Message\ResponseInterface;
19
20
/**
21
 * Class ExceptionWrapper
22
 * @package Adlogix\ConfluenceClient\Exception
23
 * @author  Cedric Michaux <[email protected]>
24
 */
25
class ExceptionWrapper
26
{
27
    const RESPONSE_AUTHENTICATED_FAILED = 'AUTHENTICATED_FAILED';
28
    const RESPONSE_AUTHENTICATION_DENIED = 'AUTHENTICATION_DENIED';
29
    const RESPONSE_AUTHORIZATION_FAILED = 'AUTHORIZATION_FAILED';
30
    const RESPONSE_AUTHORISATION_FAILED = 'AUTHORISATION_FAILED';
31
    const RESPONSE_OUT = 'OUT';
32
    /**
33
     * @var SerializerInterface
34
     */
35
    private $serializer;
36
37
    /**
38
     * ExceptionWrapper constructor.
39
     *
40
     * @param SerializerInterface $serializer
41
     */
42
    private function __construct(SerializerInterface $serializer)
43
    {
44
        $this->serializer = $serializer;
45
    }
46
47
    public static function wrap(RequestException $exception, SerializerInterface $serializer)
48
    {
49
        $wrapper = new static($serializer);
50
        return $wrapper->parseException($exception);
51
    }
52
53
    /**
54
     * @param RequestException $exception
55
     *
56
     * @return ApiException
57
     */
58
    private function parseException(RequestException $exception)
59
    {
60
        if ($exception->getCode() == 401) {
61
            return new ApiException($this->create401ErrorMessage($exception), $exception->getCode(), $exception);
62
        }
63
64
        return new ApiException($exception->getMessage(), $exception->getCode(), $exception);
65
    }
66
67
    /**
68
     * @param RequestException $exception
69
     *
70
     * @return string
71
     */
72
    private function create401ErrorMessage(RequestException $exception)
73
    {
74
        $request = $exception->getRequest();
75
        $response = $exception->getResponse();
76
77
        return $this->getExceptionMessage($request, $response);
0 ignored issues
show
Bug introduced by
It seems like $response defined by $exception->getResponse() on line 75 can be null; however, Adlogix\ConfluenceClient...::getExceptionMessage() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
78
    }
79
80
    /**
81
     * @param RequestInterface  $request
82
     * @param ResponseInterface $response
83
     *
84
     * @return string
85
     */
86
    private function getExceptionMessage(RequestInterface $request, ResponseInterface $response)
87
    {
88
        return $this->getExceptionMessageForRequest($request) ?: $this->getExceptionMessageForResponse($response);
89
    }
90
91
    /**
92
     * @param RequestInterface $request
93
     *
94
     * @return null|string
95
     */
96
    private function getExceptionMessageForRequest(RequestInterface $request)
97
    {
98
        if (!$this->isRequestValid($request)) {
99
            return 'Authentication Required';
100
        }
101
        return null;
102
    }
103
104
    /**
105
     * @param RequestInterface $request
106
     *
107
     * @return bool
108
     */
109
    private function isRequestValid(RequestInterface $request)
110
    {
111
        $uri = $request->getUri();
112
        $queryParams = \GuzzleHttp\Psr7\parse_query($uri->getQuery());
113
114
        return $request->hasHeader('Authorization')
115
        || $request->hasHeader('Authentication')
116
        || array_key_exists('jwt', $queryParams)
117
        || !empty($queryParams['jwt']);
118
    }
119
120
    /**
121
     * @param ResponseInterface $response
122
     *
123
     * @return string
124
     */
125
    private function getExceptionMessageForResponse(ResponseInterface $response)
126
    {
127
        switch ($response->getHeader('X-Seraph-LoginReason')) {
128
            case self::RESPONSE_AUTHENTICATED_FAILED:
129
                return 'Could not be authenticated';
130
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
131
132
            case self::RESPONSE_AUTHENTICATION_DENIED:
133
                return 'Not allowed to login';
134
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
135
136
            case self::RESPONSE_AUTHORISATION_FAILED:
137
                return 'Could not be authorised';
138
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
139
140
            case self::RESPONSE_OUT:
141
                return 'Logged out';
142
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
143
        }
144
        return 'Invalid Credentials';
145
    }
146
}
147