From fe5a26bd62257790849455c8cac81154f5f0e1eb Mon Sep 17 00:00:00 2001 From: Peter Deltchev Date: Wed, 15 Nov 2017 11:12:08 -0800 Subject: [PATCH] progress commit on comment replies --- app/Commands/CreateCommentCommand.php | 10 +++- app/Contracts/NotificationHandler.php | 7 +++ app/Jobs/ProcessComment.php | 60 +++++++++++++++++++ .../Notifications/NotificationManager.php | 7 +++ app/Models/Comment.php | 15 +++++ database/factories/ModelFactory.php | 25 +++----- tests/CommentsTest.php | 48 +++++++++++++++ 7 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 app/Jobs/ProcessComment.php create mode 100644 tests/CommentsTest.php diff --git a/app/Commands/CreateCommentCommand.php b/app/Commands/CreateCommentCommand.php index d5892007..688f66bc 100644 --- a/app/Commands/CreateCommentCommand.php +++ b/app/Commands/CreateCommentCommand.php @@ -20,7 +20,10 @@ namespace Poniverse\Ponyfm\Commands; +use Illuminate\Foundation\Bus\DispatchesJobs; use Notification; +use Poniverse\Ponyfm\Contracts\Commentable; +use Poniverse\Ponyfm\Jobs\ProcessComment; use Poniverse\Ponyfm\Models\Album; use Poniverse\Ponyfm\Models\Comment; use Poniverse\Ponyfm\Models\Playlist; @@ -31,6 +34,8 @@ use Validator; class CreateCommentCommand extends CommandBase { + use DispatchesJobs; + private $_input; private $_id; private $_type; @@ -110,10 +115,13 @@ class CreateCommentCommand extends CommandBase App::abort(400, 'This comment is being added to an invalid entity!'); } + /** @var Commentable comment_count */ $entity->comment_count = Comment::where($column, $this->_id)->count(); $entity->save(); - + + // Sends notifications for the comment and its mentions. Notification::newComment($comment); + $this->dispatch(new ProcessComment($comment))->onQueue('notifications'); return CommandResponse::succeed(Comment::mapPublic($comment)); } diff --git a/app/Contracts/NotificationHandler.php b/app/Contracts/NotificationHandler.php index 6feace47..c2c134ce 100644 --- a/app/Contracts/NotificationHandler.php +++ b/app/Contracts/NotificationHandler.php @@ -66,4 +66,11 @@ interface NotificationHandler * @return void */ public function newFavourite(Favouritable $entityBeingFavourited, User $favouriter); + + /** + * @param Comment $commentBeingRepliedTo + * @param Comment $theReply + * @return void + */ + public function newCommentReply(Comment $commentBeingRepliedTo, Comment $theReply); } diff --git a/app/Jobs/ProcessComment.php b/app/Jobs/ProcessComment.php new file mode 100644 index 00000000..6bfc371a --- /dev/null +++ b/app/Jobs/ProcessComment.php @@ -0,0 +1,60 @@ +. + */ + +namespace Poniverse\Ponyfm\Jobs; + +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; +use Notification; +use Poniverse\Ponyfm\Models\Comment; +use SerializesModels; + +class ProcessComment extends Job implements ShouldQueue +{ + use InteractsWithQueue, SerializesModels; + + protected $comment; + + /** + * Create a new job instance. + * + * @param Comment $comment + */ + public function __construct(Comment $comment) + { + $this->comment = $comment; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $this->beforeHandle(); + + $replies = Comment::findMany($this->comment->getMentionedCommentIds()); + + foreach ($replies as $reply) { + Notification::newCommentReply($this->comment, $reply); + } + } +} diff --git a/app/Library/Notifications/NotificationManager.php b/app/Library/Notifications/NotificationManager.php index aa06a0fa..4b437ade 100644 --- a/app/Library/Notifications/NotificationManager.php +++ b/app/Library/Notifications/NotificationManager.php @@ -86,4 +86,11 @@ class NotificationManager implements NotificationHandler { $this->dispatchNotification(__FUNCTION__, func_get_args()); } + + /** + * @inheritdoc + */ + public function newCommentReply(Comment $commentBeingRepliedTo, Comment $theReply) { + $this->dispatchNotification(__FUNCTION__, func_get_args()); + } } diff --git a/app/Models/Comment.php b/app/Models/Comment.php index b8561ef7..bf87c524 100644 --- a/app/Models/Comment.php +++ b/app/Models/Comment.php @@ -163,4 +163,19 @@ class Comment extends Model parent::delete(); }); } + + /** + * Parses the comment for any mentioned comments (replies). + * For a reply to be valid, it must either be followed by whitespace or be at + * the very end of the comment body. It also must be at the beginning of the + * string or preceded by whitespace. + * + * @return int[] + */ + public function getMentionedCommentIds():array { + $matches = []; + preg_match_all('/(\s|^)>c(?P\d+)(\s|$)/', $this->content, $matches); + + return array_map('intval', $matches['commentId']); + } } diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 071b2ff6..11e9ea2c 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -73,23 +73,6 @@ $factory->define(\Poniverse\Ponyfm\Models\Genre::class, function(\Faker\Generato ]; }); -/** - * - * @property integer $id - * @property integer $user_id - * @property string $title - * @property string $slug - * @property string $description - * @property integer $cover_id - * @property integer $track_count - * @property integer $view_count - * @property integer $download_count - * @property integer $favourite_count - * @property integer $comment_count - * @property \Carbon\Carbon $created_at - * @property string $updated_at - * @property \Carbon\Carbon $deleted_at - */ $factory->define(\Poniverse\Ponyfm\Models\Album::class, function(\Faker\Generator $faker) { return [ 'title' => $faker->sentence(5), @@ -97,3 +80,11 @@ $factory->define(\Poniverse\Ponyfm\Models\Album::class, function(\Faker\Generato 'description' => $faker->paragraph(5), ]; }); + +$factory->define(\Poniverse\Ponyfm\Models\Comment::class, function(\Faker\Generator $faker) { + return [ + 'ip_address' => $faker->ipv6, + 'content' => $faker->slug, + ]; +}); + diff --git a/tests/CommentsTest.php b/tests/CommentsTest.php new file mode 100644 index 00000000..b0a0589e --- /dev/null +++ b/tests/CommentsTest.php @@ -0,0 +1,48 @@ +. + */ + +use Carbon\Carbon; +use Illuminate\Foundation\Testing\WithoutMiddleware; +use Illuminate\Foundation\Testing\DatabaseMigrations; +use Poniverse\Ponyfm\Models\Album; +use Poniverse\Ponyfm\Models\Comment; +use Poniverse\Ponyfm\Models\Genre; +use Poniverse\Ponyfm\Models\Track; +use Poniverse\Ponyfm\Models\User; + +class CommentsTest extends TestCase { + use DatabaseMigrations; + use WithoutMiddleware; + + public function testCommentMentionsParsing() { + /** @var Comment $comment */ + $comment = factory(Comment::class)->make(); + + $comment->content = <<c1234 This>c24 is an awesome track!!! >c65437 +>u4678 +>4bsfsd +gfdsgfds>c16437boomboom +>47 +>c44 +EOF; + $this->assertEquals([1234, 65437, 44], $comment->getMentionedCommentIds()); + } +}