Passed
Pull Request — master (#41)
by Mike
02:31
created

RecordStripeEvent::rules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php namespace GeneaLabs\LaravelMixpanel\Http\Requests;
2
3
use GeneaLabs\LaravelMixpanel\Events\MixpanelEvent;
4
use Illuminate\Foundation\Http\FormRequest;
5
use Illuminate\Support\Carbon;
6
7
class RecordStripeEvent extends FormRequest
8
{
9
    public function authorize() : bool
10
    {
11
        return true;
12
    }
13
14
    public function rules() : array
15
    {
16
        return [
17
            //
18
        ];
19
    }
20
21
    public function process()
22
    {
23
        $data = $this->json()->all();
24
25
        if (! $data || ! ($data['data'] ?? false)) {
26
            return;
27
        }
28
29
        $transaction = $data['data']['object'];
30
        $originalValues = array_key_exists('previous_attributes', $data['data'])
31
            ? $data['data']['previous_attributes']
32
            : [];
33
        $stripeCustomerId = $this->findStripeCustomerId($transaction);
34
        $authModel = config('auth.providers.users.model') ?? config('auth.model');
35
        $user = app($authModel)->where('stripe_id', $stripeCustomerId)->first();
36
37
        if (! $user) {
38
            return;
39
        }
40
41
        app('mixpanel')->identify($user->id);
42
43
        if ($transaction['object'] === 'charge' && ! count($originalValues)) {
44
            $this->recordCharge($transaction, $user);
45
        }
46
47
        if ($transaction['object'] === 'subscription') {
48
            $this->recordSubscription($transaction, $user, $originalValues);
49
        }
50
    }
51
52
    private function recordCharge(array $transaction, $user)
53
    {
54
        $charge = 0;
55
        $amount = $transaction['amount'] / 100;
56
        $status = 'Failed';
57
58
        if ($transaction['paid']) {
59
            $status = 'Authorized';
60
61
            if ($transaction['captured']) {
62
                $status = 'Successful';
63
64
                if ($transaction['refunded']) {
65
                    $status = 'Refunded';
66
                }
67
            }
68
        }
69
70
        $trackingData = [
71
            'Payment',
72
            [
73
                'Status' => $status,
74
                'Amount' => $amount,
75
            ],
76
        ];
77
78
        event(new MixpanelEvent($user, $trackingData, $charge));
0 ignored issues
show
Bug introduced by
$trackingData of type array<integer,array<stri...integer|string>|string> is incompatible with the type string expected by parameter $eventName of GeneaLabs\LaravelMixpane...nelEvent::__construct(). ( Ignorable by Annotation )

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

78
        event(new MixpanelEvent($user, /** @scrutinizer ignore-type */ $trackingData, $charge));
Loading history...
79
    }
80
81
    private function recordSubscription(array $transaction, $user, array $originalValues = [])
82
    {
83
        $planStatus = array_key_exists('status', $transaction) ? $transaction['status'] : null;
84
        $planName = isset($transaction['plan']['name']) ? $transaction['plan']['name'] : null;
85
        $planStart = array_key_exists('start', $transaction) ? $transaction['start'] : null;
86
        $planAmount = isset($transaction['plan']['amount']) ? $transaction['plan']['amount'] : null;
87
        $oldPlanName = isset($originalValues['plan']['name']) ? $originalValues['plan']['name'] : null;
88
        $oldPlanAmount = isset($originalValues['plan']['amount']) ? $originalValues['plan']['amount'] : null;
89
90
        if ($planStatus === 'canceled') {
91
            $profileData = [
92
                'Subscription' => 'None',
93
                'Churned' => (new Carbon($transaction['canceled_at']))->format('Y-m-d\Th:i:s'),
94
                'Plan When Churned' => $planName,
95
                'Paid Lifetime' => (new Carbon)->createFromTimestampUTC($planStart)
96
                    ->diffInDays((new Carbon(timestamp($transaction['ended_at'])))
0 ignored issues
show
Bug introduced by
The function timestamp was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

96
                    ->diffInDays((new Carbon(/** @scrutinizer ignore-call */ timestamp($transaction['ended_at'])))
Loading history...
97
                        ->timezone('UTC')) . ' days'
98
            ];
99
            $trackingData = [
100
                ['Subscription', ['Status' => 'Canceled', 'Upgraded' => false]],
101
                ['Churn! :-('],
102
            ];
103
        }
104
105
        if (count($originalValues)) {
106
            if ($planAmount && $oldPlanAmount) {
107
                if ($planAmount < $oldPlanAmount) {
108
                    $profileData = [
109
                        'Subscription' => $planName,
110
                        'Churned' => (new Carbon($transaction['ended_at']))
111
                            ->timezone('UTC')
112
                            ->format('Y-m-d\Th:i:s'),
113
                        'Plan When Churned' => $oldPlanName,
114
                    ];
115
                    $trackingData = [
116
                        ['Subscription', [
117
                            'Upgraded' => false,
118
                            'FromPlan' => $oldPlanName,
119
                            'ToPlan' => $planName,
120
                        ]],
121
                        ['Churn! :-('],
122
                    ];
123
                }
124
125 View Code Duplication
                if ($planAmount > $oldPlanAmount) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
                    $profileData = [
127
                        'Subscription' => $planName,
128
                    ];
129
                    $trackingData = [
130
                        ['Subscription', [
131
                            'Upgraded' => true,
132
                            'FromPlan' => $oldPlanName,
133
                            'ToPlan' => $planName,
134
                        ]],
135
                        ['Unchurn! :-)'],
136
                    ];
137
                }
138
            } else {
139 View Code Duplication
                if ($planStatus === 'trialing' && ! $oldPlanName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
                    $profileData = [
141
                        'Subscription' => $planName,
142
                    ];
143
                    $trackingData = [
144
                        ['Subscription', [
145
                            'Upgraded' => true,
146
                            'FromPlan' => 'Trial',
147
                            'ToPlan' => $planName,
148
                        ]],
149
                        ['Unchurn! :-)'],
150
                    ];
151
                }
152
            }
153
        } else {
154 View Code Duplication
            if ($planStatus === 'active') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
                $profileData = [
156
                    'Subscription' => $planName,
157
                ];
158
                $trackingData = [
159
                    ['Subscription', ['Status' => 'Created']],
160
                ];
161
            }
162
163 View Code Duplication
            if ($planStatus === 'trialing') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
                $profileData = [
165
                    'Subscription' => 'Trial',
166
                ];
167
                $trackingData = [
168
                    ['Subscription', ['Status' => 'Trial']],
169
                ];
170
            }
171
        }
172
173
        event(new MixpanelEvent($user, $trackingData, 0, $profileData));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $trackingData does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $profileData does not seem to be defined for all execution paths leading up to this point.
Loading history...
174
    }
175
176
    private function findStripeCustomerId(array $transaction)
177
    {
178
        if (array_key_exists('customer', $transaction)) {
179
            return $transaction['customer'];
180
        }
181
182
        if (array_key_exists('object', $transaction) && $transaction['object'] === 'customer') {
183
            return $transaction['id'];
184
        }
185
186
        if (array_key_exists('subscriptions', $transaction)
187
            && array_key_exists('data', $transaction['subscriptions'])
188
            && array_key_exists(0, $transaction['subscriptions']['data'])
189
            && array_key_exists('customer', $transaction['subscriptions']['data'][0])
190
        ) {
191
            return $transaction['subscriptions']['data'][0]['customer'];
192
        }
193
    }
194
}
195