From 5532ea4dec349563c1260823bce6709fc299c8e8 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Sat, 1 Aug 2020 12:42:29 -0400 Subject: [PATCH] more complete fix for commission and gallery pagination error --- .../controllers/commission_controller.ex | 8 +--- .../controllers/gallery_controller.ex | 1 + lib/philomena_web/plugs/map_parameter_plug.ex | 39 +++++++++++++++++++ .../commission/_directory_sidebar.html.slime | 2 +- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 lib/philomena_web/plugs/map_parameter_plug.ex diff --git a/lib/philomena_web/controllers/commission_controller.ex b/lib/philomena_web/controllers/commission_controller.ex index 5a220549..f0af9432 100644 --- a/lib/philomena_web/controllers/commission_controller.ex +++ b/lib/philomena_web/controllers/commission_controller.ex @@ -5,6 +5,7 @@ defmodule PhilomenaWeb.CommissionController do alias Philomena.Repo import Ecto.Query + plug PhilomenaWeb.MapParameterPlug, [param: "commission"] when action in [:index] plug :preload_commission def index(conn, params) do @@ -12,10 +13,6 @@ defmodule PhilomenaWeb.CommissionController do commission_search(params["commission"]) |> Repo.paginate(conn.assigns.scrivener) - # Scrub parameters to avoid form error... - params = Map.put(conn.params, "commission", permit_map(conn.params["commission"])) - conn = Map.put(conn, :params, params) - render(conn, "index.html", title: "Commissions", commissions: commissions, @@ -88,9 +85,6 @@ defmodule PhilomenaWeb.CommissionController do defp presence(object), do: object - defp permit_map(x) when is_map(x), do: x - defp permit_map(_), do: nil - defp to_f(input) do case Float.parse(to_string(input)) do {float, _rest} -> float diff --git a/lib/philomena_web/controllers/gallery_controller.ex b/lib/philomena_web/controllers/gallery_controller.ex index fef4064f..74c22880 100644 --- a/lib/philomena_web/controllers/gallery_controller.ex +++ b/lib/philomena_web/controllers/gallery_controller.ex @@ -10,6 +10,7 @@ defmodule PhilomenaWeb.GalleryController do import Ecto.Query plug PhilomenaWeb.FilterBannedUsersPlug when action in [:new, :create, :edit, :update, :delete] + plug PhilomenaWeb.MapParameterPlug, [param: "gallery"] when action in [:index] plug :load_and_authorize_resource, model: Gallery, diff --git a/lib/philomena_web/plugs/map_parameter_plug.ex b/lib/philomena_web/plugs/map_parameter_plug.ex new file mode 100644 index 00000000..93b7cce8 --- /dev/null +++ b/lib/philomena_web/plugs/map_parameter_plug.ex @@ -0,0 +1,39 @@ +defmodule PhilomenaWeb.MapParameterPlug do + # A bunch of crappy behaviors all interacting to create a + # symphony of failure: + # + # 1.) Router helpers do not strip nil query parameters. + # iex> Routes.gallery_path(conn, :index, gallery: nil) + # "/galleries?gallery=" + # + # 2.) Pagination always sets the parameter in the route in order + # to preserve the query across multiple pages + # + # 3.) When received by the router, an empty param is treated as + # an empty string instead of nil + # + # 4.) Phoenix.HTML.Form.form_for/2 raises an error if you try to + # use it on a conn object which is a string instead of a map + # (or nil) + + @spec init(Keyword.t()) :: Keyword.t() + def init(opts) do + opts + end + + @spec call(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t() + def call(conn, opts) do + param = Keyword.fetch!(opts, :param) + value = conn.params[param] + + cond do + is_map(value) -> + conn + + true -> + params = Map.delete(conn.params, param) + + Map.put(conn, :params, params) + end + end +end diff --git a/lib/philomena_web/templates/commission/_directory_sidebar.html.slime b/lib/philomena_web/templates/commission/_directory_sidebar.html.slime index 37af712c..fcfcfe29 100644 --- a/lib/philomena_web/templates/commission/_directory_sidebar.html.slime +++ b/lib/philomena_web/templates/commission/_directory_sidebar.html.slime @@ -27,4 +27,4 @@ .field = label f, :keywords, "Search:" .field = text_input f, :keywords, class: "input input--short", placeholder: "Keywords" - = submit "Search", class: "button" \ No newline at end of file + = submit "Search", class: "button"