Calculator::from()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace MelhorEnvio\Resources\Shipment;
4
5
use GuzzleHttp\Exception\ClientException;
6
use InvalidArgumentException;
7
use MelhorEnvio\Exceptions\CalculatorException;
8
use MelhorEnvio\Exceptions\InvalidCalculatorPayloadException;
9
use MelhorEnvio\Exceptions\InvalidResourceException;
10
use MelhorEnvio\Exceptions\InvalidVolumeException;
11
use MelhorEnvio\Resources\Resource;
12
use MelhorEnvio\Validations\Location;
13
use MelhorEnvio\Validations\Number;
14
15
class Calculator
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $payload = [];
21
22
    /**
23
     * @var Resource
24
     */
25
    protected $resource;
26
27
    /**
28
     * New Calculate instance.
29
     * @param $resource
30
     * @throws InvalidArgumentException
31
     */
32
    public function __construct($resource)
33
    {
34
        if (! $resource instanceof Resource) {
35
            throw new InvalidResourceException;
36
        }
37
38
        $this->resource = $resource;
39
    }
40
41
    /**
42
     * @param $postalCode
43
     * @throws InvalidArgumentException
44
     */
45
    public function from($postalCode)
46
    {
47
        $this->addPostalCodeInPayload('from', $postalCode);
48
    }
49
50
    /**
51
     * @param  $postalCode
52
     * @throws InvalidArgumentException
53
     */
54
    public function to($postalCode)
55
    {
56
        $this->addPostalCodeInPayload('to', $postalCode);
57
    }
58
59
    /**
60
     * @param int|string $from
61
     * @param int|string $to
62
     */
63
    public function postalCode($from, $to)
64
    {
65
        $this->addPostalCodeInPayload('from', $from);
66
        $this->addPostalCodeInPayload('to', $to);
67
    }
68
69
    /**
70
     * @param string $key
71
     * @param $postalCode
72
     * @throws InvalidArgumentException
73
     */
74
    protected function addPostalCodeInPayload($key, $postalCode)
75
    {
76
        if (! $this->isValidPostalCode($postalCode)) {
77
            throw new InvalidArgumentException($key);
78
        }
79
80
        $this->payload[$key]['postal_code'] = $postalCode;
81
    }
82
83
    /**
84
     * @param  $products
85
     * @throws InvalidArgumentException
86
     */
87
    public function addProducts($products)
88
    {
89
        $products = is_array($products) ? $products : func_get_args();
90
91
        foreach ($products as $product) {
92
            $this->addProduct($product);
93
        }
94
    }
95
96
    /**
97
     * @param  $packages
98
     * @throws InvalidArgumentException
99
     */
100
    public function addPackages($packages)
101
    {
102
        $packages = is_array($packages) ? $packages : func_get_args();
103
104
        foreach ($packages as $package) {
105
            $this->addPackage($package);
106
        }
107
    }
108
109
    /**
110
     * @param Package $package
111
     * @throws InvalidVolumeException
112
     */
113
    public function addPackage($package)
114
    {
115
        if (! $this->isValidPackage($package)) {
116
            throw new InvalidVolumeException('package');
117
        }
118
119
        $this->payload['volumes'][] = $package->toArray();
120
    }
121
122
    /**
123
     * @param Product $product
124
     * @throws InvalidVolumeException
125
     */
126
    public function addProduct($product)
127
    {
128
        if (! $this->isValidProduct($product)) {
129
            throw new InvalidVolumeException('product');
130
        }
131
132
        $this->payload['products'][] = $product->toArray();
133
    }
134
135
    /**
136
     * @param $services
137
     * @throws InvalidArgumentException
138
     */
139
    public function addServices($services)
140
    {
141
        $services = is_array($services) ? $services : func_get_args();
142
143
        foreach ($services as $service) {
144
            $this->addService($service);
145
        }
146
    }
147
148
    /**
149
     * @param int $service
150
     * @throws InvalidArgumentException
151
     */
152
    public function addService($service)
153
    {
154
        if (! $this->isValidService($service)) {
155
            throw new InvalidArgumentException('service');
156
        }
157
158
        if (! isset($this->payload['services'])) {
159
            $this->payload['services'] = $service;
160
        } else {
161
            $this->payload['services'] .= ',' . $service;
162
        }
163
    }
164
165
    /**
166
     * Add Receipt in payload options
167
     * @param  $receipt
168
     * @throws InvalidArgumentException
169
     */
170
    public function setReceipt($receipt = true)
171
    {
172
        if (! is_bool($receipt)) {
173
            throw new InvalidArgumentException('receipt');
174
        }
175
176
        $this->payload['options']['receipt'] = $receipt;
177
    }
178
179
    /**
180
     * Add own hand in payload options
181
     * @param  $ownHand
182
     * @throws InvalidArgumentException
183
     */
184
    public function setOwnHand($ownHand = true)
185
    {
186
        if (! is_bool($ownHand)) {
187
            throw new InvalidArgumentException('own_hand');
188
        }
189
190
        $this->payload['options']['own_hand'] = $ownHand;
191
    }
192
193
    /**
194
     * Add collect in payload options
195
     * @param bool $collect
196
     * @throws InvalidArgumentException
197
     */
198
    public function setCollect($collect = true)
199
    {
200
        if (! is_bool($collect)) {
0 ignored issues
show
introduced by
The condition is_bool($collect) is always true.
Loading history...
201
            throw new InvalidArgumentException('collect');
202
        }
203
204
        $this->payload['options']['collect'] = $collect;
205
    }
206
207
    /**
208
     * @param $postalCode
209
     * @return bool
210
     */
211
    public function isValidPostalCode($postalCode)
212
    {
213
        return Location::isPostalCode($postalCode);
214
    }
215
216
    /**
217
     * @param Product $product
218
     * @return bool
219
     */
220
    public function isValidProduct($product)
221
    {
222
        return $product instanceof Product && $product->isValid();
223
    }
224
225
    /**
226
     * @param Package $package
227
     * @return bool
228
     */
229
    public function isValidPackage($package)
230
    {
231
        return $package instanceof Package && $package->isValid();
232
    }
233
234
    /**
235
     * @param $service
236
     * @return bool
237
     */
238
    protected function isValidService($service)
239
    {
240
        return Number::isPositiveInteger($service);
241
    }
242
243
    /**
244
     * @return void
245
     * @throws InvalidCalculatorPayloadException
246
     */
247
    protected function validatePayload()
248
    {
249
        if (empty($this->payload['from']['postal_code']) || empty($this->payload['to']['postal_code'])) {
250
            throw new InvalidCalculatorPayloadException('The CEP is invalid.');
251
        }
252
253
        if (empty($this->payload['volumes']) && empty($this->payload['products'])) {
254
            throw new InvalidCalculatorPayloadException('There are no defined products or volumes.');
255
        }
256
257
        if (! empty($this->payload['volumes']) && ! empty($this->payload['products'])) {
258
            throw new InvalidCalculatorPayloadException('Products and volumes cannot be defined together in the same payload.');
259
        }
260
    }
261
262
    /**
263
     * @return array
264
     */
265
    public function getPayload()
266
    {
267
        return $this->payload;
268
    }
269
270
    /**
271
     * @throws InvalidCalculatorPayloadException|CalculatorException
272
     */
273
    public function calculate()
274
    {
275
        $this->validatePayload();
276
277
        try {
278
            $response = $this->resource->getHttp()->post('me/shipment/calculate', [
279
                'json' => $this->payload,
280
            ]);
281
282
            return json_decode((string) $response->getBody(), true);
283
        } catch (ClientException $exception) {
284
            throw new CalculatorException($exception);
285
        }
286
    }
287
288
    /**
289
     * @return false|string
290
     */
291
    public function __toString()
292
    {
293
        return json_encode($this->getPayload());
294
    }
295
}
296