Passed
Push — v3.0 ( 2b1bd7...a14c42 )
by Raza
02:10
created

Helpers::addCustomPlan()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 5
dl 0
loc 18
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace Srmklive\PayPal\Traits\PayPalAPI\Subscriptions;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Str;
7
use Throwable;
8
9
trait Helpers
10
{
11
    /**
12
     * @var array
13
     */
14
    protected $trial_pricing = [];
15
16
    /**
17
     * @var int
18
     */
19
    protected $payment_failure_threshold = 3;
20
21
    /**
22
     * @var array
23
     */
24
    protected $product;
25
26
    /**
27
     * @var array
28
     */
29
    protected $billing_plan;
30
31
    /**
32
     * Setup a subscription.
33
     *
34
     * @param string $customer_name
35
     * @param string $customer_email
36
     * @param string $start_date
37
     *
38
     * @throws Throwable
39
     *
40
     * @return array|\Psr\Http\Message\StreamInterface|string
41
     */
42
    public function setupSubscription(string $customer_name, string $customer_email, string $start_date = '')
43
    {
44
        $start_date = isset($start_date) ? Carbon::parse($start_date)->toIso8601String() : Carbon::now()->toIso8601String();
45
46
        $subscription = $this->createSubscription([
0 ignored issues
show
Bug introduced by
It seems like createSubscription() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

46
        /** @scrutinizer ignore-call */ 
47
        $subscription = $this->createSubscription([
Loading history...
47
            'plan_id'    => $this->billing_plan['id'],
48
            'start_time' => $start_date,
49
            'quantity'   => 1,
50
            'subscriber' => [
51
                'name'          => [
52
                    'given_name' => $customer_name,
53
                ],
54
                'email_address' => $customer_email,
55
            ],
56
        ]);
57
58
        unset($this->product);
59
        unset($this->billing_plan);
60
        unset($this->trial_pricing);
61
62
        return $subscription;
63
    }
64
65
    /**
66
     * Add a subscription trial pricing tier.
67
     *
68
     * @param string    $interval_type
69
     * @param int       $interval_count
70
     * @param float|int $price
71
     *
72
     * @return \Srmklive\PayPal\Services\PayPal
73
     */
74
    public function addPlanTrialPricing(string $interval_type, int $interval_count, float $price = 0): \Srmklive\PayPal\Services\PayPal
75
    {
76
        $this->trial_pricing = $this->addPlanBillingCycle($interval_type, $interval_count, $price, true);
77
78
        return $this;
79
    }
80
81
    /**
82
     * Create a recurring daily billing plan.
83
     *
84
     * @param string    $name
85
     * @param string    $description
86
     * @param float|int $price
87
     *
88
     * @throws Throwable
89
     *
90
     * @return \Srmklive\PayPal\Services\PayPal
91
     */
92
    public function addDailyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
93
    {
94
        if (isset($this->billing_plan)) {
95
            return $this;
96
        }
97
98
        $plan_pricing = $this->addPlanBillingCycle('DAY', 1, $price);
99
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
100
101
        $this->addBillingPlan($name, $description, $billing_cycles);
102
103
        return $this;
104
    }
105
106
    /**
107
     * Create a recurring weekly billing plan.
108
     *
109
     * @param string    $name
110
     * @param string    $description
111
     * @param float|int $price
112
     *
113
     * @throws Throwable
114
     *
115
     * @return \Srmklive\PayPal\Services\PayPal
116
     */
117
    public function addWeeklyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
118
    {
119
        if (isset($this->billing_plan)) {
120
            return $this;
121
        }
122
123
        $plan_pricing = $this->addPlanBillingCycle('WEEK', 1, $price);
124
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
125
126
        $this->addBillingPlan($name, $description, $billing_cycles);
127
128
        return $this;
129
    }
130
131
    /**
132
     * Create a recurring monthly billing plan.
133
     *
134
     * @param string    $name
135
     * @param string    $description
136
     * @param float|int $price
137
     *
138
     * @throws Throwable
139
     *
140
     * @return \Srmklive\PayPal\Services\PayPal
141
     */
142
    public function addMonthlyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
143
    {
144
        if (isset($this->billing_plan)) {
145
            return $this;
146
        }
147
148
        $plan_pricing = $this->addPlanBillingCycle('MONTH', 1, $price);
149
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
150
151
        $this->addBillingPlan($name, $description, $billing_cycles);
152
153
        return $this;
154
    }
155
156
    /**
157
     * Create a recurring annual billing plan.
158
     *
159
     * @param string    $name
160
     * @param string    $description
161
     * @param float|int $price
162
     *
163
     * @throws Throwable
164
     *
165
     * @return \Srmklive\PayPal\Services\PayPal
166
     */
167
    public function addAnnualPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
168
    {
169
        if (isset($this->billing_plan)) {
170
            return $this;
171
        }
172
173
        $plan_pricing = $this->addPlanBillingCycle('YEAR', 1, $price);
174
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
175
176
        $this->addBillingPlan($name, $description, $billing_cycles);
177
178
        return $this;
179
    }
180
181
    /**
182
     * Create a recurring billing plan with custom intervals.
183
     *
184
     * @param string    $name
185
     * @param string    $description
186
     * @param float|int $price
187
     * @param string    $interval_unit
188
     * @param int       $interval_count
189
     *
190
     * @throws Throwable
191
     *
192
     * @return \Srmklive\PayPal\Services\PayPal
193
     */
194
    public function addCustomPlan(string $name, string $description, float $price, string $interval_unit, int $interval_count): \Srmklive\PayPal\Services\PayPal
195
    {
196
        $billing_intervals = ['DAY', 'WEEK', 'MONTH', 'YEAR'];
197
198
        if (isset($this->billing_plan)) {
199
            return $this;
200
        }
201
202
        if (!in_array($interval_unit, $billing_intervals)) {
203
            throw new \RuntimeException("Billing intervals should either be " . implode($billing_intervals, ", "));
0 ignored issues
show
Unused Code introduced by
The call to implode() has too many arguments starting with ', '. ( Ignorable by Annotation )

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

203
            throw new \RuntimeException("Billing intervals should either be " . /** @scrutinizer ignore-call */ implode($billing_intervals, ", "));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
204
        }
205
206
        $plan_pricing = $this->addPlanBillingCycle($interval_unit, $interval_count, $price);
207
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
208
209
        $this->addBillingPlan($name, $description, $billing_cycles);
210
211
        return $this;
212
    }
213
214
    /**
215
     * Add Plan's Billing cycle.
216
     *
217
     * @param string $interval_unit
218
     * @param int    $interval_count
219
     * @param float  $price
220
     * @param bool   $trial
221
     *
222
     * @return array
223
     */
224
    protected function addPlanBillingCycle(string $interval_unit, int $interval_count, float $price, bool $trial = false): array
225
    {
226
        $pricing_scheme = [
227
            'fixed_price' => [
228
                'value'         => $price,
229
                'currency_code' => $this->getCurrency(),
0 ignored issues
show
Bug introduced by
It seems like getCurrency() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

229
                'currency_code' => $this->/** @scrutinizer ignore-call */ getCurrency(),
Loading history...
230
            ],
231
        ];
232
233
        if (empty($this->trial_pricing)) {
234
            $plan_sequence = 1;
235
        } else {
236
            $plan_sequence = 2;
237
        }
238
239
        return [
240
            'frequency' => [
241
                'interval_unit'  => $interval_unit,
242
                'interval_count' => $interval_count,
243
            ],
244
            'tenure_type'    => ($trial === true) ? 'TRIAL' : 'REGULAR',
245
            'sequence'       => ($trial === true) ? 1 : $plan_sequence,
246
            'total_cycles'   => ($trial === true) ? 1 : 0,
247
            'pricing_scheme' => $pricing_scheme,
248
        ];
249
    }
250
251
    /**
252
     * Create a product for a subscription's billing plan.
253
     *
254
     * @param string $name
255
     * @param string $description
256
     * @param string $type
257
     * @param string $category
258
     *
259
     * @throws Throwable
260
     *
261
     * @return \Srmklive\PayPal\Services\PayPal
262
     */
263
    public function addProduct(string $name, string $description, string $type, string $category): \Srmklive\PayPal\Services\PayPal
264
    {
265
        if (isset($this->product)) {
266
            return $this;
267
        }
268
269
        $request_id = Str::random();
270
271
        $this->product = $this->createProduct([
0 ignored issues
show
Bug introduced by
It seems like createProduct() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

271
        /** @scrutinizer ignore-call */ 
272
        $this->product = $this->createProduct([
Loading history...
272
            'name'          => $name,
273
            'description'   => $description,
274
            'type'          => $type,
275
            'category'      => $category,
276
        ], $request_id);
277
278
        return $this;
279
    }
280
281
    /**
282
     * Add subscription's billing plan's product by ID.
283
     *
284
     * @param string $product_id
285
     *
286
     * @return \Srmklive\PayPal\Services\PayPal
287
     */
288
    public function addProductById(string $product_id): \Srmklive\PayPal\Services\PayPal
289
    {
290
        $this->product = [
291
            'id' => $product_id,
292
        ];
293
294
        return $this;
295
    }
296
297
    /**
298
     * Add subscription's billing plan by ID.
299
     *
300
     * @param string $plan_id
301
     *
302
     * @return \Srmklive\PayPal\Services\PayPal
303
     */
304
    public function addBillingPlanById(string $plan_id): \Srmklive\PayPal\Services\PayPal
305
    {
306
        $this->billing_plan = [
307
            'id' => $plan_id,
308
        ];
309
310
        return $this;
311
    }
312
313
    /**
314
     * Create a product for a subscription's billing plan.
315
     *
316
     * @param string $name
317
     * @param string $description
318
     * @param array  $billing_cycles
319
     *
320
     * @throws Throwable
321
     *
322
     * @return void
323
     */
324
    protected function addBillingPlan(string $name, string $description, array $billing_cycles): void
325
    {
326
        $request_id = Str::random();
327
328
        $plan_params = [
329
            'product_id'          => $this->product['id'],
330
            'name'                => $name,
331
            'description'         => $description,
332
            'status'              => 'ACTIVE',
333
            'billing_cycles'      => $billing_cycles,
334
            'payment_preferences' => [
335
                'auto_bill_outstanding'     => true,
336
                'setup_fee_failure_action'  => 'CONTINUE',
337
                'payment_failure_threshold' => $this->payment_failure_threshold,
338
            ],
339
        ];
340
341
        $this->billing_plan = $this->createPlan($plan_params, $request_id);
0 ignored issues
show
Bug introduced by
It seems like createPlan() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

341
        /** @scrutinizer ignore-call */ 
342
        $this->billing_plan = $this->createPlan($plan_params, $request_id);
Loading history...
342
    }
343
}
344