Issues (77)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Smsa.php (19 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of Smsa WebService package.
5
 * (c) Hamoud Alhoqbani <[email protected]>
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Alhoqbani\SmsaWebService;
11
12
use Alhoqbani\SmsaWebService\Exceptions\FailedResponse;
13
use Alhoqbani\SmsaWebService\Exceptions\RequestError;
14
use Alhoqbani\SmsaWebService\Models\Shipment;
15
use Alhoqbani\SmsaWebService\Response\SMSAResponse;
16
use Alhoqbani\SmsaWebService\Soap\ClassMap;
17
use Alhoqbani\SmsaWebService\Soap\Service;
18
use Alhoqbani\SmsaWebService\Soap\Type\CancelShipment;
19
use Alhoqbani\SmsaWebService\Soap\Type\GetAllRetails;
20
use Alhoqbani\SmsaWebService\Soap\Type\GetPDF;
21
use Alhoqbani\SmsaWebService\Soap\Type\GetRTLCities;
22
use Alhoqbani\SmsaWebService\Soap\Type\GetRTLRetails;
23
use Alhoqbani\SmsaWebService\Soap\Type\GetStatus;
24
use Alhoqbani\SmsaWebService\Soap\Type\GetTrackingByRef;
25
use Alhoqbani\SmsaWebService\Soap\Type\GetTrackingwithRef;
26
use WsdlToPhp\PackageBase\AbstractSoapClientBase;
27
use WsdlToPhp\PackageBase\AbstractStructBase;
28
29
class Smsa
30
{
31
32
    /**
33
     * Weather to throw exceptions when there is a request error or a failed response from SMSA.
34
     *
35
     * @var bool
36
     */
37
    public $shouldUseExceptions = true;
38
39
    /**
40
     * @var \Alhoqbani\SmsaWebService\Soap\Service
41
     */
42
    protected $service;
43
44
    /**
45
     * @var string
46
     */
47
    private $passKey;
48
49
    /**
50
     * Create a new Smsa Instance
51
     *
52
     * @param string                 $passKey The pass key to the api provided by Smsa.
53
     * @param array|null             $options WSDL option to be passed to SoapClient.
54
     * @param AbstractSoapClientBase $service The service which provide SMSA api methods.
55
     */
56
    public function __construct(
57
        string $passKey = 'Testing0',
58
        array $options = [],
59
        AbstractSoapClientBase $service = null
60
    ) {
61
        $this->passKey = $passKey;
62
63
        $options = array_merge([
64
            AbstractSoapClientBase::WSDL_URL      => 'http://track.smsaexpress.com/SECOM/SMSAwebService.asmx?WSDL',
65
            AbstractSoapClientBase::WSDL_CLASSMAP => ClassMap::get(),
66
        ], $options);
67
68
        $this->service = $service ?? new Service($options);
0 ignored issues
show
Documentation Bug introduced by
$service ?? new \Alhoqba...\Soap\Service($options) is of type object<WsdlToPhp\Package...AbstractSoapClientBase>, but the property $service was declared to be of type object<Alhoqbani\SmsaWebService\Soap\Service>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof 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 given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
69
    }
70
71
    /**
72
     * Fetch all cities that has SMSAExpress locations
73
     *
74
     * @throws RequestError
75
     *
76
     * @return SMSAResponse with array of cities with their route code.
77
     */
78 View Code Duplication
    public function cities(): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79
    {
80
        $result = $this->service->getRTLCities(
81
            $payload = new GetRTLCities($this->passKey)
82
        );
83
84
        if (false === $result) {
85
            return $this->failedRequest('getRTLCities', $payload);
86
        }
87
88
        return $this->successResponse(
89
            'getRTLCities',
90
            $payload,
91
            $this->parseCityResult($result->getGetRTLCitiesResult()->getAny())
0 ignored issues
show
The method getGetRTLCitiesResult does only exist in Alhoqbani\SmsaWebService...pe\GetRTLCitiesResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
92
        );
93
    }
94
95
    /**
96
     * Fetch all retails in a particular city.
97
     * The city code is the three letters route code
98
     * For example: RUH, JED
99
     *
100
     * @param $cityCode
101
     *
102
     * @throws RequestError
103
     *
104
     * @return SMSAResponse with array of retails in given city.
105
     */
106 View Code Duplication
    public function retailsIn($cityCode): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
    {
108
        $result = $this->service->getRTLRetails(
109
            $payload = new GetRTLRetails($cityCode, $this->passKey)
110
        );
111
112
        if (false === $result) {
113
            return $this->failedRequest('getRTLCities', $payload);
114
        }
115
116
        return $this->successResponse(
117
            'getRTLCities',
118
            $payload,
119
            $this->parseRetailsResult($result->getGetRTLRetailsResult()->getAny())
0 ignored issues
show
The method getGetRTLRetailsResult does only exist in Alhoqbani\SmsaWebService...e\GetRTLRetailsResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
120
        );
121
    }
122
123
    /**
124
     * Fetch all Smsa Express retails
125
     *
126
     * @throws RequestError
127
     *
128
     * @return SMSAResponse with list of all retails with details
129
     */
130 View Code Duplication
    public function retails(): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
    {
132
        $result = $this->service->getAllRetails(
133
            $payload = new GetAllRetails($this->passKey)
134
        );
135
136
        if (false === $result) {
137
            return $this->failedRequest('getAllRetails', $payload);
138
        }
139
140
        return $this->successResponse(
141
            'getAllRetails',
142
            $payload,
143
            $this->parseRetailsResult($result->getGetAllRetailsResult()->getAny())
0 ignored issues
show
The method getGetAllRetailsResult does only exist in Alhoqbani\SmsaWebService...e\GetAllRetailsResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
144
        );
145
    }
146
147
    /**
148
     * Track a shipment by its awb
149
     *
150
     * @param $awb
151
     *
152
     * @throws \Alhoqbani\SmsaWebService\Exceptions\RequestError
153
     * @throws \Alhoqbani\SmsaWebService\Exceptions\FailedResponse
154
     *
155
     * @return SMSAResponse
156
     */
157
    public function track($awb): SMSAResponse
158
    {
159
        $result = $this->service->getTrackingwithRef(
160
            $payload = new GetTrackingwithRef($awb, $this->passKey)
161
        );
162
163
        if (false === $result) {
164
            return $this->failedRequest('GetTrackingwithRef', $payload);
165
        }
166
167
        $result = $result->getGetTrackingwithRefResult();
0 ignored issues
show
The method getGetTrackingwithRefResult does only exist in Alhoqbani\SmsaWebService...TrackingwithRefResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
168
169
        if (is_null($result)) {
170
            return $this->failedResponse('GetTrackingwithRef', $payload, 'The awb provided is not correct.');
171
        }
172
173
        $track = $this->parseTrackResult($result->getAny());
174
175
        if (empty($track)) {
176
            return $this->failedResponse('GetTrackingwithRef', $payload, 'No shipment with provided awb.');
177
        }
178
179
        return $this->successResponse(
180
            'GetTrackingwithRef',
181
            $payload,
182
            $track
183
        );
184
    }
185
186
    /**
187
     * Get the real-time tracking information of the shipment
188
     *
189
     * @param string $reference Customer reference number
190
     *
191
     * @todo This is not working
192
     *
193
     * @throws FailedResponse
194
     * @throws RequestError
195
     *
196
     * @return SMSAResponse
197
     */
198 View Code Duplication
    public function trackByReference(string $reference)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
199
    {
200
        $result = $this->service->getTrackingByRef(
201
            $payload = new GetTrackingByRef($reference, $this->passKey)
202
        );
203
204
        if (false === $result) {
205
            return $this->failedRequest('GetTrackingwithRef', $payload);
206
        }
207
208
        $data = $result->getGetTrackingByRefResult();
0 ignored issues
show
The method getGetTrackingByRefResult does only exist in Alhoqbani\SmsaWebService...etTrackingByRefResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
209
210
        if (is_null($data)) {
211
            return $this->failedResponse('GetTrackingwithRef', $payload, 'Shipment was not found');
212
        }
213
214
        return $this->successResponse(
215
            'GetTrackingwithRef',
216
            $payload,
217
            $data->getAny()
218
        );
219
    }
220
221
    /**
222
     * @param $awb
223
     *
224
     * @throws FailedResponse
225
     * @throws RequestError
226
     *
227
     * @return SMSAResponse
228
     */
229 View Code Duplication
    public function status($awb): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
    {
231
        $result = $this->service->getStatus(
232
            $payload = new GetStatus($awb, $this->passKey)
233
        );
234
235
        if (false === $result) {
236
            return $this->failedRequest('GetStatus', $payload);
237
        }
238
239
        $status = $result->getGetStatusResult();
0 ignored issues
show
The method getGetStatusResult does only exist in Alhoqbani\SmsaWebService...\Type\GetStatusResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
240
241
        if (empty($status) || is_null($status)) {
242
            return $this->failedResponse('GetStatus', $payload, 'No status, shipment was not found');
243
        }
244
245
        if (0 === strpos(mb_strtolower($status), 'failed')) {
246
            return $this->failedResponse('GetStatus', $payload, $status);
247
        }
248
249
        return $this->successResponse(
250
            'GetStatus',
251
            $payload,
252
            $status
253
        );
254
    }
255
256
    /**
257
     * Cancel a shipment by AWB
258
     *
259
     * @param $awb string
260
     * @param $reason string
261
     *
262
     * @throws FailedResponse
263
     * @throws RequestError
264
     *
265
     * @return SMSAResponse
266
     */
267 View Code Duplication
    public function cancel($awb, $reason): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
268
    {
269
        $result = $this->service->cancelShipment(
270
            $payload = new CancelShipment($awb, $this->passKey, $reason)
271
        );
272
273
        if (false === $result) {
274
            return $this->failedRequest('CancelShipment', $payload);
275
        }
276
277
        $data = $result->getCancelShipmentResult();
0 ignored issues
show
The method getCancelShipmentResult does only exist in Alhoqbani\SmsaWebService...\CancelShipmentResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
278
279
        if (empty($data) || is_null($data)) {
280
            return $this->failedResponse('CancelShipment', $payload, 'Cannot Cancel, shipment was not found');
281
        }
282
283
        if (0 === strpos(mb_strtolower($data), 'failed')) {
284
            return $this->failedResponse('CancelShipment', $payload, $data);
285
        }
286
287
        return $this->successResponse(
288
            'CancelShipment',
289
            $payload,
290
            $data
291
        );
292
    }
293
294
    /**
295
     * Create a new shipment
296
     *
297
     * @param Shipment $shipment
298
     *
299
     * @throws FailedResponse
300
     * @throws RequestError
301
     *
302
     * @return SMSAResponse
303
     */
304
    public function createShipment(Shipment $shipment): SMSAResponse
305
    {
306
        $payload = $shipment->getTypeObject($this->passKey);
307
308
        $method = $shipment->getServiceMethod();
309
310
        $result = call_user_func([$this->service, $method], $payload);
311
312
        if (false === $result) {
313
            return $this->failedRequest($method, $payload);
314
        }
315
316
        $data = $result->{"get{$method}Result"}();
317
318
        if (0 === strpos(mb_strtolower($data), 'failed')) {
319
            return $this->failedResponse($method, $payload, $data);
320
        }
321
322
        return $this->successResponse($method, $payload, $data);
323
    }
324
325
    /**
326
     * Get AWB in PDF for printing
327
     * This method can be used to get the AWB Copy in PDF format for printing and labeling on shipment.
328
     *
329
     * @param $awb string
330
     *
331
     * @throws RequestError
332
     * @throws FailedResponse
333
     *
334
     * @return SMSAResponse
335
     */
336 View Code Duplication
    public function awbPDF(string $awb): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
    {
338
        $result = $this->service->getPDF(
339
            $payload = new GetPDF($awb, $passKey ?? $this->passKey)
340
        );
341
342
        if (false === $result) {
343
            return $this->failedRequest('GetPDF', $payload);
344
        }
345
346
        $data = $result->getGetPDFResult();
0 ignored issues
show
The method getGetPDFResult does only exist in Alhoqbani\SmsaWebService\Soap\Type\GetPDFResponse, but not in Alhoqbani\SmsaWebService...ype\StoShipmentResponse.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
347
348
        if (empty($data) || is_null($data)) {
349
            return $this->failedResponse('GetPDF', $payload, 'Cannot print pdf, shipment was not found');
350
        }
351
352
        return $this->successResponse(
353
            'GetPDF',
354
            $payload,
355
            $data
356
        );
357
    }
358
359
    /**
360
     * Parse the cities xml response into array
361
     *
362
     * @param string $citiesResult
363
     *
364
     * @return array Array of cities with its names and route code
365
     */
366
    protected function parseCityResult(string $citiesResult): array
367
    {
368
        $xml = simplexml_load_string($citiesResult);
369
        $cities = [];
370
371
        foreach ($xml->NewDataSet[0]->RetailCities as $city) {
372
            $cities[] = [
373
                'name'      => (string) $city->rCity,
374
                'routeCode' => (string) $city->routCode,
375
            ];
376
        }
377
378
        return $cities;
379
    }
380
381
    /**
382
     * Parse retails xml response into an array
383
     *
384
     * @param string $retailsResult
385
     *
386
     * @return array array of retails with their details
387
     */
388
    private function parseRetailsResult(string $retailsResult): array
389
    {
390
        $xml = simplexml_load_string($retailsResult);
391
        $retails = [];
392
393
        if ($xml->count() > 0) {
394
            foreach ($xml->NewDataSet[0]->RetailsList as $retail) {
395
                $retails[] = [
396
                    'code'       => (string) $retail->rCode,
397
                    'route_code' => (string) $retail->routCode,
398
                    'city'       => (string) $retail->rCity,
399
                    'address_en' => (string) $retail->rAddrEng,
400
                    'address_ar' => (string) $retail->rAddrAr,
401
                    'gps_point'  => (string) $retail->rGPSPt,
402
                    'phone'      => (string) $retail->rPhone,
403
                ];
404
            }
405
        }
406
407
        return $retails;
408
    }
409
410
    /**
411
     * Parse a tracking xml response
412
     *
413
     * @param string $result
414
     *
415
     * @return array Details of the tracking
416
     */
417
    private function parseTrackResult(string $result): array
418
    {
419
        $xml = simplexml_load_string($result);
420
421
        if ($xml->count() > 0) {
422
            $track = $xml->NewDataSet[0]->Tracking;
423
424
            return [
425
                'awb'       => (string) $track->awbNo,
426
                'date'      => (string) $track->Date,
427
                'activity'  => (string) $track->Activity,
428
                'details'   => (string) $track->Details,
429
                'location'  => (string) $track->Location,
430
                'reference' => (string) $track->refNo,
431
            ];
432
        }
433
434
        return [];
435
    }
436
437
    /**
438
     * Return a successful response with the data.
439
     *
440
     * @param $type string The type/function of the SOAP Api used.
441
     * @param $payload AbstractStructBase The object that was sent to the SoapClient
442
     * @param $data mixed
443
     *
444
     * @return SMSAResponse
445
     */
446 View Code Duplication
    protected function successResponse($type, $payload, $data): SMSAResponse
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
447
    {
448
        $response = new SMSAResponse(
449
            true,
450
            $data,
451
            null,
452
            $type,
453
            $payload,
454
            $this->service->getLastRequest(true),
455
            $this->service->getLastResponse(true)
456
        );
457
458
        return $response;
459
    }
460
461
    /**
462
     * Send a Response with failed request.
463
     *
464
     * @param $type string The type/function of the SOAP Api used.
465
     * @param $payload AbstractStructBase The object that was sent to the SoapClient
466
     *
467
     * @throws \Alhoqbani\SmsaWebService\Exceptions\RequestError
468
     *
469
     * @return SMSAResponse
470
     */
471
    protected function failedRequest($type, $payload)
472
    {
473
        $errors = $this->service->getLastError();
474
        $error = array_shift($errors);
475
476
        $response = new SMSAResponse(
477
            false,
478
            null,
479
            $error,
480
            $type,
481
            $payload,
482
            $this->service->getLastRequest(true),
483
            $this->service->getLastResponse(true)
484
        );
485
486
        if ($this->shouldUseExceptions()) {
487
            $this->throwRequestError($response);
488
        }
489
490
        return $response;
491
    }
492
493
    /**
494
     * Return a failed response. (Usually, wrong data was sent to SMSA Api)
495
     *
496
     * @param $type string The type/function of the SOAP Api used
497
     * @param $payload AbstractStructBase The object that was sent to the SoapClient
498
     * @param $error string The error message from SMSA.
499
     *
500
     * @throws FailedResponse
501
     *
502
     * @return SMSAResponse
503
     */
504 View Code Duplication
    protected function failedResponse($type, $payload, $error)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
505
    {
506
        $response = new SMSAResponse(
507
            false,
508
            null,
509
            $error,
510
            $type,
511
            $payload,
512
            $this->service->getLastRequest(true),
513
            $this->service->getLastResponse(true)
514
        );
515
516
        if ($this->shouldUseExceptions()) {
517
            throw new FailedResponse($response, $error);
518
        }
519
520
        return $response;
521
    }
522
523
    protected function shouldUseExceptions()
524
    {
525
        return $this->shouldUseExceptions;
526
    }
527
528
    /**
529
     * To handle response error from Smsa Soap server
530
     *
531
     * @param SMSAResponse $response
532
     *
533
     * @throws RequestError
534
     */
535
    protected function throwRequestError(SMSAResponse $response): void
536
    {
537
        $errors = $this->service->getLastError();
538
        $soapFault = array_shift($errors);
539
540
        if ($soapFault instanceof \SoapFault) {
541
            throw new RequestError($response, $soapFault->faultstring, $soapFault->getCode(), $soapFault);
0 ignored issues
show
The property faultstring does not seem to exist. Did you mean string?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
542
        }
543
544
        throw new RequestError($response, 'Smsa request failed with unknown error');
545
    }
546
}
547