├── src
├── Http
│ ├── Controllers
│ │ ├── Users.php
│ │ ├── Destroy.php
│ │ ├── Store.php
│ │ ├── Index.php
│ │ └── Update.php
│ ├── Resources
│ │ ├── TaggedUser.php
│ │ └── Comment.php
│ └── Requests
│ │ ├── ValidateCommentStore.php
│ │ ├── ValidateCommentUpdate.php
│ │ └── ValidateCommentFetch.php
├── Exceptions
│ └── CommentConflict.php
├── AuthServiceProvider.php
├── Dynamics
│ ├── CommentTags.php
│ └── Comments.php
├── Traits
│ └── Commentable.php
├── Policies
│ └── Comment.php
├── AppServiceProvider.php
├── Models
│ └── Comment.php
└── Notifications
│ └── CommentTagNotification.php
├── config
└── comments.php
├── .styleci.yml
├── resources
└── views
│ └── emails
│ └── tagged.blade.php
├── database
├── factories
│ └── CommentFactory.php
└── migrations
│ ├── 2017_01_01_144000_create_structure_for_comments.php
│ ├── 2017_01_01_143000_create_comment_user_pivot_table.php
│ └── 2017_01_01_142000_create_comments_table.php
├── .github
└── issue_template.md
├── routes
└── api.php
├── codesize.xml
├── LICENSE
├── composer.json
├── README.md
└── tests
└── features
└── CommentTest.php
/src/Http/Controllers/Users.php:
--------------------------------------------------------------------------------
1 | 24 * 60 * 60,
5 | 'onDelete' => 'cascade',
6 | 'humanReadableDates' => true,
7 | 'loggableMorph' => [
8 | 'commentable' => [],
9 | ],
10 | ];
11 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | risky: true
2 |
3 | preset: laravel
4 |
5 | enabled:
6 | - strict
7 | - unalign_double_arrow
8 | - phpdoc_order
9 | - phpdoc_separation
10 |
11 | disabled:
12 | - short_array_syntax
13 |
14 | finder:
15 | exclude:
16 | - "public"
17 | - "resources"
18 | - "tests"
19 | name:
20 | - "*.php"
21 |
--------------------------------------------------------------------------------
/src/Exceptions/CommentConflict.php:
--------------------------------------------------------------------------------
1 | $this->id,
13 | 'name' => $this->person->name,
14 | ];
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Http/Requests/ValidateCommentStore.php:
--------------------------------------------------------------------------------
1 | 'required',
15 | 'path' => 'required',
16 | 'taggedUsers' => 'array',
17 | ];
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/AuthServiceProvider.php:
--------------------------------------------------------------------------------
1 | Policy::class,
13 | ];
14 |
15 | public function boot()
16 | {
17 | $this->registerPolicies();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Http/Requests/ValidateCommentUpdate.php:
--------------------------------------------------------------------------------
1 | 'required',
18 | 'path' => 'required',
19 | 'taggedUsers' => 'array',
20 | ];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/resources/views/emails/tagged.blade.php:
--------------------------------------------------------------------------------
1 | @component('mail::message')
2 | {{ __('Hi :appellative', ['appellative' => $appellative]) }},
3 |
4 | {{ __("You were just tagged in a comment:") }}
5 |
6 | @component('mail::panel')
7 | {{ $body }}
8 | @endcomponent
9 |
10 | {{ __('To view the full conversation click the button below.') }}
11 |
12 | @component('mail::button', ['url' => $url, 'color' => 'blue'])
13 | {{ __('View conversation') }}
14 | @endcomponent
15 |
16 | {{ __('Thank you') }},
17 | {{ __(config('app.name')) }}
18 | @endcomponent
19 |
--------------------------------------------------------------------------------
/database/factories/CommentFactory.php:
--------------------------------------------------------------------------------
1 | $this->faker->randomKey,
16 | 'commentable_type' => $this->faker->word,
17 | 'body' => $this->faker->sentence,
18 | ];
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Destroy.php:
--------------------------------------------------------------------------------
1 | authorize('destroy', $comment);
16 |
17 | $comment->delete();
18 |
19 | return ['count' => $comment->commentable->comments()->count()];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Dynamics/CommentTags.php:
--------------------------------------------------------------------------------
1 | $user->belongsToMany(Comment::class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Dynamics/Comments.php:
--------------------------------------------------------------------------------
1 | $user->hasMany(Comment::class, 'created_by');
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Http/Requests/ValidateCommentFetch.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'commentable_type' => 'required|string',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 |
2 | This is a **bug | feature request**.
3 |
4 |
5 | ### Prerequisites
6 | * [ ] Are you running the latest version?
7 | * [ ] Are you reporting to the correct repository?
8 | * [ ] Did you check the documentation?
9 | * [ ] Did you perform a cursory search?
10 |
11 | ### Description
12 |
13 |
14 | ### Steps to Reproduce
15 |
20 |
21 | ### Expected behavior
22 |
23 |
24 | ### Actual behavior
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/database/migrations/2017_01_01_144000_create_structure_for_comments.php:
--------------------------------------------------------------------------------
1 | 'core.comments.users', 'description' => 'Get taggable users options for select', 'is_default' => true],
9 | ['name' => 'core.comments.index', 'description' => 'List comments for commentable', 'is_default' => true],
10 | ['name' => 'core.comments.store', 'description' => 'Create comment', 'is_default' => true],
11 | ['name' => 'core.comments.update', 'description' => 'Update edited comment', 'is_default' => true],
12 | ['name' => 'core.comments.destroy', 'description' => 'Delete comment', 'is_default' => true],
13 | ];
14 | };
15 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 | prefix('api/core/comments')
12 | ->as('core.comments.')
13 | ->group(function () {
14 | Route::get('', Index::class)->name('index');
15 | Route::post('', Store::class)->name('store');
16 | Route::patch('{comment}', Update::class)->name('update');
17 | Route::delete('{comment}', Destroy::class)->name('destroy');
18 |
19 | Route::get('users', Users::class)->name('users');
20 | });
21 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Store.php:
--------------------------------------------------------------------------------
1 | fill($request->validatedExcept('taggedUsers', 'path'));
15 |
16 | tap($comment)->save()
17 | ->syncTags($request->get('taggedUsers'))
18 | ->notify($request->get('path'));
19 |
20 | return new Resource($comment->load([
21 | 'createdBy.person', 'createdBy.avatar', 'taggedUsers.person',
22 | ]));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Index.php:
--------------------------------------------------------------------------------
1 | for($request->validated())
16 | ->with('createdBy.person', 'createdBy.avatar', 'updatedBy', 'taggedUsers')
17 | ->get();
18 |
19 | return Resource::collection($comments)->additional([
20 | 'humanReadableDates' => Config::get('enso.comments.humanReadableDates'),
21 | ]);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/codesize.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | custom rules
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Update.php:
--------------------------------------------------------------------------------
1 | authorize('update', $comment);
18 |
19 | tap($comment)->update($request->only('body'))
20 | ->syncTags($request->get('taggedUsers'))
21 | ->notify($request->get('path'));
22 |
23 | return new Resource($comment->load([
24 | 'createdBy.person', 'createdBy.avatar', 'updatedBy', 'taggedUsers.person',
25 | ]));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/database/migrations/2017_01_01_143000_create_comment_user_pivot_table.php:
--------------------------------------------------------------------------------
1 | integer('comment_id')->unsigned()->index();
13 | $table->foreign('comment_id')->references('id')->on('comments')
14 | ->onDelete('cascade');
15 |
16 | $table->integer('user_id')->unsigned()->index();
17 | $table->foreign('user_id')->references('id')->on('users')
18 | ->onDelete('cascade');
19 |
20 | $table->primary(['comment_id', 'user_id']);
21 | });
22 | }
23 |
24 | public function down()
25 | {
26 | Schema::drop('comment_user');
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/database/migrations/2017_01_01_142000_create_comments_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
13 |
14 | $table->morphs('commentable');
15 |
16 | $table->text('body');
17 |
18 | $table->integer('created_by')->unsigned()->nullable()->index();
19 | $table->foreign('created_by')->references('id')->on('users');
20 |
21 | $table->integer('updated_by')->unsigned()->nullable();
22 | $table->foreign('updated_by')->references('id')->on('users');
23 |
24 | $table->timestamps();
25 | });
26 | }
27 |
28 | public function down()
29 | {
30 | Schema::dropIfExists('comments');
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/Http/Resources/Comment.php:
--------------------------------------------------------------------------------
1 | $this->id,
14 | 'body' => $this->body,
15 | 'owner' => new User($this->whenLoaded('createdBy')),
16 | 'taggedUsers' => TaggedUser::collection($this->whenLoaded('taggedUsers')),
17 | 'isEditable' => $this->isEditable($request),
18 | 'isDeletable' => $this->isDeletable($request),
19 | 'createdAt' => $this->created_at->toDatetimeString(),
20 | 'updatedAt' => $this->updated_at->toDatetimeString(),
21 | ];
22 | }
23 |
24 | public function isEditable($request)
25 | {
26 | return $request->user()->can('update', $this->resource);
27 | }
28 |
29 | public function isDeletable($request)
30 | {
31 | return $request->user()->can('destroy', $this->resource);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 laravel-enso
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Traits/Commentable.php:
--------------------------------------------------------------------------------
1 | $model->attemptCommentableDeletion());
14 |
15 | self::deleted(fn ($model) => $model->cascadeCommentDeletion());
16 | }
17 |
18 | public function comment()
19 | {
20 | return $this->morphOne(Comment::class, 'commentable');
21 | }
22 |
23 | public function comments()
24 | {
25 | return $this->morphMany(Comment::class, 'commentable');
26 | }
27 |
28 | private function attemptCommentableDeletion()
29 | {
30 | $restricted = Config::get('enso.comments.onDelete') === 'restrict';
31 |
32 | if ($restricted && $this->comments()->exists()) {
33 | throw CommentConflict::delete();
34 | }
35 | }
36 |
37 | private function cascadeCommentDeletion()
38 | {
39 | if (Config::get('enso.comments.onDelete') === 'cascade') {
40 | $this->comments()->delete();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Policies/Comment.php:
--------------------------------------------------------------------------------
1 | isSuperior()) {
18 | return true;
19 | }
20 | }
21 |
22 | public function update(User $user, Model $comment)
23 | {
24 | return $this->ownsComment($user, $comment)
25 | && $this->isRecent($comment);
26 | }
27 |
28 | public function destroy(User $user, Model $comment)
29 | {
30 | return $this->ownsComment($user, $comment)
31 | && $this->isRecent($comment);
32 | }
33 |
34 | private function ownsComment(User $user, Model $comment)
35 | {
36 | return $user->id === (int) $comment->created_by;
37 | }
38 |
39 | private function isRecent(Model $comment)
40 | {
41 | return (int) $comment->created_at->diffInSeconds(Carbon::now(), true)
42 | < Config::get('enso.comments.editableTimeLimit');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | load()
12 | ->publish();
13 | }
14 |
15 | private function load()
16 | {
17 | $this->mergeConfigFrom(__DIR__.'/../config/comments.php', 'enso.comments');
18 |
19 | $this->loadRoutesFrom(__DIR__.'/../routes/api.php');
20 |
21 | $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
22 |
23 | $this->loadViewsFrom(__DIR__.'/../resources/views', 'laravel-enso/comments');
24 |
25 | return $this;
26 | }
27 |
28 | private function publish()
29 | {
30 | $this->publishes([
31 | __DIR__.'/../config' => config_path('enso'),
32 | ], ['comments-config', 'enso-config']);
33 |
34 | $this->publishes([
35 | __DIR__.'/../resources/views' => resource_path('views/vendor/laravel-enso/comments'),
36 | ], ['comments-mail', 'enso-mail']);
37 |
38 | $this->publishes([
39 | __DIR__.'/../database/factories' => database_path('factories'),
40 | ], ['comments-factory', 'enso-factories']);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laravel-enso/comments",
3 | "description": "Comments Manager for Laravel Enso",
4 | "keywords": [
5 | "laravel-enso",
6 | "comments",
7 | "comments-manager",
8 | "comments"
9 | ],
10 | "homepage": "https://github.com/laravel-enso/comments",
11 | "type": "library",
12 | "license": "MIT",
13 | "authors": [
14 | {
15 | "name": "Adrian Ocneanu",
16 | "email": "aocneanu@gmail.com",
17 | "homepage": "https://laravel-enso.com",
18 | "role": "Developer"
19 | }
20 | ],
21 | "require": {
22 | "laravel-enso/core": "^10.0",
23 | "laravel-enso/dynamic-methods": "^3.0",
24 | "laravel-enso/helpers": "^3.0",
25 | "laravel-enso/migrator": "^2.1",
26 | "laravel-enso/track-who": "^2.0"
27 | },
28 | "autoload": {
29 | "psr-4": {
30 | "LaravelEnso\\Comments\\": "src/",
31 | "LaravelEnso\\Comments\\Database\\Factories\\": "database/factories/"
32 | }
33 | },
34 | "extra": {
35 | "laravel": {
36 | "providers": [
37 | "LaravelEnso\\Comments\\AppServiceProvider",
38 | "LaravelEnso\\Comments\\AuthServiceProvider"
39 | ],
40 | "aliases": []
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Models/Comment.php:
--------------------------------------------------------------------------------
1 | morphTo();
26 | }
27 |
28 | public function taggedUsers()
29 | {
30 | return $this->belongsToMany(User::class);
31 | }
32 |
33 | public function scopeFor(Builder $query, array $params): Builder
34 | {
35 | return $query->whereCommentableId($params['commentable_id'])
36 | ->whereCommentableType($params['commentable_type']);
37 | }
38 |
39 | public function syncTags(array $taggedUsers)
40 | {
41 | $this->taggedUsers()->sync(
42 | Collection::wrap($taggedUsers)->pluck('id')
43 | );
44 |
45 | return $this;
46 | }
47 |
48 | public function notify(string $path)
49 | {
50 | $this->taggedUsers->each
51 | ->notify((new CommentTagNotification($this->body, $path))
52 | ->onQueue('notifications'));
53 | }
54 |
55 | public function getLoggableMorph()
56 | {
57 | return config('enso.comments.loggableMorph');
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Notifications/CommentTagNotification.php:
--------------------------------------------------------------------------------
1 | 'info',
31 | 'title' => __('New Comment Tag'),
32 | 'icon' => 'comment',
33 | 'body' => __('You were just tagged').': '.$this->body,
34 | ]);
35 | }
36 |
37 | public function toMail($notifiable)
38 | {
39 | $app = Config::get('app.name');
40 |
41 | return (new MailMessage())
42 | ->subject("[ {$app} ] {$this->subject()}")
43 | ->markdown('laravel-enso/comments::emails.tagged', [
44 | 'appellative' => $notifiable->person->appellative(),
45 | 'body' => $this->body,
46 | 'url' => url($this->path),
47 | ]);
48 | }
49 |
50 | public function toArray()
51 | {
52 | return [
53 | 'body' => $this->body,
54 | 'path' => $this->path,
55 | 'icon' => 'comment',
56 | ];
57 | }
58 |
59 | private function subject(): string
60 | {
61 | return __('Comment Tag Notification');
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Comments
2 |
3 | [](https://www.codacy.com/gh/laravel-enso/comments?utm_source=github.com&utm_medium=referral&utm_content=laravel-enso/comments&utm_campaign=Badge_Grade)
4 | [](https://github.styleci.io/repos/85583597)
5 | [](https://packagist.org/packages/laravel-enso/comments)
6 | [](https://packagist.org/packages/laravel-enso/comments)
7 | [](https://packagist.org/packages/laravel-enso/comments)
8 |
9 | Comments Manager for [Laravel Enso](https://github.com/laravel-enso/Enso).
10 |
11 | This package works exclusively within the [Enso](https://github.com/laravel-enso/Enso) ecosystem.
12 |
13 | There is a front end implementation for this this api in the [accessories](https://github.com/enso-ui/accessories) package.
14 |
15 | For live examples and demos, you may visit [laravel-enso.com](https://www.laravel-enso.com)
16 |
17 | [](https://laravel-enso.github.io/comments/videos/bulma_demo_01.webm)
18 |
19 | click on the photo to view a short demo in compatible browsers
20 |
21 | ### Installation, Configuration & Usage
22 |
23 | Be sure to check out the full documentation for this package available at [docs.laravel-enso.com](https://docs.laravel-enso.com/backend/comments.html)
24 |
25 | ### Contributions
26 |
27 | are welcome. Pull requests are great, but issues are good too.
28 |
29 | ### License
30 |
31 | This package is released under the MIT license.
32 | # Comments
33 |
34 | [](https://www.codacy.com/app/laravel-enso/comments?utm_source=github.com&utm_medium=referral&utm_content=laravel-enso/comments&utm_campaign=Badge_Grade)
35 | [](https://github.styleci.io/repos/85583597)
36 | [](https://packagist.org/packages/laravel-enso/comments)
37 | [](https://packagist.org/packages/laravel-enso/comments)
38 | [](https://packagist.org/packages/laravel-enso/comments)
39 |
40 | Comments Manager for [Laravel Enso](https://github.com/laravel-enso/Enso).
41 |
42 | This package works exclusively within the [Enso](https://github.com/laravel-enso/Enso) ecosystem.
43 |
44 | There is a front end implementation for this this api in the [accessories](https://github.com/enso-ui/accessories) package.
45 |
46 | For live examples and demos, you may visit [laravel-enso.com](https://www.laravel-enso.com)
47 |
48 | [](https://laravel-enso.github.io/comments/videos/bulma_demo_01.webm)
49 |
50 | click on the photo to view a short demo in compatible browsers
51 |
52 | ### Installation, Configuration & Usage
53 |
54 | Be sure to check out the full documentation for this package available at [docs.laravel-enso.com](https://docs.laravel-enso.com/backend/comments.html)
55 |
56 | ### Contributions
57 |
58 | are welcome. Pull requests are great, but issues are good too.
59 |
60 | ### License
61 |
62 | This package is released under the MIT license.
63 |
--------------------------------------------------------------------------------
/tests/features/CommentTest.php:
--------------------------------------------------------------------------------
1 | seed()
27 | ->actingAs($this->user = User::first());
28 |
29 | $this->createTestTable();
30 |
31 | $this->faker = Factory::create();
32 |
33 | $this->testModel = Comment::factory()->create([
34 | 'commentable_id' => CommentableTestModel::create(['name' => 'commentable'])->id,
35 | 'commentable_type' => CommentableTestModel::class,
36 | ]);
37 | }
38 |
39 | /** @test */
40 | public function can_create_comment()
41 | {
42 | $this->post(
43 | route('core.comments.store'),
44 | $this->postParams()->toArray() + [
45 | 'taggedUsers' => [],
46 | 'path' => $this->faker->url,
47 | ]
48 | )->assertStatus(201)
49 | ->assertJsonStructure(['body']);
50 | }
51 |
52 | /** @test */
53 | public function can_get_comments_index()
54 | {
55 | $this->get(route('core.comments.index', $this->testModel->toArray(), false))
56 | ->assertStatus(200)
57 | ->assertJsonStructure(['data' => 'data']);
58 | }
59 |
60 | /** @test */
61 | public function can_update_comment()
62 | {
63 | $this->testModel->body = 'edited';
64 |
65 | $this->patch(
66 | route('core.comments.update', $this->testModel->id, false),
67 | $this->testModel->toArray() + [
68 | 'taggedUsers' => [],
69 | 'path' => $this->faker->url,
70 | ]
71 | )->assertStatus(200)
72 | ->assertJsonFragment(['body' => $this->testModel->body]);
73 |
74 | $this->assertEquals(
75 | $this->testModel->body,
76 | $this->testModel->fresh()->body
77 | );
78 | }
79 |
80 | /** @test */
81 | public function can_delete_comment()
82 | {
83 | $this->assertNotNull($this->testModel);
84 |
85 | $this->delete(route('core.comments.destroy', $this->testModel->id, false))
86 | ->assertStatus(200);
87 |
88 | $this->assertNull($this->testModel->fresh());
89 | }
90 |
91 | /** @test */
92 | public function can_store_with_tagged_user()
93 | {
94 | Notification::fake();
95 |
96 | $taggedUser = User::factory()->create();
97 |
98 | $taggedUsers = [[
99 | 'id' => $taggedUser->id,
100 | 'name' => $taggedUser->person->name,
101 | ]];
102 |
103 | $response = $this->post(
104 | route('core.comments.store', [], false),
105 | $this->postParams()->toArray() + [
106 | 'taggedUsers' => $taggedUsers,
107 | 'path' => $this->faker->url,
108 | ]
109 | )->assertStatus(201)
110 | ->assertJsonFragment(['taggedUsers' => $taggedUsers]);
111 |
112 | $commentId = $response->json()['id'];
113 |
114 | $this->assertEquals(
115 | Comment::find($commentId)->taggedUsers()->first()->id,
116 | $taggedUser->id
117 | );
118 |
119 | Notification::assertSentTo(
120 | User::find($taggedUser->id),
121 | CommentTagNotification::class
122 | );
123 | }
124 |
125 | /** @test */
126 | public function can_update_with_tagged_user()
127 | {
128 | Notification::fake();
129 |
130 | $taggedUser = User::factory()->create();
131 |
132 | $this->testModel->body = 'edited';
133 |
134 | $taggedUsers = [[
135 | 'id' => $taggedUser->id,
136 | 'name' => $taggedUser->person->name,
137 | ]];
138 |
139 | $this->patch(
140 | route('core.comments.update', [$this->testModel->id], false),
141 | $this->testModel->toArray() + [
142 | 'taggedUsers' => $taggedUsers,
143 | 'path' => $this->faker->url,
144 | ]
145 | )->assertStatus(200)
146 | ->assertJsonFragment(['taggedUsers' => $taggedUsers]);
147 |
148 | $this->assertEquals(
149 | $this->testModel->taggedUsers()->first()->id,
150 | $taggedUser->id
151 | );
152 |
153 | Notification::assertSentTo(
154 | User::find($taggedUser->id),
155 | CommentTagNotification::class
156 | );
157 | }
158 |
159 | private function createTestTable()
160 | {
161 | Schema::create('commentable_test_models', function ($table) {
162 | $table->increments('id');
163 | $table->string('name');
164 | $table->timestamps();
165 | });
166 | }
167 |
168 | private function postParams()
169 | {
170 | return Comment::factory()->make([
171 | 'commentable_id' => CommentableTestModel::create(['name' => 'commentable'])->id,
172 | 'commentable_type' => CommentableTestModel::class,
173 | ]);
174 | }
175 | }
176 |
177 | class CommentableTestModel extends Model
178 | {
179 | use Commentable;
180 |
181 | protected $fillable = ['name'];
182 | }
183 |
--------------------------------------------------------------------------------