Skip to content

Commit

Permalink
Merge branch 'release/2.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasdotvin committed Oct 11, 2022
2 parents 0b67d6d + bf51bad commit 632e46a
Show file tree
Hide file tree
Showing 32 changed files with 849 additions and 71 deletions.
7 changes: 7 additions & 0 deletions .docker/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM php:8.1-cli-alpine

RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug

COPY .docker/php/php.ini /usr/local/etc/php/conf.d/xdebug.ini
1 change: 1 addition & 0 deletions .docker/php/php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xdebug.mode=coverage
32 changes: 17 additions & 15 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html

# Ignore all test and documentation with "export-ignore".
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
/art export-ignore
/docs export-ignore
/tests export-ignore
/.editorconfig export-ignore
/.php_cs.dist.php export-ignore
/psalm.xml export-ignore
/psalm.xml.dist export-ignore
/testbench.yaml export-ignore
/UPGRADING.md export-ignore
/phpstan.neon.dist export-ignore
/phpstan-baseline.neon export-ignore
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
/art export-ignore
/docker export-ignore
/docs export-ignore
/tests export-ignore
/.editorconfig export-ignore
/.php_cs.dist.php export-ignore
/psalm.xml export-ignore
/psalm.xml.dist export-ignore
/testbench.yaml export-ignore
/UPGRADING.md export-ignore
/phpstan.neon.dist export-ignore
/phpstan-baseline.neon export-ignore
/docker-compose.yml export-ignore
6 changes: 4 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Contributions are **welcome** and will be fully **credited**.

Please read and understand the contribution guide before creating an issue or pull request.

## Scope

It is important to keep in mind that **payments are out of our scope**, so any contribution to integrate with any payment gateway won't be accepted. Our goal here is to keep an agnostic structure capable of coexist with any payment service.

## Etiquette

This project is open source, and as such, the maintainers give their free time to build and maintain the source code
Expand Down Expand Up @@ -38,8 +42,6 @@ Before submitting a pull request:

## Requirements

If the project maintainer has any additional requirements, you will find them listed here.

- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).

- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
Expand Down
32 changes: 32 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

> **Note**
> Fixes # (issue)
## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

# Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.1
uses: dependabot/fetch-metadata@v1.3.4
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"

Expand Down
103 changes: 100 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ composer require lucasdotvin/laravel-soulbscription
The package migrations are loaded automatically, but you can still publish them with this command:

```bash
php artisan vendor:publish --tag="laravel-soulbscription-migrations"
php artisan vendor:publish --tag="soulbscription-migrations"
php artisan migrate
```

Expand All @@ -29,10 +29,12 @@ php artisan migrate
If you already use this package and need to move to a newer version, don't forget to publish the upgrade migrations:

```bash
php artisan vendor:publish --tag="laravel-soulbscription-migrations-upgrades"
php artisan vendor:publish --tag="soulbscription-migrations-upgrades-1.x-2.x"
php artisan migrate
```

> Check out the available upgrade migrations by looking at the [upgrades folder](https://github.com/lucasdotvin/laravel-soulbscription/tree/develop/database/migrations/upgrades).
## Usage

To start using it, you just have to add the given trait to your `User` model (or any entity you want to have subscriptions):
Expand Down Expand Up @@ -90,6 +92,60 @@ By saying the `deploy-minutes` is a consumable feature, we are telling the users
The other feature we defined was `$customDomain`, which was a not consumable feature. By being not consumable, this feature implies only that the users with access to it can perform a given action (in this case, use a custom domain).

#### Postpaid Features

You can set a feature so it can be used over its charges. To do so, you just have to set the `postpaid` attribute to `true`:

```php
$cpuUsage = Feature::create([
'consumable' => true,
'postpaid' => true,
'name' => 'cpu-usage',
]);
```

This way, the user will be able to use the feature until the end of the period, even if he doesn't have enough charges to use it (and you can charge him later, for instance).

#### Quota Features

When creating, for instance, a file storage system, you'll have to increase and decrease feature consumption as your users upload and delete files. To achieve this easily, you can use quota features. These features have an unique, unexpirable consumption, so they can reflect a constant value (as used system storage in this example).

```php
class FeatureSeeder extends Seeder
{
public function run()
{
$storage = Feature::create([
'consumable' => true,
'quota' => true,
'name' => 'storage',
]);
}
}

...

class PhotoController extends Seeder
{
public function store(Request $request)
{
$userFolder = auth()->id() . '-files';

$request->file->store($userFolder);

$usedSpace = collect(Storage::allFiles($userFolder))
->map(fn (string $subFile) => Storage::size($subFile))
->sum();

auth()->user()->setConsumedQuota('storage', $usedSpace);

return redirect()->route('files.index');
}
}
```

In the example above, we set `storage` as a quota feature inside the seeder. Then, on the controller, our code store an uploaded file on a folder, calculate this folder size by retrieving all of its subfiles, and, finally, set the consumed `storage` quota as the directory total size.

### Creating Plans

Now you need to define the plans available to subscription in your app:
Expand Down Expand Up @@ -238,6 +294,15 @@ If you don't pass any arguments, the method will suppress the current subscripti

> This call will fire a `SubscriptionStarted(Subscription $subscription)` event.
### Fetching Current Balance

If you need remaining charges of a user, simply call the method `balance`. Imagine a scenario where a student has consumable feature named `notes-download`. To get remaining downloads limit:
```php
$student->balance('notes-download');
```

> This is just an alias of `getRemainingCharges` added to enrich the developer experience.
#### Scheduling a Switch

If you want to keep your user with the current plan until its expiration, pass the `$immediately` parameter as `false`:
Expand Down Expand Up @@ -270,6 +335,20 @@ $subscriber->subscription->renew();
It will calculate a new expiration based on the current date.

#### Expired Subscriptions

In order to retrieve an expired subscription, you can use the `lastSubscription` method:

```php
$subscriber->lastSubscription();
```

This method will return the last subscription of the user, regardless of its status, so you can, for instance, get an expired subscription to renew it.:

```php
$subscriber->lastSubscription()->renew();
```

#### Canceling

> There is a thing to keep in mind when canceling a subscription: it won't revoke the access immediately. To avoid making you need to handle refunds of any kind, we keep the subscription active and just mark it as canceled, so you just have to not renew it in the future. If you need to suppress a subscription immediately, give a look on the method `suppress()`.
Expand Down Expand Up @@ -353,6 +432,16 @@ Similarly to `cantConsume`, it returns the reverse of `hasFeature`.

Tickets are a simple way to allow your subscribers to acquire charges for a feature. When a user receives a ticket, he is allowed to consume its charges, just like he would do in a normal subscription. Tickets can be used to extend regular subscriptions-based systems (so you can, for instance, sell more charges of a given feature) or even to **build a fully pre-paid service**, where your users pay only for what they want to use.

#### Enabling Tickets

In order to use this feature, you have to enable tickets in your configuration files. First, publish the package configs:

```bash
php artisan vendor:publish --tag="soulbscription-config"
```

Finally, open the `soulbscription.php` file and set the `feature_tickets` flag to `true`. That's it, you now can use tickets!

#### Creating Tickets

To create a ticket, you can use the method `giveTicketFor`. This method expects the feature name, the expiration and optionally a number of charges (you can ignore it when creating tickets for not consumable features):
Expand Down Expand Up @@ -383,7 +472,15 @@ class UserFeatureTrialController extends Controller
}
```

In the example above, the user will be able to try a feature for a certain amount of days.
#### Non-Expirable Tickets

You can create tickets that never expire, so your subscribers will receive access to them forever:

```php
$subscriber->giveTicketFor('deploy-minutes', null, 10);
```

> Don't forget to remove these tickets when your user cancels his subscription. Otherwise, they will be able to consume the charges forever.
## Testing

Expand Down
16 changes: 6 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lucasdotvin/laravel-soulbscription",
"description": "This package provides a straightforward interface to handle subscriptions and features consumption.",
"description": "A straightforward interface to handle subscriptions and features consumption.",
"keywords": [
"lucasdotvin",
"laravel",
Expand All @@ -17,15 +17,12 @@
}
],
"require": {
"php": "^8.0",
"illuminate/contracts": "^8.73"
"php": "^8.0|^8.1",
"illuminate/contracts": "^8.0|^9.0"
},
"require-dev": {
"lucasdotvin/laravel-database-queries-counter": "^0.3.0",
"nunomaduro/collision": "^5.10",
"orchestra/testbench": "^6.22",
"pestphp/pest": "^1.21",
"pestphp/pest-plugin-laravel": "^1.1",
"lucasdotvin/laravel-database-queries-counter": "^0.5.0",
"orchestra/testbench": "^6.22|^7.0",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "*"
},
Expand All @@ -42,8 +39,7 @@
},
"scripts": {
"analyse": "vendor/bin/phpcs --standard=phpcs.xml",
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage"
"test": "vendor/bin/phpunit"
},
"config": {
"sort-packages": true,
Expand Down
10 changes: 9 additions & 1 deletion config/soulbscription.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<?php

return [
'feature_tickets' => false,
'database' => [
'cancel_migrations_autoloading' => false,
],

'feature_tickets' => env('SOULBSCRIPTION_FEATURE_TICKETS', false),

'models' => [

Expand All @@ -15,6 +19,10 @@

'plan' => \LucasDotVin\Soulbscription\Models\Plan::class,

'subscriber' => [
'uses_uuid' => env('SOULBSCRIPTION_SUBSCRIBER_USES_UUID', false),
],

'subscription' => \LucasDotVin\Soulbscription\Models\Subscription::class,

'subscription_renewal' => \LucasDotVin\Soulbscription\Models\SubscriptionRenewal::class,
Expand Down
34 changes: 34 additions & 0 deletions database/factories/FeatureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function definition()
PeriodicityType::Week,
PeriodicityType::Day,
]),
'quota' => false,
'postpaid' => false,
];
}

Expand All @@ -40,9 +42,41 @@ public function consumable()
public function notConsumable()
{
return $this->state(fn (array $attributes) => [
'quota' => false,
'consumable' => false,
'periodicity' => null,
'periodicity_type' => null,
]);
}

public function quota()
{
return $this->state(fn (array $attributes) => [
'consumable' => true,
'quota' => true,
'periodicity' => null,
'periodicity_type' => null,
]);
}

public function notQuota()
{
return $this->state(fn (array $attributes) => [
'quota' => false,
]);
}

public function postpaid()
{
return $this->state(fn (array $attributes) => [
'postpaid' => true,
]);
}

public function prepaid()
{
return $this->state(fn (array $attributes) => [
'postpaid' => false,
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function up()
$table->id();
$table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Plan::class);
$table->timestamp('canceled_at')->nullable();
$table->timestamp('expired_at');
$table->timestamp('expired_at')->nullable();
$table->timestamp('grace_days_ended_at')->nullable();
$table->date('started_at');
$table->timestamp('suppressed_at')->nullable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public function up()
$table->id();
$table->string('name');
$table->boolean('consumable');
$table->boolean('quota')->default(false);
$table->boolean('postpaid')->default(false);
$table->unsignedInteger('periodicity')->nullable();
$table->string('periodicity_type')->nullable();
$table->softDeletes();
Expand Down
Loading

0 comments on commit 632e46a

Please sign in to comment.