diff --git a/AGENTS.md b/AGENTS.md index 72c08d5..88b520e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ DWS v2 WordPress framework — monorepo for 7 packages (bootstrap, shared, stora ## Status -`bootstrap`, `shared` (Error / Exception / Result / ValueObject scaffolding + Reflection helpers), `storage` (KeyValueStore + Memory / Options / UserMeta backends), `core`, `utilities` (Hooks + AdminNotices + Conditionals + Caching), and `settings` (descriptors + aggregator / dispatcher + WordPress options & object-field backends) have implementations. `woocommerce` has a settings-backend implementation (`WooCommerceSettingsBackend` + `DescriptorBackedWCSettingsPage` + `WCSettingsBuilder`, Spec C Task 3.2) and a **product-data settings tab** primitive (`ProductData/` — `ProductDataTab` + `ProductDataFieldRenderer` + `ProductDataFieldStore`, 2026-06-15); its remaining WC helpers (version conditionals, `WC_Logger` PSR-3 bridge) await plugin-migration demand. +`bootstrap`, `shared` (Error / Exception / Result / ValueObject scaffolding + Reflection helpers), `storage` (KeyValueStore + Memory / Options / UserMeta backends), `core`, `utilities` (Hooks + AdminNotices + Conditionals + Caching), and `settings` (descriptors + aggregator + WordPress options & object-field backends) have implementations. `woocommerce` has a settings-backend implementation (`WooCommerceSettingsBackend` + `DescriptorBackedWCSettingsPage` + `WCSettingsBuilder`, Spec C Task 3.2) and a **product-data settings tab** primitive (`ProductData/` — `ProductDataTab` + `ProductDataFieldRenderer` + `ProductDataFieldStore`, 2026-06-15); its remaining WC helpers (version conditionals, `WC_Logger` PSR-3 bridge) await plugin-migration demand. ## Monorepo structure @@ -46,7 +46,7 @@ wordpress-framework/ │ │ ├── Lifecycle/ # per-action markers: Hookable/, Initializable/, Renderable/, Outputtable/ │ │ └── Installer/ # install/update/activate/deactivate/uninstall + version I/O (get/set stored, get current) │ ├── utilities/ # ahegyes/wp-framework-utilities (Hooks + AdminNotices + Conditionals + Caching) -│ ├── settings/ # ahegyes/wp-framework-settings (declarative settings: descriptors + aggregator/dispatcher + WP options & object-field backends; depends on storage + shared) +│ ├── settings/ # ahegyes/wp-framework-settings (declarative settings: descriptors + aggregator + WP options & object-field backends; depends on storage + shared) │ └── woocommerce/ # ahegyes/wp-framework-woocommerce (WooCommerceSettingsBackend + page base + WCSettingsBuilder; ProductData/ tab primitive) ├── tests/Fixtures/consumer-smoke/ # plugin-template-shaped scoping smoke fixture ├── composer.json # path repos for all 7 packages + VCS for wordpress-configs + WP Packages registry for wp-plugin/woocommerce @@ -193,6 +193,7 @@ Exception, narrow and verified: patterns whose value depends on abstract-base sc 1. **Sealed-type simulation.** `Result` requires `abstract AbstractResult` + `final Success` + `final Failure` to fake a union type PHP doesn't natively support. Substituting pure interfaces drops `match()` ergonomics and the shared `is_success`/`is_failure` derivation. 2. **Reflection-driven shared behavior.** `AbstractValueObject::equals()` walks public properties via reflection and works for ANY subclass without each subclass reimplementing equality. Pure interface + per-class implementation forces every VO to duplicate equality logic — defeating the point of the base. +3. **Exception-family subtyping.** `InvalidValueObjectException` (`shared/ValueObject/Exceptions/`) is the abstract base each value object's invalidity exception extends (`InvalidVersionException` supplies its `value_object_type`), so the family shares one message format and a single `catch ( InvalidValueObjectException )` point. The abstract is intrinsic: exceptions dispatch by type, so a family of distinct catchable subtypes sharing message-building needs the subtype hierarchy — a lone `final` class collapses the subtypes, and composition yields no catchable type. Descriptors are not value objects, so their invalidity exceptions extend the generic `Abstract{InvalidArgument,Runtime}Exception` bases directly. These exceptions live in `wp-framework-shared` (runtime-WP-aware substrate; the only legitimate home for abstract-base scaffolding). Consumer plugins MAY extend these abstract bases (e.g., `PluginHeader extends AbstractValueObject`); they MUST NOT introduce new abstract base hierarchies of their own without similar intrinsic-requirement justification. @@ -365,3 +366,21 @@ Resolves parity finding A1 (the v1→v2 parity reconciliation — reports archiv **Cross-package change:** `SettingsField` gains an optional `description` (additive; the WP-backed `FieldRenderer` now renders it too, so the WP options page + object meta box benefit). `desc_tip` stays WC-only (defaulted true in the product renderer). `php-stubs/woocommerce-stubs` added to the woocommerce package's php-scoper `scoping-stubs` (the product-data + existing WC settings code reference WC symbols a consumer's scoper must leave external). **deptrac:** unchanged — `WooCommerce: [Core, Shared, Settings]` already covers the reuse of `SettingsField`/`SettingsSection`/`FieldProcessor`/`FieldType`/`OptionsResolver` + the settings exceptions; `Shared` for `InvalidProductDataTabException`'s base. No abstract base (the "intrinsically requires" exception does not fire — a tab registers via filters, with no WC class to subclass) and no new interface (single impl). Gates at landing: Unit 288 · Integration 261 · PHPStan clean · deptrac 0 · Infection 100% covered-code MSI on `woocommerce/src`. Design spec in the project vault (`drafts/2026-06-15-wc-product-settings-tab-mini-spec`). + +### Component grammar — interface placement (2026-06-21) + +One rule replaces three improvised conventions. An interface lives at the ROOT of the concept folder it names; concrete variants live in plural sub-bags beneath it (`Handlers/`, `Stores/`, `Backends/`, `ValueObjects/`, `Exceptions/`). A package whose ENTIRE content is a single concept keeps its contract flat at the package `src/` root — the package boundary IS the concept boundary (e.g. `storage`: `KeyValueStoreInterface` beside its stores). The locked core entrypoint pair (`PluginInterface` / `PluginKernel`) is the one explicit flat exception; do not generalize it. There is NO generic `Contracts/` subfolder — an interface is the concept's root type, not a nested artifact. Placement test for a new interface: does its concept share the package with other concepts? → concept-folder root. Is the package a single concept (or the locked entrypoint)? → package root. Applied: `Hooks/Contracts/HookHandlerInterface` moved to `Hooks/HookHandlerInterface`. (`settings` is multi-concept but currently under-foldered; its concept-folder reorganization is tracked as a separate item.) + +### Component grammar — value object vs descriptor (2026-06-21) + +`ValueObjects/` folders hold immutable carriers of two kinds; the folder name is kept, and the kinds are distinguished by base class + docblock, not by a marker interface. **Value object** — extends `Shared\ValueObject\AbstractValueObject`; use ONLY when reflection-driven structural `equals()` / `jsonSerialize()` is actually consumed and every public property can participate safely in structural equality (`PluginHeader`, `Version`); its docblock opens "Value object …". **Descriptor** — a bare `final readonly` class with no base; the default immutable carrier, and REQUIRED when it holds closures/callables, runtime providers, or WordPress/WooCommerce objects (`SettingsField`, `SettingsPage`, `SettingsSection`, `ObjectMetaBox`, `AdminNotice`, `DependencyRequirement`); its docblock opens "Descriptor for …". A marker `DescriptorInterface` is deferred until real code must typehint a polymorphic descriptor collection — a taxonomy-only marker is ceremony (service interfaces only on plurality). + +**Invalidity exceptions follow the same split.** A value object's invalidity exception extends `Shared\ValueObject\Exceptions\InvalidValueObjectException` (the VO-exception-family base), supplying its `value_object_type` — e.g. `InvalidVersionException` for `Version`. A descriptor's invalidity exception extends the generic `Abstract{InvalidArgument,Runtime}Exception` base directly (`InvalidSettingsFieldException`, …) — it is not a value object. The base is the one sanctioned abstract-exception family (see the abstract-base-classes block). + +### DeprecatedHooksDispatcher: speculative-by-choice (2026-06-22) + +`utilities/Hooks/DeprecatedHooksDispatcher` (fires a current hook plus a deprecated legacy alias in lock-step via WP's `do_action_deprecated()` / `apply_filters_deprecated()`) has zero consumers and no v1 precedent — it does NOT clear the demand-certain build-ahead bar (no archive call sites; the closed ecosystem has no third-party hook consumers a legacy alias would serve). It is KEPT as a deliberate, recorded speculative exception, not an oversight: a v2 plugin that renames a public hook is the obvious consumer, the primitive is self-contained and tested, and recording it keeps the build-ahead boundary principled rather than arbitrary. This is the one consciously-speculative utility in the framework. + +### Error/ErrorInterface: kept distinct, not folded into Result/ (2026-06-22) + +Considered folding `shared/Error/ErrorInterface` into `Result/` (it reads as a single-file folder). KEPT. It is load-bearing beyond `Result`: `utilities/Scheduling/Errors/SchedulingError` implements it, it is the `TError` bound across `AbstractResult` / `Failure`, and it is the deliberate counterpart to `Exception/ExceptionInterface` — the error-vs-exception split (errors are expected-failure-as-data carried by `Failure`; exceptions are unexpected and propagate via throw/catch). Folding it into `Result/` would couple a backend-agnostic error marker to the Result carrier (forcing `SchedulingError` to depend on `Result/`) and collapse that semantic boundary. The folder mirrors `Exception/` and earns its place. diff --git a/composer.lock b/composer.lock index bfce1cc..440ce48 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "45c9da7415957a2cafc149881a7eb147", + "content-hash": "9ebeab9b8d0cd3c3e827a8374a1932c4", "packages": [ { "name": "ahegyes/wp-framework-bootstrap", @@ -83,7 +83,7 @@ "dist": { "type": "path", "url": "packages/core", - "reference": "8d1b39d07cd26bbccbf3ef38f4d0c61791576318" + "reference": "6ada2f7b74e4fe22320638482e438f2936245dfe" }, "require": { "ahegyes/wp-framework-bootstrap": "^2.0@dev", @@ -137,7 +137,7 @@ "homepage": "https://github.com/ahegyes/wordpress-framework/graphs/contributors" } ], - "description": "PSR-11-based plugin kernel and lifecycle framework for WordPress — interface-driven components, three-pass boot dispatch.", + "description": "PSR-11-based plugin kernel and lifecycle framework for WordPress — interface-driven components, two-pass boot dispatch.", "homepage": "https://github.com/ahegyes/wordpress-framework", "keywords": [ "framework", @@ -161,7 +161,7 @@ "dist": { "type": "path", "url": "packages/settings", - "reference": "790c8cc1bb38065f29aaba2a4320b4326a28d522" + "reference": "e33f74f739baf1f52e8de46c6228c338e877b150" }, "require": { "ahegyes/wp-framework-shared": "^2.0@dev", @@ -169,17 +169,13 @@ "php": ">=8.5", "psr/log": "^3" }, - "suggest": { - "wp-plugin/woocommerce": "Required at runtime by WordPressObjectFieldStore, which stores fields as WooCommerce order meta." - }, "type": "library", "extra": { "branch-alias": { "dev-trunk": "2.0.x-dev" }, "scoping-stubs": [ - "php-stubs/wordpress-stubs", - "php-stubs/woocommerce-stubs" + "php-stubs/wordpress-stubs" ], "changelogger": { "versioning": "semver", @@ -387,7 +383,7 @@ "dist": { "type": "path", "url": "packages/utilities", - "reference": "274495096e66b5e9b1d0a7020c75f1318638eb10" + "reference": "02095b3ed758e1bd20507324f619f948ed18c1d3" }, "require": { "ahegyes/wp-framework-core": "^2.0@dev", @@ -401,7 +397,8 @@ "dev-trunk": "2.0.x-dev" }, "scoping-stubs": [ - "php-stubs/wordpress-stubs" + "php-stubs/wordpress-stubs", + "php-stubs/woocommerce-stubs:woocommerce-packages-stubs.php" ], "changelogger": { "versioning": "semver", @@ -652,12 +649,12 @@ "source": { "type": "git", "url": "https://github.com/ahegyes/wordpress-configs.git", - "reference": "9764855f54d8c75941667f40326227a8434febbd" + "reference": "501f26d1d8398deea4fe6829e7871432a4f46a6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ahegyes/wordpress-configs/zipball/9764855f54d8c75941667f40326227a8434febbd", - "reference": "9764855f54d8c75941667f40326227a8434febbd", + "url": "https://api.github.com/repos/ahegyes/wordpress-configs/zipball/501f26d1d8398deea4fe6829e7871432a4f46a6b", + "reference": "501f26d1d8398deea4fe6829e7871432a4f46a6b", "shasum": "" }, "require": { @@ -761,7 +758,7 @@ "source": "https://github.com/ahegyes/wordpress-configs/tree/trunk", "issues": "https://github.com/ahegyes/wordpress-configs/issues" }, - "time": "2026-06-21T09:37:46+00:00" + "time": "2026-06-27T09:52:42+00:00" }, { "name": "automattic/jetpack-changelogger", @@ -2501,16 +2498,16 @@ }, { "name": "php-stubs/woocommerce-stubs", - "version": "v10.8.0", + "version": "v10.9.1", "source": { "type": "git", "url": "https://github.com/php-stubs/woocommerce-stubs.git", - "reference": "9d59e65dcabc18153c243cb9acd85fc88ef40589" + "reference": "e6d583b9fa05b3f5ff67f86c939b45a0c35b8444" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/9d59e65dcabc18153c243cb9acd85fc88ef40589", - "reference": "9d59e65dcabc18153c243cb9acd85fc88ef40589", + "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/e6d583b9fa05b3f5ff67f86c939b45a0c35b8444", + "reference": "e6d583b9fa05b3f5ff67f86c939b45a0c35b8444", "shasum": "" }, "require": { @@ -2539,9 +2536,9 @@ ], "support": { "issues": "https://github.com/php-stubs/woocommerce-stubs/issues", - "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v10.8.0" + "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v10.9.1" }, - "time": "2026-05-27T11:46:50+00:00" + "time": "2026-06-25T10:47:57+00:00" }, { "name": "php-stubs/wordpress-stubs", @@ -4000,12 +3997,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "bfdbd26a02c71b3b00586f056c8cf5efea22a27a" + "reference": "36ba91e82e1b493faef2c13277d6bd2669ea9f31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/bfdbd26a02c71b3b00586f056c8cf5efea22a27a", - "reference": "bfdbd26a02c71b3b00586f056c8cf5efea22a27a", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/36ba91e82e1b493faef2c13277d6bd2669ea9f31", + "reference": "36ba91e82e1b493faef2c13277d6bd2669ea9f31", "shasum": "" }, "conflict": { @@ -4022,6 +4019,7 @@ "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", "aimeos/aimeos-laravel": "==2021.10", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", + "aimeos/pagible": "<0.10.4", "airesvsg/acf-to-rest-api": "<=3.1", "akaunting/akaunting": "<2.1.13", "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", @@ -4107,7 +4105,7 @@ "cachethq/cachet": "<2.5.1", "cadmium-org/cadmium-cms": "<=0.4.9", "cakephp/authentication": "<3.3.6|>=4,<4.1.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", + "cakephp/cakephp": "<4.5.11|>=4.6,<4.6.4|>=5,<5.1.7|>=5.2,<5.2.13|>=5.3,<5.3.6", "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", @@ -4139,7 +4137,7 @@ "commerceteam/commerce": ">=0.9.6,<0.9.9", "components/jquery": ">=1.0.3,<3.5", "composer/composer": "<2.2.28|>=2.3,<2.9.8", - "concrete5/concrete5": "<9.4.8", + "concrete5/concrete5": "<9.5.1", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", @@ -4284,10 +4282,10 @@ "feehi/feehicms": "<=2.1.1", "fenom/fenom": "<=2.12.1", "filament/actions": ">=3.2,<3.2.123|>=4,<=4.11.3|>=5,<=5.6.3", - "filament/filament": ">=4,<4.3.1", + "filament/filament": ">=3,<=3.3.51|>=4,<4.11.5|>=5,<5.6.5", "filament/forms": ">=3,<=3.3.52", - "filament/infolists": ">=3,<3.2.115", - "filament/tables": ">=3,<=3.3.50|>=4,<4.8.5|>=5,<5.3.5", + "filament/infolists": ">=3,<3.2.115|>=4,<=4.11.4|>=5,<=5.6.4", + "filament/tables": ">=3,<=3.3.50|>=4,<=4.11.4|>=5,<=5.6.4", "filegator/filegator": "<7.8", "filp/whoops": "<2.1.13", "fineuploader/php-traditional-server": "<=1.2.2", @@ -4616,6 +4614,7 @@ "paragonie/random_compat": "<2", "paragonie/sodium_compat": "<1.24|>=2,<2.5", "passbolt/passbolt_api": "<4.6.2", + "paymenter/paymenter": "<1.5", "paypal/adaptivepayments-sdk-php": "<=3.9.2", "paypal/invoice-sdk-php": "<=3.9", "paypal/merchant-sdk-php": "<3.12", @@ -4633,13 +4632,15 @@ "phenx/php-svg-lib": "<0.5.2", "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", "php-mod/curl": "<2.3.2", + "php-standard-library/h2": ">=6.1,<6.1.2|>=6.2,<6.2.1", + "php-standard-library/php-standard-library": ">=6.1,<6.1.2|>=6.2,<6.2.1", "phpbb/phpbb": "<3.3.16|==4.0.0.0-alpha1", "phpems/phpems": ">=6,<=6.1.3", "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<5.2.2", - "phpmyfaq/phpmyfaq": "<4.1.3", + "phpmyfaq/phpmyfaq": "<4.1.4", "phpoffice/common": "<0.2.9", "phpoffice/math": "<=0.2", "phpoffice/phpexcel": "<=1.8.2", @@ -4669,6 +4670,7 @@ "pocketmine/bedrock-protocol": "<8.0.2", "pocketmine/pocketmine-mp": "<5.42.1", "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", + "pontedilana/php-weasyprint": "<=2.5.1", "poweradmin/poweradmin": "<4.2.4|>=4.3,<4.3.3", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", @@ -4747,10 +4749,10 @@ "silverstripe-australia/advancedreports": ">=1,<=2", "silverstripe/admin": "<1.13.19|>=2,<2.1.8", "silverstripe/assets": "<2.4.5|>=3,<3.1.3", - "silverstripe/cms": "<4.11.3", + "silverstripe/cms": "<6.2.1", "silverstripe/comments": ">=1.3,<3.1.1", "silverstripe/forum": "<0.6.2|>=0.7,<0.7.4", - "silverstripe/framework": "<5.3.23", + "silverstripe/framework": "<6.2.2", "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/recipe-cms": ">=4.5,<4.5.3", @@ -4760,7 +4762,8 @@ "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", "silverstripe/subsites": ">=2,<2.6.1", "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", - "silverstripe/userforms": "<3|>=5,<5.4.2", + "silverstripe/userforms": "<6.4.9|>=7,<7.0.7|>=7.1,<7.1.1", + "silverstripe/versioned": "<3.2.1", "silverstripe/versioned-admin": ">=1,<1.11.1", "simogeo/filemanager": "<=2.5", "simple-updates/phpwhois": "<=1", @@ -4779,12 +4782,13 @@ "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", "sjbr/static-info-tables": "<2.3.1", "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", - "slim/slim": "<2.6", + "slim/slim": "<2.6|>=4.4,<=4.15.1", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<8.4.1", + "snipe/snipe-it": "<=8.6.1", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", + "solidinvoice/solidinvoice": "<=2.3.15", "solspace/craft-freeform": "<4.1.29|>=5,<=5.14.6", "soosyze/soosyze": "<=2", "spatie/browsershot": "<5.0.5", @@ -4802,7 +4806,7 @@ "starcitizentools/short-description": ">=4,<4.0.1", "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", "starcitizenwiki/embedvideo": "<=4", - "statamic/cms": "<5.73.22|>=6,<6.18.1", + "statamic/cms": "<5.74|>=6,<6.20.3", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.67", "studiomitte/friendlycaptcha": "<0.1.4", @@ -4822,6 +4826,7 @@ "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", "sylius/sylius": "<1.9.12|>=1.10,<1.10.16|>=1.11,<1.11.17|>=1.12,<=1.12.22|>=1.13,<=1.13.14|>=1.14,<=1.14.17|>=2,<=2.0.15|>=2.1,<=2.1.11|>=2.2,<=2.2.2", + "symbiote/silverstripe-advancedworkflow": "<6.4.5|>=7,<7.1.3|>=7.2,<7.2.1", "symbiote/silverstripe-multivaluefield": ">=3,<3.1", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", "symbiote/silverstripe-seed": "<6.0.3", @@ -4889,7 +4894,7 @@ "thelia/thelia": ">=2.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<4.1.3", + "thorsten/phpmyfaq": "<4.1.4", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "tinymce/tinymce": "<7.9.3|>=8,<8.5.1", @@ -4969,7 +4974,7 @@ "wapplersystems/a21glossary": "<=0.4.10", "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9|>=5.2,<5.2.4|>=5.3,<5.3.1", "web-auth/webauthn-lib": ">=4.5,<4.9|>=5.2,<5.2.4", - "web-auth/webauthn-symfony-bundle": ">=5.2,<5.2.4", + "web-auth/webauthn-symfony-bundle": "<5.3.4", "web-feet/coastercms": "==5.5", "web-token/jwt-experimental": "<=4.1.6", "web-token/jwt-framework": "<=4.2.99", @@ -5099,7 +5104,7 @@ "type": "tidelift" } ], - "time": "2026-06-19T21:28:22+00:00" + "time": "2026-06-26T23:29:05+00:00" }, { "name": "sanmai/di-container", @@ -6598,16 +6603,16 @@ }, { "name": "symfony/config", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "429783a0c649696f2058ea5ab5315f082dba6de9" + "reference": "c18ae45733f9a5006ba81a13047d08a93e0dea1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/429783a0c649696f2058ea5ab5315f082dba6de9", - "reference": "429783a0c649696f2058ea5ab5315f082dba6de9", + "url": "https://api.github.com/repos/symfony/config/zipball/c18ae45733f9a5006ba81a13047d08a93e0dea1c", + "reference": "c18ae45733f9a5006ba81a13047d08a93e0dea1c", "shasum": "" }, "require": { @@ -6652,7 +6657,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v8.1.0" + "source": "https://github.com/symfony/config/tree/v8.1.1" }, "funding": [ { @@ -6672,20 +6677,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-09T10:54:51+00:00" }, { "name": "symfony/console", - "version": "v7.4.13", + "version": "v7.4.14", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" + "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", - "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", + "url": "https://api.github.com/repos/symfony/console/zipball/92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", + "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87", "shasum": "" }, "require": { @@ -6750,7 +6755,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.13" + "source": "https://github.com/symfony/console/tree/v7.4.14" }, "funding": [ { @@ -6770,20 +6775,20 @@ "type": "tidelift" } ], - "time": "2026-05-24T08:56:14+00:00" + "time": "2026-06-16T11:50:14+00:00" }, { "name": "symfony/dependency-injection", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b6ba1f45127106885de4b77558c5ecca8feb1e1b" + "reference": "99ced9d6305c43b25a7d48fe6a7d169df275a597" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b6ba1f45127106885de4b77558c5ecca8feb1e1b", - "reference": "b6ba1f45127106885de4b77558c5ecca8feb1e1b", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/99ced9d6305c43b25a7d48fe6a7d169df275a597", + "reference": "99ced9d6305c43b25a7d48fe6a7d169df275a597", "shasum": "" }, "require": { @@ -6831,7 +6836,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v8.1.0" + "source": "https://github.com/symfony/dependency-injection/tree/v8.1.1" }, "funding": [ { @@ -6851,7 +6856,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-27T06:18:14+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6926,16 +6931,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102" + "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f249ae3f680958b6f1f9dd76e5747cf0695b4102", - "reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abd6c11dc468725d1627302ad10f6cd486e9e3d0", + "reference": "abd6c11dc468725d1627302ad10f6cd486e9e3d0", "shasum": "" }, "require": { @@ -6988,7 +6993,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.1" }, "funding": [ { @@ -7008,7 +7013,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-09T12:28:30+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -7163,16 +7168,16 @@ }, { "name": "symfony/finder", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "58d2e767a66052c1487356f953445634a8194c64" + "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/58d2e767a66052c1487356f953445634a8194c64", - "reference": "58d2e767a66052c1487356f953445634a8194c64", + "url": "https://api.github.com/repos/symfony/finder/zipball/e2989e762c70f9490fa3a00a0ac0fae5aa97a531", + "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531", "shasum": "" }, "require": { @@ -7207,7 +7212,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.1.0" + "source": "https://github.com/symfony/finder/tree/v8.1.1" }, "funding": [ { @@ -7227,7 +7232,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-27T09:05:56+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7975,22 +7980,22 @@ }, { "name": "symfony/var-exporter", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "2dd18582c5f6c024db9fc0ff9c76d873af726f34" + "reference": "75b74315b4e4be40e5534cf9c5cc30dd0907ed71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2dd18582c5f6c024db9fc0ff9c76d873af726f34", - "reference": "2dd18582c5f6c024db9fc0ff9c76d873af726f34", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/75b74315b4e4be40e5534cf9c5cc30dd0907ed71", + "reference": "75b74315b4e4be40e5534cf9c5cc30dd0907ed71", "shasum": "" }, "require": { "php": ">=8.4.1", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-deepclone": "^1.37" + "symfony/polyfill-deepclone": "^1.40" }, "require-dev": { "symfony/property-access": "^7.4|^8.0", @@ -8034,7 +8039,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v8.1.0" + "source": "https://github.com/symfony/var-exporter/tree/v8.1.1" }, "funding": [ { @@ -8054,20 +8059,20 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-27T09:05:56+00:00" }, { "name": "symfony/yaml", - "version": "v8.1.0", + "version": "v8.1.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "efb42bd2c6f4f3ccfd4683583449938b5fc146b0" + "reference": "8e4cdd4311683516be06944f4b85244063cdb886" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/efb42bd2c6f4f3ccfd4683583449938b5fc146b0", - "reference": "efb42bd2c6f4f3ccfd4683583449938b5fc146b0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/8e4cdd4311683516be06944f4b85244063cdb886", + "reference": "8e4cdd4311683516be06944f4b85244063cdb886", "shasum": "" }, "require": { @@ -8110,7 +8115,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v8.1.0" + "source": "https://github.com/symfony/yaml/tree/v8.1.1" }, "funding": [ { @@ -8130,7 +8135,7 @@ "type": "tidelift" } ], - "time": "2026-05-29T05:06:50+00:00" + "time": "2026-06-09T11:06:24+00:00" }, { "name": "szepeviktor/phpstan-wordpress", @@ -8605,15 +8610,15 @@ }, { "name": "wp-plugin/woocommerce", - "version": "10.8.1", + "version": "10.9.1", "source": { "type": "svn", "url": "https://plugins.svn.wordpress.org/woocommerce/", - "reference": "tags/10.8.1" + "reference": "tags/10.9.1" }, "dist": { "type": "zip", - "url": "https://downloads.wordpress.org/plugin/woocommerce.10.8.1.zip" + "url": "https://downloads.wordpress.org/plugin/woocommerce.10.9.1.zip" }, "require": { "composer/installers": "~1.0|~2.0" @@ -8632,7 +8637,7 @@ "issues": "https://wordpress.org/support/plugin/woocommerce", "source": "https://plugins.svn.wordpress.org/woocommerce" }, - "time": "2026-06-15T14:01:01+00:00" + "time": "2026-06-24T19:16:29+00:00" } ], "aliases": [], @@ -8645,8 +8650,7 @@ "ahegyes/wp-framework-shared": 20, "ahegyes/wp-framework-storage": 20, "ahegyes/wp-framework-utilities": 20, - "ahegyes/wp-framework-woocommerce": 20, - "johnpbloch/wordpress-core": 20 + "ahegyes/wp-framework-woocommerce": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/package-lock.json b/package-lock.json index 97c3e11..0f789d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "name": "@ahegyes/wordpress-framework", "license": "GPL-2.0-or-later", "devDependencies": { - "@wordpress/env": "^11.8.1" + "@wordpress/env": "^11.9.0" }, "engines": { "node": ">=26", @@ -1058,13 +1058,13 @@ "license": "MIT" }, "node_modules/@php-wasm/cli-util": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/cli-util/-/cli-util-3.1.40.tgz", - "integrity": "sha512-G2XALTuzUfCHbBwmeQz3vTLIYQ+Vlemr+UzONQlo2Om2cvPbtlfkaGsm4URgj6WSybFTsshZ1ZxppbMB7CBjBA==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/cli-util/-/cli-util-3.1.42.tgz", + "integrity": "sha512-zDeNLoLqTRhRnrYbg5uXjcwYyk23XGi3PMMbmQ2NYRmmGMBW1xsUhZ9Ep/iLqCjLpdv+7XUzE9qykjUcPKUhHg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/util": "3.1.40", + "@php-wasm/util": "3.1.42", "fast-xml-parser": "^5.8.0", "jsonc-parser": "3.3.1" }, @@ -1074,9 +1074,9 @@ } }, "node_modules/@php-wasm/logger": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-3.1.40.tgz", - "integrity": "sha512-6YXbBgNRpLt7wmyx5nwWixQjjzvsWNGAl7CCLc2ltiju88ORZGV68sPcaruI6SSQz0RE7A/KrL6QrIUwTLneVA==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-3.1.42.tgz", + "integrity": "sha512-TwgNpmd01ftr7Jf0gsEfjgzSU7Jb0nipFizuk5AeUpWLRNnhf63wnpglKbvls27PLBjU1ONBBK4e/EppWaEkYg==", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -1085,24 +1085,24 @@ } }, "node_modules/@php-wasm/node": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-3.1.40.tgz", - "integrity": "sha512-LNm3e2OqAfJoQ6V4FIXZviZ0VdXEqX8tXjiJNe1QtJLy7dDr4mLMvN/Hv+DzYh8ZAHhAxCYS0hzbTM/J/ynmJA==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-3.1.42.tgz", + "integrity": "sha512-689JSPuW7WFuYW8BDscJya6v5aK4ZGHn30N4LyN2Q0cQl+z69ebMEU8IjvrJF0EGWJ8pSWU98+E78aAAi20Iww==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/cli-util": "3.1.40", - "@php-wasm/logger": "3.1.40", - "@php-wasm/node-5-2": "3.1.40", - "@php-wasm/node-7-4": "3.1.40", - "@php-wasm/node-8-0": "3.1.40", - "@php-wasm/node-8-1": "3.1.40", - "@php-wasm/node-8-2": "3.1.40", - "@php-wasm/node-8-3": "3.1.40", - "@php-wasm/node-8-4": "3.1.40", - "@php-wasm/node-8-5": "3.1.40", - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40", + "@php-wasm/cli-util": "3.1.42", + "@php-wasm/logger": "3.1.42", + "@php-wasm/node-5-2": "3.1.42", + "@php-wasm/node-7-4": "3.1.42", + "@php-wasm/node-8-0": "3.1.42", + "@php-wasm/node-8-1": "3.1.42", + "@php-wasm/node-8-2": "3.1.42", + "@php-wasm/node-8-3": "3.1.42", + "@php-wasm/node-8-4": "3.1.42", + "@php-wasm/node-8-5": "3.1.42", + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42", "fs-ext-extra-prebuilt": "2.2.7", "wasm-feature-detect": "1.8.0", "ws": "8.21.0" @@ -1113,13 +1113,13 @@ } }, "node_modules/@php-wasm/node-5-2": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-5-2/-/node-5-2-3.1.40.tgz", - "integrity": "sha512-/+2UBudip0D/eCyfe/QJoNg/+NXE8YyAjunvQ4LzzrnvttBoH3O7lX8sswimtsHQ8LX+k/3gq8p2b3hN7cU44Q==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-5-2/-/node-5-2-3.1.42.tgz", + "integrity": "sha512-v0XbYbjYV+DQvNt4IZuuqMzSZyUSP/KqogwlD7hxt628PUF/pcCvQovvSrWQbO1iQ/y6y/Ibt/gXZCEHXIRxuA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1128,13 +1128,13 @@ } }, "node_modules/@php-wasm/node-7-4": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-7-4/-/node-7-4-3.1.40.tgz", - "integrity": "sha512-xcYpz9mlicYsct/P7RpGL+SFlqQyg8fZGvfLJ4yqQt2+41Duhui3EaBZz3vyCIZl1M1oL9H1IJcMu4HDk1xmSQ==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-7-4/-/node-7-4-3.1.42.tgz", + "integrity": "sha512-IsIaHZSjC5mAaOdjTU/LPJg0ew2Lhtnjdc1pac+S1vs50VBvZ6PidTflhdkxBqe+OnpyZNUnRTdKFFdB1+UTWw==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1143,13 +1143,13 @@ } }, "node_modules/@php-wasm/node-8-0": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-0/-/node-8-0-3.1.40.tgz", - "integrity": "sha512-DrbOj6vNKTouWpkjSP7tJ1P8uWYpAz7DfGs8tuv4T5S+0W3wAcJBt9WW3SKyRdMVMSlBpCYvtR10CPfkTXESLQ==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-0/-/node-8-0-3.1.42.tgz", + "integrity": "sha512-QtG95esIWEIk4JdezdMBsewqQzokXExIXX+HNOFvs98e2qhGCprXQAVi5n5kbIbhh3C+yB7BrwfB2Fjeoan4hA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1158,13 +1158,13 @@ } }, "node_modules/@php-wasm/node-8-1": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-1/-/node-8-1-3.1.40.tgz", - "integrity": "sha512-tbm6EonR/9Ibb3M3yUwFIXDyPVWkhYbmB+GJhgpsSZlZwVxZpvLiLkHWzHrUbTsZUxgMHhzf6qQWYkh48s9dlg==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-1/-/node-8-1-3.1.42.tgz", + "integrity": "sha512-uTG0EFiultyp+FvTdWL4DgmjMtJMtvOZm6xpaNRtsxE6XsBj7d81HZjS7Amp0Jvt3/wOCqB0uW4MDou31KE1QA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1173,13 +1173,13 @@ } }, "node_modules/@php-wasm/node-8-2": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-2/-/node-8-2-3.1.40.tgz", - "integrity": "sha512-D0fdZ7X0C1YI+ancJIpyjmOUiDB7g4s9QYgMu/admF/69lzInlmrctdaAda3hl5izhoDrVEy1Or39AT6brWKNQ==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-2/-/node-8-2-3.1.42.tgz", + "integrity": "sha512-qlHnmqbrgjtSA49Xx1wlVZZOumeKjgJnlvJLHrxcpgbHZRAhmWy1/w9nva4awE94KXrQHlKDrpXteYiNktV3mg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1188,13 +1188,13 @@ } }, "node_modules/@php-wasm/node-8-3": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-3/-/node-8-3-3.1.40.tgz", - "integrity": "sha512-PFfpq10tM3p394TFJuJl9/sx7l3lab8HdgBzptH1ZFTQ8zva3RsQeZMhyZA8DXIQVu23JDWvLGb7KcRol1zIsA==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-3/-/node-8-3-3.1.42.tgz", + "integrity": "sha512-OJA9bt9l9it4KCmBixh0rOZTbU1UQnyxdJFV9zFLx+P1e+kKWX9oTTRu+h3sT2riNMxF+ZWfYiJ/qPl2feevxQ==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1203,13 +1203,13 @@ } }, "node_modules/@php-wasm/node-8-4": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-4/-/node-8-4-3.1.40.tgz", - "integrity": "sha512-dJ5nvqTJ4fYK7b7kRq8o41rkZu2tu2j0oOCrg0TZrBlkTSiy2uH4kDJJbC9gURA0ieEQ3fizRAXN0XhA3te8GQ==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-4/-/node-8-4-3.1.42.tgz", + "integrity": "sha512-EnntRhHArwLFJhlEVPHqB6B/jI9RVLB0zVy6qcHVGBSEL8xO6ZiM59RTJTyKgsnYJqvb4UyzbVzosH/xx1kq/g==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1218,13 +1218,13 @@ } }, "node_modules/@php-wasm/node-8-5": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/node-8-5/-/node-8-5-3.1.40.tgz", - "integrity": "sha512-SfanxbPNi001LMxeD1bPxNhxAsMvScnMjUczfWtoixeProZgY42VzY1JKIqmagNify/IP+M/89Ig+APGBh2d5w==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/node-8-5/-/node-8-5-3.1.42.tgz", + "integrity": "sha512-bSJlm2IF8r7lOoFo1bIxndQeeB1PUwsFck4SUKSTqZe05duWiVv1nC0fsEh+7/JczC4fx108J4D7D4US56XcBQ==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", + "@php-wasm/universal": "3.1.42", "wasm-feature-detect": "1.8.0" }, "engines": { @@ -1233,13 +1233,13 @@ } }, "node_modules/@php-wasm/progress": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-3.1.40.tgz", - "integrity": "sha512-XUCM4v4eKbyOsFUNk02O9Crb/ZKlkLfYi43TAc9ctw1o6pyf7K5eeVxZKXVNqxR1hb0Jo5JpCKENSbP0NRUiIg==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-3.1.42.tgz", + "integrity": "sha512-rYhTRmISxgEhxIvD+Oytr9a38RhsMGIC//i18Q5ht0STCyvGRO2cfylACg0ObV0C9HFwQKU/DFGFUzxCOTvZaA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "3.1.40" + "@php-wasm/logger": "3.1.42" }, "engines": { "node": ">=20.10.0", @@ -1247,9 +1247,9 @@ } }, "node_modules/@php-wasm/scopes": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-3.1.40.tgz", - "integrity": "sha512-qRqh4Khng/iSOzJJl7blNmIoINFkgRyaR24b4SUctFsOUu0emiYbJ2DMEWHcr57KWbyjlSnbpI/c/yZnjkgrMw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-3.1.42.tgz", + "integrity": "sha512-FiPXH+Ra6imzdmCvxLYrCu7Cynt2mYO/74pJ9E9aKt+qJnD89CDw2h6Qb+B5ZN78wr4wSzIiXNW+CBPTXIF8Iw==", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -1258,26 +1258,26 @@ } }, "node_modules/@php-wasm/stream-compression": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-3.1.40.tgz", - "integrity": "sha512-57CVWtoze3WJy4gupoahwFsTcA8Q3sWZY7/SrlTSj0dsqhC1sdOmvVe0pwkaurX1psTZeIynA9Gd/iyobVeayw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-3.1.42.tgz", + "integrity": "sha512-OGcO5vJ/t5wGOBYLMK13plVepAacdDABbDdud9bsNkb9vm24eLoqWu2gowC5IaBxtJkHUsvBUw63BywdKetOIg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/util": "3.1.40" + "@php-wasm/util": "3.1.42" } }, "node_modules/@php-wasm/universal": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-3.1.40.tgz", - "integrity": "sha512-uDbTdhrvFCR1fz3T7dQp5KH8GmBzndf0l6selKEQNrWxM0CSaGYbnpI7Vb/wICZgDR7rz5ghdyUkeERVD6LC1A==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-3.1.42.tgz", + "integrity": "sha512-SuDKfW1S8KDr/S3a3tTokmDfjiTZk7rvKQyo/PH7Zl0UokZ/mxBZR0dvVqPcWzDgNg/ZQ0/Dpj8dZI0sW+6rfg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "3.1.40", - "@php-wasm/progress": "3.1.40", - "@php-wasm/stream-compression": "3.1.40", - "@php-wasm/util": "3.1.40", + "@php-wasm/logger": "3.1.42", + "@php-wasm/progress": "3.1.42", + "@php-wasm/stream-compression": "3.1.42", + "@php-wasm/util": "3.1.42", "ini": "4.1.2" }, "engines": { @@ -1286,9 +1286,9 @@ } }, "node_modules/@php-wasm/util": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-3.1.40.tgz", - "integrity": "sha512-U2xzEEmW7JRaAEuFErF3tt8uW4WJTYWm7vQO2LURLijDoMCUUXIGRz0mNirJRxI8DMB/zCmsWuIMduZ5WYp6kw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-3.1.42.tgz", + "integrity": "sha512-rUkLsyqirsDKPgKzN8BudFaNzDH7SMwZtbhb82yn8jgB/buD4J6r0l8PDLuYNqLGZIFYfrqb7CV8b/VJ8/Zn7A==", "dev": true, "engines": { "node": ">=20.10.0", @@ -1296,14 +1296,14 @@ } }, "node_modules/@php-wasm/web-service-worker": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-3.1.40.tgz", - "integrity": "sha512-JwkTG+2yZ25BKH2nX0J9f2pf4+oyO4vM2Gp3h7qCotWeSngLpWKLmVYt6pfO+EEeEPHxN6G//wjCgCpzGiAZlA==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-3.1.42.tgz", + "integrity": "sha512-F/Gu7fwmq7r2sMtloemnXzQS8KDlwZi0YFoE34SNF97l9Muh5DLGQf+pUfQcSkmd9BTh+3zFNS1Rtl2kNXqGRQ==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/scopes": "3.1.40", - "@php-wasm/universal": "3.1.40" + "@php-wasm/scopes": "3.1.42", + "@php-wasm/universal": "3.1.42" }, "engines": { "node": ">=20.10.0", @@ -1311,14 +1311,14 @@ } }, "node_modules/@php-wasm/xdebug-bridge": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@php-wasm/xdebug-bridge/-/xdebug-bridge-3.1.40.tgz", - "integrity": "sha512-s+TLw2CrovrkWH4ZSkrgQwvBYn4HU+QUlE8sF/grHkWIIN9E0EDFj2gC3DXC8FJRWyC31FQtUPataHK1+6odjg==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@php-wasm/xdebug-bridge/-/xdebug-bridge-3.1.42.tgz", + "integrity": "sha512-zXvtYHLqZ3uSlBKeMzbhIsKfgQyi28Y+oVfjsmEA+mqhIw1QZZDj5FHiFm61G8CYSaKUNPWzDmP+H49iziVlZQ==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "3.1.40", - "@php-wasm/universal": "3.1.40", + "@php-wasm/logger": "3.1.42", + "@php-wasm/universal": "3.1.42", "ws": "8.21.0", "xml2js": "0.6.2", "yargs": "17.7.2" @@ -1489,9 +1489,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", - "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", + "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==", "dev": true, "license": "MIT", "dependencies": { @@ -1509,9 +1509,9 @@ } }, "node_modules/@wordpress/env": { - "version": "11.8.1", - "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-11.8.1.tgz", - "integrity": "sha512-wboYnQNPfMfcgYgiNDbrGGZj8RkdeZtaz2UvmAVUrhOgAvHFpZXsKuXuLdCCSv7JdcHGG5xLWMYhvRLTGOcQ1g==", + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-11.9.0.tgz", + "integrity": "sha512-PtPqrWONclS6dXZLQztZiiFIpqAuoJRBOpPMS85QJiKzkDlvbVmUk3CicmxQbGpktS6mXtVyV5ySPCXqV8OD1g==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -1538,20 +1538,20 @@ } }, "node_modules/@wp-playground/blueprints": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-3.1.40.tgz", - "integrity": "sha512-xFIymqqJc2rF9mutQQyiqsvTM3CU2SjqQHL4Rw1qIa41K4hfO0FXcUkfMQh6FCMwSo2roHiCra+R+Y9trYBNRQ==", - "dev": true, - "dependencies": { - "@php-wasm/logger": "3.1.40", - "@php-wasm/progress": "3.1.40", - "@php-wasm/stream-compression": "3.1.40", - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40", - "@php-wasm/web-service-worker": "3.1.40", - "@wp-playground/common": "3.1.40", - "@wp-playground/storage": "3.1.40", - "@wp-playground/wordpress": "3.1.40", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-3.1.42.tgz", + "integrity": "sha512-kr82GmVljh6Y7y5/dilvI8WtCQDEqZ5B9gwQdBNC/Rb7r4eKvQQ+CTBqWQ716yfknH+coEAZBbHBS/sIkx7DaQ==", + "dev": true, + "dependencies": { + "@php-wasm/logger": "3.1.42", + "@php-wasm/progress": "3.1.42", + "@php-wasm/stream-compression": "3.1.42", + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42", + "@php-wasm/web-service-worker": "3.1.42", + "@wp-playground/common": "3.1.42", + "@wp-playground/storage": "3.1.42", + "@wp-playground/wordpress": "3.1.42", "ajv": "8.18.0" }, "engines": { @@ -1560,24 +1560,24 @@ } }, "node_modules/@wp-playground/cli": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/cli/-/cli-3.1.40.tgz", - "integrity": "sha512-Fn1BfvqORHLAVrtUjgGv11oo9q9OOCWrNXZy1mQq6mpPZ+0K57HnckDZHGFgZfouadheKL6WrNcTJXEJ+Lh3Zg==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/cli/-/cli-3.1.42.tgz", + "integrity": "sha512-dO9xJAANH0sY1fCQx4rlfscl8WGEKqhT6lVQQLizqA/jDxsQNY3LAq34X1ro1P71TU5k/7WSf0d+xIHh4G2sMg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/cli-util": "3.1.40", - "@php-wasm/logger": "3.1.40", - "@php-wasm/node": "3.1.40", - "@php-wasm/progress": "3.1.40", - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40", - "@php-wasm/xdebug-bridge": "3.1.40", - "@wp-playground/blueprints": "3.1.40", - "@wp-playground/common": "3.1.40", - "@wp-playground/storage": "3.1.40", - "@wp-playground/tools": "3.1.40", - "@wp-playground/wordpress": "3.1.40", + "@php-wasm/cli-util": "3.1.42", + "@php-wasm/logger": "3.1.42", + "@php-wasm/node": "3.1.42", + "@php-wasm/progress": "3.1.42", + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42", + "@php-wasm/xdebug-bridge": "3.1.42", + "@wp-playground/blueprints": "3.1.42", + "@wp-playground/common": "3.1.42", + "@wp-playground/storage": "3.1.42", + "@wp-playground/tools": "3.1.42", + "@wp-playground/wordpress": "3.1.42", "express": "4.22.2", "fs-extra": "11.1.1", "tmp-promise": "3.0.3", @@ -1630,14 +1630,14 @@ } }, "node_modules/@wp-playground/common": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-3.1.40.tgz", - "integrity": "sha512-4oQXGmDjNbxuc3FAir2cWQQ4EY/2UJMz3cGrUc+m2h+aQ3HncO7WMh0dKtNir4BgUbCblX7qXUnWMaTYMLR/3A==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-3.1.42.tgz", + "integrity": "sha512-T3HAoVghas11/vBrM0BEUPdwor+5MRRSG9/ZqjzhL7qsORAnU7KgVp+IvYO5kasmXI21l71wZIK9IPPiktEV/g==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40" + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42" }, "engines": { "node": ">=20.10.0", @@ -1645,15 +1645,15 @@ } }, "node_modules/@wp-playground/storage": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-3.1.40.tgz", - "integrity": "sha512-9GAdEMzyKmEs8c7hMFXz2Cg/HwIiw5JKN5nBBO+yFVoEC+kH/g6We73N/mV82/IUcWFVFUDQS5YYl7cN9YHJSw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-3.1.42.tgz", + "integrity": "sha512-M3FxveZ+XlzNxS70khfFzbB9e1M7RioEV82tUBVZUyuCVeEnJMLB/dvpAJVbWqAePO8JPndHIVESvmbPoG0T+g==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/stream-compression": "3.1.40", - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40", + "@php-wasm/stream-compression": "3.1.42", + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42", "@zip.js/zip.js": "2.7.57", "isomorphic-git": "1.37.6", "octokit": "3.1.2", @@ -1661,13 +1661,13 @@ } }, "node_modules/@wp-playground/tools": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/tools/-/tools-3.1.40.tgz", - "integrity": "sha512-Z4yTBCN4zpfUoLhRzP0OTUJBcuuTi9INZT8yg6sauHwehOqCamhGWpK2ZwfbiMJrsD48ZCh+JcYg7eXApI1VYw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/tools/-/tools-3.1.42.tgz", + "integrity": "sha512-BIryjMjXARsF7tfZTuMQWpZuSR7K4LJa9PFk01oIXGc/StgP4TPvVpijN+trKb3abvMZCVFHOOHFW8RMw0pVWA==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@wp-playground/blueprints": "3.1.40" + "@wp-playground/blueprints": "3.1.42" }, "engines": { "node": ">=20.10.0", @@ -1675,16 +1675,16 @@ } }, "node_modules/@wp-playground/wordpress": { - "version": "3.1.40", - "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-3.1.40.tgz", - "integrity": "sha512-PMgWcua0vTx+VScV2sSjzTX1OVZ6xmlUxj1xlXaY7iSuJPfUOA3PMoDqQvsmPxajs6sY+RbuWyvpmoPPkpZruw==", + "version": "3.1.42", + "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-3.1.42.tgz", + "integrity": "sha512-xYoeYmNVDWTA6UUWTTBjpXOxsk1Ijgzpk7nxXlWXquQxg8g0C4n3L2GkqCv/37MkspqutkyMTAdvMFg29ZNskg==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "3.1.40", - "@php-wasm/universal": "3.1.40", - "@php-wasm/util": "3.1.40", - "@wp-playground/common": "3.1.40" + "@php-wasm/logger": "3.1.42", + "@php-wasm/universal": "3.1.42", + "@php-wasm/util": "3.1.42", + "@wp-playground/common": "3.1.42" }, "engines": { "node": ">=20.10.0", @@ -3283,9 +3283,9 @@ } }, "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", + "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", "dev": true, "license": "MIT", "dependencies": { @@ -3704,9 +3704,9 @@ } }, "node_modules/nan": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz", - "integrity": "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", + "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", "dev": true, "license": "MIT" }, @@ -3886,9 +3886,9 @@ } }, "node_modules/path-expression-matcher": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.0.tgz", - "integrity": "sha512-e5y7RCLHKjemsgQ4eqGJtPyr10ILz25HO7flzxhTV8bgvd5yHx98DGtCAtbVW9f2TqnYI/gEVZd+vz7snrdPTw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.1.tgz", + "integrity": "sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ==", "dev": true, "funding": [ { @@ -3998,13 +3998,14 @@ } }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" diff --git a/package.json b/package.json index 6ed042f..2cef2b7 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "npm": ">=11" }, "devDependencies": { - "@wordpress/env": "^11.8.1" + "@wordpress/env": "^11.9.0" }, "scripts": { "setup": "npm run packages-install:all && npm run wp-env:start", diff --git a/packages/bootstrap/functions.php b/packages/bootstrap/functions.php index 33aa87c..d893340 100644 --- a/packages/bootstrap/functions.php +++ b/packages/bootstrap/functions.php @@ -1,7 +1,6 @@ =' ); + if ( \substr_count( $min_wp, '.' ) > 1 && \substr( $min_wp, -2 ) === '.0' ) { + $min_wp = \substr( $min_wp, 0, -2 ); + } + + return \version_compare( $current, $min_wp, '>=' ); } diff --git a/packages/bootstrap/tests/Unit/AggregatorTest.php b/packages/bootstrap/tests/Unit/AggregatorTest.php deleted file mode 100644 index c9bb263..0000000 --- a/packages/bootstrap/tests/Unit/AggregatorTest.php +++ /dev/null @@ -1,15 +0,0 @@ -/functions.php file is added under src/, require_once it here. +/** + * Aggregates this package's nested src//functions.php files. Composer autoloads only this file. + * + * @since 2.0.0 + * @version 2.0.0 + */ diff --git a/packages/core/src/PluginInterface.php b/packages/core/src/PluginInterface.php index e51d41c..72bad82 100644 --- a/packages/core/src/PluginInterface.php +++ b/packages/core/src/PluginInterface.php @@ -28,7 +28,10 @@ public function get_plugin_file(): string; /** * Typed wrapper around the plugin's main-file WP header. The get_plugin_ prefix - * keeps it clear of WordPress's theme-template get_header(). + * keeps it clear of WordPress's theme-template get_header(). A consumer-facing + * accessor for the plugin's own metadata (display name, version, text domain); + * the kernel boot reads the version from the installer, not from here, so this + * stays part of the contract even though the engine does not consult it. * * @since 2.0.0 * @version 2.0.0 diff --git a/packages/core/src/PluginKernel.php b/packages/core/src/PluginKernel.php index 2466726..315af8b 100644 --- a/packages/core/src/PluginKernel.php +++ b/packages/core/src/PluginKernel.php @@ -37,7 +37,7 @@ final class PluginKernel { * * @var bool */ - private bool $booted = false; + protected bool $booted = false; // endregion @@ -53,8 +53,8 @@ final class PluginKernel { * @param LoggerInterface|null $logger Optional logger; names each Feature or component the kernel gates out and reports a failed installer routine. */ public function __construct( - private readonly PluginInterface $plugin, - private readonly ?LoggerInterface $logger = null, + protected readonly PluginInterface $plugin, + protected readonly ?LoggerInterface $logger = null, ) {} // endregion @@ -132,7 +132,7 @@ public function boot(): void { $surviving_features = array(); foreach ( $this->plugin->get_feature_classes() as $feature_class ) { if ( $this->are_conditionals_met( $feature_class, $container ) ) { - /** @var FeatureInterface $feature */ + /** @var FeatureInterface $feature */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- inline @var type assertion, no description applies. $feature = $container->get( $feature_class ); $surviving_features[] = $feature; } @@ -169,7 +169,7 @@ public function boot(): void { * * @return bool True when the boot may proceed; false when the routine failed. */ - private function run_installer(): bool { + protected function run_installer(): bool { $installer = $this->plugin->get_installer(); try { @@ -211,7 +211,7 @@ private function run_installer(): bool { * * @return bool */ - private function are_conditionals_met( string $feature_class, ContainerInterface $container ): bool { + protected function are_conditionals_met( string $feature_class, ContainerInterface $container ): bool { foreach ( $feature_class::get_conditional_classes() as $conditional_class ) { $conditional = $container->get( $conditional_class ); @@ -251,8 +251,8 @@ private function are_conditionals_met( string $feature_class, ContainerInterface * * @throws FeatureException When a component class appears more than once in the graph. */ - private function assert_unique_component_graph( array $features ): void { - /** @var array $seen */ + protected function assert_unique_component_graph( array $features ): void { + /** @var array $seen */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- inline @var type assertion, no description applies. $seen = array(); foreach ( $features as $feature ) { foreach ( $feature->get_component_classes() as $component_class ) { @@ -273,7 +273,7 @@ private function assert_unique_component_graph( array $features ): void { * * @throws FeatureException When the class has already been seen. */ - private function assert_component_not_duplicated( string $component_class, array &$seen ): void { + protected function assert_component_not_duplicated( string $component_class, array &$seen ): void { if ( isset( $seen[ $component_class ] ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- framework-internal exception; never reaches an HTML output context unescaped. throw new FeatureException( 'Component ' . $component_class . ' is registered more than once; a component may belong to a single parent.' ); @@ -300,8 +300,8 @@ private function assert_component_not_duplicated( string $component_class, array * * @return list */ - private function collect_runnable_components( array $features, ContainerInterface $container ): array { - /** @var list $runnable */ + protected function collect_runnable_components( array $features, ContainerInterface $container ): array { + /** @var list $runnable */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- inline @var type assertion, no description applies. $runnable = array(); foreach ( $features as $feature ) { foreach ( $feature->get_component_classes() as $component_class ) { @@ -323,8 +323,8 @@ private function collect_runnable_components( array $features, ContainerInterfac * @param ContainerInterface $container Plugin container. * @param list $runnable Accumulating runnable list, by reference. */ - private function collect_runnable_subtree( string $component_class, ContainerInterface $container, array &$runnable ): void { - /** @var object $component */ + protected function collect_runnable_subtree( string $component_class, ContainerInterface $container, array &$runnable ): void { + /** @var object $component */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- inline @var type assertion, no description applies. $component = $container->get( $component_class ); if ( ! $this->is_runnable( $component ) ) { @@ -359,7 +359,7 @@ private function collect_runnable_subtree( string $component_class, ContainerInt * * @return bool */ - private function is_runnable( object $component ): bool { + protected function is_runnable( object $component ): bool { if ( $component instanceof EnabledInterface && ! $component->is_enabled() ) { return false; } diff --git a/packages/core/src/Lifecycle/Outputtable/Exceptions/OutputException.php b/packages/core/src/Rendering/Outputtable/Exceptions/OutputException.php similarity index 82% rename from packages/core/src/Lifecycle/Outputtable/Exceptions/OutputException.php rename to packages/core/src/Rendering/Outputtable/Exceptions/OutputException.php index 7cfdd39..c50fb70 100644 --- a/packages/core/src/Lifecycle/Outputtable/Exceptions/OutputException.php +++ b/packages/core/src/Rendering/Outputtable/Exceptions/OutputException.php @@ -1,6 +1,6 @@ /functions.php files. Composer autoloads only this file. + * + * @since 2.0.0 + * @version 2.0.0 + */ -// No namespace functions in settings. This file exists for workspace-wide -// consistency with the package-root functions.php aggregator pattern; when a -// /functions.php file is added under src/, require_once it here. +require_once __DIR__ . '/src/Schema/functions.php'; diff --git a/packages/settings/src/SettingsBackendInterface.php b/packages/settings/src/Backend/SettingsBackendInterface.php similarity index 84% rename from packages/settings/src/SettingsBackendInterface.php rename to packages/settings/src/Backend/SettingsBackendInterface.php index 0af5202..e4645e7 100644 --- a/packages/settings/src/SettingsBackendInterface.php +++ b/packages/settings/src/Backend/SettingsBackendInterface.php @@ -1,8 +1,8 @@ */ - private array $field_section = array(); + protected array $field_section = array(); /** * Per-section option-store cache, keyed by section id. @@ -53,7 +57,7 @@ final class WordPressSettingsBackend implements SettingsBackendInterface { * * @var array> */ - private array $stores = array(); + protected array $stores = array(); /** * Depth of in-progress programmatic writes; the backend's own writes, which may nest, bypass the form sanitizer. @@ -63,7 +67,7 @@ final class WordPressSettingsBackend implements SettingsBackendInterface { * * @var int */ - private int $writing = 0; + protected int $writing = 0; // endregion @@ -80,9 +84,9 @@ final class WordPressSettingsBackend implements SettingsBackendInterface { * @param FieldProcessor $processor Processor for sanitizing submitted values. */ public function __construct( - private ?LoggerInterface $logger = null, - private FieldRenderer $renderer = new FieldRenderer(), - private FieldProcessor $processor = new FieldProcessor(), + protected ?LoggerInterface $logger = null, + protected FieldRenderer $renderer = new FieldRenderer(), + protected FieldProcessor $processor = new FieldProcessor(), ) {} // endregion @@ -180,7 +184,7 @@ public function delete( string $field_id ): bool { * * @return array */ - private function map_fields( SettingsPage $page ): array { + protected function map_fields( SettingsPage $page ): array { $map = array(); $sections = array(); foreach ( $page->sections as $section ) { @@ -214,7 +218,7 @@ private function map_fields( SettingsPage $page ): array { * * @return OptionsStore */ - private function store_for( string $field_id ): OptionsStore { + protected function store_for( string $field_id ): OptionsStore { if ( null === $this->page || ! \array_key_exists( $field_id, $this->field_section ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- framework-internal exception; never reaches an HTML output context unescaped. throw new InvalidSettingsFieldException( "Settings field '$field_id' is not registered on this page." ); @@ -233,7 +237,7 @@ private function store_for( string $field_id ): OptionsStore { * * @param SettingsPage $page Page to add. */ - private function add_menu( SettingsPage $page ): void { + protected function add_menu( SettingsPage $page ): void { // WordPress only wptexturizes the submenu menu_title before printing it (page_title is strip_tagged // for the document title and escaped in render_page), so the menu title is escaped here. \add_submenu_page( @@ -254,7 +258,7 @@ private function add_menu( SettingsPage $page ): void { * * @param SettingsPage $page Page whose sections to register. */ - private function register_settings( SettingsPage $page ): void { + protected function register_settings( SettingsPage $page ): void { foreach ( $page->sections as $section ) { $option_name = $page->slug . '-' . $section->id; @@ -279,7 +283,7 @@ private function register_settings( SettingsPage $page ): void { * * @param SettingsPage $page Page to render. */ - private function render_page( SettingsPage $page ): void { + protected function render_page( SettingsPage $page ): void { echo '

' . \esc_html( $page->page_title ) . '

'; foreach ( $page->sections as $section ) { @@ -290,7 +294,7 @@ private function render_page( SettingsPage $page ): void { \settings_fields( $option_name ); echo ''; foreach ( $section->fields as $field ) { - if ( ! $this->can_edit( $field ) ) { + if ( ! is_field_editable_by_current_user( $field ) ) { continue; } echo '