diff --git a/app/Foundation/Providers/AppServiceProvider.php b/app/Foundation/Providers/AppServiceProvider.php index c652b039e809..3565247bc082 100644 --- a/app/Foundation/Providers/AppServiceProvider.php +++ b/app/Foundation/Providers/AppServiceProvider.php @@ -54,6 +54,7 @@ public function boot(Dispatcher $dispatcher) 'metrics' => \CachetHQ\Cachet\Models\Metric::class, 'schedules' => \CachetHQ\Cachet\Models\Schedule::class, 'subscriber' => \CachetHQ\Cachet\Models\Subscriber::class, + 'tags' => \CachetHQ\Cachet\Models\Tag::class, ]); } diff --git a/app/Models/Component.php b/app/Models/Component.php index 03b611f3b1e6..6fbe8d979d31 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -147,11 +147,11 @@ public function meta() /** * Get the tags relation. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + * @return \Illuminate\Database\Eloquent\Relations\MorphMany */ public function tags() { - return $this->belongsToMany(Tag::class); + return $this->morphMany(Taggable::class, 'taggable'); } /** diff --git a/app/Models/Taggable.php b/app/Models/Taggable.php new file mode 100644 index 000000000000..d8c0c1fb32c8 --- /dev/null +++ b/app/Models/Taggable.php @@ -0,0 +1,79 @@ + + */ +class Taggable extends Model +{ + use ValidationTrait; + + /** + * The attributes that should be casted to native types. + * + * @var string[] + */ + protected $casts = [ + 'id' => 'int', + 'tag_id' => 'int', + 'taggable_id' => 'int', + 'taggable_type' => 'string', + ]; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'tag_id', + 'taggable_id', + 'taggable_type', + ]; + + /** + * The validation rules. + * + * @var string[] + */ + public $rules = [ + 'tag_id' => 'required|int', + 'taggable_id' => 'required|int', + 'taggable_type' => 'required|string', + ]; + + /** + * Get the tag relation. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function tag() + { + return $this->belongsTo(Tag::class); + } + + /** + * Get the taggable relation. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphTo + */ + public function taggable() + { + return $this->morphTo(); + } +} diff --git a/database/migrations/2018_04_02_163328_CreateTaggablesTable.php b/database/migrations/2018_04_02_163328_CreateTaggablesTable.php new file mode 100644 index 000000000000..7a05ce3e68f8 --- /dev/null +++ b/database/migrations/2018_04_02_163328_CreateTaggablesTable.php @@ -0,0 +1,42 @@ +increments('id'); + $table->integer('tag_id')->unsigned()->index(); + $table->morphs('taggable'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('taggables'); + } +} diff --git a/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php new file mode 100644 index 000000000000..0d33597f7d61 --- /dev/null +++ b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php @@ -0,0 +1,57 @@ +get()->each(function ($tag) { + Taggable::create([ + 'tag_id' => $tag->tag_id, + 'taggable_type' => 'components', + 'taggable_id' => $tag->component_id, + ]); + }); + + Schema::dropIfExists('component_tag'); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::create('component_tag', function (Blueprint $table) { + $table->engine = 'InnoDB'; + + $table->increments('id'); + $table->integer('component_id'); + $table->integer('tag_id'); + + $table->index('component_id'); + $table->index('tag_id'); + }); + } +} diff --git a/tests/Models/TaggableTest.php b/tests/Models/TaggableTest.php new file mode 100644 index 000000000000..8a5271a35329 --- /dev/null +++ b/tests/Models/TaggableTest.php @@ -0,0 +1,31 @@ + + */ +class TaggableTest extends AbstractTestCase +{ + use ValidationTrait; + + public function testValidation() + { + $this->checkRules(new Taggable()); + } +}