Since 1.24.0 (#152206) a task can be a subtask of a master task. LH_Tasks_subtasks_class (includes/lh-tasks-subtasks-class.php) owns the relationship, the rollup and Markdown checklist rendering.
Relationship
- The master is stored in
post_parent. The post type stays non-hierarchical, so task URLs are unchanged; subtasks are read straight from the posts table, so attachments parented to a task never count. - One level deep:
validate_parent_id()refuses the task itself, a missing or trashed task, a master that is itself a subtask, and making a task that has subtasks into one. create-taskandupdate-tasktakeparent_id(0 on update makes a task standalone again),list-tasksfilters by it, andget-taskreturnsparent_idandchildren(task_id, title, status, due_date, assigned_to; soonest due first, undated last).parent_idis in the default list fields.
Who can see a master
Since 1.25.0 (#152259) LH_Tasks_visibility_class::current_user_can_view_task() also lets anyone who is the hard assignment or claimant of one of a task’s subtasks read it. A master is usually left unassigned for staff while its subtasks go to one person (a captain, say), and the email they get links to the master, which they could not open before.
Rollup
LH_Tasks_status_table_class::set_status() fires lh_tasks_task_status_changed ($post_id, $status, $from_status) on every workflow change. When a subtask changes, or is trashed, its open master is recomputed:
- Any subtask Failed: the master moves to Pending, logged as
subtask_failed, andlh_tasks_task_subtask_failedfires. - Every subtask finished (Resolved, Closed or Cancelled): the master resolves, logged as
subtasks_complete, andlh_tasks_task_completedfires. Cancelled counts as finished because only staff can cancel and it means the item does not apply. A subtask Awaiting review is not finished until it is accepted. - A finished master is left alone. Moving a subtask between masters with
update-taskrecomputes both.
Task page
The task page is written for the person doing the work, who is often new to the system (1.25.0, #152259).
- A master shows a Subtasks checklist with progress (“3 of 5 done”). Each row has a disabled checkbox for done or not done, the subtask’s title linking to it, and plain words: “due Thursday 12 November 2026 (20 days left)” while open, Waiting to be checked while it is with its reviewer, Done once finished. The owner is shown unless it is the viewer. Internal status names are not shown in rows.
- Whoever may mark a subtask done gets a button after the row, reading Mark for review when someone else will check it (
needs_review()) and Mark as done otherwise. It posts to the master’s page (fieldlh_tasks_single_task_return_to) and comes back there. The done form on a task’s own page uses the same wording. - A subtask shows Part of, linking to its master.
- Due dates include the weekday (filter
lh_tasks_due_date_format, defaultl j F Y), with days left or overdue while the task is open. The progress log is headed Timeline and ends with the task’s creation. - People who are not staff (the task capability) see a plain status in the details (To do, Waiting to be checked, Done, or the label of another finished state), and the Timeline leaves out staff records:
updated,admin_override,heartbeat,claimedandreassigned(filterlh_tasks_return_staff_only_events). Staff see everything. - List items in a description starting
[ ]or[x]render as read-only checkboxes. lh-content-converter does not yet keep Markdown task lists in that form (#152257), so this only works for HTML written that way for now.
Admin
The Tasks list has a Subtasks column: Part of the master on a subtask, or N of M done on a master, linking to edit.php?post_type=lh_tasks-task_post&lh_tasks_parent=ID, which lists that master’s subtasks. Setting the master from the block editor sidebar is not available yet: use the abilities.