20 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
Di 972ff76c95 Merge pull request #38 from beyondcode/laravel-11
Laravel 11 compatibility
2024-03-13 17:03:05 +01:00
Di fe0e7865cb wip 2024-02-13 18:09:14 +01:00
Di 488c4076f9 Updated dependencies for Laravel 11 2024-02-13 18:03:14 +01:00
Di cd2f65ed92 Added example for nesting comments to Readme 2024-02-13 18:03:03 +01:00
19 changed files with 266 additions and 120 deletions
+2
View File
@@ -5,3 +5,5 @@ docs
vendor vendor
coverage coverage
coverage.clover coverage.clover
.phpunit.result.cache
.phpunit.cache/
-19
View File
@@ -1,19 +0,0 @@
filter:
excluded_paths: [tests/*]
checks:
php:
remove_extra_empty_lines: true
remove_php_closing_tag: true
remove_trailing_whitespace: true
fix_use_statements:
remove_unused: true
preserve_multiple: false
preserve_blanklines: true
order_alphabetically: true
fix_php_opening_tag: true
fix_linefeed: true
fix_line_ending: true
fix_identation_4spaces: true
fix_doc_comments: true
-21
View File
@@ -1,21 +0,0 @@
language: php
php:
- 7.2
- 7.3
- 7.4
env:
matrix:
- COMPOSER_FLAGS="--prefer-lowest"
- COMPOSER_FLAGS=""
before_script:
- travis_retry composer self-update
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source
script:
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
after_script:
- php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover
+22 -4
View File
@@ -1,9 +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)
[![Build Status](https://img.shields.io/travis/beyondcode/laravel-comments/master.svg?style=flat-square)](https://travis-ci.org/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)
[![Quality Score](https://img.shields.io/scrutinizer/g/beyondcode/laravel-comments.svg?style=flat-square)](https://scrutinizer-ci.com/g/beyondcode/laravel-comments)
[![Total Downloads](https://img.shields.io/packagist/dt/beyondcode/laravel-comments.svg?style=flat-square)](https://packagist.org/packages/beyondcode/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.
@@ -139,6 +139,24 @@ $approved = $post->comments()->approved()->get();
``` ```
### Nesting Comments
`BeyondCode\Comments\Comment` itself implements the `HasComments` trait, so you can comment on a comment and therefore nest them:
```php
$comment = BeyondCode\Comments\Comment::first();
$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
```bash ```bash
+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" "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',
]); ]);
} }
} }