Issues (133)

src/Bpack247.php (4 issues)

1
<?php
2
3
namespace Bpost\BpostApiClient;
4
5
use Bpost\BpostApiClient\Bpack247\Customer;
6
use Bpost\BpostApiClient\Exception\BpostApiResponseException\BpostApiBusinessException;
7
use Bpost\BpostApiClient\Exception\BpostApiResponseException\BpostApiSystemException;
8
use Bpost\BpostApiClient\Exception\BpostApiResponseException\BpostCurlException;
9
use Bpost\BpostApiClient\Exception\BpostApiResponseException\BpostInvalidResponseException;
10
use DOMDocument;
11
use SimpleXMLElement;
12
13
/**
14
 * bPost Bpack24/7 class
15
 *
16
 * @author    Tijs Verkoyen <[email protected]>
17
 *
18
 * @version   3.0.0
19
 *
20
 * @copyright Copyright (c), Tijs Verkoyen. All rights reserved.
21
 * @license   BSD License
22
 */
23
class Bpack247
24
{
25
    // URL for the api
26
    const API_URL = 'http://www.bpack247.be/BpostRegistrationWebserviceREST/servicecontroller.svc';
27
28
    // current version
29
    const VERSION = '3.0.0';
30
31
    /**
32
     * The account id
33
     *
34
     * @var string
35
     */
36
    private $accountId;
37
38
    /**
39
     * A cURL instance
40
     *
41
     * @var resource
42
     */
43
    private $curl;
44
45
    /**
46
     * The passPhrase
47
     *
48
     * @var string
49
     */
50
    private $passPhrase;
51
52
    /**
53
     * The port to use.
54
     *
55
     * @var int
56
     */
57
    private $port;
0 ignored issues
show
The private property $port is not used, and could be removed.
Loading history...
58
59
    /**
60
     * The timeout
61
     *
62
     * @var int
63
     */
64
    private $timeOut = 30;
65
66
    /**
67
     * The user agent
68
     *
69
     * @var string
70
     */
71
    private $userAgent;
72
73
    /**
74
     * Make the call
75
     *
76
     * @param string $url    The URL to call.
77
     * @param string $body   The data to pass.
78
     * @param string $method The HTTP-method to use.
79
     *
80
     * @return SimpleXMLElement
81
     *
82
     * @throws BpostApiBusinessException
83
     * @throws BpostApiSystemException
84
     * @throws BpostCurlException
85
     * @throws BpostInvalidResponseException
86
     */
87
    private function doCall($url, $body = null, $method = 'GET')
88
    {
89
        // build Authorization header
90
        $headers = array();
91
        $headers[] = 'Authorization: Basic ' . $this->getAuthorizationHeader();
92
93
        // set options
94
        $options = array();
95
        $options[CURLOPT_URL] = self::API_URL . $url;
96
        $options[CURLOPT_USERAGENT] = $this->getUserAgent();
97
        $options[CURLOPT_RETURNTRANSFER] = true;
98
        $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
99
        $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
100
        $options[CURLOPT_HTTPHEADER] = $headers;
101
102
        if ($method == 'POST') {
103
            $options[CURLOPT_POST] = true;
104
            $options[CURLOPT_POSTFIELDS] = $body;
105
        }
106
107
        // init
108
        $this->curl = curl_init();
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_init() can also be of type CurlHandle. However, the property $curl is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
109
110
        // set options
111
        curl_setopt_array($this->curl, $options);
112
113
        // execute
114
        $response = curl_exec($this->curl);
115
        $headers = curl_getinfo($this->curl);
116
117
        // fetch errors
118
        $errorNumber = curl_errno($this->curl);
119
        $errorMessage = curl_error($this->curl);
120
121
        // error?
122
        if ($errorNumber != '') {
123
            throw new BpostCurlException($errorMessage, $errorNumber);
124
        }
125
126
        // valid HTTP-code
127
        if (!in_array($headers['http_code'], array(0, 200))) {
128
            $xml = @simplexml_load_string($response);
0 ignored issues
show
It seems like $response can also be of type true; however, parameter $data of simplexml_load_string() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

128
            $xml = @simplexml_load_string(/** @scrutinizer ignore-type */ $response);
Loading history...
129
130
            if (
131
                $xml !== false
132
                && ($xml->getName() == 'businessException' || $xml->getName() == 'systemException')
133
            ) {
134
                $message = (string) $xml->message;
135
                $code = isset($xml->code) ? (int) $xml->code : null;
136
                switch ($xml->getName()) {
137
                    case 'businessException':
138
                        throw new BpostApiBusinessException($message, $code);
139
                    case 'systemException':
140
                        throw new BpostApiSystemException($message, $code);
141
                }
142
            }
143
144
            throw new BpostInvalidResponseException('', $headers['http_code']);
145
        }
146
147
        // convert into XML
148
        $xml = simplexml_load_string($response);
149
150
        // validate
151
        if ($xml->getName() == 'businessException') {
152
            $message = (string) $xml->message;
153
            $code = (string) $xml->code;
154
            throw new BpostApiBusinessException($message, $code);
0 ignored issues
show
$code of type string is incompatible with the type integer expected by parameter $code of Bpost\BpostApiClient\Exc...xception::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

154
            throw new BpostApiBusinessException($message, /** @scrutinizer ignore-type */ $code);
Loading history...
155
        }
156
157
        // return the response
158
        return $xml;
159
    }
160
161
    /**
162
     * Generate the secret string for the Authorization header
163
     *
164
     * @return string
165
     */
166
    private function getAuthorizationHeader()
167
    {
168
        return base64_encode($this->accountId . ':' . $this->passPhrase);
169
    }
170
171
    /**
172
     * Set the timeout
173
     * After this time the request will stop. You should handle any errors triggered by this.
174
     *
175
     * @param int $seconds The timeout in seconds.
176
     */
177
    public function setTimeOut($seconds)
178
    {
179
        $this->timeOut = (int) $seconds;
180
    }
181
182
    /**
183
     * Get the timeout that will be used
184
     *
185
     * @return int
186
     */
187
    public function getTimeOut()
188
    {
189
        return (int) $this->timeOut;
190
    }
191
192
    /**
193
     * Get the useragent that will be used.
194
     * Our version will be prepended to yours.
195
     * It will look like: "PHP Bpost/<version> <your-user-agent>"
196
     *
197
     * @return string
198
     */
199
    public function getUserAgent()
200
    {
201
        return (string) 'PHP Bpost Bpack247/' . self::VERSION . ' ' . $this->userAgent;
202
    }
203
204
    /**
205
     * Set the user-agent for you application
206
     * It will be appended to ours, the result will look like: "PHP Bpost/<version> <your-user-agent>"
207
     *
208
     * @param string $userAgent Your user-agent, it should look like <app-name>/<app-version>.
209
     */
210
    public function setUserAgent($userAgent)
211
    {
212
        $this->userAgent = (string) $userAgent;
213
    }
214
215
    /**
216
     * Create Bpost instance
217
     *
218
     * @param string $accountId
219
     * @param string $passPhrase
220
     */
221
    public function __construct($accountId, $passPhrase)
222
    {
223
        $this->accountId = (string) $accountId;
224
        $this->passPhrase = (string) $passPhrase;
225
    }
226
227
    // webservice methods
228
    /**
229
     * @param Customer $customer
230
     *
231
     * @return SimpleXMLElement
232
     *
233
     * @throws BpostApiBusinessException
234
     * @throws BpostApiSystemException
235
     * @throws BpostCurlException
236
     * @throws BpostInvalidResponseException
237
     */
238
    public function createMember(Customer $customer)
239
    {
240
        $url = '/customer';
241
242
        $document = new DOMDocument('1.0', 'utf-8');
243
        $document->preserveWhiteSpace = false;
244
        $document->formatOutput = true;
245
246
        $document->appendChild(
247
            $customer->toXML(
248
                $document
249
            )
250
        );
251
252
        return $this->doCall(
253
            $url,
254
            $document->saveXML(),
255
            'POST'
256
        );
257
    }
258
259
    /**
260
     * Retrieve member information
261
     *
262
     * @param string $id
263
     *
264
     * @return Customer
265
     *
266
     * @throws BpostApiBusinessException
267
     * @throws BpostApiSystemException
268
     * @throws BpostCurlException
269
     * @throws BpostInvalidResponseException
270
     * @throws Exception\XmlException\BpostXmlNoUserIdFoundException
271
     */
272
    public function getMember($id)
273
    {
274
        $xml = $this->doCall(
275
            '/customer/' . $id
276
        );
277
278
        return Customer::createFromXML($xml);
279
    }
280
}
281