defmodule Xmeta.Xapi.View do
defmacro __using__(opts) do
unless opts[:title], do: raise("plaease set :title in Module: #{__MODULE__}")
quote bind_quoted: [opts: opts] do
Xmeta.Xapi.Env.put_module(__MODULE__, :xpi_api)
if opts[:schema] do
use Params.Schema, Xmeta.Xapi.View.make_schema(opts[:schema])
end
@config opts
def get_context_data(conn, params) do
%{}
end
def call(conn, params) do
{valid?, changes, errors} = valid_schema(conn,params)
ctx = %{conn: conn}
if valid? do
ctx = ctx |> put_in([:data],changes)
rsp = Xmeta.Xapi.View.check_middleware(ctx, params, __MODULE__)
if rsp[:status] == 0, do: get_context_data(ctx, params), else: rsp
else
%{status: 400, data: [], msg: Xmeta.Xapi.View.make_errors(errors)}
end
end
def config, do: @config
defp get_schema, do: @config[:schema]
defp valid_schema(conn, params) do
schema = get_schema()
unless schema do
{true, params, []}
else
%Ecto.Changeset{valid?: valid?, changes: changes, errors: errors} = __MODULE__.from(params)
{valid?,changes,errors}
end
end
def get_middleware() do
config = config()
middleware = config[:middleware]
if middleware, do: middleware, else: []
end
defoverridable get_context_data: 2, call: 2, valid_schema: 2,get_middleware: 0
end
end
def make_schema(schema) do
Enum.reduce(Map.to_list(schema), %{}, fn(x,acc) ->
{key,data} = x
if is_atom(data) do
put_in(acc,[key],data)
else
data = for x <- data, check_key?(x), do: x
put_in(acc,[key],data)
end
end)
end
defp check_key?(c) do
{key,_} = c
if key in [:name,:des] do
false
else
true
end
end
def make_errors(errors) do
for x <- errors do
{name,{msg,_}} = x
%{} |> put_in([name],msg)
end
end
def check_middleware(ctx, params, module) do
mids = get_module_middleware(module)
Enum.reduce(mids,%{status: 0, data: [], msg: ""}, fn(m,acc) ->
if acc[:status] != 0 do
acc
else
m.call(ctx,params)
end
end)
end
defp get_module_middleware(module) do
slist = Module.split(module)
site_mod = get_module_root(slist,1)
router_mod = get_module_root(slist,2)
site_mod.get_middleware() ++ router_mod.get_middleware() ++ module.get_middleware()
end
defp get_module_root(slist, num) do
new_slist = for x <- 0..num do
Enum.at(slist,x)
end
Module.concat(new_slist)
end
end