Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
52.94% covered (warning)
52.94%
18 / 34
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
PlanFeatureObserver
52.94% covered (warning)
52.94%
18 / 34
50.00% covered (danger)
50.00%
3 / 6
17.44
0.00% covered (danger)
0.00%
0 / 1
 created
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 updated
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 deleted
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 invalidateCaches
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 invalidateUserSubscriptionCaches
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
 getCacheInvalidationService
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Observers;
4
5use App\Http\Models\PlanFeature;
6use App\Http\Services\CacheInvalidationService;
7use Illuminate\Support\Facades\Log;
8
9/**
10 * Observer for PlanFeature model changes.
11 *
12 * Handles cache invalidation when plan feature assignments are created, updated, or deleted.
13 * Also dispatches jobs to invalidate user subscription caches for affected users.
14 */
15class PlanFeatureObserver
16{
17    /**
18     * Cache key prefix for plans.
19     */
20    private const PLANS_CACHE_KEY_PREFIX = 'plans:';
21
22    /**
23     * Handle the PlanFeature "created" event.
24     */
25    public function created(PlanFeature $planFeature): void
26    {
27        $this->invalidateCaches($planFeature);
28
29        // Dispatch job to invalidate user subscription caches for affected users
30        $this->invalidateUserSubscriptionCaches($planFeature);
31
32        Log::info('PlanFeature created', [
33            'plan_feature_id' => (string) $planFeature->_id,
34            'plan_id' => $planFeature->plan_id,
35            'feature_id' => $planFeature->feature_id,
36        ]);
37    }
38
39    /**
40     * Handle the PlanFeature "updated" event.
41     */
42    public function updated(PlanFeature $planFeature): void
43    {
44        $this->invalidateCaches($planFeature);
45
46        // Dispatch job to invalidate user subscription caches for affected users
47        $this->invalidateUserSubscriptionCaches($planFeature);
48
49        Log::info('PlanFeature updated', [
50            'plan_feature_id' => (string) $planFeature->_id,
51            'plan_id' => $planFeature->plan_id,
52            'feature_id' => $planFeature->feature_id,
53            'changes' => $planFeature->getChanges(),
54        ]);
55    }
56
57    /**
58     * Handle the PlanFeature "deleted" event.
59     */
60    public function deleted(PlanFeature $planFeature): void
61    {
62        $this->invalidateCaches($planFeature);
63
64        // Dispatch job to invalidate user subscription caches for affected users
65        $this->invalidateUserSubscriptionCaches($planFeature);
66
67        Log::info('PlanFeature deleted', [
68            'plan_feature_id' => (string) $planFeature->_id,
69            'plan_id' => $planFeature->plan_id,
70            'feature_id' => $planFeature->feature_id,
71        ]);
72    }
73
74    /**
75     * Invalidate all caches related to this plan feature assignment.
76     */
77    private function invalidateCaches(PlanFeature $planFeature): void
78    {
79        $planId = $planFeature->plan_id;
80
81        $this->getCacheInvalidationService()->invalidatePlanCaches(
82            $planId,
83            $planFeature->plan?->identifier
84        );
85    }
86
87    /**
88     * Dispatch job to invalidate user subscription caches for affected plan.
89     */
90    private function invalidateUserSubscriptionCaches(PlanFeature $planFeature): void
91    {
92        // Load the plan if not already loaded to get stripe_id
93        if (! $planFeature->relationLoaded('plan')) {
94            $planFeature->load('plan');
95        }
96
97        if ($planFeature->plan && $planFeature->plan->stripe_id) {
98            $this->getCacheInvalidationService()->invalidateUserSubscriptionCachesByPlan(
99                $planFeature->plan->stripe_id
100            );
101        }
102    }
103
104    /**
105     * Get the CacheInvalidationService instance.
106     */
107    private function getCacheInvalidationService(): CacheInvalidationService
108    {
109        return app(CacheInvalidationService::class);
110    }
111}