# `MishkaCmsMigration.Workers.Helpers.Needs`
[🔗](https://github.com/mishka-group/mishka_cms_migration/blob/v0.0.1/lib/mishka_cms_migration/workers/__helpers/needs.ex#L5)

What the items of a page of a job of picked items need that the job was not asked for
(`MishkaCmsMigration.Workers.Helpers.Pipeline`): each item's parent and the items of other kinds
its record points at (`MishkaCmsMigration.Target`'s `needs/1`). A full run walks a parent before
its children and a kind before the kinds that point at it; a job of picked items brings nothing
else, so what it needs comes from what earlier imports recorded
(`MishkaCmsMigration.MigrationItem`), read in one query for the page, by the run's source host,
the kinds and the source ids. What the job was asked for too is never waited on: the walk brings
it first.

`call/3` answers:

  * `waits` — by source id, why an item waits, in the words a full import uses where it has them:
    the parent named with what unblocks it (`parent/2`), `"post_missing"` for a post (as a
    comment's import says), and `"waits_for: <kinds>"` for the other kinds, joined by `"; "`.
    What it needs waits it when it has no CMS record, is not left out (by an admin, or under a
    parent left out, as the last dry run or import said, `"parent_left_out"`), and no import
    skipped it: it was never imported, failed, or waits for a decision. The walk holds back
    only an item it would create or update; one it leaves as it is, or an admin's choice,
    stands;
  * `parents` — the parents the earlier imports recorded, by source id, `true` for one left out
    either way: the walk settles each child at once, and skips one under a left-out parent as
    `"parent_left_out"`, however deep, as it does in a full run.

A full run (`picked` is `nil`) asks too, in the same one query for the page, only for what waits
for an admin's decision on its archived record, or on one deleted for good
(`MishkaCmsMigration.Workers.Helpers.Decision.record_conflicts/0`), as this run's dry run planned
it or its import left it, the walk having settled that kind first: an item it would write
pointing at that record is refused by the CMS, such as a post's archived tag, or would lose it,
such as a post's deleted tag, so it waits as `"waits_for: <kinds>"` until the admin restores the
record, imports it again or leaves it out. Nothing else holds it, and it has no `parents`. An
item that waits on that decision holds a job of picked items too, whatever record it has.

# `ancestor`

```elixir
@spec ancestor(struct() | nil, String.t()) :: String.t()
```

Why an item waits for `id`, an item higher up its branch than its parent, which has no CMS record,
as `parent/2` says it of a parent: `"ancestor_undecided: <name>"`, `"ancestor_missing: <name>"`
or `"ancestor_not_listed: <id>"` (`MishkaCmsMigration.MigrationRun.reason_label/2`), given that
item as the runs recorded it, or `nil` for one the source does not list. What
`MishkaCmsMigration.MigrationItem.waits_for_parent/1` says when a grandparent, or one above it,
is what holds the branch.

# `call`

```elixir
@spec call(map(), String.t(), [MishkaCmsMigration.Source.Item.t()]) :: %{
  waits: %{required(String.t()) =&gt; String.t()},
  parents: %{required(String.t()) =&gt; boolean()}
}
```

What the picked `items`, a page of `kind`, need, for the walk of `state`.

# `parent`

```elixir
@spec parent(struct() | nil, String.t()) :: String.t()
```

Why an item waits for its parent `id`, which has no CMS record, given the parent's item as the
runs recorded it, or `nil` for one no run met, in words that name the parent and what unblocks it
(`MishkaCmsMigration.MigrationRun.reason_label/2`):

  * `"parent_undecided: <parent>"` — the parent waits for a decision no admin has made
    (`MishkaCmsMigration.MigrationItem.undecided?/1`): decide it and import it first;
  * `"parent_missing: <parent>"` — the parent was never imported, or was skipped or failed:
    import it first;
  * `"parent_not_listed: <id>"` — the source does not list the parent, such as a page in the
    trash.

`<parent>` is the parent's title and source id as the Items page shows them, `"Team (#25)"`, or
its source id alone, `"#25"`, for one with no title. The parent's item is the one the caller has
already read, so naming it costs no query.

# `parent_name`

```elixir
@spec parent_name(struct() | nil, String.t()) :: String.t()
```

The parent `id` as the Items page shows it, given its item as the runs recorded it: its title and
source id, `"Team (#25)"`, or its source id alone, `"#25"`, for one with no title or no item.

# `without_parent`

```elixir
@spec without_parent(String.t()) :: String.t() | nil
```

`reason`, why an item of a job of picked items waits (`call/3`'s `waits`), without its parent's
part: what still holds an item an admin decided to import without its parent
(`MishkaCmsMigration.MigrationItem.without_parent?/1`), `nil` when nothing else does.

---

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