diff --git a/lib/plexus/apps.ex b/lib/plexus/apps.ex index 638d3be7..ed347db8 100644 --- a/lib/plexus/apps.ex +++ b/lib/plexus/apps.ex @@ -32,6 +32,17 @@ defmodule Plexus.Apps do |> Repo.paginate(page_opts) end + @doc """ + Fetches the most recently added app + """ + @spec fetch_most_recently_added_app! :: App.t() + def fetch_most_recently_added_app! do + App + |> order_by(:inserted_at) + |> limit(1) + |> Repo.one!() + end + @doc """ Fetches an App. diff --git a/lib/plexus_web.ex b/lib/plexus_web.ex index 1eadab3d..e401d39a 100644 --- a/lib/plexus_web.ex +++ b/lib/plexus_web.ex @@ -41,7 +41,7 @@ defmodule PlexusWeb do def controller do quote do use Phoenix.Controller, - formats: [:html, :json], + formats: [:html, :json, :xml], layouts: [html: PlexusWeb.Layouts] import Plug.Conn diff --git a/lib/plexus_web/controllers/sitemap_controller.ex b/lib/plexus_web/controllers/sitemap_controller.ex new file mode 100644 index 00000000..75a95ef1 --- /dev/null +++ b/lib/plexus_web/controllers/sitemap_controller.ex @@ -0,0 +1,67 @@ +defmodule PlexusWeb.SitemapController do + use PlexusWeb, :controller + + def index(conn, _params) do + conn + |> put_resp_content_type("text/xml") + |> put_layout(false) + |> render("sitemap.xml", routes: routes()) + end + + defp routes do + base_url = PlexusWeb.Endpoint.url() + + PlexusWeb.Router + |> Phoenix.Router.routes() + |> Enum.reduce([], fn + %{verb: :get, path: path}, acc -> + if String.starts_with?(path, "/admin") or + String.starts_with?(path, "/api") or + String.contains?(path, ":") or + String.ends_with?(path, ".xml") do + acc + else + [build_route(base_url, path) | acc] + end + + _route, acc -> + acc + end) + end + + defp build_route(base_url, path) do + %{ + path: full_path(base_url, path), + priority: priority(path), + change_freq: change_freq(path), + last_mod: last_mod(path) + } + end + + defp full_path(base_url, path) do + path = + case path do + "/" -> "/" + path -> path <> "/" + end + + base_url + |> URI.new!() + |> URI.append_path(path) + |> URI.to_string() + end + + defp priority("/"), do: 1.0 + defp priority(_path), do: 0.5 + + defp change_freq("/swaggerui"), do: "yearly" + defp change_freq(_), do: "weekly" + + defp last_mod("/") do + Plexus.Apps.fetch_most_recently_added_app!() + |> Map.fetch!(:inserted_at) + |> DateTime.to_date() + end + + defp last_mod(_), do: false +end diff --git a/lib/plexus_web/controllers/sitemap_xml.ex b/lib/plexus_web/controllers/sitemap_xml.ex new file mode 100644 index 00000000..5114e869 --- /dev/null +++ b/lib/plexus_web/controllers/sitemap_xml.ex @@ -0,0 +1,4 @@ +defmodule PlexusWeb.SitemapXML do + use PlexusWeb, :html + embed_templates "sitemap_xml/*" +end diff --git a/lib/plexus_web/controllers/sitemap_xml/sitemap.xml.eex b/lib/plexus_web/controllers/sitemap_xml/sitemap.xml.eex new file mode 100644 index 00000000..bb3c522e --- /dev/null +++ b/lib/plexus_web/controllers/sitemap_xml/sitemap.xml.eex @@ -0,0 +1,11 @@ + + + <%= for route <- @routes do %> + + <%= route.path %> + <%= if route.last_mod do %><%= route.last_mod %><% end %> + <%= route.change_freq %> + <%= route.priority %> + + <% end %> + diff --git a/lib/plexus_web/router.ex b/lib/plexus_web/router.ex index 58edddf4..063df407 100644 --- a/lib/plexus_web/router.ex +++ b/lib/plexus_web/router.ex @@ -23,6 +23,8 @@ defmodule PlexusWeb.Router do plug :auth end + get "/sitemap.xml", PlexusWeb.SitemapController, :index + scope "/" do pipe_through :browser