diff --git a/docs/v5.x/models/plan-subscription-model.md b/docs/v5.x/models/plan-subscription-model.md index 20bfda8..71f0a4c 100644 --- a/docs/v5.x/models/plan-subscription-model.md +++ b/docs/v5.x/models/plan-subscription-model.md @@ -124,15 +124,14 @@ $user->subscription(); ## Subscription Feature Usage -There are multiple ways to determine the usage and ability of a particular feature in the subscriber's subscription, the -most common one is `canUseFeature`: +You can determine the usage and ability of a particular feature in the subscriber's subscription with `canUseFeature`: The `canUseFeature` method returns `true` or `false` depending on multiple factors: -- Subscription has not ended. -- Feature _is enabled_. +- Subscription is active (on trial or currently in period). +- Feature _is enabled_ (`true`). - Feature value isn't `0`/`false`/`NULL`. -- Or feature has remaining uses available. +- Feature has remaining uses available. ```php $user->subscription('main')->canUseFeature('social_profiles'); @@ -144,9 +143,11 @@ Other feature methods on the user subscription instance are: - `getFeatureRemainings`: returns available uses for a particular feature. - `getFeatureValue`: returns the feature value. -> All methods share the same signature: e.g. `$user->subscription('main')->getFeatureUsage('social_profiles');`. +All methods share the same signature: e.g. `$user->subscription('main')->getFeatureUsage('social_profiles');`. -### Record Feature Usage +### Record Feature Usage + +> New in 5.0: Record feature check if can be used In order to effectively use the ability methods you will need to keep track of every usage of each feature (or at least those that require it). You may use the `recordFeatureUsage` method available through the user `subscription()` method: @@ -155,9 +156,14 @@ those that require it). You may use the `recordFeatureUsage` method available th $user->subscription('main')->recordFeatureUsage('social_profiles'); ``` +When recording feature `canUseFeature` is already called within the function, so you do not have to check every time. +Exception is thrown if subscriber cannot use the feature. + The `recordFeatureUsage` method accepts 3 parameters: the first one is the feature's tag, the second one is the quantity of uses to add (default is `1`), and the third one indicates if the addition should be incremental (default behavior), -when disabled the usage will be overridden by the quantity provided. E.g.: +when disabled the usage will be overridden by the quantity provided. + +::: details Click me to view example code ```php // Increment by 1 @@ -167,6 +173,7 @@ $user->subscription('main')->recordFeatureUsage('social_profiles', 1); $user->subscription('main')->recordFeatureUsage('social_profiles', 3, false); ``` +::: ### Reduce Feature Usage Reducing the feature usage is _almost_ the same as incrementing it. Here we only _substract_ a given quantity (default @@ -239,7 +246,7 @@ $user->subscription('main')->isFree(); $user->isSubscribedTo($planId); ``` -> Canceled subscriptions with an active trial or `ends_at` in the future are considered active. +Canceled subscriptions with an active trial or `ends_at` in the future are considered active. ## Renew a Subscription diff --git a/src/Exceptions/PlanSubscriptionFeatureUsageDenied.php b/src/Exceptions/PlanSubscriptionFeatureUsageDenied.php new file mode 100644 index 0000000..aff3ec8 --- /dev/null +++ b/src/Exceptions/PlanSubscriptionFeatureUsageDenied.php @@ -0,0 +1,17 @@ +canUseFeature($featureTag)) { + throw new PlanSubscriptionFeatureUsageDenied($featureTag); + } + $feature = $this->getFeatureByTag($featureTag); @@ -587,9 +592,9 @@ public function recordFeatureUsage(string $featureTag, int $uses = 1, bool $incr */ public function reduceFeatureUsage(string $featureTag, int $uses = 1): ?PlanSubscriptionUsage { - $usage = $this->usage()->byFeatureTag($featureTag)->first(); + $usage = $this->getUsageByFeatureTag($featureTag); - if (is_null($usage)) { + if (!$usage) { return null; } @@ -617,23 +622,21 @@ public function canUseFeature(string $featureTag): bool $featureValue = $this->getFeatureValue($featureTag); if ($featureValue === 'true') { - // If feature value exists and has a written true value + // If feature value exists and has a written "true" value return true; } elseif (is_null($featureValue) || $featureValue === '0' || $featureValue === 'false') { - // If feature does not exist, it's 0 or written false + // If feature does not exist, it's 0 or written "false" return false; } // Now that we know feature exists in plan, and does not meet any of // previous requirements, check for usage - $usage = $this->usage()->byFeatureTag($featureTag)->first(); + $usage = $this->getUsageByFeatureTag($featureTag); if (!$usage) { // If feature usage does not exist, it means it has never been used // so subscriber has all usage available, since usage is inserted by recordFeatureUsage return true; - } elseif ($usage->hasExpired()) { - return false; } // Check for available uses @@ -649,11 +652,23 @@ public function canUseFeature(string $featureTag): bool */ public function getFeatureUsage(string $featureTag): int { - $usage = $this->usage()->byFeatureTag($featureTag)->first(); + $usage = $this->getUsageByFeatureTag($featureTag); return (!$usage || $usage->hasExpired()) ? 0 : $usage->used; } + /** + * Get feature usage + * + * @param string $featureTag + * + * @return mixed + */ + private function getUsageByFeatureTag(string $featureTag) + { + return $this->usage()->byFeatureTag($featureTag)->first(); + } + /** * Get the available uses. *