Passed
Push — master ( cbde3b...f22511 )
by Abishek R
02:33
created

Recurring::getAmount()   A

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
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Greenlyst\BaseCommerce\Models;
6
7
use Carbon\Carbon;
8
use Carbon\CarbonInterface;
9
use Greenlyst\BaseCommerce\ClientException;
10
use Greenlyst\BaseCommerce\Core\Helpers;
11
use Greenlyst\BaseCommerce\LogicException;
12
use Greenlyst\BaseCommerce\Traits\{HasClient, HasCustomFields, HasErrorMessages};
13
use function ArrayHelpers\array_get;
14
15
final class Recurring
16
{
17
    use HasErrorMessages, HasCustomFields, HasClient;
18
19
    private $frequency;
20
21
    /**
22
     * @var Carbon
23
     */
24
    private $startDate;
25
    /**
26
     * @var Carbon
27
     */
28
    private $endDate;
29
    private $status;
30
    private $transactionId;
31
    private $card;
32
    private $amount;
33
34
    const FREQUENCY_ANNUALLY = 'ANNUALLY';
35
    const FREQUENCY_QUARTERLY = 'QUARTERLY';
36
    const FREQUENCY_MONTHLY = 'MONTHLY';
37
    const FREQUENCY_BIWEEKLY = 'BIWEEKLY';
38
    const FREQUENCY_WEEKLY = 'WEEKLY';
39
    const FREQUENCY_DAILY = 'DAILY';
40
41
    const RECURRING_STATUS_ENABLED = 'RECURRINGENABLED';
42
    const RECURRING_STATUS_FAILED = 'RECURRINGFAILED';
43
    const RECURRING_STATUS_DISABLED = 'RECURRINGDISABLED';
44
    const RECURRING_STATUS_COMPLETED = 'RECURRINGCOMPLETED';
45
46
    const CUSTOM_FIELD_PREFIX = 'recurring_transaction';
47
48
    const URI_CREATE_RECURRING_TRANSACTION = '/pcms/?f=API_processRecurringTransaction';
49
    const URI_CANCEL_RECURRING_TRANSACTION = '/pcms/?f=API_cancelRecurringTransaction';
50
51
    const TRANSACTION_TYPE_SALE = 'SALE';
52
53
    /**
54
     * @return mixed
55
     */
56
    public function getFrequency()
57
    {
58
        return $this->frequency;
59
    }
60
61
    /**
62
     * @param mixed $frequency
63
     */
64
    public function setFrequency($frequency): void
65
    {
66
        $this->frequency = $frequency;
67
    }
68
69
    /**
70
     * @return string
71
     */
72
    public function getStartDate()
73
    {
74
        if ($this->startDate == null) {
75
            return Carbon::now()->addDay()->format('m/d/Y');
76
        }
77
78
        return $this->startDate->addDay()->format('m/d/Y');
79
    }
80
81
    /**
82
     * @param CarbonInterface $startDate
83
     */
84
    public function setStartDate(CarbonInterface $startDate): void
85
    {
86
        $this->startDate = $startDate;
0 ignored issues
show
Documentation Bug introduced by
$startDate is of type Carbon\CarbonInterface, but the property $startDate was declared to be of type Carbon\Carbon. 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...
87
    }
88
89
    /**
90
     * @return CarbonInterface
91
     */
92
    public function getEndDate()
93
    {
94
        return $this->endDate;
95
    }
96
97
    /**
98
     * @param CarbonInterface $endDate
99
     */
100
    public function setEndDate(CarbonInterface $endDate): void
101
    {
102
        $this->endDate = $endDate;
0 ignored issues
show
Documentation Bug introduced by
$endDate is of type Carbon\CarbonInterface, but the property $endDate was declared to be of type Carbon\Carbon. 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...
103
    }
104
105
    /**
106
     * @return mixed
107
     */
108
    public function getStatus()
109
    {
110
        return $this->status;
111
    }
112
113
    /**
114
     * @param mixed $status
115
     */
116
    public function setStatus($status): void
117
    {
118
        $this->status = $status;
119
    }
120
121
    /**
122
     * @return mixed
123
     */
124
    public function getTransactionId()
125
    {
126
        return $this->transactionId;
127
    }
128
129
    /**
130
     * @param mixed $transactionId
131
     */
132
    public function setTransactionId($transactionId): void
133
    {
134
        $this->transactionId = $transactionId;
135
    }
136
137
    /**
138
     * @return Card
139
     */
140
    public function getCard()
141
    {
142
        return $this->card;
143
    }
144
145
    /**
146
     * @param Card $card
147
     */
148
    public function setCard($card): void
149
    {
150
        $this->card = $card;
151
    }
152
153
    /**
154
     * @return mixed
155
     */
156
    public function getAmount()
157
    {
158
        return $this->amount;
159
    }
160
161
    /**
162
     * @param mixed $amount
163
     */
164
    public function setAmount($amount): void
165
    {
166
        $this->amount = $amount;
167
    }
168
169
    protected function getCustomFieldPrefix(): string
170
    {
171
        return self::CUSTOM_FIELD_PREFIX;
172
    }
173
174
    private function isVaultTransaction()
175
    {
176
        if ($this->getCard() !== null) {
177
            return !empty($this->getCard()->getToken());
178
        }
179
180
        //TODO: Do the same for ACH Bank Account Token as well
181
        return false;
182
    }
183
184
    private function isCardTransaction()
185
    {
186
        return $this->getCard() !== null;
187
    }
188
189
    /**
190
     * @throws LogicException
191
     * @throws ClientException
192
     */
193
    public function createRecurringSale()
194
    {
195
        if ($this->isCardTransaction()) {
196
            if ($this->isVaultTransaction()) {
197
                validate_array($this->toCreateRecurringArray(), [
198
                    'bank_card', 'recurring_transaction_frequency', 'recurring_transaction_start_date',
199
                    'bank_card.bank_card_token'
200
                ]);
201
            }
202
        } else {
203
            throw LogicException::pendingImplementation('ACH Bank Transaction implementation');
204
        }
205
206
        $response = $this->client->postRequest(self::URI_CREATE_RECURRING_TRANSACTION, json_encode($this->toCreateRecurringArray()));
207
208
        $instance = $this->fromRecurringArray($response['recurring_transaction']);
209
210
        $instance->handleMessages($response);
211
212
        return $instance;
213
    }
214
215
    /**
216
     * @throws LogicException
217
     * @throws ClientException
218
     */
219
    public function cancelRecurringSale()
220
    {
221
        Helpers::validateArray($this->toCancelRecurringArray(), ['recurring_transaction_id']);
222
223
        $response = $this->client->postRequest(self::URI_CANCEL_RECURRING_TRANSACTION, array_get($this->toCancelRecurringArray(), 'recurring_transaction_id'));
224
225
        $instance = $this->fromRecurringArray($response['recurring_transaction']);
226
227
        $instance->handleMessages($response);
228
229
        return $instance;
230
    }
231
232
    private function fromRecurringArray(array $data)
233
    {
234
        $instance = new static();
235
236
        $instance->setFrequency(array_get($data, 'recurring_transaction_frequency'));
237
        $instance->setStartDate(Carbon::parse(array_get($data, 'recurring_transaction_start_date')));
238
        $instance->setEndDate(Carbon::parse(array_get($data, 'recurring_transaction_end_date')));
239
        $instance->setStatus(array_get($data, 'recurring_transaction_status.transaction_status_name'));
240
        $instance->setTransactionId(array_get($data, 'recurring_transaction_id'));
241
242
        return $instance;
243
    }
244
245
    private function toCreateRecurringArray()
246
    {
247
        return clear_array(array_merge($this->getCustomFields(), [
248
            'recurring_transaction_frequency' => $this->getFrequency(),
249
            'recurring_transaction_start_date' => $this->getStartDate(),
250
            'recurring_transaction_end_date' => $this->getEndDate() ? $this->getEndDate() : null,
251
            'recurring_transaction_amount' => $this->getAmount(),
252
            'bank_card' => $this->getCard()->toCreateCardArray(),
253
            'recurring_transaction_type' => self::TRANSACTION_TYPE_SALE
254
        ]));
255
    }
256
257
    private function toCancelRecurringArray()
258
    {
259
        return clear_array([
260
            'recurring_transaction_id' => $this->getTransactionId()
261
        ]);
262
    }
263
}