Failed Conditions
Pull Request — master (#225)
by Maximo
02:54
created

AppsPlansController::updatePaymentMethod()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 57

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
nc 8
nop 1
dl 0
loc 57
ccs 0
cts 34
cp 0
crap 30
rs 8.627
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Canvas\Api\Controllers;
6
7
use Canvas\Models\AppsPlans;
8
use Canvas\Exception\UnauthorizedHttpException;
9
use Canvas\Exception\NotFoundHttpException;
10
use Stripe\Token as StripeToken;
11
use Phalcon\Http\Response;
12
use Stripe\Customer as StripeCustomer;
13
use Phalcon\Validation\Validator\PresenceOf;
14
use Canvas\Exception\UnprocessableEntityHttpException;
15
use Canvas\Models\Subscription as CanvasSubscription;
16
use Phalcon\Cashier\Subscription;
17
use Canvas\Models\UserCompanyApps;
18
use function Canvas\Core\paymentGatewayIsActive;
19
use Canvas\Validation as CanvasValidation;
20
21
/**
22
 * Class LanguagesController.
23
 *
24
 * @package Canvas\Api\Controllers
25
 *
26
 * @property Users $userData
27
 * @property Request $request
28
 * @property Config $config
29
 * @property Apps $app
30
 * @property \Phalcon\Db\Adapter\Pdo\Mysql $db
31
 */
32
class AppsPlansController extends BaseController
33
{
34
    /*
35
     * fields we accept to create
36
     *
37
     * @var array
38
     */
39
    protected $createFields = [];
40
41
    /*
42
     * fields we accept to create
43
     *
44
     * @var array
45
     */
46
    protected $updateFields = [];
47
48
    /**
49
     * set objects.
50
     *
51
     * @return void
52
     */
53
    public function onConstruct()
54
    {
55
        $this->model = new AppsPlans();
56
        $this->additionalSearchFields = [
57
            ['is_deleted', ':', '0'],
58
            ['apps_id', ':', $this->app->getId()],
59
        ];
60
    }
61
62
    /**
63
     * Given the app plan stripe id , subscribe the current company to this aps.
64
     *
65
     * @return Response
66
     */
67
    public function create(): Response
68
    {
69
        if (!$this->userData->hasRole('Default.Admins')) {
70
            throw new UnauthorizedHttpException(_('You dont have permission to subscribe this apps'));
71
        }
72
73
        //Ok let validate user password
74
        $validation = new CanvasValidation();
75
        $validation->add('stripe_id', new PresenceOf(['message' => _('The plan is required.')]));
76
        $validation->add('card_number', new PresenceOf(['message' => _('Credit Card Number is required.')]));
77
        $validation->add('card_exp_month', new PresenceOf(['message' => _('Credit Card expiration month is required.')]));
78
        $validation->add('card_exp_year', new PresenceOf(['message' => _('Credit Card expiration year is required.')]));
79
        $validation->add('card_cvc', new PresenceOf(['message' => _('CVC is required.')]));
80
81
        //validate this form for password
82
        $messages = $validation->validate($this->request->getPost());
83
        if (count($messages)) {
84
            foreach ($messages as $message) {
85
                throw new UnprocessableEntityHttpException((string) $message);
86
            }
87
        }
88
89
        $stripeId = $this->request->getPost('stripe_id');
90
        $company = $this->userData->getDefaultCompany();
91
        $cardNumber = $this->request->getPost('card_number');
92
        $expMonth = $this->request->getPost('card_exp_month');
93
        $expYear = $this->request->getPost('card_exp_year');
94
        $cvc = $this->request->getPost('card_cvc');
95
96
        $appPlan = $this->model->findFirstByStripeId($stripeId);
97
98
        if (!is_object($appPlan)) {
99
            throw new NotFoundHttpException(_('This plan doesnt exist'));
100
        }
101
102
        $userSubscription = Subscription::findFirst([
103
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
104
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
105
        ]);
106
107
        //we can only run stripe paymenta gateway if we have the key
108
        if (paymentGatewayIsActive()) {
109
            $card = StripeToken::create([
110
                'card' => [
111
                    'number' => $cardNumber,
112
                    'exp_month' => $expMonth,
113
                    'exp_year' => $expYear,
114
                    'cvc' => $cvc,
115
                ],
116
            ], [
117
                'api_key' => $this->config->stripe->secret
118
            ])->id;
119
120
            $this->db->begin();
121
122
            if ($appPlan->free_trial_dates == 0) {
123
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->create($card);
124
            } else {
125
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->trialDays($appPlan->free_trial_dates)->create($card);
126
            }
127
128
            //update company app
129
            $companyApp = UserCompanyApps::getCurrentApp();
130
131
            if ($userSubscription) {
132
                $userSubscription->stripe_id = $this->userData->active_subscription_id;
133
                if (!$userSubscription->update()) {
134
                    $this->db->rollback();
135
                    throw new UnprocessableEntityHttpException((string)current($userSubscription->getMessages()));
136
                }
137
            }
138
139
            //update the company app to the new plan
140
            if (is_object($companyApp)) {
141
                $subscription = $this->userData->subscription($appPlan->stripe_plan);
142
                $companyApp->stripe_id = $stripeId;
143
                $companyApp->subscriptions_id = $subscription->getId();
144
                if (!$companyApp->update()) {
145
                    $this->db->rollback();
146
                    throw new UnprocessableEntityHttpException((string)current($companyApp->getMessages()));
147
                }
148
149
                //update the subscription with the plan
150
                $subscription->apps_plans_id = $appPlan->getId();
151
                if (!$subscription->update()) {
152
                    $this->db->rollback();
153
                    throw new UnprocessableEntityHttpException((string)current($subscription->getMessages()));
154
                }
155
            }
156
157
            $this->db->commit();
158
        }
159
160
        //sucess
161
        return $this->response($appPlan);
162
    }
163
164
    /**
165
     * Update a given subscription.
166
     *
167
     * @param string $stripeId
168
     * @return Response
169
     */
170
    public function edit($stripeId) : Response
171
    {
172
        $appPlan = $this->model->findFirstByStripeId($stripeId);
173
174
        if (!is_object($appPlan)) {
175
            throw new NotFoundHttpException(_('This plan doesnt exist'));
176
        }
177
178
        /**
179
         * @todo change the subscription to use getActiveForThisApp , not base on the user
180
         */
181
        $userSubscription = Subscription::findFirst([
182
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
183
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
184
        ]);
185
186
        if (!is_object($userSubscription)) {
187
            throw new NotFoundHttpException(_('No current subscription found'));
188
        }
189
190
        $this->db->begin();
191
192
        $subscription = $this->userData->subscription($userSubscription->name);
193
194
        if ($subscription->onTrial()) {
195
            $subscription->name = $appPlan->name;
196
            $subscription->stripe_plan = $appPlan->stripe_plan;
197
        } else {
198
            $subscription->swap($stripeId);
199
        }
200
201
        //update company app
202
        $companyApp = UserCompanyApps::getCurrentApp();
203
204
        //update the company app to the new plan
205
        if (is_object($companyApp)) {
206
            $subscription->name = $stripeId;
207
            $subscription->save();
208
209
            $companyApp->stripe_id = $stripeId;
210
            $companyApp->subscriptions_id = $subscription->getId();
211
            if (!$companyApp->update()) {
212
                $this->db->rollback();
213
                throw new UnprocessableEntityHttpException((string) current($companyApp->getMessages()));
214
            }
215
216
            //update the subscription with the plan
217
            $subscription->apps_plans_id = $appPlan->getId();
218
            if (!$subscription->update()) {
219
                $this->db->rollback();
220
221
                throw new UnprocessableEntityHttpException((string) current($subscription->getMessages()));
222
            }
223
        }
224
225
        $this->db->commit();
226
227
        //return the new subscription plan
228
        return $this->response($appPlan);
229
    }
230
231
    /**
232
     * Cancel a given subscription.
233
     *
234
     * @param string $stripeId
235
     * @return Response
236
     */
237
    public function delete($stripeId): Response
238
    {
239
        $appPlan = $this->model->findFirstByStripeId($stripeId);
240
241
        if (!is_object($appPlan)) {
242
            throw new NotFoundHttpException(_('This plan doesnt exist'));
243
        }
244
245
        $userSubscription = Subscription::findFirst([
246
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
247
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
248
        ]);
249
250
        if (!is_object($userSubscription)) {
251
            throw new NotFoundHttpException(_('No current subscription found'));
252
        }
253
254
        $subscription = $this->userData->subscription($userSubscription->name);
255
256
        //if on trial you can cancel without going to stripe
257
        if (!$subscription->onTrial()) {
258
            $subscription->cancel();
259
        }
260
261
        $subscription->is_cancelled = 1;
262
        $subscription->update();
263
264
        return $this->response($appPlan);
265
    }
266
267
    /**
268
     * Update payment method.
269
     * @param integer $id
0 ignored issues
show
Documentation introduced by
Should the type for parameter $id not be string|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
270
     * @return Response
271
     */
272
    public function updatePaymentMethod(string $id): Response
273
    {
274
        if (empty($this->request->hasPut('card_token'))) {
275
            $validation = new CanvasValidation();
276
            $validation->add('card_number', new PresenceOf(['message' => _('Credit Card Number is required.')]));
277
            $validation->add('card_exp_month', new PresenceOf(['message' => _('Credit Card expiration month is required.')]));
278
            $validation->add('card_exp_year', new PresenceOf(['message' => _('Credit Card expiration year is required.')]));
279
            $validation->add('card_cvc', new PresenceOf(['message' => _('CVC is required.')]));
280
281
            //validate this form for password
282
            $validation->validate($this->request->getPut());
283
284
            $cardNumber = $this->request->getPut('card_number', 'string');
285
            $expMonth = $this->request->getPut('card_exp_month', 'string');
286
            $expYear = $this->request->getPut('card_exp_year', 'string');
287
            $cvc = $this->request->getPut('card_cvc', 'string');
288
289
            //Create a new card token
290
            $token = StripeToken::create([
291
                'card' => [
292
                    'number' => $cardNumber,
293
                    'exp_month' => $expMonth,
294
                    'exp_year' => $expYear,
295
                    'cvc' => $cvc,
296
                ],
297
            ], [
298
                'api_key' => $this->config->stripe->secret
299
            ])->id;
300
        } else {
301
            $token = $this->request->getPut('card_token');
302
        }
303
304
        $address = $this->request->getPut('address', 'string');
305
        $zipcode = $this->request->getPut('zipcode', 'string');
306
307
        //update the default company info
308
        $this->userData->getDefaultCompany()->address = $address;
309
        $this->userData->getDefaultCompany()->zipcode = $zipcode;
310
        $this->userData->getDefaultCompany()->update();
311
312
        $customerId = $this->userData->stripe_id;
313
314
        //Update default payment method with new card.
315
        $stripeCustomer = $this->userData->updatePaymentMethod($customerId, $token);
316
317
        $subscription = CanvasSubscription::getActiveForThisApp();
318
319
        //not valid? ok then lets charge the credit card to active your subscription
320
        if (!$subscription->valid()) {
321
            $subscription->activate();
322
        }
323
324
        if (is_object($stripeCustomer) && $stripeCustomer instanceof StripeCustomer) {
325
            return $this->response($subscription);
326
        }
327
        return $this->response('Card could not be updated');
328
    }
329
}
330