defmodule Mix.Phoenix.Context do @moduledoc false alias Mix.Phoenix.{Context, Schema} defstruct name: nil, module: nil, schema: nil, alias: nil, base_module: nil, web_module: nil, basename: nil, file: nil, test_file: nil, test_fixtures_file: nil, dir: nil, generate?: true, context_app: nil, opts: [], scope: nil def valid?(context) do context =~ ~r/^[A-Z]\w*(\.[A-Z]\w*)*$/ end def new(context_name, opts) do new(context_name, %Schema{}, opts) end def new(context_name, %Schema{} = schema, opts) do ctx_app = opts[:context_app] || Mix.Phoenix.context_app() base = Module.concat([Mix.Phoenix.context_base(ctx_app)]) module = Module.concat(base, context_name) alias = Module.concat([module |> Module.split() |> List.last()]) basedir = Phoenix.Naming.underscore(context_name) basename = Path.basename(basedir) dir = Mix.Phoenix.context_lib_path(ctx_app, basedir) file = dir <> ".ex" test_dir = Mix.Phoenix.context_test_path(ctx_app, basedir) test_file = test_dir <> "_test.exs" test_fixtures_dir = Mix.Phoenix.context_app_path(ctx_app, "test/support/fixtures") test_fixtures_file = Path.join([test_fixtures_dir, basedir <> "_fixtures.ex"]) generate? = Keyword.get(opts, :context, true) %Context{ name: context_name, module: module, schema: schema, alias: alias, base_module: base, web_module: web_module(), basename: basename, file: file, test_file: test_file, test_fixtures_file: test_fixtures_file, dir: dir, generate?: generate?, context_app: ctx_app, opts: opts, scope: schema.scope } end def pre_existing?(%Context{file: file}), do: File.exists?(file) def pre_existing_tests?(%Context{test_file: file}), do: File.exists?(file) def pre_existing_test_fixtures?(%Context{test_fixtures_file: file}), do: File.exists?(file) def function_count(%Context{file: file}) do {_ast, count} = file |> File.read!() |> Code.string_to_quoted!() |> Macro.postwalk(0, fn {:def, _, _} = node, count -> {node, count + 1} {:defdelegate, _, _} = node, count -> {node, count + 1} node, count -> {node, count} end) count end def file_count(%Context{dir: dir}) do dir |> Path.join("**/*.ex") |> Path.wildcard() |> Enum.count() end defp web_module do base = Mix.Phoenix.base() cond do Mix.Phoenix.context_app() != Mix.Phoenix.otp_app() -> Module.concat([base]) String.ends_with?(base, "Web") -> Module.concat([base]) true -> Module.concat(["#{base}Web"]) end end end