NoticeManager
\Benecaster\Notices\NoticeManager
Manages admin notices in the Benecaster plugin. Handles three categories: health notices generated by registered HealthCheck implementations, remote notices ingested from the license server /validate response, and programmatic notices published by internal systems. register() hooks into admin_init (health check sweep, transient-gated once per admin session), benecaster_license_validated (ingest remote notices), and admin_notices (render bar notices). Add-ons that need a persistent admin notice for missing configuration should use SetupNoticeManager instead — it accepts callables via the benecaster_addon_setup_checks filter and tracks dismissal per notice key. The re_dismiss_after field allows a dismissed notice to automatically re-surface after a configurable number of days. Set re_dismiss_after: 7 in publish calls for notices that should periodically re-alert operators (e.g. license expiry warnings, hard-cap guardrail).
Methods
| Method | Visibility | Since | Description |
|---|---|---|---|
publish( array $data ): bool |
Public | — | Creates or updates a notice row. When re_dismiss_after > 0 is supplied and an existing dismissed row is found, calls dismissal_expired() — if the window has elapsed, clears dismissed_at and falls through to the update path so the notice re-surfaces. Returns true on a successful insert or update; false when notice_id or message is empty, or when the notice was dismissed and no re-dismiss window has elapsed. |
run_health_check( HealthCheck $check ): void |
Public | — | Runs a single HealthCheck instance inside a try/catch without touching the admin-session transient gate. Intended for cron-wired checks (attach to benecaster_license_cron_complete). |
prune_expired(): int |
Public | — | Deletes every notice whose expiry has passed and returns the number of rows removed. Nothing in the plugin calls it — read the note below before wiring it to a cron. |
add_health_check( HealthCheck $check ): void |
Public | — | Registers a HealthCheck to be evaluated on the next admin_init sweep. |
dismissal_expired( string $dismissed_at_mysql, int $days ): bool |
Protected | — | Returns true when (now() - dismissed_at) >= days * DAY_IN_SECONDS. Called by publish() when re_dismiss_after > 0. |
now(): int |
Protected | — | Returns current Unix timestamp. Protected so tests can override it to control re-dismiss window logic. |
sanitize_re_dismiss_after( mixed $value ): int |
Protected | — | Coerces $value to a non-negative integer. Values <= 0 are treated as absent (no re-dismiss window). |
Notes
re_dismiss_after field: pass as an integer number of days in the $notice array to publish().
Zero or absent means no re-dismiss window (standard permanent dismissal). Non-zero causes the notice
to re-surface for the operator after the specified number of days have elapsed since dismissal.
**prune_expired() has no production caller, and scheduling one silently shortens every
re-dismiss window.** While a notice is dismissed, publish() short-circuits and therefore
stops refreshing the row's expiry, so that expiry goes stale long before the re-dismiss
window elapses. The prune deletes on expiry alone and does not exclude dismissed rows —
unlike the remote-expiry sweep in ingest_remote(), which deliberately does — so it removes
those rows mid-window. The next publish() then lands as a fresh notice rather than a
suppressed one, and the notice re-appears immediately instead of after N days.
Concretely: ThresholdNoticePublisher publishes the growth warning with a two-day expiry and
a seven-day re-dismiss window, so scheduling the prune would cut a podcaster's dismissal from
a week to two days — with no error, no failing test, and no visible change at the call site.
If it is ever scheduled, exclude dismissed rows from the delete rather than lengthening the
callers' expiry: the expiry is what makes a notice clear itself once its condition resolves,
and stretching it would leave stale warnings on screen.
tip tier: The plugin's internal NoticeManager retains tip as a locally-valid notice type
for setup/milestone tips it generates itself. The license server has no tip admin-notice
tier — remote notices from the server never carry tip.