From 06af61b8c5ce1da14f7e8fc37928652fbfa4e9a7 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:27:50 +0100 Subject: [PATCH 01/11] Fix plucking of tags --- app/Presenters/ComponentPresenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Presenters/ComponentPresenter.php b/app/Presenters/ComponentPresenter.php index 30bb2239..07a2458e 100644 --- a/app/Presenters/ComponentPresenter.php +++ b/app/Presenters/ComponentPresenter.php @@ -53,7 +53,7 @@ class ComponentPresenter extends BasePresenter implements Arrayable */ public function tags() { - return $this->wrappedObject->tags->pluck('tag.name', 'tag.slug'); + return $this->wrappedObject->tags->pluck('name', 'slug'); } /** From 6810af48f709db549556d1b2c0df982369788c43 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:29:23 +0100 Subject: [PATCH 02/11] Tag syncing is now done within the Component commands --- .../Component/CreateComponentCommand.php | 28 +++-- .../Component/UpdateComponentCommand.php | 12 +- .../CreateComponentCommandHandler.php | 9 ++ .../UpdateComponentCommandHandler.php | 9 ++ .../Controllers/Api/ComponentController.php | 32 +---- .../Dashboard/ComponentController.php | 26 +--- app/Models/Tag.php | 27 +++++ app/Models/Traits/HasTags.php | 112 +++++++++++++++++- .../Component/CreateComponentCommandTest.php | 4 +- .../Component/UpdateComponentCommandTest.php | 2 + 10 files changed, 197 insertions(+), 64 deletions(-) diff --git a/app/Bus/Commands/Component/CreateComponentCommand.php b/app/Bus/Commands/Component/CreateComponentCommand.php index eeb36054..4244f42c 100644 --- a/app/Bus/Commands/Component/CreateComponentCommand.php +++ b/app/Bus/Commands/Component/CreateComponentCommand.php @@ -74,6 +74,13 @@ final class CreateComponentCommand */ public $meta; + /** + * Tags string. + * + * @var string + */ + public $tags; + /** * The validation rules. * @@ -88,23 +95,25 @@ final class CreateComponentCommand 'group_id' => 'nullable|int', 'enabled' => 'nullable|bool', 'meta' => 'nullable|array', + 'tags' => 'nullable|string', ]; /** * Create a new add component command instance. * - * @param string $name - * @param string $description - * @param int $status - * @param string $link - * @param int $order - * @param int $group_id - * @param bool $enabled - * @param array|null $meta + * @param string $name + * @param string $description + * @param int $status + * @param string $link + * @param int $order + * @param int $group_id + * @param bool $enabled + * @param array|null $meta + * @param string|null $tags * * @return void */ - public function __construct($name, $description, $status, $link, $order, $group_id, $enabled, $meta) + public function __construct($name, $description, $status, $link, $order, $group_id, $enabled, $meta, $tags = null) { $this->name = $name; $this->description = $description; @@ -114,5 +123,6 @@ final class CreateComponentCommand $this->group_id = $group_id; $this->enabled = $enabled; $this->meta = $meta; + $this->tags = $tags; } } diff --git a/app/Bus/Commands/Component/UpdateComponentCommand.php b/app/Bus/Commands/Component/UpdateComponentCommand.php index 96550fd6..99093397 100644 --- a/app/Bus/Commands/Component/UpdateComponentCommand.php +++ b/app/Bus/Commands/Component/UpdateComponentCommand.php @@ -78,6 +78,13 @@ final class UpdateComponentCommand */ public $meta; + /** + * The tags. + * + * @var string|null + */ + public $tags; + /** * If this is true, we won't notify subscribers of the change. * @@ -114,11 +121,12 @@ final class UpdateComponentCommand * @param int|null $group_id * @param bool|null $enabled * @param array|null $meta + * @param string|null $tags * @param bool $silent * * @return void */ - public function __construct(Component $component, $name = null, $description = null, $status = null, $link = null, $order = null, $group_id = null, $enabled = null, $meta = null, $silent = null) + public function __construct(Component $component, $name = null, $description = null, $status = null, $link = null, $order = null, $group_id = null, $enabled = null, $meta = null, $tags = null, $silent = null) { $this->component = $component; $this->name = $name; @@ -129,6 +137,8 @@ final class UpdateComponentCommand $this->group_id = $group_id; $this->enabled = $enabled; $this->meta = $meta; + $this->tags = $tags; $this->silent = $silent; + $this->tags = $tags; } } diff --git a/app/Bus/Handlers/Commands/Component/CreateComponentCommandHandler.php b/app/Bus/Handlers/Commands/Component/CreateComponentCommandHandler.php index d9bcc339..867f49fb 100644 --- a/app/Bus/Handlers/Commands/Component/CreateComponentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Component/CreateComponentCommandHandler.php @@ -53,6 +53,15 @@ class CreateComponentCommandHandler { $component = Component::create($this->filter($command)); + // Sync the tags into the component. + if ($command->tags) { + collect(preg_split('/ ?, ?/', $command->tags))->filter()->map(function ($tag) { + return trim($tag); + })->pipe(function ($tags) use ($component) { + $component->attachTags($tags); + }); + } + event(new ComponentWasCreatedEvent($this->auth->user(), $component)); return $component; diff --git a/app/Bus/Handlers/Commands/Component/UpdateComponentCommandHandler.php b/app/Bus/Handlers/Commands/Component/UpdateComponentCommandHandler.php index 1fdaf007..f0ad1e44 100644 --- a/app/Bus/Handlers/Commands/Component/UpdateComponentCommandHandler.php +++ b/app/Bus/Handlers/Commands/Component/UpdateComponentCommandHandler.php @@ -56,6 +56,15 @@ class UpdateComponentCommandHandler $component->update($this->filter($command)); + // Sync the tags into the component. + if ($command->tags) { + collect(preg_split('/ ?, ?/', $command->tags))->filter()->map(function ($tag) { + return trim($tag); + })->pipe(function ($tags) use ($component) { + $component->syncTags($tags); + }); + } + event(new ComponentWasUpdatedEvent($this->auth->user(), $component)); return $component; diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index 609eeba6..e2de04f0 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -84,25 +84,13 @@ class ComponentController extends AbstractApiController Binput::get('order'), Binput::get('group_id'), (bool) Binput::get('enabled', true), - Binput::get('meta', null) + Binput::get('meta'), + Binput::get('tags'), )); } catch (QueryException $e) { throw new BadRequestHttpException(); } - if (Binput::has('tags')) { - $component->tags()->delete(); - - // The component was added successfully, so now let's deal with the tags. - Collection::make(preg_split('/ ?, ?/', $tags))->map(function ($tag) { - return trim($tag); - })->map(function ($tag) { - return execute(new CreateTagCommand($tag)); - })->each(function ($tag) use ($component) { - execute(new ApplyTagCommand($component, $tag)); - }); - } - return $this->item($component); } @@ -125,26 +113,14 @@ class ComponentController extends AbstractApiController Binput::get('order'), Binput::get('group_id'), Binput::get('enabled', $component->enabled), - Binput::get('meta', null), + Binput::get('meta'), + Binput::get('tags'), (bool) Binput::get('silent', false) )); } catch (QueryException $e) { throw new BadRequestHttpException(); } - if (Binput::has('tags')) { - $component->tags()->delete(); - - // The component was added successfully, so now let's deal with the tags. - Collection::make(preg_split('/ ?, ?/', $tags))->map(function ($tag) { - return trim($tag); - })->map(function ($tag) { - return execute(new CreateTagCommand($tag)); - })->each(function ($tag) use ($component) { - execute(new ApplyTagCommand($component, $tag)); - }); - } - return $this->item($component); } diff --git a/app/Http/Controllers/Dashboard/ComponentController.php b/app/Http/Controllers/Dashboard/ComponentController.php index 7e79c12d..31026b2b 100644 --- a/app/Http/Controllers/Dashboard/ComponentController.php +++ b/app/Http/Controllers/Dashboard/ComponentController.php @@ -113,7 +113,6 @@ class ComponentController extends Controller public function updateComponentAction(Component $component) { $componentData = Binput::get('component'); - $tags = Arr::pull($componentData, 'tags'); try { $component = execute(new UpdateComponentCommand( @@ -126,6 +125,7 @@ class ComponentController extends Controller $componentData['group_id'], $componentData['enabled'], null, // Meta data cannot be supplied through the dashboard yet. + $componentData['tags'], // Meta data cannot be supplied through the dashboard yet. true // Silent since we're not really making changes to the component (this should be optional) )); } catch (ValidationException $e) { @@ -135,17 +135,6 @@ class ComponentController extends Controller ->withErrors($e->getMessageBag()); } - $component->tags()->delete(); - - // The component was added successfully, so now let's deal with the tags. - Collection::make(preg_split('/ ?, ?/', $tags))->map(function ($tag) { - return trim($tag); - })->map(function ($tag) { - return execute(new CreateTagCommand($tag)); - })->each(function ($tag) use ($component) { - execute(new ApplyTagCommand($component, $tag)); - }); - return cachet_redirect('dashboard.components.edit', [$component->id]) ->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('dashboard.components.edit.success'))); } @@ -170,7 +159,6 @@ class ComponentController extends Controller public function createComponentAction() { $componentData = Binput::get('component'); - $tags = Arr::pull($componentData, 'tags'); try { $component = execute(new CreateComponentCommand( @@ -181,7 +169,8 @@ class ComponentController extends Controller $componentData['order'], $componentData['group_id'], $componentData['enabled'], - null // Meta data cannot be supplied through the dashboard yet. + null, // Meta data cannot be supplied through the dashboard yet. + $componentData['tags'] )); } catch (ValidationException $e) { return cachet_redirect('dashboard.components.create') @@ -190,15 +179,6 @@ class ComponentController extends Controller ->withErrors($e->getMessageBag()); } - // The component was added successfully, so now let's deal with the tags. - Collection::make(preg_split('/ ?, ?/', $tags))->map(function ($tag) { - return trim($tag); - })->map(function ($tag) { - return execute(new CreateTagCommand($tag)); - })->each(function ($tag) use ($component) { - execute(new ApplyTagCommand($component, $tag)); - }); - return cachet_redirect('dashboard.components') ->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('dashboard.components.add.success'))); } diff --git a/app/Models/Tag.php b/app/Models/Tag.php index f0a18eec..874b07ca 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -55,4 +55,31 @@ class Tag extends Model { return $this->belongsToMany(Component::class); } + + /** + * @param array|\ArrayAccess $values + * + * @return \CachetHQ\Cachet\Models\Tag|static + */ + public static function findOrCreate($values) + { + $tags = collect($values)->map(function ($value) { + if ($value instanceof Tag) { + return $value; + } + + $tag = static::where('name', '=', $value)->first(); + + if (!$tag instanceof Tag) { + $tag = static::create([ + 'name' => $value, + 'slug' => Str::slug($value), + ]); + } + + return $tag; + }); + + return is_string($values) ? $tags->first() : $tags; + } } diff --git a/app/Models/Traits/HasTags.php b/app/Models/Traits/HasTags.php index dbb62b75..75f1a606 100644 --- a/app/Models/Traits/HasTags.php +++ b/app/Models/Traits/HasTags.php @@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Models\Traits; use CachetHQ\Cachet\Models\Tag; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; /** * This is the has tags trait. @@ -21,6 +22,33 @@ use Illuminate\Database\Eloquent\Builder; */ trait HasTags { + /** + * @var array + */ + protected $queuedTags = []; + + /** + * Boot the trait. + * + * @return void + */ + public static function bootHasTags() + { + static::created(function (Model $taggableModel) { + if (count($taggableModel->queuedTags) > 0) { + $taggableModel->attachTags($taggableModel->queuedTags); + + $taggableModel->queuedTags = []; + } + }); + + static::deleted(function (Model $deletedModel) { + $tags = $deletedModel->tags()->get(); + + $deletedModel->detachTags($tags); + }); + } + /** * Get the tags relation. * @@ -31,6 +59,20 @@ trait HasTags return $this->morphToMany(Tag::class, 'taggable'); } + /** + * @param string|array|\ArrayAccess|\CachetHQ\Cachet\Models\Tag $tags + */ + public function setTagsAttribute($tags) + { + if (! $this->exists) { + $this->queuedTags = $tags; + + return; + } + + $this->attachTags($tags); + } + /** * @param \Illuminate\Database\Eloquent\Builder $query * @param array|\ArrayAccess $tags @@ -61,12 +103,78 @@ trait HasTags $tags = static::convertToTags($tags); return $query->whereHas('tags', function (Builder $query) use ($tags) { - $tagIds = $tags->pluck('id')->toArray(); + $tagIds = collect($tags)->pluck('id'); - $query->whereIn('taggables.tag_id', $tagIds); + $query->whereIn('tags.id', $tagIds); }); } + /** + * @param array|\ArrayAccess|\CachetHQ\Cachet\Models\Tag $tags + * + * @return $this + */ + public function attachTags($tags) + { + $tags = collect(Tag::findOrCreate($tags)); + + $this->tags()->syncWithoutDetaching($tags->pluck('id')->toArray()); + + return $this; + } + + /** + * @param string|\CachetHQ\Cachet\Models\Tag $tag + * + * @return $this + */ + public function attachTag($tag) + { + return $this->attachTags([$tag]); + } + + /** + * @param array|\ArrayAccess $tags + * + * @return $this + */ + public function detachTags($tags) + { + $tags = static::convertToTags($tags); + + collect($tags) + ->filter() + ->each(function (Tag $tag) { + $this->tags()->detach($tag); + }); + + return $this; + } + + /** + * @param string|\CachetHQ\Cachet\Models\Tag $tag + * + * @return $this + */ + public function detachTag($tag) + { + return $this->detachTags([$tag]); + } + + /** + * @param array|\ArrayAccess $tags + * + * @return $this + */ + public function syncTags($tags) + { + $tags = collect(Tag::findOrCreate($tags)); + + $this->tags()->sync($tags->pluck('id')->toArray()); + + return $this; + } + /** * Convert a list of tags into a collection of \CachetHQ\Cachet\Models\Tag. * diff --git a/tests/Bus/Commands/Component/CreateComponentCommandTest.php b/tests/Bus/Commands/Component/CreateComponentCommandTest.php index 454beeb5..a2f3e272 100644 --- a/tests/Bus/Commands/Component/CreateComponentCommandTest.php +++ b/tests/Bus/Commands/Component/CreateComponentCommandTest.php @@ -37,6 +37,7 @@ class CreateComponentCommandTest extends AbstractTestCase 'group_id' => 0, 'enabled' => true, 'meta' => null, + 'tags' => 'Foo, Bar', ]; $object = new CreateComponentCommand( $params['name'], @@ -46,7 +47,8 @@ class CreateComponentCommandTest extends AbstractTestCase $params['order'], $params['group_id'], $params['enabled'], - $params['meta'] + $params['meta'], + $params['tags'] ); return compact('params', 'object'); diff --git a/tests/Bus/Commands/Component/UpdateComponentCommandTest.php b/tests/Bus/Commands/Component/UpdateComponentCommandTest.php index 59f808be..4360b28f 100644 --- a/tests/Bus/Commands/Component/UpdateComponentCommandTest.php +++ b/tests/Bus/Commands/Component/UpdateComponentCommandTest.php @@ -39,6 +39,7 @@ class UpdateComponentCommandTest extends AbstractTestCase 'group_id' => 0, 'enabled' => true, 'meta' => null, + 'tags' => null, 'silent' => false, ]; @@ -52,6 +53,7 @@ class UpdateComponentCommandTest extends AbstractTestCase $params['group_id'], $params['enabled'], $params['meta'], + $params['tags'], $params['silent'] ); From b0b0883ae1cd34d03ea720764e95e220a35db7eb Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:41:51 +0100 Subject: [PATCH 03/11] Fix bug --- app/Models/Traits/HasTags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Traits/HasTags.php b/app/Models/Traits/HasTags.php index 75f1a606..40ea6447 100644 --- a/app/Models/Traits/HasTags.php +++ b/app/Models/Traits/HasTags.php @@ -85,7 +85,7 @@ trait HasTags $tags->each(function ($tag) use ($query) { $query->whereHas('tags', function (Builder $query) use ($tag) { - return $query->where('id', $tag ? $tag->id : 0); + return $query->where('tags.id', $tag ? $tag->id : 0); }); }); From 3807a6b3bb806a1cc30737c6bdd6447ab51640f1 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:41:55 +0100 Subject: [PATCH 04/11] Fix another bug --- app/Http/Controllers/Api/ComponentController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index e2de04f0..510c62c8 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -85,7 +85,7 @@ class ComponentController extends AbstractApiController Binput::get('group_id'), (bool) Binput::get('enabled', true), Binput::get('meta'), - Binput::get('tags'), + Binput::get('tags') )); } catch (QueryException $e) { throw new BadRequestHttpException(); From d9e27b5f46d302fc6d997c4f8b35a0a114725f6a Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:41:58 +0100 Subject: [PATCH 05/11] Add tests for tags --- tests/Api/ComponentTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Api/ComponentTest.php b/tests/Api/ComponentTest.php index afabe71f..bcb0dcae 100644 --- a/tests/Api/ComponentTest.php +++ b/tests/Api/ComponentTest.php @@ -37,6 +37,19 @@ class ComponentTest extends AbstractApiTestCase $response->assertJsonFragment(['id' => $components[2]->id]); } + public function test_can_get_all_components_with_tags() + { + $components = factory(Component::class, 2)->create(); + $components[0]->attachTags(["Hello World"]); + $components[1]->attachTags(["Foo", "Bar"]); + + $response = $this->json('GET', '/api/v1/components', ['tags' => ['foo']]); + + $response->assertStatus(200); + $response->assertJsonMissing(['id' => $components[0]->id]); + $response->assertJsonFragment(['id' => $components[1]->id]); + } + public function test_cannot_get_invalid_component() { $response = $this->json('GET', '/api/v1/components/1'); From 32a3adb43cbad70ee1551d9d28c5ccaef1f96657 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 10:43:25 +0100 Subject: [PATCH 06/11] Add more tag tests --- tests/Api/ComponentTest.php | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/Api/ComponentTest.php b/tests/Api/ComponentTest.php index bcb0dcae..e396b553 100644 --- a/tests/Api/ComponentTest.php +++ b/tests/Api/ComponentTest.php @@ -112,6 +112,27 @@ class ComponentTest extends AbstractApiTestCase $response->assertJsonFragment(['name' => 'Foo']); } + public function test_can_create_component_with_tags() + { + $this->beUser(); + + $this->expectsEvents(ComponentWasCreatedEvent::class); + + $response = $this->json('POST', '/api/v1/components', [ + 'name' => 'Foo', + 'description' => 'Bar', + 'status' => 1, + 'link' => 'http://example.com', + 'order' => 1, + 'group_id' => 1, + 'enabled' => true, + 'tags' => 'Foo,Bar', + ]); + + $response->assertStatus(200); + $response->assertJsonFragment(['name' => 'Foo', 'tags' => ['foo' => 'Foo', 'bar' => 'Bar']]); + } + public function test_can_create_component_without_enabled_field() { $this->beUser(); @@ -205,6 +226,23 @@ class ComponentTest extends AbstractApiTestCase $response->assertJsonFragment(['name' => 'Foo', 'enabled' => $component->enabled]); } + public function test_can_update_component_tags() + { + $this->beUser(); + $component = factory(Component::class)->create(); + + $this->expectsEvents(ComponentWasUpdatedEvent::class); + + $response = $this->json('PUT', '/api/v1/components/1', [ + 'name' => 'Foo', + 'tags' => 'Hello' + ]); + + $response->assertStatus(200); + $response->assertJsonFragment(['name' => 'Foo', 'enabled' => $component->enabled, 'tags' => ['hello' => 'Hello']]); + } + + public function test_can_update_component_without_status_change() { $this->beUser(); From 3ac74928586e0c210d2d44a8b9055c1ec74c434f Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 11:08:25 +0100 Subject: [PATCH 07/11] Remove old Tag commands, refactor migration etc --- app/Bus/Commands/Tag/ApplyTagCommand.php | 51 ------------ app/Bus/Commands/Tag/CreateTagCommand.php | 48 ----------- app/Bus/Commands/Tag/DeleteTagCommand.php | 41 ---------- app/Bus/Commands/Tag/UpdateTagCommand.php | 59 -------------- .../Commands/Tag/ApplyTagCommandHandler.php | 39 --------- .../Commands/Tag/CreateTagCommandHandler.php | 39 --------- .../Commands/Tag/DeleteTagCommandHandler.php | 34 -------- .../Commands/Tag/UpdateTagCommandHandler.php | 38 --------- .../Controllers/Api/ComponentController.php | 2 - .../Dashboard/ComponentController.php | 2 - app/Models/Taggable.php | 79 ------------------- ..._04_02_163658_MigrateComponentTagTable.php | 10 +-- .../Bus/Commands/Tag/ApplyTagCommandTest.php | 54 ------------- .../Bus/Commands/Tag/CreateTagCommandTest.php | 52 ------------ .../Bus/Commands/Tag/DeleteTagCommandTest.php | 51 ------------ .../Bus/Commands/Tag/UpdateTagCommandTest.php | 55 ------------- tests/Models/TaggableTest.php | 31 -------- 17 files changed, 5 insertions(+), 680 deletions(-) delete mode 100644 app/Bus/Commands/Tag/ApplyTagCommand.php delete mode 100644 app/Bus/Commands/Tag/CreateTagCommand.php delete mode 100644 app/Bus/Commands/Tag/DeleteTagCommand.php delete mode 100644 app/Bus/Commands/Tag/UpdateTagCommand.php delete mode 100644 app/Bus/Handlers/Commands/Tag/ApplyTagCommandHandler.php delete mode 100644 app/Bus/Handlers/Commands/Tag/CreateTagCommandHandler.php delete mode 100644 app/Bus/Handlers/Commands/Tag/DeleteTagCommandHandler.php delete mode 100644 app/Bus/Handlers/Commands/Tag/UpdateTagCommandHandler.php delete mode 100644 app/Models/Taggable.php delete mode 100644 tests/Bus/Commands/Tag/ApplyTagCommandTest.php delete mode 100644 tests/Bus/Commands/Tag/CreateTagCommandTest.php delete mode 100644 tests/Bus/Commands/Tag/DeleteTagCommandTest.php delete mode 100644 tests/Bus/Commands/Tag/UpdateTagCommandTest.php delete mode 100644 tests/Models/TaggableTest.php diff --git a/app/Bus/Commands/Tag/ApplyTagCommand.php b/app/Bus/Commands/Tag/ApplyTagCommand.php deleted file mode 100644 index 1fbd7421..00000000 --- a/app/Bus/Commands/Tag/ApplyTagCommand.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class ApplyTagCommand -{ - /** - * The model to apply the tag to. - * - * @var \Illuminate\Database\Eloquent\Model - */ - public $model; - - /** - * The tag to apply. - * - * @var \CachetHQ\Cachet\Models\Tag - */ - public $tag; - - /** - * Create a new apply tag command instance. - * - * @param \Illuminate\Database\Eloquent\Model $model - * @param \CachetHQ\Cachet\Models\Tag $tag - * - * @return void - */ - public function __construct(Model $model, Tag $tag) - { - $this->model = $model; - $this->tag = $tag; - } -} diff --git a/app/Bus/Commands/Tag/CreateTagCommand.php b/app/Bus/Commands/Tag/CreateTagCommand.php deleted file mode 100644 index 69ae89eb..00000000 --- a/app/Bus/Commands/Tag/CreateTagCommand.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class CreateTagCommand -{ - /** - * The tag name. - * - * @var string - */ - public $name; - - /** - * The tag slug. - * - * @var string|null - */ - public $slug; - - /** - * Create a new create tag command instance. - * - * @param string $name - * @param string|null $slug - * - * @return void - */ - public function __construct($name, $slug = null) - { - $this->name = $name; - $this->slug = $slug; - } -} diff --git a/app/Bus/Commands/Tag/DeleteTagCommand.php b/app/Bus/Commands/Tag/DeleteTagCommand.php deleted file mode 100644 index 7ab95001..00000000 --- a/app/Bus/Commands/Tag/DeleteTagCommand.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final class DeleteTagCommand -{ - /** - * The tag. - * - * @var \CachetHQ\Cachet\Models\Tag - */ - public $tag; - - /** - * Create a new delete tag command instance. - * - * @param \CachetHQ\Cachet\Models\Tag $tag - * - * @return void - */ - public function __construct(Tag $tag) - { - $this->tag = $tag; - } -} diff --git a/app/Bus/Commands/Tag/UpdateTagCommand.php b/app/Bus/Commands/Tag/UpdateTagCommand.php deleted file mode 100644 index f2747500..00000000 --- a/app/Bus/Commands/Tag/UpdateTagCommand.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -final class UpdateTagCommand -{ - /** - * The tag. - * - * @var \CachetHQ\Cachet\Models\Tag - */ - public $tag; - - /** - * The new tag name. - * - * @var string|null - */ - public $name; - - /** - * The new tag slug. - * - * @var string|null - */ - public $slug; - - /** - * Create a new update tag command instance. - * - * @param \CachetHQ\Cachet\Models\Tag $tag - * @param string|null $name - * @param string|null $slug - * - * @return void - */ - public function __construct(Tag $tag, $name, $slug) - { - $this->tag = $tag; - $this->name = $name; - $this->slug = $slug; - } -} diff --git a/app/Bus/Handlers/Commands/Tag/ApplyTagCommandHandler.php b/app/Bus/Handlers/Commands/Tag/ApplyTagCommandHandler.php deleted file mode 100644 index 7f1c4f4b..00000000 --- a/app/Bus/Handlers/Commands/Tag/ApplyTagCommandHandler.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -class ApplyTagCommandHandler -{ - /** - * Handle the command. - * - * @param \CachetHQ\Cachet\Bus\Commands\Tag\ApplyTagCommand $command - * - * @return void - */ - public function handle(ApplyTagCommand $command) - { - Taggable::firstOrCreate([ - 'tag_id' => $command->tag->id, - 'taggable_id' => $command->model->id, - 'taggable_type' => $command->model->getTable(), - ]); - } -} diff --git a/app/Bus/Handlers/Commands/Tag/CreateTagCommandHandler.php b/app/Bus/Handlers/Commands/Tag/CreateTagCommandHandler.php deleted file mode 100644 index 71f616dd..00000000 --- a/app/Bus/Handlers/Commands/Tag/CreateTagCommandHandler.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -class CreateTagCommandHandler -{ - /** - * Handle the command. - * - * @param \CachetHQ\Cachet\Bus\Commands\Tag\CreateTagCommand $command - * - * @return \CachetHQ\Cachet\Models\Tag - */ - public function handle(CreateTagCommand $command) - { - return Tag::firstOrCreate([ - 'name' => $command->name, - 'slug' => $command->slug ? $command->slug : Str::slug($command->name), - ]); - } -} diff --git a/app/Bus/Handlers/Commands/Tag/DeleteTagCommandHandler.php b/app/Bus/Handlers/Commands/Tag/DeleteTagCommandHandler.php deleted file mode 100644 index 08189349..00000000 --- a/app/Bus/Handlers/Commands/Tag/DeleteTagCommandHandler.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -class DeleteTagCommandHandler -{ - /** - * Handle the command. - * - * @param \CachetHQ\Cachet\Bus\Commands\Tag\DeleteTagCommand $command - * - * @return \CachetHQ\Cachet\Models\Tag - */ - public function handle(DeleteTagCommand $command) - { - $command->tag->delete(); - } -} diff --git a/app/Bus/Handlers/Commands/Tag/UpdateTagCommandHandler.php b/app/Bus/Handlers/Commands/Tag/UpdateTagCommandHandler.php deleted file mode 100644 index 5a21d7d6..00000000 --- a/app/Bus/Handlers/Commands/Tag/UpdateTagCommandHandler.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -class UpdateTagCommandHandler -{ - /** - * Handle the command. - * - * @param \CachetHQ\Cachet\Bus\Commands\Tag\UpdateTagCommand $command - * - * @return void - */ - public function handle(UpdateTagCommand $command) - { - return $command->tag->update([ - 'name' => $command->name, - 'slug' => $command->slug ? $command->slug : Str::slug($command->name), - ]); - } -} diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index 510c62c8..c4d1a178 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -14,8 +14,6 @@ namespace CachetHQ\Cachet\Http\Controllers\Api; use CachetHQ\Cachet\Bus\Commands\Component\CreateComponentCommand; use CachetHQ\Cachet\Bus\Commands\Component\RemoveComponentCommand; use CachetHQ\Cachet\Bus\Commands\Component\UpdateComponentCommand; -use CachetHQ\Cachet\Bus\Commands\Tag\ApplyTagCommand; -use CachetHQ\Cachet\Bus\Commands\Tag\CreateTagCommand; use CachetHQ\Cachet\Models\Component; use GrahamCampbell\Binput\Facades\Binput; use Illuminate\Contracts\Auth\Guard; diff --git a/app/Http/Controllers/Dashboard/ComponentController.php b/app/Http/Controllers/Dashboard/ComponentController.php index 31026b2b..43dfd6a2 100644 --- a/app/Http/Controllers/Dashboard/ComponentController.php +++ b/app/Http/Controllers/Dashboard/ComponentController.php @@ -15,8 +15,6 @@ use AltThree\Validator\ValidationException; use CachetHQ\Cachet\Bus\Commands\Component\CreateComponentCommand; use CachetHQ\Cachet\Bus\Commands\Component\RemoveComponentCommand; use CachetHQ\Cachet\Bus\Commands\Component\UpdateComponentCommand; -use CachetHQ\Cachet\Bus\Commands\Tag\ApplyTagCommand; -use CachetHQ\Cachet\Bus\Commands\Tag\CreateTagCommand; use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\ComponentGroup; use GrahamCampbell\Binput\Facades\Binput; diff --git a/app/Models/Taggable.php b/app/Models/Taggable.php deleted file mode 100644 index 9b6c94a1..00000000 --- a/app/Models/Taggable.php +++ /dev/null @@ -1,79 +0,0 @@ - - */ -class Taggable extends Model -{ - use ValidatingTrait; - - /** - * 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_163658_MigrateComponentTagTable.php b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php index 0d33597f..9a708899 100644 --- a/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php +++ b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -use CachetHQ\Cachet\Models\Taggable; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\DB; @@ -24,15 +23,16 @@ class MigrateComponentTagTable extends Migration */ public function up() { - // Start by migrating the data into the new taggables field. - DB::table('component_tag')->get()->each(function ($tag) { - Taggable::create([ + $tags = DB::table('component_tag')->get()->map(function ($tag) { + return [ 'tag_id' => $tag->tag_id, 'taggable_type' => 'components', 'taggable_id' => $tag->component_id, - ]); + ]; }); + DB::table('taggables')->insert($tags); + Schema::dropIfExists('component_tag'); } diff --git a/tests/Bus/Commands/Tag/ApplyTagCommandTest.php b/tests/Bus/Commands/Tag/ApplyTagCommandTest.php deleted file mode 100644 index a1c8bd25..00000000 --- a/tests/Bus/Commands/Tag/ApplyTagCommandTest.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -class ApplyTagCommandTest extends AbstractTestCase -{ - use CommandTrait; - - protected function getObjectAndParams() - { - $params = [ - 'model' => new Component(), - 'tag' => new Tag(), - ]; - - $object = new ApplyTagCommand( - $params['model'], - $params['tag'] - ); - - return compact('params', 'object'); - } - - protected function objectHasRules() - { - return false; - } - - protected function getHandlerClass() - { - return ApplyTagCommandHandler::class; - } -} diff --git a/tests/Bus/Commands/Tag/CreateTagCommandTest.php b/tests/Bus/Commands/Tag/CreateTagCommandTest.php deleted file mode 100644 index 59bf6369..00000000 --- a/tests/Bus/Commands/Tag/CreateTagCommandTest.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -class CreateTagCommandTest extends AbstractTestCase -{ - use CommandTrait; - - protected function getObjectAndParams() - { - $params = [ - 'name' => 'Test', - 'slug' => 'test', - ]; - - $object = new CreateTagCommand( - $params['name'], - $params['slug'] - ); - - return compact('params', 'object'); - } - - protected function objectHasRules() - { - return false; - } - - protected function getHandlerClass() - { - return CreateTagCommandHandler::class; - } -} diff --git a/tests/Bus/Commands/Tag/DeleteTagCommandTest.php b/tests/Bus/Commands/Tag/DeleteTagCommandTest.php deleted file mode 100644 index 2bee7b97..00000000 --- a/tests/Bus/Commands/Tag/DeleteTagCommandTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -class DeleteTagCommandTest extends AbstractTestCase -{ - use CommandTrait; - - protected function getObjectAndParams() - { - $params = [ - 'tag' => new Tag(), - ]; - - $object = new DeleteTagCommand( - $params['tag'] - ); - - return compact('params', 'object'); - } - - protected function objectHasRules() - { - return false; - } - - protected function getHandlerClass() - { - return DeleteTagCommandHandler::class; - } -} diff --git a/tests/Bus/Commands/Tag/UpdateTagCommandTest.php b/tests/Bus/Commands/Tag/UpdateTagCommandTest.php deleted file mode 100644 index 163c7477..00000000 --- a/tests/Bus/Commands/Tag/UpdateTagCommandTest.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ -class UpdateTagCommandTest extends AbstractTestCase -{ - use CommandTrait; - - protected function getObjectAndParams() - { - $params = [ - 'tag' => new Tag(), - 'name' => 'Test', - 'slug' => 'test', - ]; - - $object = new UpdateTagCommand( - $params['tag'], - $params['name'], - $params['slug'] - ); - - return compact('params', 'object'); - } - - protected function objectHasRules() - { - return false; - } - - protected function getHandlerClass() - { - return UpdateTagCommandHandler::class; - } -} diff --git a/tests/Models/TaggableTest.php b/tests/Models/TaggableTest.php deleted file mode 100644 index 8a5271a3..00000000 --- a/tests/Models/TaggableTest.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -class TaggableTest extends AbstractTestCase -{ - use ValidationTrait; - - public function testValidation() - { - $this->checkRules(new Taggable()); - } -} From bdb3619bc919cd8b7e455e5febc387130c11a610 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 12:38:58 +0000 Subject: [PATCH 08/11] Apply fixes from StyleCI --- app/Http/Controllers/Api/ComponentController.php | 1 - app/Http/Controllers/Dashboard/ComponentController.php | 2 -- app/Models/Tag.php | 4 ++-- app/Models/Traits/HasTags.php | 2 +- tests/Api/ComponentTest.php | 7 +++---- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Api/ComponentController.php b/app/Http/Controllers/Api/ComponentController.php index c4d1a178..9bda7b09 100644 --- a/app/Http/Controllers/Api/ComponentController.php +++ b/app/Http/Controllers/Api/ComponentController.php @@ -18,7 +18,6 @@ use CachetHQ\Cachet\Models\Component; use GrahamCampbell\Binput\Facades\Binput; use Illuminate\Contracts\Auth\Guard; use Illuminate\Database\QueryException; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; diff --git a/app/Http/Controllers/Dashboard/ComponentController.php b/app/Http/Controllers/Dashboard/ComponentController.php index 43dfd6a2..c9c8e679 100644 --- a/app/Http/Controllers/Dashboard/ComponentController.php +++ b/app/Http/Controllers/Dashboard/ComponentController.php @@ -19,8 +19,6 @@ use CachetHQ\Cachet\Models\Component; use CachetHQ\Cachet\Models\ComponentGroup; use GrahamCampbell\Binput\Facades\Binput; use Illuminate\Routing\Controller; -use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\View; /** diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 874b07ca..022ceb8c 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -64,13 +64,13 @@ class Tag extends Model public static function findOrCreate($values) { $tags = collect($values)->map(function ($value) { - if ($value instanceof Tag) { + if ($value instanceof self) { return $value; } $tag = static::where('name', '=', $value)->first(); - if (!$tag instanceof Tag) { + if (!$tag instanceof self) { $tag = static::create([ 'name' => $value, 'slug' => Str::slug($value), diff --git a/app/Models/Traits/HasTags.php b/app/Models/Traits/HasTags.php index 40ea6447..3e470841 100644 --- a/app/Models/Traits/HasTags.php +++ b/app/Models/Traits/HasTags.php @@ -64,7 +64,7 @@ trait HasTags */ public function setTagsAttribute($tags) { - if (! $this->exists) { + if (!$this->exists) { $this->queuedTags = $tags; return; diff --git a/tests/Api/ComponentTest.php b/tests/Api/ComponentTest.php index e396b553..c3f71e0c 100644 --- a/tests/Api/ComponentTest.php +++ b/tests/Api/ComponentTest.php @@ -40,8 +40,8 @@ class ComponentTest extends AbstractApiTestCase public function test_can_get_all_components_with_tags() { $components = factory(Component::class, 2)->create(); - $components[0]->attachTags(["Hello World"]); - $components[1]->attachTags(["Foo", "Bar"]); + $components[0]->attachTags(['Hello World']); + $components[1]->attachTags(['Foo', 'Bar']); $response = $this->json('GET', '/api/v1/components', ['tags' => ['foo']]); @@ -235,14 +235,13 @@ class ComponentTest extends AbstractApiTestCase $response = $this->json('PUT', '/api/v1/components/1', [ 'name' => 'Foo', - 'tags' => 'Hello' + 'tags' => 'Hello', ]); $response->assertStatus(200); $response->assertJsonFragment(['name' => 'Foo', 'enabled' => $component->enabled, 'tags' => ['hello' => 'Hello']]); } - public function test_can_update_component_without_status_change() { $this->beUser(); From 17ad1ae5af9617ef3f580bc99cab052710a89829 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Fri, 12 Jul 2019 14:43:31 +0100 Subject: [PATCH 09/11] Update 2018_04_02_163658_MigrateComponentTagTable.php --- .../migrations/2018_04_02_163658_MigrateComponentTagTable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php index 9a708899..92690fb3 100644 --- a/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php +++ b/database/migrations/2018_04_02_163658_MigrateComponentTagTable.php @@ -31,7 +31,7 @@ class MigrateComponentTagTable extends Migration ]; }); - DB::table('taggables')->insert($tags); + DB::table('taggables')->insert($tags->toArray()); Schema::dropIfExists('component_tag'); } From bd1e839ede558c99bbdc69552fa5076842873321 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Sat, 13 Jul 2019 08:31:08 +0100 Subject: [PATCH 10/11] Add link to spatie/laravel-tags --- app/Models/Traits/HasTags.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Models/Traits/HasTags.php b/app/Models/Traits/HasTags.php index 3e470841..ed81214d 100644 --- a/app/Models/Traits/HasTags.php +++ b/app/Models/Traits/HasTags.php @@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\Model; /** * This is the has tags trait. + * Code based on https://github.com/spatie/laravel-tags * * @author James Brooks */ From ac43591403447bbaeb32ea62abd0a4a06e739235 Mon Sep 17 00:00:00 2001 From: James Brooks Date: Sat, 13 Jul 2019 07:31:25 +0000 Subject: [PATCH 11/11] Apply fixes from StyleCI --- app/Models/Traits/HasTags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Traits/HasTags.php b/app/Models/Traits/HasTags.php index ed81214d..b707e050 100644 --- a/app/Models/Traits/HasTags.php +++ b/app/Models/Traits/HasTags.php @@ -17,7 +17,7 @@ use Illuminate\Database\Eloquent\Model; /** * This is the has tags trait. - * Code based on https://github.com/spatie/laravel-tags + * Code based on https://github.com/spatie/laravel-tags. * * @author James Brooks */