Repository navigation
Require course certificate templates #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
b17ac70
feat: add optional course certificate templates
362a327
Fix styling
johnwesely 348504f
fix: satisfy PHPStan on course templates
05a9a15
fix: allow template actions without policy
b0144f8
feat: migrate award blades to templates
78bbae4
feat!: require certificate templates on courses
79f8397
fix: satisfy PHPStan on award layout helpers
6b12c0f
Merge branch '4.x' into lms-certificate-builder-CU-868m0zvvx
7e4aca1
fix: default templates after award drop
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Upgrading | ||
|
|
||
| ## Award certificates → certificate templates | ||
|
|
||
| This is a breaking change. Course certificates are builder-only. The `lms_courses.award` column is removed. | ||
|
|
||
| ### Before you deploy | ||
|
|
||
| 1. Require the builder in the host app: | ||
|
|
||
| ```bash | ||
| composer require tapp/filament-certificate-builder | ||
| ``` | ||
|
|
||
| 2. Keep `filament-lms.awards` in the host config until `php artisan migrate` has run. The upgrade reads those labels (and any `award` values already on courses) to name templates. After migrate succeeds you can delete the `awards` array. | ||
|
|
||
| 3. Keep published award Blades on disk until migrate has run (`resources/views/vendor/filament-lms/certificates/*.blade.php`). They are the source for logos, copy, borders, and headers. | ||
|
|
||
| 4. Enable the course token set in `config/certificate-builder.php` and point `filament-lms.integrations.certificate_builder.template_resource` at your Filament resource. | ||
|
|
||
| ### Upgrade | ||
|
|
||
| ```bash | ||
| php artisan filament-lms:upgrade-awards --dry-run | ||
| php artisan migrate | ||
| ``` | ||
|
|
||
| `php artisan migrate` runs `drop_award_from_lms_courses_table`, which: | ||
|
|
||
| 1. Creates or reuses one certificate template per award key | ||
| 2. Assigns a template to every course that does not already have a living `certificate_template_id` (`award = null` uses **Default Certificate**) | ||
| 3. Does **not** overwrite hand-edited templates or retarget courses that already point at a different template | ||
| 4. Fails if any course still lacks a template | ||
| 5. Makes `certificate_template_id` required (`restrictOnDelete`) and drops `award` | ||
|
|
||
| Preview or force-refresh migrated layouts (not custom templates) with: | ||
|
|
||
| ```bash | ||
| php artisan filament-lms:upgrade-awards --dump=storage/logs/lms-award-upgrade.json | ||
| php artisan filament-lms:upgrade-awards --force | ||
| php artisan filament-lms:upgrade-awards --award=decan | ||
| ``` | ||
|
|
||
| `filament-lms:migrate-awards-to-templates` is a hidden alias and will be removed in a later release. | ||
|
|
||
| ### After migrate | ||
|
|
||
| - Delete published LMS award Blades and any Tailwind `@source` aimed only at those views | ||
| - Remove `awards` from `config/filament-lms.php` | ||
| - Point SCORM imports and new courses at a certificate template (the course form and `CourseFactory` default to **Default Certificate**) | ||
| - Training / certification certificates (CHECK `awardCertification()`) are unchanged | ||
|
|
||
| ### Notes | ||
|
|
||
| - Layouts are not pixel-perfect copies of the old Blades | ||
| - `--force` only refreshes templates named `{Award label} Certificate` | ||
| - Courses with `award` values that had no Blade (for example CHECK `chwad`) get the default Blade source | ||
| - Rollback cannot restore per-course `award` values unless you keep the `--dump` JSON |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
database/migrations/add_certificate_template_id_to_lms_courses_table.php.stub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <?php | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| /** | ||
| * Run the migrations. | ||
| */ | ||
| public function up(): void | ||
| { | ||
| if (Schema::hasColumn('lms_courses', 'certificate_template_id')) { | ||
| return; | ||
| } | ||
|
|
||
| Schema::table('lms_courses', function (Blueprint $table) { | ||
| $table->unsignedBigInteger('certificate_template_id') | ||
| ->nullable() | ||
| ->after('award') | ||
| ->index(); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Reverse the migrations. | ||
| */ | ||
| public function down(): void | ||
| { | ||
| Schema::table('lms_courses', function (Blueprint $table) { | ||
| $table->dropIndex(['certificate_template_id']); | ||
| $table->dropColumn('certificate_template_id'); | ||
| }); | ||
| } | ||
| }; |
55 changes: 55 additions & 0 deletions
55
database/migrations/drop_award_from_lms_courses_table.php.stub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <?php | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
| use Tapp\FilamentLms\Services\MigrateAwardsToCertificateTemplates; | ||
| use Tapp\FilamentLms\Support\CertificateBuilder; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| if (! Schema::hasColumn('lms_courses', 'award')) { | ||
| return; | ||
| } | ||
|
|
||
| if (! CertificateBuilder::enabled()) { | ||
| throw new RuntimeException('tapp/filament-certificate-builder must be installed before dropping lms_courses.award. See UPGRADING.md.'); | ||
| } | ||
|
|
||
| app(MigrateAwardsToCertificateTemplates::class)->handle(); | ||
|
|
||
| $unverified = app(MigrateAwardsToCertificateTemplates::class)->unverifiedCourseIds(); | ||
|
|
||
| if ($unverified !== []) { | ||
| throw new RuntimeException( | ||
| 'Cannot drop lms_courses.award while courses lack a certificate template (ids: '.implode(', ', $unverified).'). Run php artisan filament-lms:upgrade-awards.', | ||
| ); | ||
| } | ||
|
|
||
| $hasForeignKey = collect(Schema::getForeignKeys('lms_courses')) | ||
| ->contains(fn (array $foreignKey): bool => in_array('certificate_template_id', $foreignKey['columns'], true)); | ||
|
|
||
| if ($hasForeignKey) { | ||
| Schema::table('lms_courses', function (Blueprint $table): void { | ||
| $table->dropForeign(['certificate_template_id']); | ||
| }); | ||
| } | ||
|
|
||
| Schema::table('lms_courses', function (Blueprint $table): void { | ||
| $table->unsignedBigInteger('certificate_template_id')->nullable(false)->change(); | ||
| }); | ||
|
|
||
| Schema::table('lms_courses', function (Blueprint $table): void { | ||
| $table->foreign('certificate_template_id') | ||
| ->references('id') | ||
| ->on('certificate_templates') | ||
| ->restrictOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('lms_courses', function (Blueprint $table): void { | ||
| $table->dropColumn('award'); | ||
| }); | ||
| } | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
src/Console/Commands/MigrateAwardsToCertificateTemplatesCommand.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tapp\FilamentLms\Console\Commands; | ||
|
|
||
| use Illuminate\Console\Command; | ||
|
|
||
| final class MigrateAwardsToCertificateTemplatesCommand extends Command | ||
| { | ||
| protected $hidden = true; | ||
|
|
||
| protected $signature = 'filament-lms:migrate-awards-to-templates | ||
| {--award= : Only migrate this award key} | ||
| {--dry-run : Show the plan without writing} | ||
| {--force : Recreate layouts for migrated template names} | ||
| {--dump= : Write a JSON summary to this path}'; | ||
|
|
||
| protected $description = 'Deprecated alias of filament-lms:upgrade-awards'; | ||
|
|
||
| public function handle(): int | ||
| { | ||
| $this->warn('filament-lms:migrate-awards-to-templates is deprecated. Use filament-lms:upgrade-awards.'); | ||
|
|
||
| return $this->call('filament-lms:upgrade-awards', [ | ||
| '--award' => $this->option('award'), | ||
| '--dry-run' => $this->option('dry-run'), | ||
| '--force' => $this->option('force'), | ||
| '--dump' => $this->option('dump'), | ||
| ]); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.