Download the PHP package williamundqvist/scheduled-page-reviews without Composer

On this page you can find all versions of the php package williamundqvist/scheduled-page-reviews. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package scheduled-page-reviews

Scheduled Page Reviews

A WordPress plugin for content freshness reminders: per-page review intervals, assignees, hierarchical rule inheritance, due/overdue tracking, batched email digests, a Gutenberg sidebar, and a React page-tree admin UI.

This is a stand-alone generic WordPress plugin. It does not depend on any specific theme or framework.

Requirements

Installation (development)

Then activate the plugin in wp-admin → Plugins.

Installation (test / production ZIP)

Releases are built in CI from a tag on main. The ZIP includes vendor/ and dist/; you do not need Node or Composer on the server.

  1. Download the ZIP from the GitHub Release for your tag (see RELEASE.md).
  2. Plugins → Add New → Upload Plugin and activate.

To build a ZIP locally:

Output: .build/scheduled-page-reviews-<version>.zip

Scripts

Command What it does
npm run dev Build assets and watch for changes
npm run build tsc --noEmit then production bundle
npm run typecheck Type-check only
npm run release Build installable ZIP under .build/ (see RELEASE.md)
composer release npm run build then release ZIP
composer test Run PHPUnit
composer lint Run PHP_CodeSniffer
composer lint:fix Run PHP Code Beautifier
npm run i18n:pot Regenerate single POT (PHP + React)
npm run i18n:mo Compile .po.mo (after translations exist)
npm run i18n:json Build Jed JSON for React script translations

See LOCALIZATION.md for the full i18n plan (PHP, emails, admin SPA, editor sidebar).

Architecture (short tour)

Each service constructor self-registers its WordPress hooks. App::boot() wires the object graph; it contains no add_action calls of its own. This keeps the dependency graph explicit and the bootstrap class small.

Data model

Where What
wp_options.scheduled_page_reviews_settings GlobalSettings JSON (default_interval_days, notify_days_before, send_reminder_after_due, reminder_cadence_days, default_recipient_emails, cron_batch_size, sync_wp_modified_on_review)
wp_postmeta._scheduled_page_reviews_rule Per-page Rule JSON: {interval_days, recipients, notify_before} each as {value, scope} where scope ∈ 'self' | 'subtree'. recipients is a list of typed Target objects (see below). Legacy owners keys are merged into recipients on load.
wp_postmeta._scheduled_page_reviews_last_reviewed_at ISO 8601 string, set by the row action / REST mark-reviewed / Gutenberg button
wp_postmeta._scheduled_page_reviews_last_reviewed_by WP user ID
wp_postmeta._scheduled_page_reviews_last_notified_at ISO 8601 string of the last sent reminder; throttles notifications

Empty rules are deleted from post meta automatically — no orphan rows.

Target model (who to notify)

recipients is a list of Target objects rather than plain ID or email arrays. Every target has the shape { type, value }:

type value Dashboard widget Email notifications
user int (WP user ID) Yes Yes (via WP account email)
role string (slug) Yes (role members) Yes (expanded at cron time)
email string No Yes (standalone mailbox)

Example rule fragment:

Role targets are expanded at notification time by ReviewScanner, so changing a role's membership in WP (or via a SAML/OIDC sync) is reflected on the very next cron run. Roles that no longer exist simply expand to zero users — no error, no notifications.

Legacy data shapes (plain integer arrays in the old owners field, plain string arrays in recipients) are still accepted by Rule::fromArray() and merged into recipients on load.

Inheritance model (tri-state)

A page's effective value for each field (interval_days, recipients, notify_before) resolves as follows:

  1. If the page has a local rule for that field → use it.
  2. Otherwise walk ancestors top-down looking for the nearest ancestor with a subtree rule for that field → use it.
  3. Otherwise fall back to global settings.

Resolution is lazy: there is no materialized table of effective settings. InheritanceResolver::resolveForPage() does the ancestor walk on demand (cached per request via WpPageHierarchy). InheritanceResolver::walkTree() is the bulk DFS used by cron.

Who sees review status in wp-admin

The Pages list badges ("Review overdue" / "Review due soon"), the dashboard widget, and the REST /dashboard endpoint all use the same visibility rules via RecipientVisibility:

Viewer Sees status for…
Assigned recipient (WP user or role member) Pages where they appear in the effective recipients list (including nested pages via inheritance)
Site overview user (default: overview_capability, usually manage_options) All pages that need review — oversight only, not personal responsibility
Standalone email targets Never — they receive email digests but have no WP account

Email-only recipient pages show no badge to any WP user unless a site overview user is viewing.

Override via filters:

REST API

Namespace: scheduled-page-reviews/v1. All endpoints require is_user_logged_in() minimum.

Method Path Permission Purpose
GET/POST /settings Settings admin Read or write GlobalSettings
GET /dashboard?bucket=... Logged in (filtered) Pages needing review for the current user
GET /tree?parent=<id> Settings admin Shallow tree node listing (for the React tree)
GET /pages/<id>/rule Recipient, overview, or settings admin Read rule + effective settings + review status
PUT /pages/<id>/rule Settings admin Write per-page rule
POST /pages/<id>/mark-reviewed Recipient, overview, or settings admin Stamp last_reviewed meta
POST /cron/run-now Settings admin Run a full synchronous scan and send digest emails
GET /cron/schedule-info Settings admin Read automatic scan schedule and next WP-Cron run
GET /roles Settings admin Selectable WP roles for the group picker
GET /users?search=&role=&per_page=&include= Settings admin Async user search for the picker + role-member preview

The /pages/<id>/rule GET response also includes last_reviewed_at, last_reviewed_by, next_review_at, and bucket so the editor sidebar renders in a single request.

Public extension API

All actions and filters are namespaced under scheduled_page_reviews/....

Actions

Action Args Fired by When
scheduled_page_reviews/settings/updated GlobalSettings $settings SettingsRepository After a successful option save
scheduled_page_reviews/rule/save_completed int $pageId RuleRepository After a per-page rule is persisted
scheduled_page_reviews/page/marked_reviewed int $pageId, int $userId, string $nowIso RowActions, MarkReviewedController After last-reviewed meta is written
scheduled_page_reviews/cron/before_run array $stateArray Scheduler Before each batch tick begins
scheduled_page_reviews/cron/run_completed array $stateArray, array<string,QueuedItem[]> $grouped Scheduler When a full run finishes — drives notifications
scheduled_page_reviews/cron/run_now_requested int $userId, int $timestamp CronController When an admin clicks "Run now"
scheduled_page_reviews/notification/sent string $email, array $pages NotificationDispatcher After a successful wp_mail

Filters

Filter Args Default What you control
scheduled_page_reviews/cron/batch_size int $batchSize cron_batch_size opt Pages processed per cron tick
scheduled_page_reviews/cron/should_process_page bool $should, int $pageId true Skip selected pages from the scanner
scheduled_page_reviews/can_view_site_overview bool $can, int $userId user_can($userId, overview_capability) Site-wide review overview (Pages list + dashboard)
scheduled_page_reviews/can_manage_settings bool $can, int $userId user_can($userId, admin_capability) Settings SPA menu, admin REST, and links to settings
scheduled_page_reviews/post_states/show bool $show, int $pageId, EffectiveSettings $effective, int $userId computed Per-page Pages list badge visibility
scheduled_page_reviews/owner/should_notify bool $should, int $userId true Per-user opt-out from WP-user notifications
scheduled_page_reviews/notification/pages array $pages, string $email unchanged Add/remove pages from a recipient's digest
scheduled_page_reviews/email/subject string $subject, string $email, array $pages computed Override digest subject
scheduled_page_reviews/email/body_html string $html, string $email, array $pages rendered template Override or wrap HTML body
scheduled_page_reviews/email/body_text string $text, string $email, array $pages rendered template Override or wrap plain-text body
scheduled_page_reviews/email/headers array $headers, string $email, array $pages Content-Type: text/html Add CC/BCC/From/Reply-To etc.
scheduled_page_reviews/rest/dashboard_response array $items, string $bucketFilter unchanged Filter the dashboard REST payload
scheduled_page_reviews/rest/tree_response array $nodes, int $parentId unchanged Filter the tree REST payload
scheduled_page_reviews/selectable_roles list<string> $slugs, array $rolesMeta all registered roles Prune the list of roles offered by the picker (e.g. hide WP defaults, only surface custom/SAML-imported ones)

Example: redirect owner reminders to a Slack webhook instead of email

Example: hide WP default roles from the picker, expose only SAML-imported ones

Example: stop the scanner from touching auto-draft pages

Reminders (email throttling)

Two global settings under General settings → Reminders control repeat digests:

Setting Behaviour
Send reminders after due date Off: each page is notified at most once while it stays due/overdue. Marking it reviewed clears notification state so the next review cycle can email again. On: the same page may be included again after the cadence interval if it is still due or overdue.
Reminder cadence (days) When repeat reminders are on, minimum gap before the same page can be queued again. Ignored when repeat reminders are off (the one-shot rule applies instead).

Digest grouping is per recipient per cron run — all eligible pages for that person appear in one email, regardless of review date.

Current cadence model (per page)

_scheduled_page_reviews_last_notified_at is stored on each page. Cadence throttles re-notifying that page, not how often a person receives mail overall.

Implication: if you own many pages that become due on different days, you may receive more than one email per cadence period (e.g. one digest when page A is due, another when page B becomes due a day later). Pages are not lost — they wait for the next eligible cron run.

Possible future change (per recipient) — not implemented

A per-recipient cadence would cap digest mail to at most one email per address every N days and batch all actionable pages into that single mail. That avoids staggered daily digests when someone owns many pages. Tracked as a future improvement; the plugin still uses per-page cadence today.

Scanning & WP-Cron

Three ways to start a scan:

Trigger Mode Behaviour
Send reminders (admin SPA header) Synchronous Processes all batches in one request, sends emails, returns stats
Schedule tab → WP Cron Background Registers scheduled_page_reviews_daily at the configured time; when that event runs it schedules batched scheduled_page_reviews_tick events
WP-CLI Sync or background See below

WP-CLI

Server crontab example (sync, daily at 22:00):

If using --background, also run due WP events regularly:

Background tick pipeline

When a scan runs in background mode (scheduled_page_reviews_daily, --background, or legacy tick resume):

  1. Acquires a transient lock (6 hours) to prevent overlap.
  2. Processes up to cron_batch_size pages per tick (filterable).
  3. Persists RunState (cursor, totals) in a transient.
  4. If more pages remain, reschedules scheduled_page_reviews_tick (+60 seconds).
  5. When complete, fires scheduled_page_reviews/cron/run_completed which the dispatcher consumes.

Important: WP Cron settings in the Schedule tab register the daily event — they do not execute it. Something must run due scheduled events (page loads with WP-Cron enabled, or wp cron event run --due-now from server crontab).

On deactivation the daily event, any pending tick events, and run-state transients are cleared.

Permission layers

The plugin separates three independent concerns. They must not be conflated — a user can hold one, two, or all three.

Layer Who What they can do Configured via
Plugin configuration Users passing scheduled_page_reviews/can_manage_settings (default: user_can(admin_capability)) Open the settings SPA, change global defaults, browse the page tree, run cron manually admin_capability + scheduled_page_reviews/can_manage_settings filter
Site-wide overview Users passing scheduled_page_reviews/can_view_site_overview (default: user_can(overview_capability)) See review badges and dashboard entries for all actionable pages, and mark any page reviewed overview_capability + scheduled_page_reviews/can_view_site_overview filter
Content owner Users or roles listed in a page's effective recipients See review status and mark pages reviewed for pages they are assigned to (including nested pages via inheritance) Per-page rules in the admin SPA

Editor workflow (content owners only): dashboard widget, Pages list badges, Gutenberg sidebar, row actions, and email digests. None of these require the settings SPA. Links to the settings page are shown only to users who pass scheduled_page_reviews/can_manage_settings.

WordPress page editing (edit_post) is separate from ownership actions. Editors who are not configured recipients can still edit page content in WordPress, but they do not see ownership UI or mark pages reviewed.

Per-page ownership actions (view status, mark reviewed) are gated by PageAuthorization: recipient assignment, site overview, or settings admin. Rule writes (PUT /pages/<id>/rule) require settings admin only.

Site-specific tuning (for example, restrict both overview and settings access to the administrator role while other manage_options users remain content owners only) is done with scheduled_page_reviews/can_view_site_overview and scheduled_page_reviews/can_manage_settings in site code — not by hardcoding roles in the plugin.

The legacy capability config key is still read as a fallback when either dedicated key is missing.

Testing

Domain logic is fully unit-tested with in-memory fakes for RuleSource, PageHierarchy, and NotificationQueueInterface, so the inheritance resolver, cron scanner, and email renderer run without WordPress loaded.

License

GPL-3.0-or-later


All versions of scheduled-page-reviews with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package williamundqvist/scheduled-page-reviews contains the following files

Loading the files please wait ...