Releases: phpnomad/wordpress-integration
4.3.3
Follow-up to 4.3.2: the derived permission_callback no longer runs middleware for controllers whose HTTP method doesn't match the dispatching request. The Allow-header pass (rest_send_allow_header) checks every method registered on a route; running a sibling verb's middleware against a wrong-shaped request fired validations with null parameters — PHP warnings and unbound-placeholder database errors under WP_DEBUG. Method-mismatched checks now return true without executing the chain; real requests of that verb still run their own middleware. All consumers of 4.3.x should upgrade.
4.3.2
Fixes the derived REST permission_callback fataling requests on repeat invocation.
WordPress calls a route's permission callbacks more than once per request — at dispatch, then again for every method on the matched route while rest_send_allow_header builds the Allow header, all against the same WP_REST_Request. 4.3.1 re-ran the controller middleware chain on each call; non-idempotent middleware (e.g. ConvertCsvMiddleware) threw on the second pass and the resulting TypeError escaped catch (Exception), killing the request after the route callback had already produced a correct response. Symptom: HTTP 200 with an empty body on every middleware-bearing GET endpoint.
- Middleware outcomes memoized per (request, controller class); repeat permission checks return the stored answer without re-running the chain
- Per-controller keying prevents the Allow-header pass over sibling methods from clobbering the matched controller's outcome
catch \Throwableso middleware engine errors become a 500WP_Errorinstead of a fatal
Four new regression tests. All consumers of 4.3.0/4.3.1 should upgrade.
4.3.1
Packaging hygiene: tests, CI, and tool configs are now excluded from dist archives (export-ignore); LICENSE metadata ensured. No code changes.
4.3.0
Security & hardening
- REST permission callbacks derived from controller middleware — routes are no longer registered with
permission_callback => '__return_true'. The permission gate runs the controller's own middleware chain (no contract change): 401/403 rejections surface asWP_Error, validation/existence failures keep the legacy error payload shape, and the chain runs exactly once per request. Controllers without middleware remain public. (#31, PR #38) - Exception messages no longer leak SQL or
$wpdb->last_error— database failure messages are stable; diagnostic detail is recorded server-side viaerror_logat the point of failure. RecordNotFound control-flow exceptions stripped without logging. (#32, PR #37)
Requires PHP 8.0+ (WeakMap).
4.2.0
Security hardening
- AdminScreenResolver: the four raw
$_REQUESTreads now go throughsanitize_key(wp_unslash(...))via a shared helper; non-string values resolve to null. (#34, PR #35) - Table strategies: all table/column identifiers now use
$wpdb->prepare()with the%iidentifier placeholder; INFORMATION_SCHEMA's TABLE_NAME comparison is a proper%svalue placeholder; removed a zero-argumentprepare()call that fired_doing_it_wrongon every column sync. (#33, PR #36)
Requires WordPress 6.2+ (for the %i placeholder).
4.1.0
Wires WordPress to the phpnomad/chrono catalog.
What's new
WordPressClockStrategy now implements the cluster of chrono interfaces that WordPress core functions naturally fulfill:
ClockStrategy—current_datetime()HasTimezone—wp_timezone()HasLocale—determine_locale()CanFormatLocalizedDate—wp_date()CanFormatRelativeTime—human_time_diff()wrapped in__('%s ago')for past instants and__('in %s')for future instants
WordPressInitializer binds the single concrete against all five interfaces via the existing array-binding pattern used by DatabaseDateAdapter.
What's not implemented (deliberately)
Stdlib-backed chrono capabilities (predicates, arithmetic, calendar boundaries, diff, parsing, non-localized format) are left to other integrations or consumer code. WordPress core has no platform-specific implementation for these, so wrapping native PHP behavior here would add no value. Pair with phpnomad/carbon-integration if you want the rest of the catalog covered — its CarbonChronoStrategy consumes the HasTimezone and HasLocale bindings this package provides.
New dependency
phpnomad/chrono ^1.0
Tests
WordPressClockStrategyTest covers interface membership, value passthrough, argument delegation to WordPress core functions, return shape, and directional branching in relative(). Full suite: 59 tests, 98 assertions, all green.
4.0.2
Summary
- use
wpdb->last_errordirectly whenget_results()returnsnull - enrich record-not-found exceptions with the actual query or update identity context
- improve support visibility for hidden WordPress datastore failures
Included
Why
This patch came out of the Siren obligation investigation. The WordPress query layer was discarding the most useful wpdb error text and throwing unhelpful not-found exceptions in the exact places support needed more context.
4.0.1
Allow phpnomad/loader ^2.0 and phpnomad/framework ^3.0 for phpnomad/di v2.0 compatibility.
v4.0.0
Breaking Changes
TranslationStrategyupdated for phpnomad/translate v2.0.0- Old:
translate(string $translate, ?string $language, $context): string - New:
translate(string $text, ?string $context = null): stringandtranslatePlural(string $singular, string $plural, int $count, ?string $context = null): string
- Old:
HasLanguageremoved from constructor — WordPress manages locale via its own globals- Requires
phpnomad/translate ^2.0
Bug Fixes
- Fixed
_x()call — was passing domain as context argument instead of the actual context
3.0.2
What's Changed
- Fix: Correct option parameter parsing in ConsoleStrategy by @alexstandiford in #26
Full Changelog: 3.0.1...3.0.2