From 2c590738547bd7f807d40905ff0ec279899e2aab Mon Sep 17 00:00:00 2001 From: Olivier Gorzalka Date: Thu, 15 Oct 2026 16:35:54 +0200 Subject: [PATCH 1/2] feat: require pollora/query 2.0 and add the term, user, comment, site and network query facades --- CHANGELOG.md | 2 + composer.json | 2 +- src/Providers/QueryServiceProvider.php | 15 +++++ src/Support/Facades/CommentQuery.php | 35 +++++++++++ src/Support/Facades/NetworkQuery.php | 35 +++++++++++ src/Support/Facades/SiteQuery.php | 35 +++++++++++ src/Support/Facades/TermQuery.php | 35 +++++++++++ src/Support/Facades/UserQuery.php | 35 +++++++++++ tests/Unit/Support/QueryFacadesTest.php | 84 +++++++++++++++++++++++++ 9 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 src/Support/Facades/CommentQuery.php create mode 100644 src/Support/Facades/NetworkQuery.php create mode 100644 src/Support/Facades/SiteQuery.php create mode 100644 src/Support/Facades/TermQuery.php create mode 100644 src/Support/Facades/UserQuery.php create mode 100644 tests/Unit/Support/QueryFacadesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a6aca8..ec8c89e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/Pollora/framework/compare/v13.36.0...develop) ### Added +- `TermQuery`, `UserQuery`, `CommentQuery`, `SiteQuery` and `NetworkQuery` facades, one for each query class [`pollora/query`](https://github.com/Pollora/Query) 2.0 adds (`WP_Term_Query`, `WP_User_Query`, `WP_Comment_Query`, `WP_Site_Query` and `WP_Network_Query`), bound as `wp.query.term`, `wp.query.user`, `wp.query.comment`, `wp.query.site` and `wp.query.network`. They do not cache the builder they resolve: each call starts a fresh one, so `TermQuery::taxonomy('category')` does not reach the next query - Roles and capabilities live in their own package, [`pollora/roles`](https://github.com/Pollora/roles), which the framework requires: `RoleDefinitionBuilder`, `RoleRegistry`, `RoleCompiler`, `PostTypeCapabilityMap`, the capability readers, the WordPress adapters (stored roles, `WP_Roles` injection, label translation, role usage) and `RoleDiscovery`, with their tests. Class names do not change. The framework keeps the Laravel side: `RoleServiceProvider`, the `role` middleware, the `@role` directive, the `HasRoles` bridge (`$user->can()`, `@can`), the `pollora:roles:*` commands and the `pollora:doctor` check - Typed meta lives in its own package, [`pollora/meta`](https://github.com/Pollora/meta), which the framework requires: `MetaAccessor` (`of()`, `schemas()`, `schemaFor()`, `extend()`), the fluent `MetaRecord`, the schema builder and repository, `MetaAuditor`, `MetaUiDrivers`, the value caster, the WordPress adapters, `MetaDiscovery` and `MetaUiDriverConformance`, with their tests. Class names do not change. The framework keeps what needs Laravel: `MetaServiceProvider`, the `Meta` facade and `HasTypedMeta`, the Laravel validator (`LaravelMetaValidator`), the `pollora:meta:*` commands and the `pollora:doctor` check - The asset classes live in their own package, [`pollora/assets`](https://github.com/Pollora/assets), which the framework requires: `AssetManager`, `AssetContainer`, `AssetEnqueuer` (`Asset::add()->container()->useVite()`), `AssetFile`, the record and the wp-admin notice of a missing build. Class names do not change. The package also resolves Vite builds without Laravel, for a classic theme, a plugin or a Bedrock site. The framework keeps what needs Laravel: the service provider, the `Asset` facade, `ViteManager` (Laravel's Vite, where `ASSET_URL`, a CDN and the application URL keep applying), `RootAssetManager` and the Laravel implementations of the package's three contracts (`ViteManagerFactory`, `RuntimeContext`, `PublicPath`) ### Changed +- Requires `pollora/query` `^2.0`, up from `^1.0`: the package now covers every WordPress query class, with terminal methods (`first()`, `ids()`, `count()`, `exists()`) and the documentation of each builder. Class names and the three existing facades do not change. A few fixes change the result of a query that used to run: `where()` followed by `orWhere()` groups the earlier clauses (`(a AND b) OR c`), `DateQuery::inclusive()` now takes effect, dates use a 24-hour clock, and an invalid `fields()`, `userPermission()` or `orderBy()` direction throws a `QueryException` instead of being ignored. The package's [upgrading guide](https://github.com/Pollora/Query/blob/2.0.0/docs/upgrading.md) lists them - The asset classes that left for the package no longer reach for Laravel: `AssetEnqueuer` receives the hook services, the Vite factory, the runtime and a PSR-3 logger instead of resolving them from the container, `AssetFile` is resolved through a resolver the provider sets (`AssetFile::resolveUsing()`), and `AssetManager`, `MissingBuilds` and `MissingBuildNotice` take their public directory, logger and project root as arguments. The rendered HTML of a Pollora site is unchanged, in build and while Vite runs hot - An `AssetEnqueuer` destroyed after its application, as in a test, no longer throws while it reports a failure of its deferred enqueue - The typed meta classes that will leave for `pollora/meta` no longer reach for Laravel: `MetaUiDrivers` and `MetaAccessor::extend()` take a PSR-11 `ContainerInterface` (the Laravel container is one, a driver closure receives the same object), and the key of a data object's property is derived by `Pollora\Attributes\Support\Naming` instead of `Str::snake()`. What needs Laravel moved to `Pollora\Meta\Infrastructure\Laravel`: `MetaServiceProvider`, `LaravelMetaValidator`, `TypedMetaCheck`, `MetaListCommand` and `MetaAuditCommand`. The rendered pages, the REST responses and the output of the `pollora:meta:*`, `pollora:binding:list`, `pollora:roles:*` and `pollora:doctor` commands of a Pollora site are unchanged diff --git a/composer.json b/composer.json index 10e60937..1fe99a78 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "pollora/colt": "^10.0.1", "log1x/sage-directives": "^2.0", "roots/bedrock-autoloader": "^1.1", - "pollora/query": "^1.0", + "pollora/query": "^2.0", "spatie/php-structure-discoverer": "^2.4", "coduo/php-humanizer": "5.0.3", "nwidart/laravel-modules": "^13.0", diff --git a/src/Providers/QueryServiceProvider.php b/src/Providers/QueryServiceProvider.php index 3bcfada1..8c81023e 100755 --- a/src/Providers/QueryServiceProvider.php +++ b/src/Providers/QueryServiceProvider.php @@ -8,10 +8,15 @@ use Pollora\Colt\Model\User as BaseUser; use Pollora\Models\Post; use Pollora\Models\User; +use Pollora\Query\CommentQuery; use Pollora\Query\DateQuery; use Pollora\Query\MetaQuery; +use Pollora\Query\NetworkQuery; use Pollora\Query\PostQuery; +use Pollora\Query\SiteQuery; use Pollora\Query\TaxQuery; +use Pollora\Query\TermQuery; +use Pollora\Query\UserQuery; /** * Service provider for WordPress query functionality. @@ -22,6 +27,7 @@ * - Taxonomy queries * - Meta queries * - Date queries + * - Term, user, comment, site and network queries */ class QueryServiceProvider extends ServiceProvider { @@ -34,6 +40,7 @@ class QueryServiceProvider extends ServiceProvider * - Taxonomy query singleton * - Meta query singleton * - Date query singleton + * - Term, user, comment, site and network query bindings * - WordPress loop binding * - Current post binding */ @@ -48,6 +55,14 @@ public function register(): void $this->app->singleton('wp.query.meta', fn (): MetaQuery => new MetaQuery); $this->app->singleton('wp.query.date', fn (): DateQuery => new DateQuery); + // A query builder keeps what it is given, so these are bound, not shared, and their facades do not + // cache the instance: `TermQuery::taxonomy('category')` cannot leak into the next query. + $this->app->bind('wp.query.term', fn (): TermQuery => new TermQuery); + $this->app->bind('wp.query.user', fn (): UserQuery => new UserQuery); + $this->app->bind('wp.query.comment', fn (): CommentQuery => new CommentQuery); + $this->app->bind('wp.query.site', fn (): SiteQuery => new SiteQuery); + $this->app->bind('wp.query.network', fn (): NetworkQuery => new NetworkQuery); + // Current post binding $this->app->singleton(Post::class, fn () => Post::find(get_the_ID())); } diff --git a/src/Support/Facades/CommentQuery.php b/src/Support/Facades/CommentQuery.php new file mode 100644 index 00000000..b603ad86 --- /dev/null +++ b/src/Support/Facades/CommentQuery.php @@ -0,0 +1,35 @@ +app = new Application(sys_get_temp_dir()); + (new QueryServiceProvider($this->app))->register(); + + Facade::clearResolvedInstances(); + Facade::setFacadeApplication($this->app); +}); + +afterEach(function (): void { + Facade::clearResolvedInstances(); + Facade::setFacadeApplication(null); +}); + +it('binds a query for every WordPress query class', function (string $key, string $class): void { + expect($this->app->make($key))->toBeInstanceOf($class); +})->with([ + 'posts' => ['wp.query.post', PostQueryBuilder::class], + 'taxonomies' => ['wp.query.taxonomy', TaxQuery::class], + 'meta' => ['wp.query.meta', MetaQuery::class], + 'dates' => ['wp.query.date', DateQuery::class], + 'terms' => ['wp.query.term', TermQueryBuilder::class], + 'users' => ['wp.query.user', UserQueryBuilder::class], + 'comments' => ['wp.query.comment', CommentQueryBuilder::class], + 'sites' => ['wp.query.site', SiteQueryBuilder::class], + 'networks' => ['wp.query.network', NetworkQueryBuilder::class], +]); + +it('builds the arguments of every query through its facade', function (): void { + expect(PostQuery::select()->postType('page')->getArguments())->toMatchArray(['post_type' => 'page']) + ->and(TermQuery::select()->taxonomy('category')->rootOnly()->getArguments())->toMatchArray(['taxonomy' => 'category', 'parent' => 0, 'hide_empty' => false]) + ->and(UserQuery::select()->roleIn(['editor', 'author'])->getArguments())->toMatchArray(['role__in' => ['editor', 'author']]) + ->and(CommentQuery::select()->postId(42)->pending()->getArguments())->toMatchArray(['post_id' => 42, 'status' => 'hold']) + ->and(SiteQuery::select()->networkId(1)->wherePublic()->getArguments())->toMatchArray(['network_id' => 1, 'public' => 1, 'number' => 0]) + ->and(NetworkQuery::select()->domain('example.com')->getArguments())->toMatchArray(['domain' => 'example.com']); +}); + +it('uses the same arguments through the facades as through the classes', function (): void { + expect(TermQuery::find(5)->getArguments())->toBe(TermQueryBuilder::find(5)->getArguments()) + ->and(UserQuery::find([1, 2])->getArguments())->toBe(UserQueryBuilder::find([1, 2])->getArguments()); +}); + +it('starts a fresh builder at each call of the new facades', function (string $facade, string $method, array $arguments, string $key): void { + $facade::$method(...$arguments); + + expect($facade::getFacadeRoot()->getArguments())->not->toHaveKey($key) + ->and($facade::getFacadeRoot())->not->toBe($facade::getFacadeRoot()); +})->with([ + 'terms' => [TermQuery::class, 'taxonomy', ['category'], 'taxonomy'], + 'users' => [UserQuery::class, 'role', ['editor'], 'role'], + 'comments' => [CommentQuery::class, 'postId', [42], 'post_id'], + 'sites' => [SiteQuery::class, 'networkId', [1], 'network_id'], + 'networks' => [NetworkQuery::class, 'domain', ['example.com'], 'domain'], +]); + +it('keeps resolving the sub-query and post facades as before', function (): void { + expect(PostQuery::getFacadeRoot())->toBeInstanceOf(PostQueryBuilder::class) + ->and(TaxQueryFacade::getFacadeRoot())->toBeInstanceOf(TaxQuery::class) + ->and(MetaQueryFacade::getFacadeRoot())->toBeInstanceOf(MetaQuery::class); +}); From 1770b1af92eac44bfc37194d5428e2db17bada40 Mon Sep 17 00:00:00 2001 From: Olivier Gorzalka Date: Thu, 15 Oct 2026 17:24:35 +0200 Subject: [PATCH 2/2] chore: accept pollora/query 1.x and 2.x, leave the new query facades for a minor release --- CHANGELOG.md | 3 +- composer.json | 2 +- src/Providers/QueryServiceProvider.php | 15 ------- src/Support/Facades/CommentQuery.php | 35 ---------------- src/Support/Facades/NetworkQuery.php | 35 ---------------- src/Support/Facades/SiteQuery.php | 35 ---------------- src/Support/Facades/TermQuery.php | 35 ---------------- src/Support/Facades/UserQuery.php | 35 ---------------- tests/Unit/Support/QueryFacadesTest.php | 53 +++++-------------------- 9 files changed, 11 insertions(+), 237 deletions(-) delete mode 100644 src/Support/Facades/CommentQuery.php delete mode 100644 src/Support/Facades/NetworkQuery.php delete mode 100644 src/Support/Facades/SiteQuery.php delete mode 100644 src/Support/Facades/TermQuery.php delete mode 100644 src/Support/Facades/UserQuery.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ec8c89e6..78c17c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/Pollora/framework/compare/v13.36.0...develop) ### Added -- `TermQuery`, `UserQuery`, `CommentQuery`, `SiteQuery` and `NetworkQuery` facades, one for each query class [`pollora/query`](https://github.com/Pollora/Query) 2.0 adds (`WP_Term_Query`, `WP_User_Query`, `WP_Comment_Query`, `WP_Site_Query` and `WP_Network_Query`), bound as `wp.query.term`, `wp.query.user`, `wp.query.comment`, `wp.query.site` and `wp.query.network`. They do not cache the builder they resolve: each call starts a fresh one, so `TermQuery::taxonomy('category')` does not reach the next query - Roles and capabilities live in their own package, [`pollora/roles`](https://github.com/Pollora/roles), which the framework requires: `RoleDefinitionBuilder`, `RoleRegistry`, `RoleCompiler`, `PostTypeCapabilityMap`, the capability readers, the WordPress adapters (stored roles, `WP_Roles` injection, label translation, role usage) and `RoleDiscovery`, with their tests. Class names do not change. The framework keeps the Laravel side: `RoleServiceProvider`, the `role` middleware, the `@role` directive, the `HasRoles` bridge (`$user->can()`, `@can`), the `pollora:roles:*` commands and the `pollora:doctor` check - Typed meta lives in its own package, [`pollora/meta`](https://github.com/Pollora/meta), which the framework requires: `MetaAccessor` (`of()`, `schemas()`, `schemaFor()`, `extend()`), the fluent `MetaRecord`, the schema builder and repository, `MetaAuditor`, `MetaUiDrivers`, the value caster, the WordPress adapters, `MetaDiscovery` and `MetaUiDriverConformance`, with their tests. Class names do not change. The framework keeps what needs Laravel: `MetaServiceProvider`, the `Meta` facade and `HasTypedMeta`, the Laravel validator (`LaravelMetaValidator`), the `pollora:meta:*` commands and the `pollora:doctor` check - The asset classes live in their own package, [`pollora/assets`](https://github.com/Pollora/assets), which the framework requires: `AssetManager`, `AssetContainer`, `AssetEnqueuer` (`Asset::add()->container()->useVite()`), `AssetFile`, the record and the wp-admin notice of a missing build. Class names do not change. The package also resolves Vite builds without Laravel, for a classic theme, a plugin or a Bedrock site. The framework keeps what needs Laravel: the service provider, the `Asset` facade, `ViteManager` (Laravel's Vite, where `ASSET_URL`, a CDN and the application URL keep applying), `RootAssetManager` and the Laravel implementations of the package's three contracts (`ViteManagerFactory`, `RuntimeContext`, `PublicPath`) ### Changed -- Requires `pollora/query` `^2.0`, up from `^1.0`: the package now covers every WordPress query class, with terminal methods (`first()`, `ids()`, `count()`, `exists()`) and the documentation of each builder. Class names and the three existing facades do not change. A few fixes change the result of a query that used to run: `where()` followed by `orWhere()` groups the earlier clauses (`(a AND b) OR c`), `DateQuery::inclusive()` now takes effect, dates use a 24-hour clock, and an invalid `fields()`, `userPermission()` or `orderBy()` direction throws a `QueryException` instead of being ignored. The package's [upgrading guide](https://github.com/Pollora/Query/blob/2.0.0/docs/upgrading.md) lists them +- Accepts `pollora/query` 2.0 alongside 1.x (`^1.0 || ^2.0`, up from `^1.0`): the package now covers every WordPress query class, with terminal methods (`first()`, `ids()`, `count()`, `exists()`) and the documentation of each builder. Class names and the three existing facades do not change. `composer update` takes 2.0, and a project that needs 1.x requires `pollora/query` `^1.0` itself. A few fixes in 2.0 change the result of a query that used to run: `where()` followed by `orWhere()` groups the earlier clauses (`(a AND b) OR c`), `DateQuery::inclusive()` now takes effect, dates use a 24-hour clock, and an invalid `fields()`, `userPermission()` or `orderBy()` direction throws a `QueryException` instead of being ignored. The package's [upgrading guide](https://github.com/Pollora/Query/blob/2.0.0/docs/upgrading.md) lists them - The asset classes that left for the package no longer reach for Laravel: `AssetEnqueuer` receives the hook services, the Vite factory, the runtime and a PSR-3 logger instead of resolving them from the container, `AssetFile` is resolved through a resolver the provider sets (`AssetFile::resolveUsing()`), and `AssetManager`, `MissingBuilds` and `MissingBuildNotice` take their public directory, logger and project root as arguments. The rendered HTML of a Pollora site is unchanged, in build and while Vite runs hot - An `AssetEnqueuer` destroyed after its application, as in a test, no longer throws while it reports a failure of its deferred enqueue - The typed meta classes that will leave for `pollora/meta` no longer reach for Laravel: `MetaUiDrivers` and `MetaAccessor::extend()` take a PSR-11 `ContainerInterface` (the Laravel container is one, a driver closure receives the same object), and the key of a data object's property is derived by `Pollora\Attributes\Support\Naming` instead of `Str::snake()`. What needs Laravel moved to `Pollora\Meta\Infrastructure\Laravel`: `MetaServiceProvider`, `LaravelMetaValidator`, `TypedMetaCheck`, `MetaListCommand` and `MetaAuditCommand`. The rendered pages, the REST responses and the output of the `pollora:meta:*`, `pollora:binding:list`, `pollora:roles:*` and `pollora:doctor` commands of a Pollora site are unchanged diff --git a/composer.json b/composer.json index 1fe99a78..be024011 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "pollora/colt": "^10.0.1", "log1x/sage-directives": "^2.0", "roots/bedrock-autoloader": "^1.1", - "pollora/query": "^2.0", + "pollora/query": "^1.0 || ^2.0", "spatie/php-structure-discoverer": "^2.4", "coduo/php-humanizer": "5.0.3", "nwidart/laravel-modules": "^13.0", diff --git a/src/Providers/QueryServiceProvider.php b/src/Providers/QueryServiceProvider.php index 8c81023e..3bcfada1 100755 --- a/src/Providers/QueryServiceProvider.php +++ b/src/Providers/QueryServiceProvider.php @@ -8,15 +8,10 @@ use Pollora\Colt\Model\User as BaseUser; use Pollora\Models\Post; use Pollora\Models\User; -use Pollora\Query\CommentQuery; use Pollora\Query\DateQuery; use Pollora\Query\MetaQuery; -use Pollora\Query\NetworkQuery; use Pollora\Query\PostQuery; -use Pollora\Query\SiteQuery; use Pollora\Query\TaxQuery; -use Pollora\Query\TermQuery; -use Pollora\Query\UserQuery; /** * Service provider for WordPress query functionality. @@ -27,7 +22,6 @@ * - Taxonomy queries * - Meta queries * - Date queries - * - Term, user, comment, site and network queries */ class QueryServiceProvider extends ServiceProvider { @@ -40,7 +34,6 @@ class QueryServiceProvider extends ServiceProvider * - Taxonomy query singleton * - Meta query singleton * - Date query singleton - * - Term, user, comment, site and network query bindings * - WordPress loop binding * - Current post binding */ @@ -55,14 +48,6 @@ public function register(): void $this->app->singleton('wp.query.meta', fn (): MetaQuery => new MetaQuery); $this->app->singleton('wp.query.date', fn (): DateQuery => new DateQuery); - // A query builder keeps what it is given, so these are bound, not shared, and their facades do not - // cache the instance: `TermQuery::taxonomy('category')` cannot leak into the next query. - $this->app->bind('wp.query.term', fn (): TermQuery => new TermQuery); - $this->app->bind('wp.query.user', fn (): UserQuery => new UserQuery); - $this->app->bind('wp.query.comment', fn (): CommentQuery => new CommentQuery); - $this->app->bind('wp.query.site', fn (): SiteQuery => new SiteQuery); - $this->app->bind('wp.query.network', fn (): NetworkQuery => new NetworkQuery); - // Current post binding $this->app->singleton(Post::class, fn () => Post::find(get_the_ID())); } diff --git a/src/Support/Facades/CommentQuery.php b/src/Support/Facades/CommentQuery.php deleted file mode 100644 index b603ad86..00000000 --- a/src/Support/Facades/CommentQuery.php +++ /dev/null @@ -1,35 +0,0 @@ -app = new Application(sys_get_temp_dir()); @@ -36,49 +28,22 @@ Facade::setFacadeApplication(null); }); -it('binds a query for every WordPress query class', function (string $key, string $class): void { +it('binds the post, taxonomy, meta and date queries', function (string $key, string $class): void { expect($this->app->make($key))->toBeInstanceOf($class); })->with([ 'posts' => ['wp.query.post', PostQueryBuilder::class], 'taxonomies' => ['wp.query.taxonomy', TaxQuery::class], 'meta' => ['wp.query.meta', MetaQuery::class], 'dates' => ['wp.query.date', DateQuery::class], - 'terms' => ['wp.query.term', TermQueryBuilder::class], - 'users' => ['wp.query.user', UserQueryBuilder::class], - 'comments' => ['wp.query.comment', CommentQueryBuilder::class], - 'sites' => ['wp.query.site', SiteQueryBuilder::class], - 'networks' => ['wp.query.network', NetworkQueryBuilder::class], ]); -it('builds the arguments of every query through its facade', function (): void { - expect(PostQuery::select()->postType('page')->getArguments())->toMatchArray(['post_type' => 'page']) - ->and(TermQuery::select()->taxonomy('category')->rootOnly()->getArguments())->toMatchArray(['taxonomy' => 'category', 'parent' => 0, 'hide_empty' => false]) - ->and(UserQuery::select()->roleIn(['editor', 'author'])->getArguments())->toMatchArray(['role__in' => ['editor', 'author']]) - ->and(CommentQuery::select()->postId(42)->pending()->getArguments())->toMatchArray(['post_id' => 42, 'status' => 'hold']) - ->and(SiteQuery::select()->networkId(1)->wherePublic()->getArguments())->toMatchArray(['network_id' => 1, 'public' => 1, 'number' => 0]) - ->and(NetworkQuery::select()->domain('example.com')->getArguments())->toMatchArray(['domain' => 'example.com']); -}); - -it('uses the same arguments through the facades as through the classes', function (): void { - expect(TermQuery::find(5)->getArguments())->toBe(TermQueryBuilder::find(5)->getArguments()) - ->and(UserQuery::find([1, 2])->getArguments())->toBe(UserQueryBuilder::find([1, 2])->getArguments()); -}); - -it('starts a fresh builder at each call of the new facades', function (string $facade, string $method, array $arguments, string $key): void { - $facade::$method(...$arguments); - - expect($facade::getFacadeRoot()->getArguments())->not->toHaveKey($key) - ->and($facade::getFacadeRoot())->not->toBe($facade::getFacadeRoot()); -})->with([ - 'terms' => [TermQuery::class, 'taxonomy', ['category'], 'taxonomy'], - 'users' => [UserQuery::class, 'role', ['editor'], 'role'], - 'comments' => [CommentQuery::class, 'postId', [42], 'post_id'], - 'sites' => [SiteQuery::class, 'networkId', [1], 'network_id'], - 'networks' => [NetworkQuery::class, 'domain', ['example.com'], 'domain'], -]); - -it('keeps resolving the sub-query and post facades as before', function (): void { +it('resolves the post, taxonomy and meta facades to their query', function (): void { expect(PostQuery::getFacadeRoot())->toBeInstanceOf(PostQueryBuilder::class) ->and(TaxQueryFacade::getFacadeRoot())->toBeInstanceOf(TaxQuery::class) ->and(MetaQueryFacade::getFacadeRoot())->toBeInstanceOf(MetaQuery::class); }); + +it('builds the arguments of a post query through its facade', function (): void { + expect(PostQuery::select()->postType('page')->postParent(5)->getArguments()) + ->toMatchArray(['post_type' => 'page', 'post_parent' => 5]); +});