Skip to content

Commit

Permalink
Implement plugin execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Dalgona committed Apr 10, 2019
1 parent c5dd69c commit 689dcb7
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 1 deletion.
159 changes: 159 additions & 0 deletions lib/serum/plugin.ex
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,163 @@ defmodule Serum.Plugin do
rescue
e in UndefinedFunctionError -> {:error, Exception.message(e)}
end

@doc false
@spec build_started(src :: binary(), dest :: binary()) :: Result.t()
def build_started(src, dest) do
call_action(:build_started, [src, dest])
end

@doc false
@spec reading_pages(files :: [binary()]) :: Result.t([binary()])
def reading_pages(files) do
call_function(:reading_pages, [files])
end

@doc false
@spec reading_posts(files :: [binary()]) :: Result.t([binary()])
def reading_posts(files) do
call_function(:reading_posts, [files])
end

@doc false
@spec reading_templates(files :: [binary()]) :: Result.t([binary()])
def reading_templates(files) do
call_function(:reading_templates, [files])
end

@doc false
@spec processing_page(file :: File.t()) :: Result.t(File.t())
def processing_page(file) do
call_function(:processing_page, [file])
end

@doc false
@spec processing_post(file :: File.t()) :: Result.t(File.t())
def processing_post(file) do
call_function(:processing_post, [file])
end

@doc false
@spec processing_template(file :: File.t()) :: Result.t(File.t())
def processing_template(file) do
call_function(:processing_template, [file])
end

@doc false
@spec processed_page(page :: Page.t()) :: Result.t(Page.t())
def processed_page(page) do
call_function(:processed_page, [page])
end

@doc false
@spec processed_post(post :: Post.t()) :: Result.t(Post.t())
def processed_post(post) do
call_function(:processed_post, [post])
end

@doc false
@spec processed_template(template :: Template.t()) :: Result.t(Template.t())
def processed_template(template) do
call_function(:processed_template, [template])
end

@doc false
@spec processed_list(list :: PostList.t()) :: Result.t(PostList.t())
def processed_list(list) do
call_function(:processed_list, [list])
end

@doc false
@spec rendered_fragment(frag :: Fragment.t()) :: Result.t(Fragment.t())
def rendered_fragment(frag) do
call_function(:rendered_fragment, [frag])
end

@doc false
@spec rendered_page(file :: File.t()) :: Result.t(File.t())
def rendered_page(file) do
call_function(:rendered_page, [file])
end

@doc false
@spec wrote_file(file :: File.t()) :: Result.t()
def wrote_file(file) do
call_action(:wrote_file, [file])
end

@doc false
@spec build_succeeded(src :: binary(), dest :: binary()) :: Result.t()
def build_succeeded(src, dest) do
call_action(:build_succeeded, [src, dest])
end

@doc false
@spec build_failed(src :: binary(), dest :: binary(), result :: Result.t() | Result.t(term)) ::
Result.t()
def build_failed(src, dest, result) do
call_action(:build_failed, [src, dest, result])
end

@doc false
@spec finalizing(src :: binary(), dest :: binary()) :: Result.t()
def finalizing(src, dest) do
call_action(:finalizing, [src, dest])
end

@spec call_action(atom(), [term()]) :: Result.t()
defp call_action(fun, args) do
__MODULE__
|> Agent.get(&(&1[fun] || []))
|> do_call_action(fun, args)
end

@spec do_call_action([t()], atom(), [term()]) :: Result.t()
defp do_call_action(plugins, fun, args)
defp do_call_action([], _fun, _args), do: :ok

defp do_call_action([plugin | plugins], fun, args) do
case apply(plugin.module, fun, args) do
:ok ->
do_call_action(plugins, fun, args)

{:error, _} = error ->
error

term ->
message =
"#{plugin.name} (#{plugin.version}): #{fun} returned an " <>
"unexpected value: #{inspect(term)}"

{:error, message}
end
end

@spec call_function(atom(), [term()]) :: Result.t(term())
defp call_function(fun, [arg | args]) do
__MODULE__
|> Agent.get(&(&1[fun] || []))
|> do_call_function(fun, args, arg)
end

@spec do_call_function([t()], atom(), [term()], term()) :: Result.t(term())
defp do_call_function(plugins, fun, args, acc)
defp do_call_function([], _fun, _args, acc), do: {:ok, acc}

defp do_call_function([plugin | plugins], fun, args, acc) do
case apply(plugin.module, fun, [acc | args]) do
{:ok, new_acc} ->
do_call_function(plugins, fun, args, new_acc)

{:error, _} = error ->
error

term ->
message =
"#{plugin.name} (#{plugin.version}): #{fun} returned an " <>
"unexpected value: #{inspect(term)}"

{:error, message}
end
end
end
12 changes: 12 additions & 0 deletions priv/test_plugins/dummy_plugin_1.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,38 @@ defmodule Serum.DummyPlugin1 do

def reading_posts(files) do
debug("reading_posts: #{length(files)}")

{:ok, files}
end

def processing_page(file) do
debug("processing_page: #{file.src}")

{:ok, file}
end

def processing_template(file) do
debug("processing_template: #{file.src}")

{:ok, file}
end

def processed_post(post) do
debug("processed_post: #{post.title}")

{:ok, post}
end

def processed_list(list) do
debug("processed_list: #{list.title}")

{:ok, list}
end

def rendered_page(file) do
debug("rendered_page: #{file.dest}")

{:ok, file}
end

def build_succeeded(src, dest) do
Expand Down
12 changes: 12 additions & 0 deletions priv/test_plugins/dummy_plugin_2.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,38 @@ defmodule Serum.DummyPlugin2 do

def reading_pages(files) do
debug("reading_pages: #{length(files)}")

{:ok, files}
end

def processing_page(file) do
debug("processing_page: #{file.src}")

{:ok, file}
end

def processing_post(file) do
debug("processing_post: #{file.src}")

{:ok, file}
end

def processed_post(post) do
debug("processed_post: #{post.title}")

{:ok, post}
end

def processed_template(template) do
debug("processed_template: #{template.file}")

{:ok, template}
end

def rendered_page(file) do
debug("rendered_page: #{file.dest}")

{:ok, file}
end

def wrote_file(file) do
Expand Down
12 changes: 12 additions & 0 deletions priv/test_plugins/dummy_plugin_3.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,38 @@ defmodule Serum.DummyPlugin3 do

def reading_pages(files) do
debug("reading_pages: #{length(files)}")

{:ok, files}
end

def reading_posts(files) do
debug("reading_posts: #{length(files)}")

{:ok, files}
end

def processing_template(file) do
debug("processing_template: #{file.src}")

{:ok, file}
end

def processed_page(page) do
debug("processed_page: #{page.title}")

{:ok, page}
end

def processed_post(post) do
debug("processed_post: #{post.title}")

{:ok, post}
end

def rendered_page(file) do
debug("rendered_page: #{file.dest}")

{:ok, file}
end

def wrote_file(file) do
Expand Down
34 changes: 33 additions & 1 deletion test/serum/plugin_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
defmodule Serum.PluginTest do
use ExUnit.Case
use ExUnit.Case, async: false
import Serum.Plugin
alias Serum.File
alias Serum.Fragment
alias Serum.Page
alias Serum.Post
alias Serum.PostList
alias Serum.Template

priv_dir = :serum |> :code.priv_dir() |> IO.iodata_to_binary()

Expand All @@ -22,5 +28,31 @@ defmodule Serum.PluginTest do
end)

assert count == 27

Agent.update(Serum.Plugin, fn _ -> %{} end)
end

test "callback test" do
{:ok, _} = load_plugins([Serum.DummyPlugin1, Serum.DummyPlugin2, Serum.DummyPlugin3])

assert :ok = build_started("/path/to/src", "/path/to/dest")
assert {:ok, _} = reading_pages(["a", "b", "c"])
assert {:ok, _} = reading_posts(["a", "b", "c"])
assert {:ok, _} = reading_templates(["a", "b", "c"])
assert {:ok, _} = processing_page(%File{src: "page.md"})
assert {:ok, _} = processing_post(%File{src: "post.md"})
assert {:ok, _} = processing_template(%File{src: "template.html.eex"})
assert {:ok, _} = processed_page(%Page{title: "Test Page"})
assert {:ok, _} = processed_post(%Post{title: "Test Post"})
assert {:ok, _} = processed_template(%Template{file: "template.html.eex"})
assert {:ok, _} = processed_list(%PostList{title: "Test Post List"})
assert {:ok, _} = rendered_fragment(%Fragment{output: "test.html"})
assert {:ok, _} = rendered_page(%File{dest: "test.html"})
assert :ok = wrote_file(%File{dest: "test.html"})
assert :ok = build_succeeded("/src", "/dest")
assert :ok = build_failed("/src", "/dest", {:error, "sample error"})
assert :ok = finalizing("/src", "/dest")

Agent.update(Serum.Plugin, fn _ -> %{} end)
end
end

0 comments on commit 689dcb7

Please sign in to comment.