Skip to content

Commit

Permalink
Episode 57
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyWay committed Jul 6, 2017
1 parent a8eb9d1 commit 66fc118
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 17 deletions.
23 changes: 23 additions & 0 deletions app/Events/ThreadReceivedNewReply.php
@@ -0,0 +1,23 @@
<?php

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class ThreadReceivedNewReply
{
use Dispatchable, SerializesModels;

public $reply;

/**
* Create a new event instance.
*
* @param $reply
*/
public function __construct($reply)
{
$this->reply = $reply;
}
}
28 changes: 28 additions & 0 deletions app/Listeners/NotifyMentionedUsers.php
@@ -0,0 +1,28 @@
<?php

namespace App\Listeners;

use App\Events\ThreadReceivedNewReply;
use App\Notifications\YouWereMentioned;
use App\User;

class NotifyMentionedUsers
{
/**
* Handle the event.
*
* @param ThreadReceivedNewReply $event
* @return void
*/
public function handle(ThreadReceivedNewReply $event)
{
collect($event->reply->mentionedUsers())
->map(function ($name) {
return User::where('name', $name)->first();
})
->filter()
->each(function ($user) use ($event) {
$user->notify(new YouWereMentioned($event->reply));
});
}
}
24 changes: 24 additions & 0 deletions app/Listeners/NotifySubscribers.php
@@ -0,0 +1,24 @@
<?php

namespace App\Listeners;

use App\Events\ThreadReceivedNewReply;

class NotifySubscribers
{
/**
* Handle the event.
*
* @param ThreadReceivedNewReply $event
* @return void
*/
public function handle(ThreadReceivedNewReply $event)
{
$thread = $event->reply->thread;

$thread->subscriptions
->where('user_id', '!=', $event->reply->user_id)
->each
->notify($event->reply);
}
}
51 changes: 51 additions & 0 deletions app/Notifications/YouWereMentioned.php
@@ -0,0 +1,51 @@
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;

class YouWereMentioned extends Notification
{
use Queueable;

/**
* @var \App\Reply
*/
protected $reply;

/**
* Create a new notification instance.
*
* @param \App\Reply $reply
*/
public function __construct($reply)
{
$this->reply = $reply;
}

/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['database'];
}

/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'message' => $this->reply->owner->name . ' mentioned you in ' . $this->reply->thread->title,
'link' => $this->reply->path()
];
}
}
6 changes: 3 additions & 3 deletions app/Providers/EventServiceProvider.php
Expand Up @@ -2,7 +2,6 @@

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
Expand All @@ -13,8 +12,9 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
'App\Events\SomeEvent' => [
'App\Listeners\EventListener',
'App\Events\ThreadReceivedNewReply' => [
'App\Listeners\NotifyMentionedUsers',
'App\Listeners\NotifySubscribers'
],
];

Expand Down
12 changes: 12 additions & 0 deletions app/Reply.php
Expand Up @@ -76,6 +76,18 @@ public function wasJustPublished()
return $this->created_at->gt(Carbon::now()->subMinute());
}

/**
* Fetch all mentioned users within the reply's body.
*
* @return array
*/
public function mentionedUsers()
{
preg_match_all('/\@([^\s\.]+)/', $this->body, $matches);

return $matches[1];
}

/**
* Determine the path to the reply.
*
Expand Down
16 changes: 2 additions & 14 deletions app/Thread.php
Expand Up @@ -2,6 +2,7 @@

namespace App;

use App\Events\ThreadReceivedNewReply;
use App\Filters\ThreadFilters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -93,24 +94,11 @@ public function addReply($reply)
{
$reply = $this->replies()->create($reply);

$this->notifySubscribers($reply);
event(new ThreadReceivedNewReply($reply));

return $reply;
}

/**
* Notify all thread subscribers about a new reply.
*
* @param \App\Reply $reply
*/
public function notifySubscribers($reply)
{
$this->subscriptions
->where('user_id', '!=', $reply->user_id)
->each
->notify($reply);
}

/**
* Apply all relevant thread filters.
*
Expand Down
36 changes: 36 additions & 0 deletions tests/Feature/MentionUsersTest.php
@@ -0,0 +1,36 @@
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class MentionUsersTest extends TestCase
{
use DatabaseMigrations;

/** @test */
function mentioned_users_in_a_reply_are_notified()
{
// Given we have a user, JohnDoe, who is signed in.
$john = create('App\User', ['name' => 'JohnDoe']);

$this->signIn($john);

// And we also have a user, JaneDoe.
$jane = create('App\User', ['name' => 'JaneDoe']);

// If we have a thread
$thread = create('App\Thread');

// And JohnDoe replies to that thread and mentions @JaneDoe.
$reply = make('App\Reply', [
'body' => 'Hey @JaneDoe check this out.'
]);

$this->json('post', $thread->path() . '/replies', $reply->toArray());

// Then @JaneDoe should receive a notification.
$this->assertCount(1, $jane->notifications);
}
}
10 changes: 10 additions & 0 deletions tests/Unit/ReplyTest.php
Expand Up @@ -29,4 +29,14 @@ function it_knows_if_it_was_just_published()

$this->assertFalse($reply->wasJustPublished());
}

/** @test */
function it_can_detect_all_mentioned_users_in_the_body()
{
$reply = create('App\Reply', [
'body' => '@JaneDoe wants to talk to @JohnDoe'
]);

$this->assertEquals(['JaneDoe', 'JohnDoe'], $reply->mentionedUsers());
}
}

0 comments on commit 66fc118

Please sign in to comment.