Elph

Elph is a modular and easily customizable content management library that gives you pretty much everything you need for your basic phoenix project in terms of content-management.

It offers you easy content-management and a media library.

Just plug it into your existing phoenix app, add some configs, run migrations and you're ready to go.

NOTE: For the time being elph has no authentication//authorization integrated. This will be added in the future, probably as a plug-in module.

Prerequisites

Usage

<YourAppWeb>.Router

To have the most control over everything you can use elph's contexts and controllers and need to do the routing yourself.

FallbackController

Elph has a default phoenix FallbackController to show errors and such. If you want to use your own customized FallbackController add the following to config.exs: config :elph, fallback_controller: <YourAppWeb>.FallbackController

Custom Types

Elph brings with it a list of default types. Those can be found in elph/contents/types. Those are included and available by default without more configuration.

In case this is not enough, you'll need to setup the use of custom types once and adding new types after that is pretty easy.

Setup

First we need to create the central point where we define our custom types.

Adding Types

Start off with a new schema created by mix phx.gen.schema. For example: mix phx.gen.schema Contents.Types.Markdown markdown_contents markdown:text

Now we need to change some stuff in the <YourApp>.Contents.Types.Markdown module.

Add your new type in your central content definition module (See paragraph above).

We also need to alter the created migration.

Cleanup

If you need your custom types to be cleaned up after them, you can add one or more callbacks.

Per Content-Type (preferred)

Add a def after_delete_callback(content) do to your custom content type module. This callback will be called once for each (explicitly or via garbage collection) deleted content with the deleted content as parameter. If you need the cleanup to re-run afterwards return :cleanup. All other returns are ignored.

Global (Not preferred)

As with custom types you'll first need to create a module:

defmodule <YourApp>.Callbacks do
  use Elph.Contents.Callbacks

  elph_cleanup_callbacks()
end

Now you can add one or more callbacks; for example cleanup_callback(&IO.inspect/1)

Each callback will be called with a list of explicitly deleted and garbage-colledted content (without its children, as one would get from Contents.list_contents). So the above example would print a list of the deleted contents on your console.

If you want to rerun the cleanup after all callbacks were run, return :cleanup in your function. Every other return will be ignored. Care not to produce infinity loops!

Development

For the development of elph we created a project called Elph-Shell. It provides an api with some basic functionality. It also has some configuration set to make developing elph a little easier.

Testing

To test elph you'll need a database. Per default Elph uses a mysql Database and reads the DATABASE_URL environment variable to aquire credentials. In case you don't want to use MySql or a DATABASE_URL you can change your config.ex file. Additionally you'll need to change the adapter in Elph.Test.Repo and import your dependancy via mix.

Preparations

To run tests from within elph-shell you need to create a new database for testing, since using the development database will give you errors. For that open a shell to the docker-container

Running

To run your test simply change to the elph folder in case you're in the shell-directory with cd elph. For the first time - and after changing your migrations - you'll have to run DATABASE_URL=mysql://mysql:mysql@db/elph_test MIX_ENV=test mix ecto.reset.

After that you can run DATABASE_URL=mysql://mysql:mysql@db/elph_test mix test and everything should work out. If you want to see test-coverage you can add the parameter --cover to the command and elixir will show you a coverage percentage and put detailed reports into the cover-subdirectory.