From 3eb417da1df5914c065d6a3faf8ba8773d30cc01 Mon Sep 17 00:00:00 2001 From: Arthur Monney Date: Wed, 24 Jul 2024 04:47:46 +0200 Subject: [PATCH] feat: Add support for Laravel 11 --- .github/dependabot.yml | 15 ++--- .github/workflows/phpstan.yml | 28 ++++++--- .github/workflows/tests.yml | 27 +++++++-- .github/workflows/update-changelog.yml | 28 +++++++++ README.md | 6 +- composer.json | 12 ++-- .../migrations/create_plan_features_table.php | 8 +-- .../create_plan_subscription_usage_table.php | 11 ++-- .../create_plan_subscriptions_table.php | 8 +-- database/migrations/create_plans_table.php | 6 +- phpstan.neon | 2 +- src/Models/Plan.php | 2 +- src/Models/Subscription.php | 57 +++---------------- src/Services/Period.php | 11 ++-- src/Traits/HasPlanSubscriptions.php | 2 +- src/Traits/HasTranslations.php | 2 +- tests/Pest.php | 2 - tests/src/TestCase.php | 2 + 18 files changed, 122 insertions(+), 107 deletions(-) create mode 100644 .github/workflows/update-changelog.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 25127b1..675ffae 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,9 +1,10 @@ version: 2 + updates: -- package-ecosystem: composer - directory: "/" - schedule: - interval: daily - time: "03:00" - open-pull-requests-limit: 10 - target-branch: develop + - package-ecosystem: composer + directory: "/" + schedule: + interval: daily + time: "03:00" + open-pull-requests-limit: 10 + target-branch: main diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 3fc46d2..ab92542 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -1,33 +1,47 @@ name: PHPStan -on: - push: - pull_request: +on: [push, pull_request] jobs: phpstan: runs-on: ubuntu-latest strategy: - fail-fast: false + fail-fast: true matrix: php: [8.1, 8.2] - laravel: [9.*, 10.*] - dependency-version: [prefer-stable] + laravel: [9.*, 10.*, 11.*] + dependency-version: [prefer-lowest, prefer-stable] + include: + - laravel: 11.* + testbench: 9.* + - laravel: 10.* + testbench: 8.* + - laravel: 9.* + testbench: 7.* + exclude: + - laravel: 11.* + php: 8.1 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} + steps: - - uses: actions/checkout@v3 + - name: Checkout code + uses: actions/checkout@v4 + - name: Cache dependencies uses: actions/cache@v2 with: path: ~/.composer/cache/files key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite coverage: none + - name: Install dependencies run: composer install --prefer-dist --no-interaction + - name: Run PHPStan run: composer stan diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c6bb3cb..2f0c0da 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,21 +5,40 @@ on: [push, pull_request] jobs: tests: runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: [8.1, 8.2] + laravel: [9.*, 10.*, 11.*] + dependency-version: [prefer-lowest, prefer-stable] + include: + - laravel: 11.* + testbench: 9.* + - laravel: 10.* + testbench: 8.* + - laravel: 9.* + testbench: 7.* + exclude: + - laravel: 11.* + php: 8.1 + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite tools: composer:v2 coverage: none - name: Install Composer dependencies - run: composer install --prefer-dist --no-interaction + run: | + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update + composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction - name: Execute tests - run: composer pest + run: vendor/bin/pest diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 0000000..0cdea23 --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,28 @@ +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: main + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.name }} + release-notes: ${{ github.event.release.body }} + + - name: Commit updated CHANGELOG + uses: stefanzweifel/git-auto-commit-action@v5 + with: + branch: main + commit_message: Update CHANGELOG + file_pattern: CHANGELOG.md diff --git a/README.md b/README.md index 92d5204..cf13d32 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ $plan = Plan::find(1); $plan->features; // Get all plan subscriptions -$plan->planSubscriptions; +$plan->subscriptions; // Check if the plan is free $plan->isFree(); @@ -130,7 +130,7 @@ $plan->hasTrial(); $plan->hasGrace(); ``` -Both `$plan->features` and `$plan->planSubscriptions` are collections, driven from relationships, and thus you can query these relations as any normal Eloquent relationship. E.g. `$plan->features()->where('name', 'listing_title_bold')->first()`. +Both `$plan->features` and `$plan->subscriptions` are collections, driven from relationships, and thus you can query these relations as any normal Eloquent relationship. E.g. `$plan->features()->where('name', 'listing_title_bold')->first()`. ### Get Feature Value @@ -181,7 +181,7 @@ $subscription = Subscription::find(1); $subscription->changePlan($plan); ``` -If both plans (current and new plan) have the same billing frequency (e.g., `invoice_period` and `invoice_interval`) the subscription will retain the same billing dates. If the plans don't have the same billing frequency, the subscription will have the new plan billing frequency, starting on the day of the change and _the subscription usage data will be cleared_. Also if the new plan has a trial period and it's a new subscription, the trial period will be applied. +If both plans (current and new plan) have the same billing frequency (e.g., `invoice_period` and `invoice_interval`) the subscription will retain the same billing dates. If the plans don't have the same billing frequency, the subscription will have the new plan billing frequency, starting on the day of the change and _the subscription usage data will be cleared_. Also, if the new plan has a trial period, and it's a new subscription, the trial period will be applied. ### Feature Options diff --git a/composer.json b/composer.json index bdba1ac..c507a0e 100644 --- a/composer.json +++ b/composer.json @@ -32,10 +32,10 @@ ], "require": { "php": "^8.1", - "illuminate/console": "^9.0|^10.0", - "illuminate/container": "^9.0|^10.0", - "illuminate/database": "^9.0|^10.0", - "illuminate/support": "^9.0|^10.0", + "illuminate/console": "^9.0|^10.0|^11.0", + "illuminate/container": "^9.0|^10.0|^11.0", + "illuminate/database": "^9.0|^10.0|^11.0", + "illuminate/support": "^9.0|^10.0|^11.0", "spatie/eloquent-sortable": "^4.0.0", "spatie/laravel-package-tools": "^1.16", "spatie/laravel-sluggable": "^3.4.2", @@ -43,8 +43,8 @@ }, "require-dev": { "laravel/pint": "^1.13", - "nunomaduro/larastan": "^2.0", - "orchestra/testbench": "^7.0|^8.0", + "larastan/larastan": "^2.0", + "orchestra/testbench": "^7.0|^8.0|^9.0", "pestphp/pest": "^2.18" }, "autoload": { diff --git a/database/migrations/create_plan_features_table.php b/database/migrations/create_plan_features_table.php index 739c72b..b3276c1 100755 --- a/database/migrations/create_plan_features_table.php +++ b/database/migrations/create_plan_features_table.php @@ -2,18 +2,18 @@ declare(strict_types=1); -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -use Laravelcm\Subscriptions\Models\Plan; -return new class () extends Migration { +return new class() extends Migration +{ public function up(): void { Schema::create(config('laravel-subscriptions.tables.features'), function (Blueprint $table): void { $table->id(); - $table->foreignIdFor(Plan::class); + $table->foreignIdFor(config('laravel-subscriptions.models.plan')); $table->json('name'); $table->string('slug')->unique(); $table->json('description')->nullable(); diff --git a/database/migrations/create_plan_subscription_usage_table.php b/database/migrations/create_plan_subscription_usage_table.php index 389c976..d0ede94 100755 --- a/database/migrations/create_plan_subscription_usage_table.php +++ b/database/migrations/create_plan_subscription_usage_table.php @@ -2,20 +2,19 @@ declare(strict_types=1); -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -use Laravelcm\Subscriptions\Models\Feature; -use Laravelcm\Subscriptions\Models\Subscription; -return new class () extends Migration { +return new class() extends Migration +{ public function up(): void { Schema::create(config('laravel-subscriptions.tables.subscription_usage'), function (Blueprint $table): void { $table->id(); - $table->foreignIdFor(Subscription::class); - $table->foreignIdFor(Feature::class); + $table->foreignIdFor(config('laravel-subscriptions.models.subscription')); + $table->foreignIdFor(config('laravel-subscriptions.models.feature')); $table->unsignedSmallInteger('used'); $table->string('timezone')->nullable(); diff --git a/database/migrations/create_plan_subscriptions_table.php b/database/migrations/create_plan_subscriptions_table.php index c15fae9..0d27068 100755 --- a/database/migrations/create_plan_subscriptions_table.php +++ b/database/migrations/create_plan_subscriptions_table.php @@ -2,19 +2,19 @@ declare(strict_types=1); -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -use Laravelcm\Subscriptions\Models\Plan; -return new class () extends Migration { +return new class() extends Migration +{ public function up(): void { Schema::create(config('laravel-subscriptions.tables.subscriptions'), function (Blueprint $table): void { $table->id(); $table->morphs('subscriber'); - $table->foreignIdFor(Plan::class); + $table->foreignIdFor(config('laravel-subscriptions.models.plan')); $table->json('name'); $table->string('slug')->unique(); $table->json('description')->nullable(); diff --git a/database/migrations/create_plans_table.php b/database/migrations/create_plans_table.php index 2bbcbe5..574ccc2 100755 --- a/database/migrations/create_plans_table.php +++ b/database/migrations/create_plans_table.php @@ -2,12 +2,13 @@ declare(strict_types=1); -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Laravelcm\Subscriptions\Interval; -return new class () extends Migration { +return new class() extends Migration +{ public function up(): void { Schema::create(config('laravel-subscriptions.tables.plans'), function (Blueprint $table): void { @@ -37,7 +38,6 @@ public function up(): void }); } - public function down(): void { Schema::dropIfExists(config('laravel-subscriptions.tables.plans')); diff --git a/phpstan.neon b/phpstan.neon index 0dae1b1..a8a40bf 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ includes: -- ./vendor/nunomaduro/larastan/extension.neon +- ./vendor/larastan/larastan/extension.neon parameters: diff --git a/src/Models/Plan.php b/src/Models/Plan.php index 8545f6b..f32fbc9 100755 --- a/src/Models/Plan.php +++ b/src/Models/Plan.php @@ -138,7 +138,7 @@ protected static function boot(): void { parent::boot(); - static::deleted(function (Plan $plan): void { + static::deleted(function ($plan): void { $plan->features()->delete(); $plan->subscriptions()->delete(); }); diff --git a/src/Models/Subscription.php b/src/Models/Subscription.php index a312326..fc808de 100755 --- a/src/Models/Subscription.php +++ b/src/Models/Subscription.php @@ -5,15 +5,15 @@ namespace Laravelcm\Subscriptions\Models; use Carbon\Carbon; -use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphTo; -use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\DB; -use Laravelcm\Subscriptions\Traits\BelongsToPlan; use Laravelcm\Subscriptions\Services\Period; +use Laravelcm\Subscriptions\Traits\BelongsToPlan; use Laravelcm\Subscriptions\Traits\HasSlug; use Laravelcm\Subscriptions\Traits\HasTranslations; use LogicException; @@ -205,9 +205,9 @@ public function changePlan(Plan $plan): self /** * Renew subscription period. * - * @throws LogicException - * * @return $this + * + * @throws LogicException */ public function renew(): self { @@ -232,11 +232,6 @@ public function renew(): self /** * Get bookings of the given subscriber. - * - * @param Builder $builder - * @param Model $subscriber - * - * @return Builder */ public function scopeOfSubscriber(Builder $builder, Model $subscriber): Builder { @@ -246,11 +241,6 @@ public function scopeOfSubscriber(Builder $builder, Model $subscriber): Builder /** * Scope subscriptions with ending trial. - * - * @param Builder $builder - * @param int $dayRange - * - * @return Builder */ public function scopeFindEndingTrial(Builder $builder, int $dayRange = 3): Builder { @@ -262,10 +252,6 @@ public function scopeFindEndingTrial(Builder $builder, int $dayRange = 3): Build /** * Scope subscriptions with ended trial. - * - * @param Builder $builder - * - * @return Builder */ public function scopeFindEndedTrial(Builder $builder): Builder { @@ -274,11 +260,6 @@ public function scopeFindEndedTrial(Builder $builder): Builder /** * Scope subscriptions with ending periods. - * - * @param Builder $builder - * @param int $dayRange - * - * @return Builder */ public function scopeFindEndingPeriod(Builder $builder, int $dayRange = 3): Builder { @@ -290,10 +271,6 @@ public function scopeFindEndingPeriod(Builder $builder, int $dayRange = 3): Buil /** * Scope subscriptions with ended periods. - * - * @param Builder $builder - * - * @return Builder */ public function scopeFindEndedPeriod(Builder $builder): Builder { @@ -302,10 +279,6 @@ public function scopeFindEndedPeriod(Builder $builder): Builder /** * Scope all active subscriptions for a user. - * - * @param Builder $builder - * - * @return Builder */ public function scopeFindActive(Builder $builder): Builder { @@ -315,13 +288,9 @@ public function scopeFindActive(Builder $builder): Builder /** * Set new subscription period. * - * @param string $invoice_interval - * @param int|null $invoice_period - * @param Carbon|null $start - * * @return $this */ - protected function setNewPeriod(string $invoice_interval = '', int $invoice_period = null, Carbon $start = null): self + protected function setNewPeriod(string $invoice_interval = '', ?int $invoice_period = null, ?Carbon $start = null): self { if (empty($invoice_interval)) { $invoice_interval = $this->plan->invoice_interval; @@ -390,10 +359,6 @@ public function reduceFeatureUsage(string $featureSlug, int $uses = 1): ?Subscri /** * Determine if the feature can be used. - * - * @param string $featureSlug - * - * @return bool */ public function canUseFeature(string $featureSlug): bool { @@ -416,10 +381,6 @@ public function canUseFeature(string $featureSlug): bool /** * Get how many times the feature has been used. - * - * @param string $featureSlug - * - * @return int */ public function getFeatureUsage(string $featureSlug): int { @@ -430,10 +391,6 @@ public function getFeatureUsage(string $featureSlug): int /** * Get the available uses. - * - * @param string $featureSlug - * - * @return int */ public function getFeatureRemainings(string $featureSlug): int { diff --git a/src/Services/Period.php b/src/Services/Period.php index 420c968..ef39c41 100755 --- a/src/Services/Period.php +++ b/src/Services/Period.php @@ -8,24 +8,21 @@ final class Period { - private Carbon | string $start; + private Carbon|string $start; - private Carbon | string $end; + private Carbon|string $end; private string $interval; - private int $period = 1; + private int $period; /** * Create a new Period instance. * - * @param string $interval - * @param int $count - * @param Carbon|null $start * * @return void */ - public function __construct(string $interval = 'month', int $count = 1, Carbon $start = null) + public function __construct(string $interval = 'month', int $count = 1, ?Carbon $start = null) { $this->interval = $interval; diff --git a/src/Traits/HasPlanSubscriptions.php b/src/Traits/HasPlanSubscriptions.php index 1b15836..83844c3 100755 --- a/src/Traits/HasPlanSubscriptions.php +++ b/src/Traits/HasPlanSubscriptions.php @@ -16,7 +16,7 @@ trait HasPlanSubscriptions protected static function bootHasSubscriptions(): void { static::deleted(function ($plan): void { - $plan->planSubscriptions()->delete(); + $plan->subscriptions()->delete(); }); } diff --git a/src/Traits/HasTranslations.php b/src/Traits/HasTranslations.php index ea2acc2..c19e5df 100644 --- a/src/Traits/HasTranslations.php +++ b/src/Traits/HasTranslations.php @@ -26,7 +26,7 @@ public function getAttributeValue(mixed $key): mixed /** * @throws AttributeIsNotTranslatable */ - public function getTranslations(string $key = null): array + public function getTranslations(?string $key = null): array { if ($key !== null) { $this->guardAgainstNonTranslatableAttribute($key); diff --git a/tests/Pest.php b/tests/Pest.php index 437c9b7..5eb33c1 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -5,5 +5,3 @@ use Tests\TestCase; uses(TestCase::class)->in('Feature'); - -expect()->extend('toBeOne', fn () => $this->toBe(1)); diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php index 47168d1..e79606d 100644 --- a/tests/src/TestCase.php +++ b/tests/src/TestCase.php @@ -6,12 +6,14 @@ use Illuminate\Foundation\Testing\LazilyRefreshDatabase; use Laravelcm\Subscriptions\SubscriptionServiceProvider; +use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase as BaseTestCase; use Tests\Models\User; abstract class TestCase extends BaseTestCase { use LazilyRefreshDatabase; + use WithWorkbench; protected function getPackageProviders($app): array {