Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Editorial Review Queue

A WordPress plugin that lets an editorial team track posts through a review workflow — assign a status, list what's pending, and update it — before publication.

Status: v0.1-rc. This is a checkpoint, not a finished release. See Known debt below for what's explicitly not done yet.

How it works

Every post moves through three custom sub-statuses while WordPress's own post_status is pending:

  • unassigned — no reviewer has looked at it yet (default on creation).
  • reviewing — a reviewer has picked it up.
  • approved — a reviewer signed off; the post can then be published, scheduled, or left in the queue.

The sub-status is stored as a non-public custom taxonomy, erq_review_statuses, with exactly one term assigned per post. The reasoning behind that choice (over post meta, a CPT, or a custom table) is written up in ADR.md.

Architecture

Code lives under src/, namespace EditorialReviewQueue, autoloaded via Composer/PSR-4. Each class owns one concern:

Class Responsibility
BootstrapManager Registers the taxonomy, seeds its three terms, and backfills unassigned onto any pre-existing pending post that has no status yet.
QueryManager Read-only domain logic: list pending posts, fetch a single post by ID, check the current user's capability to review. Knows nothing about REST or the CLI.
StatusManager Owns the valid status list (StatusManager::VALID_STATUSES) and the only place that changes a post's status.
RestRegister Registers the REST routes and adapts REST-specific input (WP_REST_Request) into plain arguments for QueryManager/StatusManager.
CliRegister Registers the WP-CLI erq command and adapts CLI-specific input ($args/$assoc_args) the same way.

Both RestRegister and CliRegister are thin adapters over the same domain classes — REST and WP-CLI expose the same underlying data and actions through two different transports, not two different implementations.

ChecklistManager, NotesManager, ReviewsManager, and RoleManager exist as empty placeholders, matching sections already decided in the ADR (review checklist, reviewer notes, the Reviews CPT, and the custom reviewer role/capability) that are not implemented yet — see Known debt.

REST API

Namespace: editorial-review-queue/v1. All routes currently require the manage_options capability.

Method Route Description
GET /posts List all pending posts with their review status.
GET /posts/{id} Get a single post's review status. 404 if the ID doesn't match a post.
PATCH /posts/{id} Update a post's review status. Body: {"review_status": "reviewing"}. review_status is validated against the enum of valid statuses at the schema level (400 rest_not_in_enum if invalid); id is validated with a custom validate_callback (400 rest_invalid_param if not a real post).

Errors are returned as standard WP_Error responses with an appropriate HTTP status, not raw PHP fatals.

WP-CLI

wp erq get_posts                                    # table of all pending posts
wp erq get_post <id>                                # single post, or an observable error if invalid/missing
wp erq update_post <id> --review-status=<status>     # updates the status; exits non-zero on invalid id or status

Logging

Failures in QueryManager::get_single_post() and StatusManager::update_single_post_status() are recorded via PHP's error_log() with the post ID and/or requested status — never the reviewer's internal note or any personal data.

Known debt before v0.1

  • No automated tests, static analysis, or CI yet. Everything so far has been verified manually (Postman for REST, wp erq ... --debug for CLI).
  • Checklist, reviewer notes, the Reviews CPT, and the dedicated reviewer role/capability are designed in the ADR but not built. check_user_can_review() currently gates everything on manage_options as a placeholder.
  • Validation is intentionally duplicated in places (e.g. REST's args schema and a manual check inside the callback) as a deliberate defense-in-depth choice, not an oversight — but it means the same rule has to be kept in sync in two places if it ever changes.
  • No versioning/compatibility matrix yet (minimum/current PHP and WordPress versions, upgrade path).
  • No packaged release/zip — only runnable from a working copy with composer install.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages