Request::setTemplate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace ThreePlCentral;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Psr7;
7
8
class Request implements RequestInterface
9
{
10
    private $id;
11
    private $customerId;
12
    private $facilityId;
13
    private $login;
14
    private $password;
15
    private $method;
16
    private $url;
17
    private $template;
18
19
    public function __construct($method, $url)
20
    {
21
        $this->method = $method;
22
        $this->url = $url;
23
    }
24
25
    public function fetch(array $data)
26
    {
27
        $client = new Client();
28
        $request = new Psr7\Request(
29
            $this->method,
30
            'https://secure-wms.com/webserviceexternal/contracts.asmx',
31
            [
32
                'SOAPAction' => $this->url,
33
                'Content-Type' => 'text/xml; charset=utf-8'
34
            ],
35
            $this->getBody($data)
36
        );
37
38
        try {
39
            $reponse = $client->send($request);
40
        } catch (\Exception $error) {
41
            $response = new Response($error->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. 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...
42
            throw new Exception($response->json()['error'], $error->getCode(), $error);
43
        }
44
        
45
        return new Response($reponse);
46
    }
47
48
    private function getBody(array $data)
49
    {
50
        $content = file_get_contents($this->template);
51
52
        $data = array_merge($data, [
53
          'ThreePLID' => $this->getId(),
54
          'Login' => $this->getLogin(),
55
          'Password' => $this->getPassword(),
56
          'CustomerID' => $this->getCustomerId(),
57
          'FacilityID' => $this->getFacilityId()
58
        ]);
59
60
        foreach ($data as $prop => $value) {
61
            $content = str_replace("{{$prop}}", $value, $content);
62
        }
63
64
        return $content;
65
    }
66
67
    public function setTemplate($template)
68
    {
69
        $this->template = $template;
70
    }
71
72
    public function getId()
73
    {
74
        return $this->id;
75
    }
76
77
    public function setId($id)
78
    {
79
        $this->id = $id;
80
    }
81
82
    public function getCustomerId()
83
    {
84
        return $this->customerId;
85
    }
86
87
    public function setCustomerId($customerId)
88
    {
89
        $this->customerId = $customerId;
90
    }
91
92
    public function getFacilityId()
93
    {
94
        return $this->facilityId;
95
    }
96
97
    public function setFacilityId($facilityId)
98
    {
99
        $this->facilityId = $facilityId;
100
    }
101
102
    public function getLogin()
103
    {
104
        return $this->login;
105
    }
106
107
    public function setLogin($login)
108
    {
109
        $this->login = $login;
110
    }
111
112
    public function getPassword()
113
    {
114
        return $this->password;
115
    }
116
117
    public function setPassword($password)
118
    {
119
        $this->password = $password;
120
    }
121
122
    public function getUrl()
123
    {
124
        return $this->url;
125
    }
126
}
127