Skip to content

Commit 397b060

Browse files
committed
Add support for conditional intercepts
1 parent 6bc3edc commit 397b060

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

lib/phoenix/channel.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,14 +521,18 @@ defmodule Phoenix.Channel do
521521
"""
522522
defmacro intercept(events) do
523523
quote do
524-
@phoenix_intercepts unquote(events)
524+
@phoenix_intercepts Map.new(unquote(events),
525+
fn {event, predicate} -> {event, predicate}
526+
event -> {event, true}
527+
end)
525528
end
526529
end
527530

528531
@doc false
529532
def __on_definition__(env, :def, :handle_out, [event, _payload, _socket], _, _)
530533
when is_binary(event) do
531-
unless event in Module.get_attribute(env.module, :phoenix_intercepts) do
534+
intercepts = Module.get_attribute(env.module, :phoenix_intercepts)
535+
unless event in Map.keys(intercepts) do
532536
IO.write(
533537
"#{Path.relative_to(env.file, File.cwd!())}:#{env.line}: [warning] " <>
534538
"An intercept for event \"#{event}\" has not yet been defined in #{env.module}.handle_out/3. " <>

lib/phoenix/channel/server.ex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,14 @@ defmodule Phoenix.Channel.Server do
8989
{pid, _}, cache when pid == from ->
9090
cache
9191

92-
{pid, {:fastlane, fastlane_pid, serializer, event_intercepts}}, cache ->
93-
if event in event_intercepts do
92+
{pid, {:fastlane, fastlane_pid, serializer, socket, event_intercepts}}, cache ->
93+
intercept? = case Map.get(event_intercepts, event) do
94+
true -> true
95+
predicate when is_function(predicate, 1) -> predicate.(socket)
96+
_ -> false
97+
end
98+
99+
if intercept? do
94100
send(pid, msg)
95101
cache
96102
else
@@ -433,7 +439,7 @@ defmodule Phoenix.Channel.Server do
433439
end
434440

435441
Process.monitor(transport_pid)
436-
fastlane = {:fastlane, transport_pid, serializer, channel.__intercepts__()}
442+
fastlane = {:fastlane, transport_pid, serializer, socket, channel.__intercepts__()}
437443
PubSub.subscribe(pubsub_server, topic, metadata: fastlane)
438444

439445
{:noreply, %{socket | joined: true}}

test/phoenix/test/channel_test.exs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ defmodule Phoenix.Test.ChannelTest do
2929
defmodule Channel do
3030
use Phoenix.Channel
3131

32-
intercept ["stop"]
32+
intercept ["stop", {"intercept", &Channel.intercept_predicate/1}]
33+
34+
def intercept_predicate(socket), do: socket.assigns[:intercept]
3335

3436
def join("foo:ok", _, socket) do
3537
{:ok, socket}
@@ -62,6 +64,10 @@ defmodule Phoenix.Test.ChannelTest do
6264
{:ok, socket}
6365
end
6466

67+
def join("foo:intercept", payload, socket) do
68+
{:ok, assign(socket, :intercept, payload["intercept"])}
69+
end
70+
6571
def handle_in("broadcast", broadcast, socket) do
6672
broadcast_from!(socket, "broadcast", broadcast)
6773
{:noreply, socket}
@@ -102,6 +108,12 @@ defmodule Phoenix.Test.ChannelTest do
102108
{:stop, :shutdown, :ok, socket}
103109
end
104110

111+
def handle_out("intercept", payload, socket) do
112+
payload = Map.put(payload, "intercepted", true)
113+
push(socket, "intercept", payload)
114+
{:noreply, socket}
115+
end
116+
105117
def handle_out("stop", _payload, socket) do
106118
{:stop, :shutdown, socket}
107119
end
@@ -435,6 +447,18 @@ defmodule Phoenix.Test.ChannelTest do
435447
assert_graceful_exit(pid)
436448
end
437449

450+
test "broadcast is intercepted when socket predicate returns true" do
451+
{:ok, _, socket} = subscribe_and_join(socket(UserSocket), Channel, "foo:intercept", %{"intercept" => true})
452+
broadcast_from!(socket, "intercept", %{"intercepted" => false})
453+
assert_push "intercept", %{"intercepted" => true}
454+
end
455+
456+
test "broadcast isn't intercepted when socket predicate returns false" do
457+
{:ok, _, socket} = subscribe_and_join(socket(UserSocket), Channel, "foo:intercept")
458+
broadcast_from!(socket, "intercept", %{"intercepted" => false})
459+
assert_push "intercept", %{"intercepted" => false}
460+
end
461+
438462
## handle_info
439463

440464
test "handles messages and stops" do

0 commit comments

Comments
 (0)