SubscriptionBuilder   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 20
eloc 71
c 4
b 0
f 0
dl 0
loc 278
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A quantity() 0 5 1
A buildPayload() 0 9 1
A withCoupon() 0 5 1
A add() 0 3 1
A getTrialEndForPayload() 0 8 3
A getTaxPercentageForPayload() 0 4 2
A create() 0 32 4
A skipTrial() 0 5 1
A withMetadata() 0 5 1
A trialDays() 0 5 1
A __construct() 0 7 1
A getStripeCustomer() 0 16 3
1
<?php
2
3
namespace Phalcon\Cashier;
4
5
use Carbon\Carbon;
6
use Exception;
7
use Phalcon\Mvc\Model;
8
use Baka\Database\Apps;
9
10
class SubscriptionBuilder
11
{
12
    /**
13
     * The user model that is subscribing.
14
     *
15
     */
16
    protected $user;
17
18
    /**
19
     * The name of the subscription.
20
     *
21
     * @var string
22
     */
23
    protected $name;
24
25
    /**
26
     * The name of the plan being subscribed to.
27
     *
28
     * @var string
29
     */
30
    protected $plan;
31
32
    /**
33
     * The quantity of the subscription.
34
     *
35
     * @var int
36
     */
37
    protected $quantity = 1;
38
39
    /**
40
     * The number of trial days to apply to the subscription.
41
     *
42
     * @var int|null
43
     */
44
    protected $trialDays;
45
46
    /**
47
     * Indicates that the trial should end immediately.
48
     *
49
     * @var bool
50
     */
51
    protected $skipTrial = false;
52
53
    /**
54
     * The coupon code being applied to the customer.
55
     *
56
     * @var string|null
57
     */
58
    protected $coupon;
59
60
    /**
61
     * The metadata to apply to the subscription.
62
     *
63
     * @var array|null
64
     */
65
    protected $metadata;
66
67
    /**
68
     * Company.
0 ignored issues
show
Bug introduced by
The type Phalcon\Cashier\Company was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
69
     *
70
     * @var Company
71
     */
72
    protected $company;
73
74
    /**
75
     * App.
76
     *
77
     * @var Apps
78
     */
79
    protected $apps;
80
81
    /**
82
     * Active Subscription Id.
83
     *
84
     * @var string
85
     */
86
    protected $activeSubscriptionId;
87
88
    /**
89
     * Create a new subscription builder instance.
90
     *
91
     * @param  mixed  $user
92
     * @param  string  $name
93
     * @param  string  $plan
94
     * @return void
95
     */
96
    public function __construct($user, $name, $plan, Model $company, Apps $apps)
97
    {
98
        $this->user = $user;
99
        $this->name = $name;
100
        $this->plan = $plan;
101
        $this->company = $company;
102
        $this->apps = $apps;
103
    }
104
105
    /**
106
     * Specify the quantity of the subscription.
107
     *
108
     * @param  int  $quantity
109
     * @return $this
110
     */
111
    public function quantity($quantity)
112
    {
113
        $this->quantity = $quantity;
114
115
        return $this;
116
    }
117
118
    /**
119
     * Specify the ending date of the trial.
120
     *
121
     * @param  int  $trialDays
122
     * @return $this
123
     */
124
    public function trialDays($trialDays)
125
    {
126
        $this->trialDays = $trialDays;
127
128
        return $this;
129
    }
130
131
    /**
132
     * Force the trial to end immediately.
133
     *
134
     * @return $this
135
     */
136
    public function skipTrial()
137
    {
138
        $this->skipTrial = true;
139
140
        return $this;
141
    }
142
143
    /**
144
     * The coupon to apply to a new subscription.
145
     *
146
     * @param  string  $coupon
147
     * @return $this
148
     */
149
    public function withCoupon($coupon)
150
    {
151
        $this->coupon = $coupon;
152
153
        return $this;
154
    }
155
156
    /**
157
     * The metadata to apply to a new subscription.
158
     *
159
     * @param  array  $metadata
160
     * @return $this
161
     */
162
    public function withMetadata($metadata)
163
    {
164
        $this->metadata = $metadata;
165
166
        return $this;
167
    }
168
169
    /**
170
     * Add a new Stripe subscription to the user.
171
     *
172
     * @param  array  $options
173
     * @return \Laravel\Cashier\Subscription
0 ignored issues
show
Bug introduced by
The type Laravel\Cashier\Subscription was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
174
     */
175
    public function add(array $options = [])
176
    {
177
        return $this->create(null, $options);
178
    }
179
180
    /**
181
     * Create a new Stripe subscription.
182
     *
183
     * @param  string|null  $token
184
     * @param  array  $options
185
     * @return \Phalcon\Cashier\Subscription
186
     */
187
    public function create($token = null, array $options = [])
188
    {
189
        $customer = $this->getStripeCustomer($token, $options);
190
191
        $subscription = $customer->subscriptions->create($this->buildPayload());
192
193
        if ($this->skipTrial) {
194
            $trialEndsAt = null;
195
        } else {
196
            $object = Carbon::now()->addDays($this->trialDays);
197
            $trialEndsAt = $this->trialDays ? $object->toDateTimeString() : null;
198
        }
199
200
        $object = new Subscription();
201
        $object->name = $this->name;
202
        $object->stripe_id = $subscription->id;
203
        $object->stripe_plan = $this->plan;
204
        $object->quantity = $this->quantity;
0 ignored issues
show
Bug Best Practice introduced by
The property quantity does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
205
        $object->trial_ends_at = $trialEndsAt;
206
        $object->companies_id = $this->company->getId();
207
        $object->apps_id = $this->apps->getId();
208
209
        //Need call it before save relationship
210
        $this->user->subscriptions();
211
        $this->user->subscriptions = $object;
212
        $this->user->active_subscription_id = $subscription->id;
213
214
        if (!$this->user->save()) {
215
            throw new Exception((string) current($this->user->getMessages()));
216
        }
217
218
        return $this->user;
219
    }
220
221
    /**
222
     * Get the Stripe customer instance for the current user and token.
223
     *
224
     * @param  string|null  $token
225
     * @param  array  $options
226
     * @return \Stripe\Customer
227
     */
228
    protected function getStripeCustomer($token = null, array $options = [])
229
    {
230
        if (!$this->user->stripe_id) {
231
            $customer = $this->user->createAsStripeCustomer(
232
                $token,
233
                array_merge($options, array_filter(['coupon' => $this->coupon]))
234
            );
235
        } else {
236
            $customer = $this->user->asStripeCustomer();
237
238
            if ($token) {
239
                $this->user->updateCard($token);
240
            }
241
        }
242
243
        return $customer;
244
    }
245
246
    /**
247
     * Build the payload for subscription creation.
248
     *
249
     * @return array
250
     */
251
    protected function buildPayload()
252
    {
253
        return array_filter([
254
            'plan' => $this->plan,
255
            'quantity' => $this->quantity,
256
            'coupon' => $this->coupon,
257
            'trial_end' => $this->getTrialEndForPayload(),
258
            'tax_percent' => $this->getTaxPercentageForPayload(),
259
            'metadata' => $this->metadata,
260
        ]);
261
    }
262
263
    /**
264
     * Get the trial ending date for the Stripe payload.
265
     *
266
     * @return int|null
267
     */
268
    protected function getTrialEndForPayload()
269
    {
270
        if ($this->skipTrial) {
271
            return 'now';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'now' returns the type string which is incompatible with the documented return type integer|null.
Loading history...
272
        }
273
274
        if ($this->trialDays) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->trialDays of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
275
            return Carbon::now()->addDays($this->trialDays)->getTimestamp();
276
        }
277
    }
278
279
    /**
280
     * Get the tax percentage for the Stripe payload.
281
     *
282
     * @return int|null
283
     */
284
    protected function getTaxPercentageForPayload()
285
    {
286
        if ($taxPercentage = $this->user->taxPercentage()) {
287
            return $taxPercentage;
288
        }
289
    }
290
}
291