Skip to content
This repository has been archived by the owner on Nov 9, 2021. It is now read-only.

Commit

Permalink
[5.x] String casting (#37)
Browse files Browse the repository at this point in the history
* Added string casting for identifiable objects
  • Loading branch information
rennokki authored May 13, 2021
1 parent 8ea593b commit 8e7f8cf
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 71 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,11 @@ use RenokiCo\CashierRegister\Saas;
$freePlan = Saas::plan('Free Plan', 'price_free'); // already subscribed to this plan
$paidPlan = Saas::plan('Paid Plan', 'price_paid');

$overQuotaFeatures = $subscription->featuresOverQuotaWhenSwapping($paidPlan->getId());
$overQuotaFeatures = $subscription->featuresOverQuotaWhenSwapping($paidPlan);

// If no features are over quotas before swapping, apply the plan swap.
if ($overQuotaFeatures->count() === 0) {
$subscription->swap($freePlan);
$subscription->swap($freePlan->getId());
}

foreach ($overQuotaFeatures as $feature) {
Expand Down
12 changes: 8 additions & 4 deletions src/Concerns/HasFeatures.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ public function getMeteredFeatures()
/**
* Get a specific feature by id.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @return \RenokiCo\CashierRegister\Feature|null
*/
public function getFeature($id)
public function getFeature($feature)
{
return $this->getFeatures()->first(function (Feature $feature) use ($id) {
return $feature->getId() == $id;
if ($feature instanceof Feature) {
return $feature;
}

return $this->getFeatures()->first(function (Feature $f) use ($feature) {
return $f->getId() == $feature;
});
}
}
104 changes: 51 additions & 53 deletions src/Concerns/HasQuotas.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ public function usage()
/**
* Increment the feature usage.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param int|float $value
* @param bool $incremental
* @param Closure|null $exceedHandler
* @return \RenokiCo\CashierRegister\Models\Usage|null
*/
public function recordFeatureUsage($id, $value = 1, bool $incremental = true, Closure $exceedHandler = null)
public function recordFeatureUsage($feature, $value = 1, bool $incremental = true, Closure $exceedHandler = null)
{
$feature = $this->getPlan()->getFeature($id);
$plan = $this->getPlan();
$feature = $plan->getFeature($feature);

if (! $feature) {
return;
Expand All @@ -42,7 +43,7 @@ public function recordFeatureUsage($id, $value = 1, bool $incremental = true, Cl
/** @var \RenokiCo\CashierRegister\Models\Usage $usage */
$usage = $this->usage()->firstOrNew([
'subscription_id' => $this->getKey(),
'feature_id' => $feature->getId(),
'feature_id' => $feature,
]);

// Try to recalculate the usage based on user-defined callbacks.
Expand All @@ -53,11 +54,10 @@ public function recordFeatureUsage($id, $value = 1, bool $incremental = true, Cl
'used_total' => $incremental ? $usage->used_total + $value : $value,
]);

$planId = $this->getPlanIdentifier();
$featureOverQuota = $this->featureOverQuotaFor($id, $usage, $planId);
$featureOverQuota = $this->featureOverQuotaFor($feature, $usage, $plan);

if (! $feature->isUnlimited() && $featureOverQuota) {
$remainingQuota = $this->getRemainingQuotaFor($id, $usage, $planId);
$remainingQuota = $this->getRemainingQuotaFor($feature, $usage, $plan);

$valueOverQuota = value(function () use ($value, $remainingQuota) {
return $remainingQuota < 0
Expand All @@ -84,7 +84,7 @@ public function recordFeatureUsage($id, $value = 1, bool $incremental = true, Cl
// This way, the next time the customer uses again the feature, it will jump straight up
// to billing using metering instead of calculating the difference.
$usage->fill([
'used' => $this->getFeatureQuota($id, $planId),
'used' => $this->getFeatureQuota($feature, $plan),
'used_total' => $incremental ? $usage->used_total + $value : $value,
]);

Expand All @@ -99,17 +99,17 @@ public function recordFeatureUsage($id, $value = 1, bool $incremental = true, Cl
/**
* Reduce the usage amount.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $id
* @param int|float $uses
* @return null|\RenokiCo\CashierRegister\Models\Usage
*/
public function reduceFeatureUsage($id, $uses = 1, bool $incremental = true)
public function reduceFeatureUsage($feature, $uses = 1, bool $incremental = true)
{
/** @var \RenokiCo\CashierRegister\Models\Usage|null $usage */
$feature = $this->getPlan()->getFeature($id);
$feature = $this->getPlan()->getFeature($feature);

$usage = $this->usage()
->whereFeatureId($id)
->whereFeatureId($feature)
->first();

if (is_null($usage)) {
Expand All @@ -132,38 +132,38 @@ public function reduceFeatureUsage($id, $uses = 1, bool $incremental = true)
/**
* Reduce the usage amount.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param int|float $uses
* @return null|\RenokiCo\CashierRegister\Models\Usage
*/
public function decrementFeatureUsage($id, $uses = 1, bool $incremental = true)
public function decrementFeatureUsage($feature, $uses = 1, bool $incremental = true)
{
return $this->reduceFeatureUsage($id, $uses, $incremental);
return $this->reduceFeatureUsage($feature, $uses, $incremental);
}

/**
* Set the feature usage to a specific value.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param int|float $value
* @return \RenokiCo\CashierRegister\Models\Usage|null
*/
public function setFeatureUsage($id, $value)
public function setFeatureUsage($feature, $value)
{
return $this->recordFeatureUsage($id, $value, false);
return $this->recordFeatureUsage($feature, $value, false);
}

/**
* Get the feature used quota.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @return int|float
*/
public function getUsedQuota($id)
public function getUsedQuota($feature)
{
/** @var \RenokiCo\CashierRegister\Models\Usage|null $usage */
$usage = $this->usage()
->whereFeatureId($id)
->whereFeatureId($feature)
->first();

return $usage ? $usage->used : 0;
Expand All @@ -172,32 +172,32 @@ public function getUsedQuota($id)
/**
* Get the feature quota remaining.
*
* @param string|int $id
* @param string|null $planId
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return int|float
*/
public function getRemainingQuota($id, $planId = null)
public function getRemainingQuota($feature, $plan = null)
{
$featureValue = $this->getFeatureQuota($id, $planId);
$featureValue = $this->getFeatureQuota($feature, $plan);

if ($featureValue < 0) {
return -1;
}

return $featureValue - $this->getUsedQuota($id);
return $featureValue - $this->getUsedQuota($feature);
}

/**
* Get the feature quota remaining.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param \RenokiCo\CashierRegister\Models\Usage $usage
* @param string|null $planId
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return int|float
*/
public function getRemainingQuotaFor($id, $usage, $planId = null)
public function getRemainingQuotaFor($feature, $usage, $plan = null)
{
$featureValue = $this->getFeatureQuota($id, $planId);
$featureValue = $this->getFeatureQuota($feature, $plan);

if ($featureValue < 0) {
return -1;
Expand All @@ -209,15 +209,15 @@ public function getRemainingQuotaFor($id, $usage, $planId = null)
/**
* Get the feature quota.
*
* @param string|int $id
* @param string|null $planId
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return int|float
*/
public function getFeatureQuota($id, $planId = null)
public function getFeatureQuota($feature, $plan = null)
{
$plan = $planId ? Saas::getPlan($planId) : $this->getPlan();
$plan = $plan ? Saas::getPlan($plan) : $this->getPlan();

$feature = $plan->getFeature($id);
$feature = $plan->getFeature($feature);

if (! $feature) {
return 0;
Expand All @@ -229,63 +229,61 @@ public function getFeatureQuota($id, $planId = null)
/**
* Check if the feature is over the assigned quota.
*
* @param string|int $id
* @param string|null $planId
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return bool
*/
public function featureOverQuota($id, $planId = null): bool
public function featureOverQuota($feature, $plan = null): bool
{
$plan = $planId ? Saas::getPlan($planId) : $this->getPlan();
$plan = $plan ? Saas::getPlan($plan) : $this->getPlan();

$feature = $plan->getFeature($id);
$feature = $plan->getFeature($feature);

if ($feature->isUnlimited()) {
return false;
}

return $this->getRemainingQuota($id, $planId) < 0;
return $this->getRemainingQuota($feature, $plan) < 0;
}

/**
* Check if the feature is over the assigned quota.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Feature|string|int $feature
* @param \RenokiCo\CashierRegister\Models\Usage $usage
* @param string|null $planId
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return bool
*/
public function featureOverQuotaFor($id, $usage, $planId = null): bool
public function featureOverQuotaFor($feature, $usage, $plan = null): bool
{
$plan = $planId ? Saas::getPlan($planId) : $this->getPlan();
$plan = $plan ? Saas::getPlan($plan) : $this->getPlan();

$feature = $plan->getFeature($id);
$feature = $plan->getFeature($feature);

if ($feature->isUnlimited()) {
return false;
}

return $this->getRemainingQuotaFor($id, $usage, $planId) < 0;
return $this->getRemainingQuotaFor($feature, $usage, $plan) < 0;
}

/**
* Check if there are features over quota
* if the current subscription would be swapped
* to a new one.
*
* @param string $planId
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return \Illuminate\Support\Collection
*/
public function featuresOverQuotaWhenSwapping(string $planId)
public function featuresOverQuotaWhenSwapping($plan)
{
$plan = Saas::getPlan($planId);
$plan = Saas::getPlan($plan);

return $plan->getFeatures()
->reject->isResettable()
->reject->isUnlimited()
->filter(function (Feature $feature) use ($plan) {
$remainingQuota = $this->getRemainingQuota(
$feature->getId(), $plan->getId()
);
$remainingQuota = $this->getRemainingQuota($feature, $plan);

return $remainingQuota < 0;
});
Expand Down
10 changes: 10 additions & 0 deletions src/Concerns/IsIdentifiable.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,14 @@ public function getDescription()
{
return $this->description;
}

/**
* Convert the identifiable to string.
*
* @return string
*/
public function __toString()
{
return $this->getId();
}
}
24 changes: 16 additions & 8 deletions src/Saas.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,17 @@ public static function getAvailablePlans()
/**
* Get a specific plan by id or by yearly ID.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Plan|string|int|null $plan
* @return \RenokiCo\CashierRegister\Plan|null
*/
public static function getPlan($id)
public static function getPlan($plan)
{
return collect(static::$plans)->filter(function (Plan $plan) use ($id) {
return $plan->getId() == $id || $plan->getYearlyId() == $id;
if ($plan instanceof Plan) {
return $plan;
}

return collect(static::$plans)->filter(function (Plan $p) use ($plan) {
return $p->getId() == $plan || $p->getYearlyId() == $plan;
})->first();
}

Expand All @@ -193,13 +197,17 @@ public static function getItems()
/**
* Get a specific item by id.
*
* @param string|int $id
* @param \RenokiCo\CashierRegister\Item|string|int $item
* @return \RenokiCo\CashierRegister\Item|null
*/
public static function getItem($id)
public static function getItem($item)
{
return collect(static::$items)->filter(function (Item $item) use ($id) {
return $item->getId() == $id;
if ($item instanceof Item) {
return $item;
}

return collect(static::$items)->filter(function (Item $i) use ($item) {
return $i->getId() == $item;
})->first();
}

Expand Down
4 changes: 1 addition & 3 deletions tests/PaddleFeatureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,7 @@ public function test_downgrading_plan()

$subscription->recordFeatureUsage('teams', 10);

$overQuotaFeatures = $subscription->featuresOverQuotaWhenSwapping(
$freePlan->getId()
);
$overQuotaFeatures = $subscription->featuresOverQuotaWhenSwapping($freePlan);

$this->assertCount(
1, $overQuotaFeatures
Expand Down
2 changes: 1 addition & 1 deletion tests/StripeFeatureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public function test_downgrading_plan()
'teams', $overQuotaFeatures->first()->getId()
);

$subscription->swap($freePlan->getId());
$subscription->swap((string) $freePlan);

$this->assertTrue($subscription->featureOverQuota('teams'));
}
Expand Down

0 comments on commit 8e7f8cf

Please sign in to comment.