Current section

Files

Jump to
thesis lib mix tasks thesis.install.ex
Raw

lib/mix/tasks/thesis.install.ex

defmodule Mix.Tasks.Thesis.Install do
use Mix.Task
import Mix.Thesis.Utils
@migrations [
"create_thesis_tables",
"add_meta_to_thesis_page_contents",
"add_indexes_to_tables",
"add_template_and_redirect_url_to_thesis_pages",
"change_content_default_for_page_content",
"create_thesis_files_table",
"create_thesis_backups_table",
"change_and_convert_page_data_type_in_backups_table"
]
@template_files [
{"priv/templates/thesis.install/thesis_auth.exs", "lib/YOURAPP/thesis_auth.ex"}
]
@shortdoc "Generates Thesis code in your Phoenix app"
@moduledoc """
Installs Thesis by adding these to your host app:
* lib/thesis_auth.ex - Contains a function to handle authorization
* migration - creates the two tables needed for Thesis.EctoStore
* config/config.exs - adds Thesis config code
* web/web.ex - adds Thesis `use` statements
You should be able to run this mix task multiple times without harm. It will
automatically detect when a file or line of code exists and skip that step.
"""
@doc false
def run(_args) do
thesis_templates()
thesis_config()
thesis_web()
status_msg("done",
"Now run #{IO.ANSI.blue}mix ecto.migrate#{IO.ANSI.reset} to ensure your database is up to date.")
end
@doc false
def thesis_templates do
migration_files = @migrations
|> Enum.filter(&migration_missing?/1)
|> Enum.with_index
|> Enum.map(&migration_tuple/1)
all_templates = @template_files ++ migration_files
all_templates
|> Stream.map(&render_eex/1)
|> Stream.map(&replace_yourapp(&1, to_string(Mix.Phoenix.otp_app))) # TODO: better way to infer app path?
|> Stream.map(&copy_to_target/1)
|> Stream.run
end
@doc false
def thesis_config do
status_msg("updating", "config/config.exs")
dest_file_path = Path.join [File.cwd! | ~w(config config.exs)]
dest_file_path
|> File.read!()
|> insert_thesis()
|> overwrite_file(dest_file_path)
end
@doc false
def thesis_web do
status_msg("updating", "web.ex")
# Phoenix 1.2 style
phx_12 = "web/web.ex"
phx_13 = List.first(Path.wildcard("lib/*_web.ex")) || ""
dest_file_path =
(File.exists?(phx_12) && phx_12)
|| (File.exists?(phx_13) && phx_13)
if dest_file_path do
dest_file_path
|> File.read!()
|> insert_controller()
|> insert_view()
|> insert_router()
|> overwrite_file(dest_file_path)
else
status_msg("warning", "couldn't find web.ex! See https://github.com/infinitered/thesis-phoenix/blob/master/README_INSTALL.md.")
end
end
defp insert_controller(source) do
insert_in(source, "controller", "\n use Thesis.Controller\n")
end
defp insert_view(source) do
insert_in(source, "view", "\n use Thesis.View\n")
end
defp insert_router(source) do
insert_in(source, "router", "\n use Thesis.Router\n")
end
defp insert_in(source, block, insertion) do
if String.contains?(source, insertion) do
source
else
match =
Regex.scan(~r/def #{block} do\n\s.+end\n\s*end/Usm, source)
|> List.flatten
|> List.first
if match do
inserted = String.replace(match, " end\n end", "#{insertion} end\n end")
String.replace(source, match, inserted)
else
source
end
end
end
# defp insert_at(source, pattern, inserted) do
# if String.contains?(source, inserted) do
# source
# else
# String.replace(source, pattern, pattern <> inserted)
# end
# end
defp insert_thesis(source) do
if String.contains? source, "config :thesis," do
status_msg("skipping", "thesis config. It already exists.")
:skip
else
source <> """
# Thesis Main Config
config :thesis,
store: Thesis.EctoStore,
authorization: #{Mix.Phoenix.base}.ThesisAuth,
uploader: Thesis.RepoUploader
# Thesis Store Config
config :thesis, Thesis.EctoStore, repo: #{Mix.Phoenix.base}.Repo
# Thesis Notifications Config
# config :thesis, :notifications,
# add_page: [],
# page_settings: [],
# import_export_restore: []
# Thesis Dynamic Pages Config
# config :thesis, :dynamic_pages,
# view: #{Mix.Phoenix.base}Web.PageView,
# templates: ["index.html", "otherview.html"],
# not_found_view: #{Mix.Phoenix.base}Web.ErrorView,
# not_found_template: "404.html"
"""
end
end
defp migration_missing?(filename) do
"priv/repo/migrations"
|> File.ls!
|> Enum.all?(fn (f) -> !String.contains?(f, filename) end)
end
defp migration_tuple({filename, i}) do
ts = String.to_integer(timestamp()) + i
{"priv/templates/thesis.install/#{filename}.exs", "priv/repo/migrations/#{ts}_#{filename}.exs"}
end
end