HTTPClient::getResponseStatusCodeFromException()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 3.0416
1
<?php
2
/**
3
 * Copyright (c) Padosoft.com 2016.
4
 */
5
6
namespace Padosoft\HTTPClient;
7
8
9
use Padosoft\HTTPClient\Response;
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\LogLevel;
12
use GuzzleHttp\Client;
13
use GuzzleHttp\Exception;
14
use GuzzleHttp\Exception\ClientException;
15
use GuzzleHttp\Exception\RequestException;
16
use GuzzleHttp\Exception\BadResponseException;
17
use GuzzleHttp\Exception\ServerException;
18
use GuzzleHttp\Exception\TooManyRedirectsException;
19
use GuzzleHttp\Exception\ConnectException;
20
use GuzzleHttp\Exception\TransferException;
21
22
/**
23
 * Class HTTPClient
24
 * Perform HTTP Request using Guzzle.
25
 * @package Padosoft\HTTPClient
26
 */
27
class HTTPClient
28
{
29
    /**
30
     * @var \GuzzleHttp\Client
31
     */
32
    protected $httpclient;
33
    /**
34
     * @var \Padosoft\HTTPClient\Response
35
     */
36
    protected $response;
37
    /**
38
     * @var \Psr\Log\LoggerInterface
39
     */
40
    protected $log;
41
    /**
42
     * @var \Padosoft\HTTPClient\RequestHelper
43
     */
44
    protected $requestHelper;
45
46
    /**
47
     * HTTPClient constructor.
48
     * @param Client $objguzzle
49
     * @param RequestHelper $requestHelper
50
     * @param LoggerInterface|null $log
51
     */
52 15
    public function __construct(Client $objguzzle, RequestHelper $requestHelper, LoggerInterface $log=null)
53
    {
54 15
        $this->httpclient = $objguzzle;
55 15
        $this->requestHelper=$requestHelper;
56 15
        $this->response = new Response();
57 15
        $this->log = $log;
58 15
    }
59
60
61
62
    /**
63
     * Send a HTTP Request and return Response or thrown Exception.
64
     *
65
     * @param string $method HTTP verb
66
     * @param string  null $uri
67
     * @return \Padosoft\HTTPClient\Response
68
     * @throws Exception
69 15
     * @throws \Exception
70
     */
71
    public function sendRequest($method ,$uri = null)
72 15
    {
73
74
        $this->reset();
75
76 15
        try {
77
            //log request
78
            $this->setLog(LogLevel::INFO, 'Try to send Request: Method: '.$method.' uri: '.$uri, $this->requestHelper->options);
0 ignored issues
show
Documentation introduced by
The property $options is declared protected in Padosoft\HTTPClient\RequestHelper. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
79 15
80
            //send request
81
            $this->response->psr7response = $this->httpclient->request($method, $uri, $this->requestHelper->options );
0 ignored issues
show
Documentation introduced by
The property $psr7response is declared protected in Padosoft\HTTPClient\Response. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $options is declared protected in Padosoft\HTTPClient\RequestHelper. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
82 9
83
            //log headers
84
            $this->setLog(LogLevel::INFO, 'Request send with Headers: '.$this->getHeadersString($this->response->psr7response), $this->requestHelper->options);
0 ignored issues
show
Documentation introduced by
The property $psr7response is declared protected in Padosoft\HTTPClient\Response. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $options is declared protected in Padosoft\HTTPClient\RequestHelper. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
85
86
            // To retrive body, do not use ->getContents()
87
            // it turns out that this gets the “remaining contents of the body as a string”
88
            // and since the middleware already accessed the body (for example in order to log it),
89
            // there isn’t any content remaining to retrieve.
90 9
            // The correct way to access the response content is to cast the body to a string.
91
            // See: https://michaelstivala.com/logging-guzzle-requests/
92
            $this->response->body = (string) $this->response->psr7response->getBody();
0 ignored issues
show
Documentation introduced by
The property $body is declared protected in Padosoft\HTTPClient\Response. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $psr7response is declared protected in Padosoft\HTTPClient\Response. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
93 9
94
            //log status code
95
            $this->response->status_code =  $this->response->psr7response->getStatusCode();
0 ignored issues
show
Documentation introduced by
The property $status_code is declared protected in Padosoft\HTTPClient\Response. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $psr7response is declared protected in Padosoft\HTTPClient\Response. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
96 9
97
            //log response
98 15
            $this->setLog(LogLevel::INFO,'Response ',['status code'=>$this->response->status_code,'body'=>$this->response->body]);
0 ignored issues
show
Documentation introduced by
The property $status_code is declared protected in Padosoft\HTTPClient\Response. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property $body is declared protected in Padosoft\HTTPClient\Response. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
99
100 6
        } catch (\GuzzleHttp\Exception\ClientException $e) {
101 6
102 6
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
103 6
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\ClientException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
104
                                            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\ClientException',['trace'=>$e->getTraceAsString()]);
105 3
            throw new \GuzzleHttp\Exception\ClientException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e->getResponse(),$e,$e->getHandlerContext());
106
107 3
        } catch (\GuzzleHttp\Exception\ServerException $e) {
108 3
109 3
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
110 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\ServerException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
111
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\ServerException',['trace'=>$e->getTraceAsString()]);
112
            throw new \GuzzleHttp\Exception\ServerException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e->getResponse(),$e,$e->getHandlerContext());
113 3
114
115 3
        } catch (\GuzzleHttp\Exception\BadResponseException $e) {
116 3
117 3
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
118 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\BadResponseException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
119
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\BadResponseException',['trace'=>$e->getTraceAsString()]);
120 3
            throw new \GuzzleHttp\Exception\BadResponseException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e->getResponse(),$e,$e->getHandlerContext());
121
122 3
        } catch (\GuzzleHttp\Exception\ConnectException $e) {
123 3
124 3
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
125 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\ConnectException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
126
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\ConnectException',['trace'=>$e->getTraceAsString()]);
127 3
            throw new \GuzzleHttp\Exception\ConnectException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e,$e->getHandlerContext());
128
129 3
        } catch (\GuzzleHttp\Exception\TooManyRedirectsException $e) {
130 3
131 3
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
132 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\TooManyRedirectsException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
133
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\TooManyRedirectsException',['trace'=>$e->getTraceAsString()]);
134 3
            throw new \GuzzleHttp\Exception\TooManyRedirectsException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e->getResponse(),$e,$e->getHandlerContext());
135
136 3
        } catch (\GuzzleHttp\Exception\RequestException $e) {
137 3
138 3
            $responseStatusCode = $this->getResponseStatusCodeFromException($e);
139 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\RequestException',['message'=>$e->getMessage(),'path request'=>$e->getRequest()->getUri()->getPath(),'method'=>$e->getRequest()->getMethod(),'response status code'=>$responseStatusCode]);
140
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\RequestException',['trace'=>$e->getTraceAsString()]);
141 3
            throw new \GuzzleHttp\Exception\RequestException($e->getMessage().' '.$responseStatusCode,$e->getRequest(),$e->getResponse(),$e,$e->getHandlerContext());
142
143 3
        } catch (\GuzzleHttp\Exception\TransferException $e) {
144 3
145 3
            $this->setLog(LogLevel::ERROR,'\GuzzleHttp\Exception\TransferException',['message'=>$e->getMessage(),'code'=>$e->getCode()]);
146
            $this->setLog(LogLevel::DEBUG,'\GuzzleHttp\Exception\TransferException',['trace'=>$e->getTraceAsString()]);
147 3
            throw new \GuzzleHttp\Exception\TransferException($e->getMessage(),$e->getCode(),$e);
148
149 3
        } catch (\RuntimeException $e) {
150 3
151 3
            $this->setLog(LogLevel::ERROR,'\RuntimeException',['message'=>$e->getMessage(),'code'=>$e->getCode()]);
152
            $this->setLog(LogLevel::DEBUG,'\RuntimeException',['trace'=>$e->getTraceAsString()]);
153
            throw new \RuntimeException($e->getMessage(),$e->getCode(),$e);
154
155 9
        }
156
157
        return $this->response;
158
    }
159
160
    /**
161
     * @param string $logLevel
162
     * @param string $message
163
     * @param null Array $context
164 15
     * @throws Exception
165
     */
166 15
    private function setLog($logLevel, $message, $context = null)
167 15
    {
168
        if(!isset($this->log)){
169
            return;
170
        }
171
        if(! is_array($context)){
172
            throw new Exception('$context must be an array',0);
173
        }
174
        $this->log->log($logLevel, $message, $context);
175
    }
176
177
    /**
178
     * @param $property
179 3
     * @return mixed
180 3
     */
181 3
    public function __get($property) {
182
        if (property_exists($this, $property)) {
183
            return $this->$property;
184
        }
185
    }
186
187
    /**
188
     * @param $property
189
     * @param $value
190
     */
191
    public function __set($property, $value) {
192
        if (property_exists($this, $property)) {
193
            $this->$property = $value;
194
        }
195
    }
196
197
    /**
198 15
     * Reset all variable to start new request.
199
     */
200 15
    public function reset()
201 15
    {
202
        $this->response = new Response();
203
    }
204
205
    /**
206
     * @param \Exception $e
207 6
     * @return string
208
     */
209 6
    public function getResponseStatusCodeFromException(\Exception $e)
210 3
    {
211
        if (null === $e->getResponse()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Exception as the method getResponse() does only exist in the following sub-classes of Exception: GuzzleHttp\Exception\BadResponseException, GuzzleHttp\Exception\ClientException, GuzzleHttp\Exception\ConnectException, GuzzleHttp\Exception\RequestException, GuzzleHttp\Exception\ServerException, GuzzleHttp\Exception\TooManyRedirectsException, Guzzle\Http\Exception\BadResponseException, Guzzle\Http\Exception\ClientErrorResponseException, Guzzle\Http\Exception\ServerErrorResponseException, Guzzle\Http\Exception\TooManyRedirectsException. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
212 6
            return '';
213
        }
214
        if (! is_a($e->getResponse(), '\GuzzleHttp\Psr7\Response')){
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Exception as the method getResponse() does only exist in the following sub-classes of Exception: GuzzleHttp\Exception\BadResponseException, GuzzleHttp\Exception\ClientException, GuzzleHttp\Exception\ConnectException, GuzzleHttp\Exception\RequestException, GuzzleHttp\Exception\ServerException, GuzzleHttp\Exception\TooManyRedirectsException, Guzzle\Http\Exception\BadResponseException, Guzzle\Http\Exception\ClientErrorResponseException, Guzzle\Http\Exception\ServerErrorResponseException, Guzzle\Http\Exception\TooManyRedirectsException. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
215
            return '';
216 6
        }
217 6
218
        $responseStatusCode = $e->getResponse()->getStatusCode();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Exception as the method getResponse() does only exist in the following sub-classes of Exception: GuzzleHttp\Exception\BadResponseException, GuzzleHttp\Exception\ClientException, GuzzleHttp\Exception\ConnectException, GuzzleHttp\Exception\RequestException, GuzzleHttp\Exception\ServerException, GuzzleHttp\Exception\TooManyRedirectsException, Guzzle\Http\Exception\BadResponseException, Guzzle\Http\Exception\ClientErrorResponseException, Guzzle\Http\Exception\ServerErrorResponseException, Guzzle\Http\Exception\TooManyRedirectsException. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
219
        return $responseStatusCode;
220
    }
221
222
    /**
223
     * Get psr7 headers array and return string representation.
224
     * @param \Psr\Http\Message\ResponseInterface
225 9
     * @return string
226
     */
227 9
    public function getHeadersString(\Psr\Http\Message\ResponseInterface $psr7response)
228 9
    {
229 9
        $strHeaders = '';
230
        if($psr7response === null)
231
        {
232
            return $strHeaders;
233 9
        }
234 9
235 6
        $arrHeaders = $psr7response->getHeaders();
236
        if (!is_array($arrHeaders) || count($arrHeaders) < 1) {
237
            return '';
238 3
        }
239
240 3
        foreach ($arrHeaders as $key => $value) {
241 3
242 3
            $strVal = '';
243
            if(is_array($value) && count($value)>0){
244 3
                $strVal = $value[0];
245
246
            }elseif (is_string($value)){
247
                $strVal = $value;
248 3
            }
249 3
250
            $strHeaders .= $key.':'.$strVal.PHP_EOL;
251 3
        }
252
253
        return $strHeaders;
254
    }
255
256
257
258
259
}
260