# `MishkaCmsMigration.Events`
[🔗](https://github.com/mishka-group/mishka_cms_migration/blob/v0.0.1/lib/mishka_cms_migration/events.ex#L5)

The three `mishka_installer` events an import fires, through `MishkaInstaller.Event.Hook.call/3`.
Each carries the run it belongs to, and `meta: %{actor: actor, site_id: site_id}` for a plugin
that takes `call/2`. A dry run fires none of them: it writes nothing in the CMS and asks no plugin.

## When a plugin fails

The two events that decide what is written fail closed. They are called with the `raised:` option
of `MishkaInstaller.Event.Hook.call/3`, so when one of their plugins raises, or replies with
something other than `{:reply, _}` or `{:reply, :halt, _}`, the plugins after it do not run and
the call answers `:failed` instead of the payload. That answer, or any other that is not the
payload, skips the item as `"plugins_failed"`. While one of an event's plugins is not loaded, so
the event cannot run, the item is skipped as `"plugins_cannot_run"`. Either way nothing is written
behind a plugin that would have changed or kept out the item. An event with no started plugin,
such as one whose plugins an operator stopped, hands the payload back as it was sent: a piece
stays unconverted and the item is written as the import made it. A plugin answers the payload it
is handed, with all its keys.

## `migration:content:convert`

Fired for each piece of an item's content the source could not convert itself
(`MishkaCmsMigration.Source.Item`), before the item is written:

    %{
      site_id: "…", run_id: "…", source: "wordpress", source_host: "example.com",
      kind: "post", source_id: "12",
      name: "gallery", attrs: %{"ids" => "4,5"}, raw: "[gallery ids=\"4,5\"]",
      html: nil
    }

A plugin that knows the piece answers with `html` set to the markup it becomes. A piece nobody
converts is kept as text: `raw`, escaped.

## `migration:item:before_import`

Fired for each item about to be written, after its content is converted:

    %{
      site_id: "…", run_id: "…", source: "wordpress", source_host: "example.com",
      outcome: :created, item: %MishkaCmsMigration.Source.Item{}, reason: nil
    }

`outcome` is what the import will record once the item is written: `:created` for a new CMS
record, `:updated` for one an earlier run wrote. A plugin may answer with a changed `item` (its
`kind` and `source_id` stay as they were), or with `outcome: :skipped` and a `reason` to leave the
item out: a plugin that writes the item itself skips it with a reason saying so. A skipped item is
recorded as skipped, with the plugin's reason, or `"skipped by a plugin"` when it gave none. Any
other outcome a plugin answers is not used: the import's own stands.

## `migration:import:finished`

Fired once an import is done and its run is saved, with the run's report
(`MishkaCmsMigration.Report`):

    %{
      site_id: "…", run_id: "…", source: "wordpress", source_host: "example.com",
      report: %{counts: %{created: 10, updated: 2, skipped: 1, failed: 0}, kinds: [...], entries: [...]}
    }

What a plugin answers is not used.

# `decision`

```elixir
@type decision() :: {:ok, MishkaCmsMigration.Source.Item.t()} | {:skipped, String.t()}
```

What a plugin decides for an item about to be written.

# `before_import`

```elixir
@spec before_import(
  MishkaCmsMigration.Source.Item.t(),
  :created | :updated,
  map(),
  map() | nil
) ::
  decision()
```

What the plugins decide for `item` about to be written as `outcome`: `{:ok, item}`, with the item
as a plugin left it, or `{:skipped, reason}`.

# `before_import_event`

```elixir
@spec before_import_event() :: String.t()
```

The event an item is offered on before it is written: what a plugin that changes or skips items
names in `use MishkaInstaller.Event.Hook, event: ...`, and what a test registers one for.

# `convert`

```elixir
@spec convert(map(), MishkaCmsMigration.Source.Item.t(), map(), map() | nil) ::
  {:ok, String.t()} | :unconverted | :cannot_run | :failed
```

The markup a plugin converts `piece` of `item` to: `{:ok, html}`, `:unconverted` when none does,
`:cannot_run` while one of the event's plugins is not loaded, or `:failed` when the plugins
failed (see "When a plugin fails").

# `convert_event`

```elixir
@spec convert_event() :: String.t()
```

The event a piece of content is offered on: what a converter plugin names in
`use MishkaInstaller.Event.Hook, event: ...`, and what a test registers one for.

# `finished`

```elixir
@spec finished(map(), map(), map() | nil) :: :ok
```

Hands `report` of the finished import of `run` to the plugins.

# `finished_event`

```elixir
@spec finished_event() :: String.t()
```

The event an import's report is handed to: what a plugin that acts on a finished import names in
`use MishkaInstaller.Event.Hook, event: ...`, and what a test registers one for.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
