Skip to content

Ship a default style for the outdated post notice - #3

Merged
schlessera merged 4 commits into
mainfrom
feat/2-notice-default-style
Oct 24, 2026
Merged

schlessera merged 4 commits into
mainfrom
feat/2-notice-default-style

Conversation

@schlessera

@schlessera schlessera commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Refs #2

Depends on mwpd/basic-scaffold#177 landing: src/Infrastructure/, the architecture rules and their tests are that branch's asset capability at c72bf64, renamed to this plugin, so the infrastructure copy stays in sync with the scaffold. If the scaffold PR changes again before it merges, this PR follows.

What changed

The outdated post notice ships a default style. OutdatedPostNotice implements HasAssets and declares assets/css/notice.css at the front-end enqueue point when the queried post is outdated, so the stylesheet is in the head before the notice shows; a fresh post, an archive, a feed or an admin screen loads nothing. The look is the agreed one (soft amber box, dot marker, em sizing, forced-colors fallback), which the project website mirrors. Themes adjust it by overriding .mwpd-content-freshness-notice, or replace it by dequeuing the mwpd-content-freshness-notice handle. README, readme.txt, the docs and the changelog say so; the version is not bumped.

The first commit ports the scaffold's asset capability (HasAssets, Asset\*, InvalidAsset, the ServiceBasedPlugin orchestration, the PHPStan rule changes, the API snapshot and the infrastructure tests), without the scaffold's sample assets. The second adds the notice's style. The third resyncs the port with the reviewed scaffold branch (get_asset_location() and get_debug_mode() template methods instead of injector delegations, the re-entrancy guard, AssetHandle, normalized script registrations, the prefix rule's dynamic receivers) and overrides get_debug_mode() in the composition root so the asset boundary checks the same DebugMode the services are bound to.

Why this shape

The predicate runs in the head, so it asks MainLoop::queried_post() and the FreshnessPolicy rather than is_rendering_queried_post(), which needs the loop. The service does not catch its own failure in get_assets(): the plugin's enqueue listener is the boundary there, as the service's own filter callback is for the_content, so the behaviour is the same (loud with WP_DEBUG, no style without it) and the service does not decide twice. The composition root returns the bound DebugMode from get_debug_mode(), so rebinding it once, through the bindings filter or in the root, covers the notice and the plugin's asset loading alike; the integration tests rely on that to exercise both modes.

Proof

composer test              # OK (781 tests, 3994 assertions)
composer lint              # phpcs, PHPStan, Psalm: no errors; 139 rule tests OK
composer check:autoloader  # Bundled autoloader loaded all 108 source declarations.
composer api:snapshot      # regenerated; only additions

Run in a php:8.3-cli container. The end-to-end tests ran in CI on the previous head and passed; tests/e2e/run.sh now also expects the stylesheet link on the old post, and the existing "no notice" checks cover its absence elsewhere, since the handle contains the class name.

Checklist

Anything left open

A service declares the scripts and styles it needs by implementing
HasAssets; the plugin hooks the enqueue actions once, asks every registered
service at each of them, and loads the declarations through the Assets
boundary. Handles are checked for the plugin's prefix where they are
declared, and a subsystem may name the infrastructure's value objects.

Ported from mwpd/basic-scaffold@6302cb2 with the test and fixture fixes of
4431c78 (mwpd/basic-scaffold#37), renamed to this plugin, without the
scaffold's sample assets.

Refs #2
OutdatedPostNotice declares assets/css/notice.css at the front-end enqueue
point when the queried post is outdated, so the style is in the head before
the notice shows, and a fresh post, an archive or an admin screen loads
nothing. The decision is made from the queried post and the policy, as the
head comes before the loop. Themes adjust the look by overriding the
mwpd-content-freshness-notice class, or replace it by dequeuing the handle.

Refs #2
Follows mwpd/basic-scaffold@c72bf64 (mwpd/basic-scaffold#177): the plugin no
longer delegates AssetLocation and DebugMode in the injector but asks the
template methods get_asset_location() and get_debug_mode(), an enqueue action
fired from inside get_assets() is only remembered, handles are AssetHandle
values that reject what WordPress cannot print, equivalent script
registrations compare equal, and the prefix rule sees dynamic receivers.

The composition root overrides get_debug_mode() to return the DebugMode its
services are bound to, so one rebinding covers the notice and the plugin's
asset boundary alike.

Refs #2
@schlessera
schlessera force-pushed the feat/2-notice-default-style branch from 718f514 to 16421a7 Compare October 24, 2026 00:28
@schlessera
schlessera merged commit a4ee1cb into main Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant