Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
elixirstatus-web/web/controllers/posting_controller.ex
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
346 lines (276 sloc)
9.68 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ElixirStatus.PostingController do | |
use ElixirStatus.Web, :controller | |
alias ElixirStatus.Auth | |
alias ElixirStatus.Date | |
alias ElixirStatus.Publisher | |
alias ElixirStatus.PostingTypifier | |
alias ElixirStatus.PostingUrlFinder | |
# seconds | |
@just_created_timeout 60 | |
@current_posting_assign_key :posting | |
@posting_filters ~w(blog_post project_update) | |
@preview_default_title "-- insert title --" | |
@preview_default_text "-- insert text --" | |
plug(:load_posting when action in [:edit, :update, :delete, :show]) | |
plug(ElixirStatus.Plugs.LoggedIn when action in [:new, :create, :edit, :update, :delete]) | |
plug(ElixirStatus.Plugs.Admin when action in [:republish, :unpublish]) | |
plug( | |
ElixirStatus.Plugs.SameUserOrAdmin, | |
@current_posting_assign_key when action in [:edit, :update, :delete] | |
) | |
plug(:scrub_params, "posting" when action in [:create, :update]) | |
def index(conn, params) do | |
current_user = Auth.current_user(conn) | |
admin? = Auth.admin?(conn) | |
page = ElixirStatus.Persistence.Posting.published(params, current_user, admin?) | |
assigns = [ | |
postings: page.entries, | |
page_number: page.page_number, | |
total_pages: page.total_pages, | |
created_posting: load_created_posting(conn), | |
just_signed_in: params["just_signed_in"] == "true", | |
referred_via_elixirweekly: params["ref"] == "elixirweekly", | |
searching?: !is_nil(params["q"]), | |
search_query: params["q"], | |
current_posting_filter: params["filter"] |> nil_if_empty(), | |
posting_filters: @posting_filters, | |
search: params["q"] |> nil_if_empty(), | |
changeset: changeset() | |
] | |
conn | |
|> ElixirStatus.Impressionist.record("frontpage") | |
|> render("index.html", assigns) | |
end | |
def user(conn, %{"user_name" => user_name} = params) do | |
user = ElixirStatus.Persistence.User.find_by_user_name(user_name) | |
page = ElixirStatus.Persistence.Posting.published_by_user(user) | |
assigns = [ | |
postings: page.entries, | |
page_number: page.page_number, | |
total_pages: page.total_pages, | |
created_posting: load_created_posting(conn), | |
just_signed_in: params["just_signed_in"] == "true", | |
searching?: !is_nil(params["q"]), | |
search_query: params["q"], | |
changeset: changeset() | |
] | |
conn | |
|> ElixirStatus.Impressionist.record("frontpage") | |
|> render("user.html", assigns) | |
end | |
def new(conn, _params) do | |
render(conn, "new.html", changeset: changeset()) | |
end | |
def create(conn, %{"posting" => posting_params}) do | |
posting_params = | |
posting_params | |
|> extract_valid_params | |
|> to_create_params(conn) | |
changeset = ElixirStatus.Posting.changeset(%ElixirStatus.Posting{}, posting_params) | |
if changeset.valid? do | |
posting = Repo.insert!(changeset) | |
current_user = Auth.current_user(conn) | |
Publisher.after_create(posting, current_user) | |
conn | |
|> put_session(:created_posting_uid, posting.uid) | |
|> redirect(to: posting_path(conn, :index)) | |
else | |
render(conn, "new.html", changeset: changeset) | |
end | |
end | |
def preview(conn, params) do | |
render( | |
conn, | |
"preview.html", | |
layout: {ElixirStatus.LayoutView, "blank.html"}, | |
posting: %ElixirStatus.Posting{ | |
title: default(params["title"], @preview_default_title), | |
text: default(params["text"], @preview_default_text) | |
} | |
) | |
end | |
def show(conn, %{"permalink" => _}) do | |
show(conn, %{"id" => current_posting(conn)}) | |
end | |
def show(conn, %{"id" => _}) do | |
posting = current_posting(conn) | |
assigns = [ | |
posting: posting, | |
created_posting: load_created_posting(conn), | |
prev_posting: load_prev_posting(posting), | |
next_posting: load_next_posting(posting) | |
] | |
conn | |
|> ElixirStatus.Impressionist.record("detail", "posting", posting.uid) | |
|> render("show.html", assigns) | |
end | |
def edit(conn, %{"permalink" => _}) do | |
edit(conn, %{"id" => current_posting(conn)}) | |
end | |
def edit(conn, %{"id" => _}) do | |
posting = current_posting(conn) | |
changeset = ElixirStatus.Posting.changeset(posting) | |
render(conn, "edit.html", posting: posting, changeset: changeset) | |
end | |
def update(conn, %{"id" => id, "posting" => original_params}) do | |
posting = Repo.get!(ElixirStatus.Posting, id) | |
posting_params = original_params |> extract_valid_params | |
changeset = ElixirStatus.Posting.changeset(posting, posting_params) | |
if changeset.valid? do | |
current_user = Auth.current_user(conn) | |
Repo.update!(changeset) | |
|> Publisher.after_update(current_user) | |
conn | |
|> put_flash(:info, "Posting updated successfully.") | |
|> redirect(to: posting_path(conn, :index)) | |
else | |
render(conn, "edit.html", posting: posting, changeset: changeset) | |
end | |
end | |
defp changeset do | |
ElixirStatus.Posting.changeset(%ElixirStatus.Posting{}) | |
end | |
defp default(nil, value), do: value | |
defp default("", value), do: value | |
defp default(value, _), do: value | |
def unpublish(conn, %{"id" => id}) do | |
posting = ElixirStatus.Persistence.Posting.find_by_id(id) | |
ElixirStatus.Persistence.Posting.unpublish(posting) | |
Publisher.after_unpublish(posting) | |
redirect(conn, to: posting_path(conn, :index)) | |
end | |
def republish(conn, %{"id" => id}) do | |
posting = ElixirStatus.Persistence.Posting.find_by_id(id) | |
ElixirStatus.Persistence.Posting.republish(posting) | |
# TODO: Publisher.after_republish(posting) | |
redirect(conn, to: posting_path(conn, :index)) | |
end | |
def delete(conn, %{"id" => id}) do | |
posting = Repo.get!(ElixirStatus.Posting, id) | |
Repo.delete!(posting) | |
conn | |
|> put_flash(:info, "Posting deleted successfully.") | |
|> redirect(to: posting_path(conn, :index)) | |
end | |
def moderate(conn, %{"moderation_key" => moderation_key}) do | |
assigns = [ | |
moderation_key: moderation_key, | |
posting: ElixirStatus.Persistence.Posting.find_by_moderation_key(moderation_key) | |
] | |
render(conn, "moderate.html", assigns) | |
end | |
def moderate_mark_as_spam(conn, %{"moderation_key" => moderation_key}) do | |
posting = ElixirStatus.Persistence.Posting.find_by_moderation_key(moderation_key) | |
ElixirStatus.Persistence.Posting.mark_as_spam(posting) | |
Publisher.after_mark_as_spam(posting) | |
conn | |
|> put_flash(:info, "Posting was not published.") | |
|> redirect(to: posting_path(conn, :index)) | |
end | |
def moderate_publish(conn, %{"moderation_key" => moderation_key}) do | |
posting = ElixirStatus.Persistence.Posting.find_by_moderation_key(moderation_key) | |
ElixirStatus.Persistence.Posting.publish_moderated(posting) | |
Publisher.after_publish_moderated(posting, posting.user) | |
conn | |
|> put_flash(:info, "Posting was successfully published.") | |
|> redirect(to: posting_path(conn, :index)) | |
end | |
defp load_posting(conn, _) do | |
posting = | |
case conn do | |
%{params: %{"id" => id}} -> | |
ElixirStatus.Persistence.Posting.find_by_id(id) | |
%{params: %{"permalink" => permalink}} -> | |
ElixirStatus.Persistence.Posting.find_by_permalink(permalink) | |
_ -> | |
nil | |
end | |
if is_nil(posting) || posting.public == false do | |
conn | |
|> put_status(:not_found) | |
|> render(ElixirStatus.ErrorView, "404.html") | |
|> halt | |
else | |
conn | |
|> assign(@current_posting_assign_key, posting) | |
end | |
end | |
defp load_prev_posting(posting) do | |
query = | |
from( | |
p in ElixirStatus.Posting, | |
where: p.public == ^true and p.published_at < ^posting.published_at, | |
order_by: [desc: :published_at], | |
limit: 1 | |
) | |
query |> Ecto.Query.preload(:user) |> Repo.one() | |
end | |
defp load_next_posting(posting) do | |
query = | |
from( | |
p in ElixirStatus.Posting, | |
where: p.public == ^true and p.published_at > ^posting.published_at, | |
order_by: [asc: :published_at], | |
limit: 1 | |
) | |
query |> Ecto.Query.preload(:user) |> Repo.one() | |
end | |
defp load_created_posting(conn) do | |
uid = get_session(conn, :created_posting_uid) | |
case load_created_posting_by_uid(uid) do | |
nil -> | |
conn | |
|> put_session(:created_posting_uid, nil) | |
nil | |
posting -> | |
posting | |
end | |
end | |
defp load_created_posting_by_uid(nil), do: nil | |
defp load_created_posting_by_uid(uid) do | |
case ElixirStatus.Persistence.Posting.find_by_uid(uid) do | |
nil -> | |
nil | |
posting -> | |
seconds_since_posting = Date.diff(posting.published_at, Ecto.DateTime.utc()) | |
if seconds_since_posting < @just_created_timeout do | |
posting | |
else | |
nil | |
end | |
end | |
end | |
defp current_posting(conn) do | |
conn.assigns[@current_posting_assign_key] | |
end | |
defp extract_valid_params(%{"title" => title, "text" => text, "type" => type}) do | |
%{"title" => title || "", "text" => text || "", "type" => type} | |
end | |
defp extract_valid_params(%{"title" => title, "text" => text}) do | |
%{"title" => title || "", "text" => text || ""} | |
end | |
defp extract_valid_params(_) do | |
%{"title" => "", "text" => ""} | |
end | |
defp to_create_params(params, conn) do | |
uid = ElixirStatus.UID.generate(ElixirStatus.Posting) | |
tmp_post = %ElixirStatus.Posting{title: params["title"], text: params["text"]} | |
%{ | |
user_id: Auth.current_user(conn).id, | |
uid: uid, | |
permalink: Publisher.permalink(uid, params["title"]), | |
text: params["text"], | |
title: params["title"], | |
scheduled_at: params["scheduled_at"], | |
published_at: Ecto.DateTime.utc(), | |
metadata: %{}, | |
awaiting_moderation: false, | |
public: true, | |
moderation_key: Ecto.UUID.generate(), | |
type: PostingTypifier.run(tmp_post)["choice"] |> to_string, | |
referenced_urls: PostingUrlFinder.run(tmp_post) |> Poison.encode!() | |
} | |
end | |
defp nil_if_empty(""), do: nil | |
defp nil_if_empty(val), do: val | |
end |