16 Commits
Author SHA1 Message Date
Joel Male 46adc30c33 docs: update README to reflect wearepixel fork 2026-06-06 08:59:28 +10:00
Joel Male 17af48a05c feat: add Laravel 13 support 2026-06-06 08:56:46 +10:00
Marcel Pociot 4635f98118 Merge pull request #44 from atmonshi/laravel-12
add support for laravel 12
2025-03-02 19:47:27 +01:00
Lara Zeus 0e48b09bfc Update composer.json 2025-02-25 20:54:46 +03:00
Di 584405fba7 Merge pull request #43 from bessone/master
Minimum required version Laravel 10.30
2024-12-09 16:33:52 +01:00
Riccardo Bessone fafec066ab Minimum required version Laravel 10.30 2024-11-28 13:07:02 +01:00
Di 9605cd8545 Merge pull request #41 from beyondcode/updates
1.6.0
2024-10-11 18:47:15 +02:00
Di 30d95562b0 Updated Readme 2024-10-11 18:46:23 +02:00
Di 1ae27fe5e3 Fix deprecation warning 2024-10-11 18:44:00 +02:00
Di 7c598d62a8 Merge pull request #40 from toneflix-forks/master
Emit events and allow deleting replies when comments are deleted.
2024-10-11 18:41:00 +02:00
3m1n3nc3 d3523d9809 Merge branch 'master' of github.com:toneflix-forks/laravel-comments 2024-07-09 05:01:18 +01:00
3m1n3nc3 3ddea7ece2 Update the README.md with the new features documentation. 2024-07-09 05:01:10 +01:00
3m1n3nc3 fcce301be6 Run Laravel Pint 2024-07-09 04:54:23 +01:00
3m1n3nc3 c652a9cfe0 Update config with the new features 2024-07-09 04:54:01 +01:00
3m1n3nc3 e9663034fe Allow deleting replies when comments are deleted. 2024-07-09 04:44:30 +01:00
3m1n3nc3 d5a15036b8 Migrate phpunit XML to new schema 2024-07-09 04:16:31 +01:00
16 changed files with 252 additions and 76 deletions
+12 -2
View File
@@ -1,7 +1,9 @@
# Add comments to your Laravel application # Add comments to your Laravel application
[![Latest Version on Packagist](https://img.shields.io/packagist/v/beyondcode/laravel-comments.svg?style=flat-square)](https://packagist.org/packages/beyondcode/laravel-comments) [![Latest Version on Packagist](https://img.shields.io/packagist/v/wearepixel/laravel-comments.svg?style=flat-square)](https://packagist.org/packages/wearepixel/laravel-comments)
[![Total Downloads](https://img.shields.io/packagist/dt/beyondcode/laravel-comments.svg?style=flat-square)](https://packagist.org/packages/beyondcode/laravel-comments) [![Total Downloads](https://img.shields.io/packagist/dt/wearepixel/laravel-comments.svg?style=flat-square)](https://packagist.org/packages/wearepixel/laravel-comments)
> **Maintained fork** - This is a fork of [beyondcode/laravel-comments](https://github.com/beyondcode/laravel-comments) maintained by [Pixel](https://wearepixel.com.au). We forked this package to keep it up to date with newer versions of Laravel. Full credit to the original author [Marcel Pociot](https://github.com/mpociot).
Add the ability to associate comments to your Laravel Eloquent models. The comments can be approved and nested. Add the ability to associate comments to your Laravel Eloquent models. The comments can be approved and nested.
@@ -146,6 +148,14 @@ $comment = BeyondCode\Comments\Comment::first();
$comment->commentAsUser($user, "Hey there!"); $comment->commentAsUser($user, "Hey there!");
``` ```
#### Deleting Replies
When you delete a comment, you may optionally want to delete all its nested comments (replies). To optionally enable this feature, set the `delete_replies_along_comments` config property in the `config/comments.php` file to `true`.
### Events
When a new comment is added the `BeyondCode\Comments\Events\CommentAdded` event will be dispatched.
When a comment is deleted the `BeyondCode\Comments\Events\CommentDeleted` event will be dispatched.
### Testing ### Testing
+5 -5
View File
@@ -1,12 +1,12 @@
{ {
"name": "beyondcode/laravel-comments", "name": "wearepixel/laravel-comments",
"description": "Add comments to your Laravel application", "description": "Add comments to your Laravel application",
"keywords": [ "keywords": [
"beyondcode", "beyondcode",
"comments", "comments",
"laravel-comments" "laravel-comments"
], ],
"homepage": "https://github.com/beyondcode/laravel-comments", "homepage": "https://github.com/wearepixel/laravel-comments",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
{ {
@@ -17,12 +17,12 @@
} }
], ],
"require": { "require": {
"php": "^7.2.5|^8.0", "php": "^8.1",
"illuminate/support": "~5.6.0|~5.7.0|~5.8.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0" "illuminate/support": "^10.0|^11.0|^12.0|^13.0"
}, },
"require-dev": { "require-dev": {
"orchestra/testbench": "^3.6|^5.0|^6.0|^7.0|^8.0", "orchestra/testbench": "^3.6|^5.0|^6.0|^7.0|^8.0",
"phpunit/phpunit": "^7.0|^8.0|9.2.*|^9.5.10" "phpunit/phpunit": "^9.5.8|^10.0.7"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
+4
View File
@@ -15,4 +15,8 @@ return [
*/ */
'user_model' => null, 'user_model' => null,
/**
* Determines if replies will be deleted when comments are deleted
*/
'delete_replies_along_comments' => false,
]; ];
+16 -11
View File
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" <phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false" backupGlobals="false"
backupStaticAttributes="false" backupStaticAttributes="false"
colors="true" colors="true"
@@ -8,21 +10,24 @@
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="false" processIsolation="false"
stopOnFailure="false"> stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml" />
<html outputDirectory="build/coverage" />
<text outputFile="build/coverage.txt" />
</report>
</coverage>
<testsuites> <testsuites>
<testsuite name="BeyondCode Test Suite"> <testsuite name="BeyondCode Test Suite">
<directory>tests</directory> <directory>tests</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<logging> <logging>
<log type="junit" target="build/report.junit.xml"/> <junit outputFile="build/report.junit.xml" />
<log type="coverage-html" target="build/coverage" />
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging> </logging>
</phpunit> </phpunit>
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="BeyondCode Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<logging>
<log type="junit" target="build/report.junit.xml" />
<log type="coverage-html" target="build/coverage" />
<log type="coverage-text" target="build/coverage.txt" />
<log type="coverage-clover" target="build/logs/clover.xml" />
</logging>
</phpunit>
+24 -4
View File
@@ -2,9 +2,11 @@
namespace BeyondCode\Comments; namespace BeyondCode\Comments;
use BeyondCode\Comments\Events\CommentAdded;
use BeyondCode\Comments\Events\CommentDeleted;
use BeyondCode\Comments\Traits\HasComments;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use BeyondCode\Comments\Traits\HasComments;
class Comment extends Model class Comment extends Model
{ {
@@ -13,13 +15,32 @@ class Comment extends Model
protected $fillable = [ protected $fillable = [
'comment', 'comment',
'user_id', 'user_id',
'is_approved' 'is_approved',
]; ];
protected $casts = [ protected $casts = [
'is_approved' => 'boolean' 'is_approved' => 'boolean',
]; ];
public static function boot(): void
{
parent::boot();
static::deleting(function (self $model) {
if (config('comments.delete_replies_along_comments')) {
$model->comments()->delete();
}
});
static::deleted(function (self $model) {
CommentDeleted::dispatch($model);
});
static::created(function (self $model) {
CommentAdded::dispatch($model);
});
}
public function scopeApproved($query) public function scopeApproved($query)
{ {
return $query->where('is_approved', true); return $query->where('is_approved', true);
@@ -65,5 +86,4 @@ class Comment extends Model
throw new Exception('Could not determine the commentator model name.'); throw new Exception('Could not determine the commentator model name.');
} }
} }
-1
View File
@@ -16,7 +16,6 @@ class CommentsServiceProvider extends ServiceProvider
__DIR__.'/../config/config.php' => config_path('comments.php'), __DIR__.'/../config/config.php' => config_path('comments.php'),
], 'config'); ], 'config');
if (! class_exists('CreateCommentsTable')) { if (! class_exists('CreateCommentsTable')) {
$this->publishes([ $this->publishes([
__DIR__.'/../database/migrations/create_comments_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_comments_table.php'), __DIR__.'/../database/migrations/create_comments_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_comments_table.php'),
+1 -3
View File
@@ -2,14 +2,12 @@
namespace BeyondCode\Comments\Contracts; namespace BeyondCode\Comments\Contracts;
interface Commentator interface Commentator
{ {
/** /**
* Check if a comment for a specific model needs to be approved. * Check if a comment for a specific model needs to be approved.
*
* @param mixed $model * @param mixed $model
* @return bool
*/ */
public function needsCommentApproval($model): bool; public function needsCommentApproval($model): bool;
} }
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace BeyondCode\Comments\Events;
use BeyondCode\Comments\Comment;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class CommentAdded implements ShouldDispatchAfterCommit
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(
public Comment $comment,
) {
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace BeyondCode\Comments\Events;
use BeyondCode\Comments\Comment;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class CommentDeleted implements ShouldDispatchAfterCommit
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(
public Comment $comment,
) {
}
}
+1 -2
View File
@@ -2,13 +2,12 @@
namespace BeyondCode\Comments\Traits; namespace BeyondCode\Comments\Traits;
trait CanComment trait CanComment
{ {
/** /**
* Check if a comment for a specific model needs to be approved. * Check if a comment for a specific model needs to be approved.
*
* @param mixed $model * @param mixed $model
* @return bool
*/ */
public function needsCommentApproval($model): bool public function needsCommentApproval($model): bool
{ {
+2 -7
View File
@@ -2,9 +2,8 @@
namespace BeyondCode\Comments\Traits; namespace BeyondCode\Comments\Traits;
use Illuminate\Database\Eloquent\Model;
use BeyondCode\Comments\Contracts\Commentator; use BeyondCode\Comments\Contracts\Commentator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\Relations\MorphMany;
trait HasComments trait HasComments
@@ -22,7 +21,6 @@ trait HasComments
/** /**
* Attach a comment to this model. * Attach a comment to this model.
* *
* @param string $comment
* @return \Illuminate\Database\Eloquent\Model * @return \Illuminate\Database\Eloquent\Model
*/ */
public function comment(string $comment) public function comment(string $comment)
@@ -33,8 +31,6 @@ trait HasComments
/** /**
* Attach a comment to this model as a specific user. * Attach a comment to this model as a specific user.
* *
* @param Model|null $user
* @param string $comment
* @return \Illuminate\Database\Eloquent\Model * @return \Illuminate\Database\Eloquent\Model
*/ */
public function commentAsUser(?Model $user, string $comment) public function commentAsUser(?Model $user, string $comment)
@@ -46,10 +42,9 @@ trait HasComments
'is_approved' => ($user instanceof Commentator) ? ! $user->needsCommentApproval($this) : false, 'is_approved' => ($user instanceof Commentator) ? ! $user->needsCommentApproval($this) : false,
'user_id' => is_null($user) ? null : $user->getKey(), 'user_id' => is_null($user) ? null : $user->getKey(),
'commentable_id' => $this->getKey(), 'commentable_id' => $this->getKey(),
'commentable_type' => get_class(), 'commentable_type' => get_class($this),
]); ]);
return $this->comments()->save($comment); return $this->comments()->save($comment);
} }
} }
+77 -9
View File
@@ -2,9 +2,12 @@
namespace BeyondCode\Comments\Tests; namespace BeyondCode\Comments\Tests;
use BeyondCode\Comments\Events\CommentAdded;
use BeyondCode\Comments\Events\CommentDeleted;
use BeyondCode\Comments\Tests\Models\ApprovedUser; use BeyondCode\Comments\Tests\Models\ApprovedUser;
use BeyondCode\Comments\Tests\Models\Post; use BeyondCode\Comments\Tests\Models\Post;
use Illuminate\Foundation\Auth\User; use Illuminate\Foundation\Auth\User;
use Illuminate\Support\Facades\Event;
class CommentsTest extends TestCase class CommentsTest extends TestCase
{ {
@@ -12,7 +15,7 @@ class CommentsTest extends TestCase
public function users_without_commentator_interface_do_not_get_approved() public function users_without_commentator_interface_do_not_get_approved()
{ {
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$post->comment('this is a comment'); $post->comment('this is a comment');
@@ -26,7 +29,7 @@ class CommentsTest extends TestCase
public function models_can_store_comments() public function models_can_store_comments()
{ {
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$post->comment('this is a comment'); $post->comment('this is a comment');
@@ -42,7 +45,7 @@ class CommentsTest extends TestCase
public function comments_without_users_have_no_relation() public function comments_without_users_have_no_relation()
{ {
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->comment('this is a comment'); $comment = $post->comment('this is a comment');
@@ -59,7 +62,7 @@ class CommentsTest extends TestCase
auth()->login($user); auth()->login($user);
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->comment('this is a comment'); $comment = $post->comment('this is a comment');
@@ -73,7 +76,7 @@ class CommentsTest extends TestCase
$user = User::first(); $user = User::first();
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->commentAsUser($user, 'this is a comment'); $comment = $post->commentAsUser($user, 'this is a comment');
@@ -87,7 +90,7 @@ class CommentsTest extends TestCase
$user = User::first(); $user = User::first();
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->comment('this is a comment'); $comment = $post->comment('this is a comment');
@@ -105,7 +108,7 @@ class CommentsTest extends TestCase
$user = User::first(); $user = User::first();
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->comment('this is a comment'); $comment = $post->comment('this is a comment');
@@ -120,7 +123,7 @@ class CommentsTest extends TestCase
$user = ApprovedUser::first(); $user = ApprovedUser::first();
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$comment = $post->commentAsUser($user, 'this is a comment'); $comment = $post->commentAsUser($user, 'this is a comment');
@@ -134,7 +137,7 @@ class CommentsTest extends TestCase
$user = ApprovedUser::first(); $user = ApprovedUser::first();
$post = Post::create([ $post = Post::create([
'title' => 'Some post' 'title' => 'Some post',
]); ]);
$post->comment('this comment is not approved'); $post->comment('this comment is not approved');
@@ -145,4 +148,69 @@ class CommentsTest extends TestCase
$this->assertSame('this comment is approved', $post->comments()->approved()->first()->comment); $this->assertSame('this comment is approved', $post->comments()->approved()->first()->comment);
} }
/** @test */
public function comments_are_deleted_when_posts_are_deleted()
{
$post = Post::create([
'title' => 'Some post',
]);
$comment = $post->comment('this comment will be deleted');
$post->delete();
$this->assertFalse($comment->exists());
}
/** @test */
public function replies_are_deleted_when_post_comments_are_deleted()
{
config(['comments.delete_replies_along_comments' => true]);
$post = Post::create([
'title' => 'Some post',
]);
$comment = $post->comment('this comment will be deleted');
$reply = $comment->comment('this comment will be deleted too');
$comment->delete();
$this->assertFalse($reply->exists());
}
/** @test */
public function comment_added_event_is_dispatched_when_comment_is_created()
{
Event::fake([CommentAdded::class]);
$post = Post::create([
'title' => 'Some post',
]);
$comment = $post->comment('this comment is added');
Event::assertDispatched(CommentAdded::class, function ($event) use ($comment) {
return $event->comment->is($comment);
});
}
/** @test */
public function comment_deleted_event_is_dispatched_when_comment_is_deleted()
{
Event::fake([CommentDeleted::class]);
$post = Post::create([
'title' => 'Some post',
]);
$comment = $post->comment('this comment is added');
$comment->delete();
Event::assertDispatched(CommentDeleted::class, function ($event) use ($comment) {
return $event->comment->is($comment);
});
}
} }
+2 -4
View File
@@ -2,22 +2,20 @@
namespace BeyondCode\Comments\Tests\Models; namespace BeyondCode\Comments\Tests\Models;
use Illuminate\Foundation\Auth\User;
use BeyondCode\Comments\Contracts\Commentator; use BeyondCode\Comments\Contracts\Commentator;
use Illuminate\Foundation\Auth\User;
class ApprovedUser extends User implements Commentator class ApprovedUser extends User implements Commentator
{ {
protected $table = 'users'; protected $table = 'users';
/** /**
* Check if a comment for a specific model needs to be approved. * Check if a comment for a specific model needs to be approved.
*
* @param mixed $model * @param mixed $model
* @return bool
*/ */
public function needsCommentApproval($model): bool public function needsCommentApproval($model): bool
{ {
return false; return false;
} }
} }
+9
View File
@@ -10,4 +10,13 @@ class Post extends Model
use HasComments; use HasComments;
protected $guarded = []; protected $guarded = [];
public static function boot(): void
{
parent::boot();
static::deleting(function (self $model) {
$model->comments()->delete();
});
}
} }
+3 -5
View File
@@ -2,13 +2,12 @@
namespace BeyondCode\Comments\Tests; namespace BeyondCode\Comments\Tests;
use Illuminate\Foundation\Auth\User;
use Illuminate\Database\Schema\Blueprint;
use BeyondCode\Comments\CommentsServiceProvider; use BeyondCode\Comments\CommentsServiceProvider;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Foundation\Auth\User;
abstract class TestCase extends \Orchestra\Testbench\TestCase abstract class TestCase extends \Orchestra\Testbench\TestCase
{ {
public function setUp(): void public function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -54,8 +53,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
User::forceCreate([ User::forceCreate([
'name' => 'User', 'name' => 'User',
'email' => 'user@email.com', 'email' => 'user@email.com',
'password' => 'test' 'password' => 'test',
]); ]);
} }
} }