Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
1.42% covered (danger)
1.42%
5 / 352
0.00% covered (danger)
0.00%
0 / 25
CRAP
0.00% covered (danger)
0.00%
0 / 1
SubscriptionTrait
1.42% covered (danger)
1.42%
5 / 352
0.00% covered (danger)
0.00%
0 / 25
14616.41
0.00% covered (danger)
0.00%
0 / 1
 getCurrentPlan
22.73% covered (danger)
22.73%
5 / 22
0.00% covered (danger)
0.00%
0 / 1
37.53
 getCurrentAddOns
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 getGrammarQuota
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 getQuotaUsed
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getFlyAIQuota
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 getFlyCutsQuota
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 getPromptQuota
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getCurrentSubscription
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
72
 extractStylesFromHtml
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 hasTag
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 hasHyperlink
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 checkIfStyleExists
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 countStyles
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getMediaStorage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkStylesTagsPermissions
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 1
1406
 checkIfGiphyExists
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
20
 getDomainName
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 checkCharacterCount
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
56
 checkFlyCutsCount
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 restrictAdvacedSearch
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 checkCategoriesCount
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
132
 checkSubCategoriesCount
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 checkFlyPlates
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
132
 checkShortcutVersionRollBackCount
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 retrieveCouponObject
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Traits;
4
5use App\Helpers\Constants;
6use DOMDocument;
7use Stripe\StripeClient;
8use App\Http\Models\Plans;
9use Illuminate\Support\Str;
10use Illuminate\Http\Request;
11use App\Http\Models\Shortcut;
12use App\Http\Models\Auth\User;
13use App\Http\Models\FlyGrammarActions;
14use App\Http\Models\FlyMsgUserDailyUsage;
15use App\Http\Models\Prompts\CustomPrompts;
16use App\Http\Models\ShortcutCategory;
17use App\Http\Models\TemplateCategory;
18use App\Http\Models\ShortcutSubCategoryLv1;
19use App\Http\Models\UserAddOns;
20use App\Traits\AccountCenter\Reporting\FlyMsgAITrackingTrait;
21use Carbon\Carbon;
22use Illuminate\Support\Facades\Log;
23use MongoDB\BSON\UTCDateTime;
24
25trait SubscriptionTrait
26{
27    use FlyMsgAITrackingTrait;
28
29    /**
30     * @param User $user
31     *
32     * @return Plans
33     */
34    public function getCurrentPlan($user)
35    {
36        $currentSubscription = $user->subscription('main');
37
38        if (filled($currentSubscription) && $currentSubscription->valid() && filled($currentSubscription->plan)) {
39            // Team users a not managed on stripe so once subscription
40            // is cancelled in DB then thats it, no grace periods, no nothing.
41            $is_team_user = $currentSubscription->plan->identifier == Plans::ProPlanTeamsSMB || $currentSubscription->plan->identifier == Plans::ProPlanTeamsENT;
42            if (($is_team_user && !$currentSubscription->proTeamEnded()) || !$is_team_user) {
43                return $currentSubscription->plan;
44            }
45        }
46
47        return Plans::select(
48            'title',
49            'identifier',
50            'features',
51            'currency',
52            'interval',
53            'unit_amount',
54            'user_persona_available',
55            'user_custom_prompts',
56            'has_fly_learning',
57            'regenerate_count',
58            'flygrammar_actions',
59            'flycut_deployment',
60            'prompts_per_day',
61            'can_disable_flygrammar'
62        )
63            ->firstWhere('identifier', Plans::FREEMIUM_IDENTIFIER);
64    }
65
66    public function getCurrentAddOns(string $userId)
67    {
68        $userAddOns = UserAddOns::where('user_id', $userId)
69            ->where('status', 'active')
70            ->orderBy('created_at', 'desc')
71            ->get()
72            ->load('addOn');
73
74        $userAddOns = $userAddOns->sortBy(function ($userAddOn) {
75            return $userAddOn->addOn->priority ?? 9999;
76        });
77
78        return $userAddOns;
79    }
80
81    public function getGrammarQuota(User $user)
82    {
83        $plan = $this->getCurrentPlan($user);
84
85        $today = now();
86
87        $actionsPerformedToday = FlyGrammarActions::where('user_id', $user->id)->where('created_at', '>=', new UTCDateTime(strtotime($today->startOfDay()->toDateTimeString()) * 1000))->where('created_at', '<=', new UTCDateTime(strtotime($today->endOfDay()->toDateTimeString()) * 1000))->count();
88
89        $remaining = $plan->flygrammar_actions - $actionsPerformedToday;
90
91        return [
92            'total' => $plan->flygrammar_actions,
93            'used' => $actionsPerformedToday,
94            'remaining' => $plan->flygrammar_actions === -1 ? -1 : max($remaining, 0),
95        ];
96    }
97
98    public function getQuotaUsed($userId)
99    {
100        $tracking = $this->getTrackingUserId($userId);
101
102        return $tracking ? $tracking->count() : 0;
103    }
104
105    public function getFlyAIQuota($user)
106    {
107        $currentSubscriptionPlan = $this->getCurrentPlan($user);
108        $total = Constants::CURRENT_SUBSCRIPTION_PLAN_IDENTIFIERS[$currentSubscriptionPlan->identifier];
109
110        $used = $this->getQuotaUsed($user->id);
111
112        return [
113            'used' => $used,
114            'total' => $total,
115            'remaining' => max($total - $used, 0),
116            'seconds_remaining_until_next_prompt_refill' => now()->diffInSeconds(now()->startOfDay()->addDay())
117        ];
118    }
119
120    public function getFlyCutsQuota($user)
121    {
122        $currentSubscriptionPlan = $this->getCurrentPlan($user);
123        $total = $currentSubscriptionPlan['flycut_deployment'] ?? 0;
124        $startDay = Carbon::now()->startOfDay();
125
126        $used = FlyMsgUserDailyUsage::where('user_id', $user->id)
127            ->where("created_at", ">=", new UTCDateTime($startDay->getTimestamp() * 1000))
128            ->first()
129            ->flycut_count ?? 0;
130
131        return [
132            'used' => $used,
133            'total' => $total,
134            'remaining' => max($total - $used, 0),
135            'seconds_remaining_until_next_prompt_refill' => now()->diffInSeconds(now()->startOfDay()->addDay())
136        ];
137    }
138
139    public function getPromptQuota(User $user)
140    {
141        $currentSubscriptionPlan = $this->getCurrentPlan($user);
142        $promptsQuotaUsed = CustomPrompts::where('user_id', $user->id)->count();
143
144        return [
145            'used' => $promptsQuotaUsed,
146            'total' => $currentSubscriptionPlan->user_custom_prompts,
147            'remaining' => max($currentSubscriptionPlan->user_custom_prompts - $promptsQuotaUsed, 0),
148        ];
149    }
150
151    public function getCurrentSubscription($user)
152    {
153        $currentSubscription =  $user->subscription('main');
154
155        if (filled($currentSubscription) && $currentSubscription->valid() && filled($currentSubscription->plan)) {
156            // Team users a not managed on stripe so once subscription
157            // is cancelled in DB then thats it, no grace periods, no nothing.
158            $is_team_user = $currentSubscription->plan->identifier == Plans::ProPlanTeamsSMB || $currentSubscription->plan->identifier == Plans::ProPlanTeamsENT;
159            if ($is_team_user && !$currentSubscription->proTeamEnded()) {
160                return $currentSubscription;
161            } else if (!$is_team_user) {
162                return $currentSubscription;
163            }
164        }
165
166        return null;
167    }
168
169    protected function extractStylesFromHtml($html)
170    {
171        $re = '/style="(.+?)"/m';
172
173        preg_match_all($re, $html, $matches, PREG_SET_ORDER, 0);
174
175        $styles = [];
176
177        collect($matches)->map(function ($match) use (&$styles) {
178            $arr = explode(';', $match[1]);
179
180            foreach ($arr as $prop) {
181                $new_arr_explode = explode(':', $prop);
182                $attr = trim($new_arr_explode[0]);
183
184                if (! array_key_exists($attr, $styles) && $attr != '') {
185                    $styles[$attr] = [];
186                }
187
188                $styles[$attr][] = @trim($new_arr_explode[1]);
189            }
190        });
191
192        return $styles;
193    }
194
195    protected function hasTag($re, $html)
196    {
197        preg_match_all($re, $html, $matches, PREG_SET_ORDER, 0);
198        return !empty($matches);
199    }
200
201    protected function hasHyperlink($re, $html)
202    {
203        $re = '/<a(.+?)<\/a>/m';
204
205        preg_match_all($re, $html, $matches, PREG_SET_ORDER, 0);
206
207        return ! empty($matches);
208    }
209
210    protected function checkIfStyleExists($key, $value, $styles)
211    {
212        return in_array($value, $styles[$key] ?? []) && (count(array_unique($styles[$key] ?? [])) == 1);
213    }
214
215    protected function countStyles($key, $styles)
216    {
217        $targeted_styles = $styles[$key] ?? [];
218
219        return count(array_unique($targeted_styles));
220    }
221
222    protected function getMediaStorage(User $user)
223    {
224        return $user->fileMetaData()->sum('size');
225    }
226
227    protected function checkStylesTagsPermissions(Request $request, $html)
228    {
229        $html = str_replace("\n", '', str_replace(PHP_EOL, '', $html));
230
231        $current_subscription = $this->getCurrentPlan($request->user());
232        $features = $current_subscription->features;
233        /** Check for Bold Text */
234        $bold = $features['Bold'] ?? false;
235        $has_bold_text_in_html = $this->hasTag('/<strong>(.+?)<\/strong>/m', $html);
236
237        if (! $bold && ($has_bold_text_in_html)) {
238            return [
239                'error' => true,
240                'message' => 'You are not authorized to add bold text'
241            ];
242            //abort(403, 'You are not authorized to add bold text');
243        }
244        /** Check for Italic Text */
245        $italic = $features['Italic'] ?? false;
246        $has_italic_text_in_html = $this->hasTag('/<em>(.+?)<\/em>/m', $html);
247
248        if (! $italic && ($has_italic_text_in_html)) {
249            return [
250                'error' => true,
251                'message' => 'You are not authorized to add italic text'
252            ];
253            //abort(403, 'You are not authorized to add italic text');
254        }
255        $html_styles = $this->extractStylesFromHtml($html);
256
257        /** Check for underline */
258        $under_line = $features['Underline'] ?? false;
259        $under_line_exists = $this->checkIfStyleExists('text-decoration', 'underline', $html_styles);
260
261        if ($under_line_exists && ! $under_line) {
262            return [
263                'error' => true,
264                'message' => 'You are not authorized to add underline text'
265            ];
266
267            //abort(403, 'You are not authorized to add underline text');
268        }
269
270        /** Strikethrough */
271        $strike_through = $features['Strikethrough'] ?? false;
272        $strike_through_exists = $this->checkIfStyleExists('text-decoration', 'line-through', $html_styles);
273
274        if ($strike_through_exists && ! $strike_through) {
275            return [
276                'error' => true,
277                'message' => 'You are not authorized to add strikethrough text'
278            ];
279
280            //abort(403, 'You are not authorized to add strikethrough text');
281        }
282
283        /** Hyperlink */
284        $hyperlink = $features['Hyperlink'] ?? false;
285        $has_hyperlink_html = $this->hasTag('/<a(.+?)<\/a>/m', $html);
286
287        if ($has_hyperlink_html && ! $hyperlink) {
288            return [
289                'error' => true,
290                'message' => 'You are not authorized to add hyperlink'
291            ];
292
293            //abort(403, 'You are not authorized to add hyperlink');
294        }
295
296        /** Alignment - Left */
297        $alignment_left = $features['Alignment - Left'] ?? false;
298        $alignment_left_exists = $this->checkIfStyleExists('text-align', 'left', $html_styles);
299
300        if ($alignment_left_exists && ! $alignment_left) {
301            return [
302                'error' => true,
303                'message' => 'You are not authorized to add left alignment text'
304            ];
305
306            //abort(403, 'You are not authorized to add left alignment text');
307        }
308
309        /** Alignment - Centered */
310        $alignment_center = $features['Alignment - Centered'] ?? false;
311        $alignment_center_exists = $this->checkIfStyleExists('text-align', 'center', $html_styles);
312
313        if ($alignment_center_exists && ! $alignment_center) {
314            return [
315                'error' => true,
316                'message' => 'You are not authorized to add center alignment text'
317            ];
318
319            //abort(403, 'You are not authorized to add center alignment text');
320        }
321
322        /** Alignment - Right */
323        $alignment_right = $features['Alignment - Right'] ?? false;
324        $alignment_right_exists = $this->checkIfStyleExists('text-align', 'right', $html_styles);
325
326        if ($alignment_right_exists && ! $alignment_right) {
327            return [
328                'error' => true,
329                'message' => 'You are not authorized to add right alignment text'
330            ];
331
332            //abort(403, 'You are not authorized to add right alignment text');
333        }
334
335        /** Font Size */
336        $font_size = $features['Font Size'] ?? False;
337        if (is_array($font_size)) {
338            if (array_key_exists("font-size", $html_styles)) {
339                $inputString = $html_styles['font-size'][0] ?: '10pt';
340                preg_match('/\d+/', $inputString, $matches);
341                $extractedNumber = (int)$matches[0];
342            } else {
343                $extractedNumber = 10;
344            }
345            if (array_key_exists('font-size', $html_styles) && !in_array($extractedNumber, $font_size)) {
346                return [
347                    'error' => true,
348                    'message' => 'Exceeds font size limit, use 10, 11 or 12pt size or upgrade plan ' . $extractedNumber . 'px'
349                ];
350
351                //abort(403, 'Exceeds font size limit, use 10, 11 or 12pt size or upgrade plan ' . $extractedNumber . 'px');
352            }
353        } else {
354            $font_size_match = $this->checkIfStyleExists('font-size', $font_size . 'px', $html_styles);
355
356            if ($font_size != -1 && !$font_size_match && array_key_exists('font-size', $html_styles)) {
357                return [
358                    'error' => true,
359                    'message' => 'Exceeds font size limit, use 10, 11 or 12pt size or upgrade plan ' . $font_size . 'px'
360                ];
361
362                //abort(403, 'Exceeds font size limit, use 10, 11 or 12pt size or upgrade plan ' . $font_size . 'px');
363            }
364        }
365
366        //** Font Family */
367        $font = $features['Fonts'] ?? False;
368        if (is_array($font)) {
369            if (array_key_exists('font-family', $html_styles)) {
370                $extractedFontFamily = strtolower($html_styles['font-family'][0]);
371                if (!in_array($extractedFontFamily, $font)) {
372                    return [
373                        'error' => true,
374                        'message' => 'You are not authorized to add a font family other than Arial, Sans Serif and Calibri.'
375                    ];
376
377                    //abort(403, 'You are not authorized to add a font family other than Arial, Sans Serif and Calibri.');
378                }
379            }
380        } else {
381            if ($font != -1 && $font) {
382                $count_unique_fonts = $this->countStyles('font-family', $html_styles);
383                if ($count_unique_fonts > $font) {
384                    return [
385                        'error' => true,
386                        'message' => Str::replaceArray('?', [$font], 'You can not add more than ? font per flycut with current plan')
387                    ];
388
389                    //abort(403, Str::replaceArray('?', [$font], 'You can not add more than ? font per flycut with current plan'));
390                }
391            }
392        }
393
394        /** Bullet Points */
395        $bullet_points = $features['Bullet Points'] ?? false;
396        $has_bullet_points_html = $this->hasTag('/<ul(.+?)<\/ul>/m', $html);
397
398        if ($has_bullet_points_html && ! $bullet_points) {
399            return [
400                'error' => true,
401                'message' => 'You are not authorized to add Bullet Points'
402            ];
403
404            //abort(403, 'You are not authorized to add Bullet Points');
405        }
406
407        /** Numbered List */
408        $numbered_list = $features['Numbered List'] ?? false;
409        $has_numbered_list = $this->hasTag('/<ol(.+?)<\/ol>/m', $html);
410
411        if ($has_numbered_list && ! $numbered_list) {
412            return [
413                'error' => true,
414                'message' => 'You are not authorized to add Numbered List'
415            ];
416
417            //abort(403, 'You are not authorized to add Numbered List');
418        }
419
420        /** Increase Indent */
421        $increase_indent = $features['Increase Indent'] ?? false;
422        $has_increase_indent = array_key_exists('padding-left', $html_styles);
423
424        if ($has_increase_indent && ! $increase_indent) {
425            return [
426                'error' => true,
427                'message' => 'You are not authorized to add Increase Indent'
428            ];
429
430            //abort(403, 'You are not authorized to add Increase Indent');
431        }
432
433        // /** Font Color */
434        // $font_color = $features['Font Color'] ?? False;
435        // $font_color_exists = array_key_exists('color', $html_styles);
436
437        // if ($font_color_exists && !$font_color) :
438        //     abort(403, 'You are not authorized to add Font Color');
439        // endif;
440
441        // /** Background Color */
442        // $background_color = $features['Background Color'] ?? False;
443        // $background_color_exists = array_key_exists('background-color', $html_styles);
444
445        // if ($background_color_exists && !$background_color) :
446        //     abort(403, 'You are not authorized to add Background Color');
447        // endif;
448
449        // /** Numbered List */
450        // $headings = $features['Blocks (Headings)'] ?? False;
451        // $has_headings =
452        //     $this->hasTag('/<h1(.+?)<\/h1>/m', $html) || $this->hasTag('/<h2(.+?)<\/h2>/m', $html)
453        //     || $this->hasTag('/<h3(.+?)<\/h3>/m', $html) || $this->hasTag('/<h4(.+?)<\/h4>/m', $html)
454        //     || $this->hasTag('/<h5(.+?)<\/h5>/m', $html) || $this->hasTag('/<h6(.+?)<\/h6>/m', $html)
455        //     || $this->hasTag('/<pre(.+?)<\/pre>/m', $html);
456
457        // if ($has_headings && !$headings) :
458        //     abort(403, 'You are not authorized to add Blocks');
459        // endif;
460        return true;
461    }
462
463    protected function checkIfGiphyExists(Request $request, $html)
464    {
465        $html = str_replace("\n", '', str_replace(PHP_EOL, '', $html));
466
467        $current_subscription = $this->getCurrentPlan($request->user());
468        $features = $current_subscription->features;
469        $allow_giphy = $features['Giphy'] ?? false;
470
471        $doc = new DOMDocument();
472        @$doc->loadHTML($html);
473        $imageTags = $doc->getElementsByTagName('img');
474
475        $gifs = collect($imageTags)->filter(function ($tag) {
476            return (pathinfo(parse_url($tag->getAttribute('src'), PHP_URL_PATH), PATHINFO_EXTENSION) == 'gif')
477                && ($this->getDomainName($tag->getAttribute('src')) == 'media2.giphy.com');
478        });
479
480        if (! $allow_giphy && $gifs->isNotEmpty()) {
481            return [
482                'error' => true,
483                'message' => 'You are not allowed to add giphy with current plan'
484            ];
485
486            //abort(403, 'You are not allowed to add giphy with current plan');
487        }
488        return true;
489    }
490
491    protected function getDomainName($url): string
492    {
493        $arr_url = parse_url($url);
494
495        return $arr_url['host'] ?? '';
496    }
497
498    protected function checkCharacterCount(Request $request, $html)
499    {
500        $current_subscription = $this->getCurrentPlan($request->user());
501        $features = $current_subscription->features;
502
503        $user = $request->user();
504
505        $flycut_char_limit = $features['Number of Characters that can be used per flycut'];
506        $char_count = strlen($html);
507
508        $is_rewardable = (isset($user->rewardable)) ? $user->rewardable : '';
509        $rewards_level = (isset($user->rewards_level)) ? $user->rewards_level : '';
510
511        if ($is_rewardable) {
512            if ($rewards_level >= 2) {
513                $flycut_char_limit = -1;
514            }
515        }
516
517        if ($char_count > $flycut_char_limit && $flycut_char_limit > -1) {
518            return [
519                'error' => true,
520                'message' => Str::replaceArray('?', [$flycut_char_limit], 'You can not add more than ? character per flycut with current plan')
521            ];
522
523
524            //abort(403, Str::replaceArray('?', [$flycut_char_limit], 'You can not add more than ? character per flycut with current plan'));
525        }
526
527        return true;
528    }
529
530    protected function checkFlyCutsCount(Request $request)
531    {
532        $current_subscription = $this->getCurrentPlan($request->user());
533        $features = $current_subscription->features;
534
535        $user = $request->user();
536
537        $total_allowed_shortcuts = $features['Number of FlyCuts that can be created'];
538
539        $is_rewardable = (isset($user->rewardable)) ? $user->rewardable : '';
540        $rewards_level = (isset($user->rewards_level)) ? $user->rewards_level : '';
541
542        if ($is_rewardable) {
543            if ($rewards_level >= 1) {
544                $total_allowed_shortcuts = -1;
545            }
546        }
547
548        $number_of_flyCuts_that_can_be_created = $total_allowed_shortcuts;
549        $current_flycuts_created = Shortcut::where('user_id', $user->id)->count();
550
551        if ($current_flycuts_created >= $number_of_flyCuts_that_can_be_created && $number_of_flyCuts_that_can_be_created > -1) {
552            return [
553                'error' => true,
554                'message' => 'You have reached the limit. The number of flycuts that can be created with the current plan has been exceeded.'
555            ];
556        }
557        return true;
558    }
559
560    protected function restrictAdvacedSearch(Request $request)
561    {
562        $current_subscription = $this->getCurrentPlan($request->user());
563        $features = $current_subscription->features;
564
565        $search_bar = $features['Search Bar'] ?? false;
566
567        if ($search_bar !== 'advanced') {
568            return [
569                'error' => true,
570                'message' => 'You are not allowed to perform advanced search with current plan'
571            ];
572
573            // abort(403, 'You are not allowed to perform advanced search with current plan');
574        }
575        return true;
576    }
577
578    protected function checkCategoriesCount(Request $request)
579    {
580        $current_subscription = $this->getCurrentPlan($request->user());
581        $features = $current_subscription->features;
582
583        $total_allowed_categories = $features['Categories'];
584
585        $user = $request->user();
586
587        $is_rewardable = (isset($user->rewardable)) ? $user->rewardable : '';
588        $rewards_level = (isset($user->rewards_level)) ? $user->rewards_level : '';
589
590        if ($is_rewardable) {
591            if ($rewards_level >= 3) {
592                if (
593                    $current_subscription['identifier'] == Plans::FREEMIUM_IDENTIFIER ||
594                    $current_subscription['identifier'] == Plans::STARTER_MONTHLY_IDENTIFIER ||
595                    $current_subscription['identifier'] == Plans::STARTER_YEARLY_IDENTIFIER
596                ) {
597                    $total_allowed_categories = $total_allowed_categories + 1;
598                }
599            }
600        }
601
602        $categories_limit = $total_allowed_categories ?? 0;
603        $categories_count = ShortcutCategory::where('user_id', request()->user()->id)->count();
604
605        if ($categories_count >= $categories_limit && $categories_limit != -1 && ! $request->category_id) {
606            return [
607                'error' => true,
608                'message' => Str::replaceArray('?', [$categories_limit], 'You can not add more than ? categories with current plan')
609            ];
610
611            //abort(403, Str::replaceArray('?', [$categories_limit], 'You can not add more than ? categories with current plan'));
612        }
613        return true;
614    }
615
616    protected function checkSubCategoriesCount(Request $request)
617    {
618        $current_subscription = $this->getCurrentPlan($request->user());
619        $features = $current_subscription->features;
620
621        $sub_categories_limit = $features['Subcategory'] ?? 0;
622        $sub_categories_count = ShortcutSubCategoryLv1::whereHas('ShortcutCategory')->where('user_id', request()->user()->id)->count();
623
624        if ($sub_categories_count >= $sub_categories_limit && $sub_categories_limit != -1) {
625            return [
626                'error' => true,
627                'message' => Str::replaceArray('?', [$sub_categories_limit], 'You can not add more than ? sub categories with current plan')
628            ];
629
630            //abort(403, Str::replaceArray('?', [$sub_categories_limit], 'You can not add more than ? sub categories with current plan'));
631        }
632        return true;
633    }
634
635    protected function checkFlyPlates(Request $request)
636    {
637        $user = $request->user();
638
639        $is_rewardable = (isset($user->rewardable)) ? $user->rewardable : '';
640        $rewards_level = (isset($user->rewards_level)) ? $user->rewards_level : '';
641
642        if (! $is_rewardable || $rewards_level < 4) {
643            $template_id = $request->template_id;
644            $categorydata = TemplateCategory::with('templates')
645                ->whereHas('templates', function ($q) use ($template_id) {
646                    $searchArray = ['_id' => $template_id];
647
648                    return $q->where($searchArray);
649                })
650                ->first();
651
652            if (!empty($categorydata) && (isset($categorydata->name)) && $categorydata->name != "General") {
653                $current_subscription = $this->getCurrentPlan($request->user());
654                $features = $current_subscription->features;
655
656                $can_access_flyplates = $features['FlyPlates'] ?? false;
657
658                if (! $can_access_flyplates) {
659                    return [
660                        'error' => true,
661                        'message' => 'You are not authorized to add flyplates'
662                    ];
663
664                    //abort(403, 'You are not authorized to add flyplates');
665                }
666
667                $flyplates_count = Shortcut::where(['user_defined' => false])->count();
668
669                if ($flyplates_count > $can_access_flyplates && $can_access_flyplates != -1) {
670                    return [
671                        'error' => true,
672                        'message' => Str::replaceArray('?', [$can_access_flyplates], 'You can not create more than ? flycut from flyplates with current plan')
673                    ];
674
675                    //abort(403, Str::replaceArray('?', [$can_access_flyplates], 'You can not create more than ? flycut from flyplates with current plan'));
676                }
677            }
678        }
679        return true;
680    }
681
682    protected function checkShortcutVersionRollBackCount(Request $request)
683    {
684        $current_subscription = $this->getCurrentPlan($request->user());
685        $features = $current_subscription->features;
686        $rollback_limit = $features['ShortcutVersionRollBack'] ?? 0;
687        $rollback_counts = Shortcut::where('_id', $request->shortcutId)->pluck('rollback_counts')->first();
688        if ($rollback_limit == 0) {
689            return [
690                'error' => true,
691                'message' => 'You are not authorized to roll back shortcut versions'
692            ];
693
694            //abort(403, 'You are not authorized to roll back shortcut versions');
695        }
696
697        if ($rollback_counts && ($rollback_counts >= $rollback_limit) && ($rollback_limit != -1)) {
698            return [
699                'error' => true,
700                'message' => Str::replaceArray('?', [$rollback_limit], 'You can not rollback more than ? shortcut versions')
701            ];
702
703            //abort(403, Str::replaceArray('?', [$rollback_limit], 'You can not rollback more than ? shortcut versions'));
704        }
705        return true;
706    }
707
708    /**
709     * Retrieve coupon object
710     *
711     * @param string $couponCode
712     * @return mixed
713     */
714    private function retrieveCouponObject(string $couponCode)
715    {
716        $stripe = new StripeClient(config('services.stripe.secret'));
717
718        return $stripe->coupons->retrieve($couponCode, ['expand' => ['applies_to']]);
719    }
720}