diff --git a/src/LaravelEcho/Pusher/Channels/Channel.php b/src/LaravelEcho/Pusher/Channels/Channel.php index 58f70d2..e095c72 100644 --- a/src/LaravelEcho/Pusher/Channels/Channel.php +++ b/src/LaravelEcho/Pusher/Channels/Channel.php @@ -18,6 +18,11 @@ class Channel $this->channelId = $channelId; } + public function hasConnections(): bool + { + return count($this->connections) > 0; + } + /** * @link https://pusher.com/docs/pusher_protocol#presence-channel-events * @@ -35,6 +40,11 @@ class Channel ])); } + public function unsubscribe(ConnectionInterface $connection) + { + unset($this->connections[$connection->socketId]); + } + protected function saveConnection(ConnectionInterface $conn) { $this->connections[$conn->socketId] = $conn; @@ -49,10 +59,8 @@ class Channel public function broadcastToOthers($conn, $payload) { - Collection::make($this->connections)->reject(function($connection) use ($conn) { + Collection::make($this->connections)->reject(function ($connection) use ($conn) { return $connection->socketId === $conn->socketId; })->each->send(json_encode($payload)); } - - //TODO: add unsubscribe } \ No newline at end of file diff --git a/src/LaravelEcho/Pusher/Channels/ChannelManager.php b/src/LaravelEcho/Pusher/Channels/ChannelManager.php index 4b8a213..3bb0f16 100644 --- a/src/LaravelEcho/Pusher/Channels/ChannelManager.php +++ b/src/LaravelEcho/Pusher/Channels/ChannelManager.php @@ -3,6 +3,8 @@ namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels; +use Ratchet\ConnectionInterface; + class ChannelManager { /** @var array */ @@ -13,7 +15,7 @@ class ChannelManager public function findOrCreate(string $appId, string $channelId): Channel { - if (! isset($this->channels[$appId][$channelId])) { + if (!isset($this->channels[$appId][$channelId])) { /**TODO: make this variable to go away */ $channelClass = $this->detectChannelClass($channelId); @@ -28,15 +30,30 @@ class ChannelManager return $this->channels[$appId][$channelId] ?? null; } - protected function detectChannelClass($channelId) : string + protected function detectChannelClass($channelId): string { if (starts_with($channelId, 'private-')) { return PrivateChannel::class; } - if(starts_with($channelId, 'presence-')) { + if (starts_with($channelId, 'presence-')) { return PresenceChannel::class; } return Channel::class; } + + public function removeFromAllChannels(ConnectionInterface $connection) + { + collect($this->channels[$connection->appId])->each->unsubscribe($connection); + + collect($this->channels[$connection->appId]) + ->reject->hasConnections() + ->each(function (Channel $channel, string $channelId) use ($connection) { + unset($this->channels[$connection->appId][$channelId]); + }); + + if (count($this->channels[$connection->appId]) === 0) { + unset($this->channels[$connection->appId]); + }; + } } \ No newline at end of file diff --git a/src/LaravelEcho/Pusher/Channels/PresenceChannel.php b/src/LaravelEcho/Pusher/Channels/PresenceChannel.php index 9029bd1..233737d 100644 --- a/src/LaravelEcho/Pusher/Channels/PresenceChannel.php +++ b/src/LaravelEcho/Pusher/Channels/PresenceChannel.php @@ -31,6 +31,13 @@ class PresenceChannel extends Channel //TODO: send member_added message back to client, and broadcast to everyone on channel } + public function unsubscribe(ConnectionInterface $connection) + { + parent::unsubscribe($connection); + + //TODO: send member_removed message back to client, and broadcast to everyone on channel + } + /** * @return array */ diff --git a/src/LaravelEcho/WebSocket/EchoServer.php b/src/LaravelEcho/WebSocket/EchoServer.php index 4a73cb9..34bc53b 100644 --- a/src/LaravelEcho/WebSocket/EchoServer.php +++ b/src/LaravelEcho/WebSocket/EchoServer.php @@ -6,6 +6,7 @@ use Ratchet\ConnectionInterface; use Ratchet\RFC6455\Messaging\MessageInterface; use BeyondCode\LaravelWebSockets\WebSocketController; use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager; +use stdClass; class EchoServer extends WebSocketController { @@ -75,6 +76,11 @@ class EchoServer extends WebSocketController } } + public function onClose(ConnectionInterface $connection) + { + $this->channelManager->removeFromAllChannels($connection); + } + /** * @link https://pusher.com/docs/pusher_protocol#ping-pong * @param ConnectionInterface $conn @@ -97,6 +103,14 @@ class EchoServer extends WebSocketController $channel->subscribe($conn, $payload); } + public function pusherUnsubscribe(ConnectionInterface $connection, stdClass $payload) + { + $channel = $this->channelManager->findOrCreate($connection->appId, $payload->channel); + + $channel->unsubscribe($connection); + + } + protected function buildPayload($event, $data = []) { return json_encode([