# `MishkaCmsMigration.Targets.BlogComment`
[🔗](https://github.com/mishka-group/mishka_cms_migration/blob/v0.0.1/lib/mishka_cms_migration/targets/blog_comment.ex#L6)

The `"comment"` items of a source written as the Blog's comments (`MishkaBlog.Comment`),
through the `:create` and `:update` an admin's own comment form runs, on the run's site and as
the admin who pressed Import: the admin needs the Blog's `admin:dashboard:blog:comment` to write
them and `admin:dashboard:blog:post` to find the posts and bloggers they belong to, and the
Blog's own rules decide the rest, such as how a comment's text is cleaned (it is plain text).
The Blog's `:create` keeps the author it is given (`author_id`), or a guest's name, instead of
making the acting admin the author.

An item's content is the comment's text, with its tags taken out and its entities read
(`MishkaCmsCore.PlainText.from_html/1`), as the Blog stores a comment. Its `"status"` is the
comment's: `"approved"` is approved and `"hold"` (held for moderation) is pending. The Blog
sets when a comment is created, so a comment is dated the day it is imported, not the day it
was written. The commenter's IP address and browser are not copied into the comment; they stay
in the item's `extra`.

## Which comments

By the run's `comments` choice (`MishkaCmsMigration.MigrationRun`'s options), read with
`existing/2` before anything is written, in the dry run too:

  * off (the default) — every item is skipped as `"not_chosen"`, and nothing is written;
  * on — a comment is written, except:
    * one that is not a comment, a pingback or a trackback (`"type"`) — skipped as
      `"not_a_comment"`;
    * one that is not approved or held (`"status"`), such as spam or in the trash — skipped as
      `"spam_or_trash"`;
    * one on a page (`"post_type"`), which the Blog has no place for — skipped as
      `"page_comment"`;
    * in an import, one whose post has no Blog post, because it failed, was never written or
      an admin left it out — skipped as `"post_missing"`, as is a reply whose parent comment
      was not written (the walk's `"parent_missing: <parent>"` and the like) or was left out
      (`"parent_left_out"`).

A dry run writes no post, so it does not look for one: an item it plans may still be skipped
for its post when the import runs.

## Whose comment

The comment's author is a user of the run's site, found in this order:

  * the user whose blogger profile the same run, or an earlier one, wrote or connected for the
    comment's `"author"`, the source's user (`MishkaCmsMigration.Targets.BlogBlogger`);
  * the user whose email is the comment's `"author_email"`, among the users of the run's site
    (`MishkaCmsMigration.Targets.BlogBlogger.users/2`), so the admin needs the core's
    `admin:dashboard:user` to find any.

A comment with neither is a guest's: it is written with the name and email the commenter gave
(`guest_name`, `guest_email`) and no author. A guest who gave no name is written as
`"Anonymous"`, the name WordPress shows for one. An email the Blog would refuse is left out of
the comment instead of failing it, and the report says so (`"guest_email_dropped"`).

The report says a guest's comment is one (`"guest_comment: <name>"`, which
`MishkaCmsMigration.Report` counts as `guests`). The authors of a page's comments, and in an
import the posts they are on, are found together in `existing/2`, one read for the page in a
dry run and in an import, from the comments as the source lists them, and handed to each
comment's note and write as its context's `prepared` (`{:created, prepared}`). A dry run writes
no blogger, so it finds the authors from the users the site has, and plans a comment by a
source's user as a user's when the run's `authors` choice is `"create"`, which makes every such
user.

## Its post and its place in a thread

The comment is written on the Blog post the same run, or an earlier one, wrote for its
`"post"` (`MishkaCmsMigration.Targets.BlogPost`), under the comment written for its parent: the
walk writes a parent first. Its post, parent and author are set when the comment is created and
never changed by a later run, which writes its text and status over a comment it wrote. Its post
is what it needs (`needs/1`), so Import this item writes a comment alone only on a post an
import wrote.

A re-run is held to the rules every target is: a comment WordPress did not change is
`"unchanged"`, and one an admin edited or moderated in the CMS is kept as the admin left it
(`MishkaCmsMigration.Workers.Helpers.Decision`). 

Defined only where Mishka Blog is loaded, and supervised by `MishkaCmsMigration.Application`
only then; on a node without the Blog its items wait for it (`"blog_missing"`).

# `error_return`

```elixir
@type error_return() ::
  {:error, [%{action: atom(), field: atom(), message: String.t()}]}
```

# `okey_return`

```elixir
@type okey_return() :: {:ok, struct() | map() | module() | [any()]}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `config`

```elixir
@spec config() :: keyword()
```

# `config`

```elixir
@spec config(atom()) :: any()
```

# `enable`

```elixir
@spec enable() :: okey_return() | error_return()
```

# `get`

```elixir
@spec get() :: keyword()
```

# `health_check`

```elixir
@spec health_check() :: :ok | {:degraded, term()} | {:error, term()}
```

Optional. See `c:MishkaInstaller.Event.Hook.health_check/0`. Override to report health.

# `on_dependency_error`

```elixir
@spec on_dependency_error(term()) :: term()
```

Optional. See `c:MishkaInstaller.Event.Hook.on_dependency_error/1`. Override to react.

# `register`

```elixir
@spec register() :: okey_return() | error_return()
```

# `restart`

```elixir
@spec restart() :: okey_return() | error_return()
```

# `start`

```elixir
@spec start() :: okey_return() | error_return()
```

# `start_link`

# `stop`

```elixir
@spec stop() :: okey_return() | error_return()
```

# `unregister`

```elixir
@spec unregister() :: okey_return() | error_return()
```

---

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