From 4e1824d49a0f29fae6c86dfd2f08d37acb6c313d Mon Sep 17 00:00:00 2001 From: jon brookes Date: Thu, 8 Jan 2026 13:41:18 +0000 Subject: [PATCH] feat: add tagging functionality to entries model and related migrations --- CHANGELOG.md | 12 + .../Resources/Entries/Schemas/EntryForm.php | 4 + app/Models/Entry.php | 3 +- composer.json | 4 +- composer.lock | 288 +++++++++++++++++- config/tags.php | 28 ++ .../2026_01_08_130657_create_tag_tables.php | 36 +++ 7 files changed, 361 insertions(+), 14 deletions(-) create mode 100644 config/tags.php create mode 100644 database/migrations/2026_01_08_130657_create_tag_tables.php diff --git a/CHANGELOG.md b/CHANGELOG.md index babbc36..363ddff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # CHANGELOG +## 2026-01-08 + +added tags to entry model + +## 2026-01-07 + +added simple API for entries model +- to view entries +- implement initial access control + +this is sufficient to test static site generation + ## 2026-01-06 added diff --git a/app/Filament/Resources/Entries/Schemas/EntryForm.php b/app/Filament/Resources/Entries/Schemas/EntryForm.php index b7bdf36..bd48f4d 100644 --- a/app/Filament/Resources/Entries/Schemas/EntryForm.php +++ b/app/Filament/Resources/Entries/Schemas/EntryForm.php @@ -14,6 +14,7 @@ use Filament\Schemas\Schema; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Spatie\MediaLibrary\MediaCollections\Models\Media; +use Filament\Forms\Components\SpatieTagsInput; class EntryForm { @@ -33,6 +34,9 @@ class EntryForm ->readOnly(), Textarea::make('description') ->columnSpanFull(), + SpatieTagsInput::make('tags') + ->type('entry-tags') + ->columnSpanFull(), SpatieMediaLibraryFileUpload::make('featured_image') ->collection('featured-image') ->image() diff --git a/app/Models/Entry.php b/app/Models/Entry.php index 98d1e2e..0e7df8d 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; +use Spatie\Tags\HasTags; /* Entry model with rich content and media library integration @@ -19,7 +20,7 @@ class Entry extends Model implements HasRichContent, HasMedia { - use InteractsWithMedia, InteractsWithRichContent, HasFactory; + use InteractsWithMedia, InteractsWithRichContent, HasFactory, HasTags; protected $fillable = [ 'title', diff --git a/composer.json b/composer.json index 3d29291..19e926f 100644 --- a/composer.json +++ b/composer.json @@ -9,12 +9,14 @@ "php": "^8.2", "filament/filament": "^4.0", "filament/spatie-laravel-media-library-plugin": "^4.4", + "filament/spatie-laravel-tags-plugin": "^4.0", "laravel/fortify": "^1.30", "laravel/framework": "^12.0", "laravel/sanctum": "^4.0", "laravel/tinker": "^2.10.1", "livewire/flux": "^2.9.0", - "spatie/laravel-medialibrary": "^11.17" + "spatie/laravel-medialibrary": "^11.17", + "spatie/laravel-tags": "^4.10" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/composer.lock b/composer.lock index 4eaf27f..d086086 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "32f224d40d70f511e2d89add38a0d2cf", + "content-hash": "f4958020fbef658afa0859ba9b23a152", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -1546,6 +1546,43 @@ }, "time": "2025-12-09T09:54:02+00:00" }, + { + "name": "filament/spatie-laravel-tags-plugin", + "version": "v4.4.0", + "source": { + "type": "git", + "url": "https://github.com/filamentphp/spatie-laravel-tags-plugin.git", + "reference": "2f90daee868c1d1031180c51045baa77afebf9a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filamentphp/spatie-laravel-tags-plugin/zipball/2f90daee868c1d1031180c51045baa77afebf9a7", + "reference": "2f90daee868c1d1031180c51045baa77afebf9a7", + "shasum": "" + }, + "require": { + "filament/support": "self.version", + "php": "^8.2", + "spatie/laravel-tags": "^4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Filament\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Filament support for `spatie/laravel-tags`.", + "homepage": "https://github.com/filamentphp/filament", + "support": { + "issues": "https://github.com/filamentphp/filament/issues", + "source": "https://github.com/filamentphp/filament" + }, + "time": "2025-12-09T09:52:55+00:00" + }, { "name": "filament/support", "version": "v4.4.0", @@ -2366,16 +2403,16 @@ }, { "name": "laravel/framework", - "version": "v12.44.0", + "version": "v12.46.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "592bbf1c036042958332eb98e3e8131b29102f33" + "reference": "9dcff48d25a632c1fadb713024c952fec489c4ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/592bbf1c036042958332eb98e3e8131b29102f33", - "reference": "592bbf1c036042958332eb98e3e8131b29102f33", + "url": "https://api.github.com/repos/laravel/framework/zipball/9dcff48d25a632c1fadb713024c952fec489c4ae", + "reference": "9dcff48d25a632c1fadb713024c952fec489c4ae", "shasum": "" }, "require": { @@ -2584,7 +2621,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-12-23T15:29:43+00:00" + "time": "2026-01-07T23:26:53+00:00" }, { "name": "laravel/prompts", @@ -5637,6 +5674,80 @@ ], "time": "2022-12-17T21:53:22+00:00" }, + { + "name": "spatie/eloquent-sortable", + "version": "4.5.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/eloquent-sortable.git", + "reference": "c1c4f3a66cd41eb7458783c8a4c8e5d7924a9f20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/eloquent-sortable/zipball/c1c4f3a66cd41eb7458783c8a4c8e5d7924a9f20", + "reference": "c1c4f3a66cd41eb7458783c8a4c8e5d7924a9f20", + "shasum": "" + }, + "require": { + "illuminate/database": "^9.31|^10.0|^11.0|^12.0", + "illuminate/support": "^9.31|^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.63|^3.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.9" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpunit/phpunit": "^9.5|^10.0|^11.5.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\EloquentSortable\\EloquentSortableServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\EloquentSortable\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be" + } + ], + "description": "Sortable behaviour for eloquent models", + "homepage": "https://github.com/spatie/eloquent-sortable", + "keywords": [ + "behaviour", + "eloquent", + "laravel", + "model", + "sort", + "sortable" + ], + "support": { + "issues": "https://github.com/spatie/eloquent-sortable/issues", + "source": "https://github.com/spatie/eloquent-sortable/tree/4.5.2" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-08-25T11:46:57+00:00" + }, { "name": "spatie/image", "version": "3.8.7", @@ -5995,6 +6106,159 @@ ], "time": "2025-07-17T15:46:43+00:00" }, + { + "name": "spatie/laravel-tags", + "version": "4.10.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-tags.git", + "reference": "26fe2ad5490e65e2a3475c3fe8a4d9609934aa40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-tags/zipball/26fe2ad5490e65e2a3475c3fe8a4d9609934aa40", + "reference": "26fe2ad5490e65e2a3475c3fe8a4d9609934aa40", + "shasum": "" + }, + "require": { + "laravel/framework": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.63|^3.0", + "php": "^8.1", + "spatie/eloquent-sortable": "^4.0", + "spatie/laravel-package-tools": "^1.4", + "spatie/laravel-translatable": "^6.0" + }, + "require-dev": { + "orchestra/testbench": "^8.0|^9.0|^10.0", + "pestphp/pest": "^1.22|^2.0", + "phpunit/phpunit": "^9.5.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Tags\\TagsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\Tags\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Add tags and taggable behaviour to your Laravel app", + "homepage": "https://github.com/spatie/laravel-tags", + "keywords": [ + "laravel-tags", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-tags/issues", + "source": "https://github.com/spatie/laravel-tags/tree/4.10.1" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-10-13T14:16:14+00:00" + }, + { + "name": "spatie/laravel-translatable", + "version": "6.12.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-translatable.git", + "reference": "8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349", + "reference": "8fc0c1dd5ab4013c27a28e5d5590f2ce849bd349", + "shasum": "" + }, + "require": { + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "php": "^8.3", + "spatie/laravel-package-tools": "^1.92.7" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.90", + "mockery/mockery": "^1.6.12", + "orchestra/testbench": "^9.0|^10.0", + "pestphp/pest": "^4.0.0" + }, + "type": "library", + "extra": { + "aliases": { + "Translatable": "Spatie\\Translatable\\Facades\\Translatable" + }, + "laravel": { + "providers": [ + "Spatie\\Translatable\\TranslatableServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\Translatable\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Sebastian De Deyne", + "email": "sebastian@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A trait to make an Eloquent model hold translations", + "homepage": "https://github.com/spatie/laravel-translatable", + "keywords": [ + "eloquent", + "i8n", + "laravel-translatable", + "model", + "multilingual", + "spatie", + "translate" + ], + "support": { + "issues": "https://github.com/spatie/laravel-translatable/issues", + "source": "https://github.com/spatie/laravel-translatable/tree/6.12.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-11-24T15:57:48+00:00" + }, { "name": "spatie/shiki-php", "version": "2.3.2", @@ -12595,16 +12859,16 @@ }, { "name": "webmozart/assert", - "version": "2.0.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "1b34b004e35a164bc5bb6ebd33c844b2d8069a54" + "reference": "bdbabc199a7ba9965484e4725d66170e5711323b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/1b34b004e35a164bc5bb6ebd33c844b2d8069a54", - "reference": "1b34b004e35a164bc5bb6ebd33c844b2d8069a54", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bdbabc199a7ba9965484e4725d66170e5711323b", + "reference": "bdbabc199a7ba9965484e4725d66170e5711323b", "shasum": "" }, "require": { @@ -12651,9 +12915,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.0.0" + "source": "https://github.com/webmozarts/assert/tree/2.1.1" }, - "time": "2025-12-16T21:36:00+00:00" + "time": "2026-01-08T11:28:40+00:00" } ], "aliases": [], diff --git a/config/tags.php b/config/tags.php new file mode 100644 index 0000000..628dc1a --- /dev/null +++ b/config/tags.php @@ -0,0 +1,28 @@ + null, + + /* + * The fully qualified class name of the tag model. + */ + 'tag_model' => Spatie\Tags\Tag::class, + + /* + * The name of the table associated with the taggable morph relation. + */ + 'taggable' => [ + 'table_name' => 'taggables', + 'morph_name' => 'taggable', + + /* + * The fully qualified class name of the pivot model. + */ + 'class_name' => Illuminate\Database\Eloquent\Relations\MorphPivot::class, + ] +]; diff --git a/database/migrations/2026_01_08_130657_create_tag_tables.php b/database/migrations/2026_01_08_130657_create_tag_tables.php new file mode 100644 index 0000000..5925c6c --- /dev/null +++ b/database/migrations/2026_01_08_130657_create_tag_tables.php @@ -0,0 +1,36 @@ +id(); + + $table->json('name'); + $table->json('slug'); + $table->string('type')->nullable(); + $table->integer('order_column')->nullable(); + + $table->timestamps(); + }); + + Schema::create('taggables', function (Blueprint $table) { + $table->foreignId('tag_id')->constrained()->cascadeOnDelete(); + + $table->morphs('taggable'); + + $table->unique(['tag_id', 'taggable_id', 'taggable_type']); + }); + } + + public function down(): void + { + Schema::dropIfExists('taggables'); + Schema::dropIfExists('tags'); + } +};