94 lines
2.8 KiB
Elixir
94 lines
2.8 KiB
Elixir
defmodule Phoenix.LiveView.Route do
|
|
@moduledoc false
|
|
|
|
alias Phoenix.LiveView.{Route, Socket}
|
|
|
|
defstruct path: nil,
|
|
view: nil,
|
|
action: nil,
|
|
opts: [],
|
|
live_session: %{},
|
|
params: %{},
|
|
uri: nil
|
|
|
|
@doc """
|
|
Computes the container from the route options and falls backs to use options.
|
|
"""
|
|
def container(%Route{} = route) do
|
|
route.opts[:container] || route.view.__live__()[:container]
|
|
end
|
|
|
|
@doc """
|
|
Returns the internal or external matched LiveView route info for the given socket
|
|
and uri, raises if none is available.
|
|
"""
|
|
def live_link_info!(%Socket{router: nil}, view, _uri) do
|
|
raise ArgumentError,
|
|
"cannot invoke handle_params/3 on #{inspect(view)} " <>
|
|
"because it is not mounted nor accessed through the router live/3 macro"
|
|
end
|
|
|
|
def live_link_info!(%Socket{} = socket, view, uri) do
|
|
case live_link_info(socket.endpoint, socket.router, uri) do
|
|
{:internal, %Route{view: ^view} = route} ->
|
|
{:internal, route}
|
|
|
|
{:internal, %Route{view: _view} = route} ->
|
|
{:external, route.uri}
|
|
|
|
{:external, _parsed_uri} = external ->
|
|
external
|
|
|
|
:error ->
|
|
raise ArgumentError,
|
|
"cannot invoke handle_params nor live_redirect/live_patch to #{inspect(uri)} " <>
|
|
"because it isn't defined in #{inspect(socket.router)}"
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Returns the internal or external matched LiveView route info for the given uri.
|
|
"""
|
|
def live_link_info(endpoint, router, uri) when is_binary(uri) do
|
|
live_link_info(endpoint, router, URI.parse(uri))
|
|
end
|
|
|
|
def live_link_info(endpoint, router, %URI{} = parsed_uri)
|
|
when is_atom(endpoint) and is_atom(router) do
|
|
%URI{host: host, path: path, query: query} = parsed_uri
|
|
query_params = if query, do: Plug.Conn.Query.decode(query), else: %{}
|
|
|
|
split_path =
|
|
for segment <- String.split(path || "", "/"), segment != "", do: URI.decode(segment)
|
|
|
|
route_path = strip_segments(endpoint.script_name(), split_path) || split_path
|
|
|
|
case Phoenix.Router.route_info(router, "GET", route_path, host) do
|
|
%{plug: Phoenix.LiveView.Plug, phoenix_live_view: lv, path_params: path_params} ->
|
|
{view, action, opts, live_session} = lv
|
|
|
|
route = %Route{
|
|
view: view,
|
|
path: route_path,
|
|
action: action,
|
|
uri: parsed_uri,
|
|
opts: opts,
|
|
live_session: live_session,
|
|
params: Map.merge(query_params, path_params)
|
|
}
|
|
|
|
{:internal, route}
|
|
|
|
%{} ->
|
|
{:external, parsed_uri}
|
|
|
|
:error ->
|
|
:error
|
|
end
|
|
end
|
|
|
|
defp strip_segments([head | tail1], [head | tail2]), do: strip_segments(tail1, tail2)
|
|
defp strip_segments([], tail2), do: tail2
|
|
defp strip_segments(_, _), do: nil
|
|
end
|