Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,38 @@ CommentQuery::select()

> WP's default status is `all`, which is `hold` and `approve`: **spam and trash comments are left out** unless you ask for them with `status()`. `CommentQuery` does not change that. WP also skips counting the total rows by default (`no_found_rows`), call `noFoundRows(false)` if you need it.

## SiteQuery and NetworkQuery

Multisite queries: `SiteQuery` builds `WP_Site_Query` arguments, `NetworkQuery` builds `WP_Network_Query` arguments.

```php
use Pollora\Query\NetworkQuery;
use Pollora\Query\SiteQuery;

SiteQuery::select()
->networkId(1)
->wherePublic()->whereDeleted(false)
->search('*shop*')->searchColumns(['domain'])
->latest()
->get(); // WP_Site_Query

NetworkQuery::select()->domain('example.com')->first();
```

**SiteQuery**
- **Sites**: `whereIn()` (`site__in`), `whereNotIn()`, `networkId()`, `networkIn()`, `networkNotIn()`, `domain*()`, `path*()`, `langId()`, `langIn()`, `langNotIn()`. `SiteQuery::find(3)` or `find([1, 2])` is `site__in`; WP's `ID` argument is the same thing.
- **Status**: `wherePublic()`, `whereArchived()`, `whereMature()`, `whereSpam()`, `whereDeleted()`, each taking a bool (sent as 1 or 0). Without them WP applies no filter, so archived, spam and deleted sites are returned.
- **Search**: `search()` (a leading/trailing `*` is a wildcard) and `searchColumns()`, which only accepts `domain` and `path`.
- **Meta and dates**: `metaKey()`, `metaValue()`, `metaQuery()` as for posts; `dateQuery()` filters on the `registered` column.
- **Order**: `orderBy($field, $direction)` can be chained (sent as a map); `orderByDomain()`, `orderByPath()`, `orderByDomainLength()`, `orderByPathLength()`, `orderByLastUpdated()`, `orderByInclude()`, `orderByNetworkIn()`, `latest()`, `oldest()`, `withoutOrder()`.
- **Cache**: `noFoundRows()`, `updateCache()`, `updateMetaCache()`.

**NetworkQuery**: `whereIn()` (`network__in`), `whereNotIn()`, `domain*()`, `path*()`, `search()`, `orderByDomain()`, `orderByPath()`, `orderByDomainLength()`, `orderByPathLength()`, `orderByInclude()`, `withoutOrder()`, `noFoundRows()`, `updateCache()`. `NetworkQuery::find(2)` is `network__in`.

**Both**: `limit()` / `take()` (`number`), `offset()` / `skip()`, `select('ids')` or `fields('ids')`, and the terminals `get()`, `first()`, `ids()`, `count()` and `exists()`, which run on a copy of the builder.

> `WP_Site_Query` returns at most 100 sites unless told otherwise, which silently truncates large networks. `SiteQuery` sends `number => 0` (no cap) by default: call `limit()` if you want one. WP only applies `offset` together with a `number`, so use `skip()` with `limit()`.

## Testing

```bash
Expand Down
4 changes: 2 additions & 2 deletions src/CommentQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
namespace Pollora\Query;

use Pollora\Query\Traits\Comments\Caching;
use Pollora\Query\Traits\Comments\Fields;
use Pollora\Query\Traits\Comments\Filters;
use Pollora\Query\Traits\Comments\Order;
use Pollora\Query\Traits\Comments\PostFilters;
use Pollora\Query\Traits\Comments\Retrieval;
use Pollora\Query\Traits\Concerns\BuildsArguments;
use Pollora\Query\Traits\Concerns\LimitsResults;
use Pollora\Query\Traits\Concerns\PagedResults;
use Pollora\Query\Traits\Concerns\SelectsIds;
use Pollora\Query\Traits\DateQuery;
use Pollora\Query\Traits\MetaField;
use Pollora\Query\Traits\MetaQuery;
use WP_Comment_Query;

class CommentQuery
{
use BuildsArguments, Caching, DateQuery, Fields, Filters, LimitsResults, MetaField, MetaQuery, Order, PagedResults, PostFilters, Retrieval;
use BuildsArguments, Caching, DateQuery, Filters, LimitsResults, MetaField, MetaQuery, Order, PagedResults, PostFilters, Retrieval, SelectsIds;

/**
* @param array<int>|int|null $commentId A comment ID, or a list of comment IDs.
Expand Down
56 changes: 56 additions & 0 deletions src/NetworkQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Pollora\Query;

use Pollora\Query\Traits\Concerns\BuildsArguments;
use Pollora\Query\Traits\Concerns\LimitsResults;
use Pollora\Query\Traits\Concerns\SelectsIds;
use Pollora\Query\Traits\Networks\Caching;
use Pollora\Query\Traits\Networks\Filters;
use Pollora\Query\Traits\Networks\Order;
use Pollora\Query\Traits\Networks\Retrieval;
use WP_Network_Query;

/**
* Multisite.
*/
class NetworkQuery
{
use BuildsArguments, Caching, Filters, LimitsResults, Order, Retrieval, SelectsIds;

/**
* @param array<int>|int|null $networkId A network ID, or a list of network IDs.
*/
public function __construct(array|int|null $networkId = null, ?string $fields = null)
{
if (is_int($networkId)) {
$this->whereIn([$networkId]);
} elseif (is_array($networkId)) {
$this->whereIn($networkId);
}

if ($fields) {
$this->fields($fields);
}
}

/**
* @param array<int>|int|null $networkId
*/
public static function find(array|int|null $networkId = null): self
{
return new static($networkId);
}

public static function select(?string $fields = 'all'): self
{
return new static(null, $fields);
}

public function get(): WP_Network_Query
{
return new WP_Network_Query($this->getArguments());
}
}
62 changes: 62 additions & 0 deletions src/SiteQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Pollora\Query;

use Pollora\Query\Traits\Concerns\BuildsArguments;
use Pollora\Query\Traits\Concerns\LimitsResults;
use Pollora\Query\Traits\Concerns\SelectsIds;
use Pollora\Query\Traits\DateQuery;
use Pollora\Query\Traits\MetaField;
use Pollora\Query\Traits\MetaQuery;
use Pollora\Query\Traits\Sites\Caching;
use Pollora\Query\Traits\Sites\Filters;
use Pollora\Query\Traits\Sites\Order;
use Pollora\Query\Traits\Sites\Retrieval;
use WP_Site_Query;

/**
* Multisite. The `ID` argument of WP_Site_Query is `whereIn([$id])`.
*/
class SiteQuery
{
use BuildsArguments, Caching, DateQuery, Filters, LimitsResults, MetaField, MetaQuery, Order, Retrieval, SelectsIds;

/**
* @param array<int>|int|null $siteId A site ID, or a list of site IDs.
*/
public function __construct(array|int|null $siteId = null, ?string $fields = null)
{
// WP_Site_Query returns at most 100 sites unless told otherwise: no cap is applied here (0 is "all").
$this->number = 0;

if (is_int($siteId)) {
$this->whereIn([$siteId]);
} elseif (is_array($siteId)) {
$this->whereIn($siteId);
}

if ($fields) {
$this->fields($fields);
}
}

/**
* @param array<int>|int|null $siteId
*/
public static function find(array|int|null $siteId = null): self
{
return new static($siteId);
}

public static function select(?string $fields = 'all'): self
{
return new static(null, $fields);
}

public function get(): WP_Site_Query
{
return new WP_Site_Query($this->getArguments());
}
}
15 changes: 3 additions & 12 deletions src/Traits/Comments/Caching.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,18 @@

namespace Pollora\Query\Traits\Comments;

use Pollora\Query\Traits\Concerns\SkipsFoundRows;

trait Caching
{
protected ?bool $noFoundRows = null;
use SkipsFoundRows;

protected ?bool $updateCommentMetaCache = null;

protected ?bool $updateCommentPostCache = null;

protected ?string $cacheDomain = null;

/**
* Whether the total number of comments is skipped. WP skips it by default, call `noFoundRows(false)`
* if you need the total or the number of pages.
*/
public function noFoundRows(bool $value = true): self
{
$this->noFoundRows = $value;

return $this;
}

public function updateMetaCache(bool $value = true): self
{
$this->updateCommentMetaCache = $value;
Expand Down
13 changes: 2 additions & 11 deletions src/Traits/Comments/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

namespace Pollora\Query\Traits\Comments;

use Pollora\Query\Traits\Concerns\DisablesOrder;
use Pollora\Query\Traits\Concerns\OrdersByMap;

trait Order
{
use OrdersByMap;
use DisablesOrder, OrdersByMap;

public function orderByDate(string $order = 'DESC'): self
{
Expand Down Expand Up @@ -40,14 +41,4 @@ public function oldest(): self
{
return $this->orderByDate('ASC');
}

/**
* Disables the ORDER BY clause.
*/
public function withoutOrder(): self
{
$this->orderby = 'none';

return $this;
}
}
74 changes: 7 additions & 67 deletions src/Traits/Comments/Retrieval.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,23 @@

namespace Pollora\Query\Traits\Comments;

use Pollora\Query\Traits\Concerns\CopiesBuilder;
use Pollora\Query\Traits\Concerns\RetrievesRecords;
use WP_Comment_Query;

/**
* Terminal methods that run the query with the arguments that fit their purpose.
*
* They work on a copy: the builder keeps its own arguments, so it can still be reused afterwards.
*/
trait Retrieval
{
use CopiesBuilder;
use RetrievesRecords;

/**
* Set by count() on a copy only.
*/
protected ?bool $count = null;

/**
* The first matching comment (a WP_Comment), or null. A comment ID with `fields('ids')`.
*/
public function first(): object|int|null
{
$comments = $this->runOnCopy(function (self $copy): void {
$copy->number = 1;
$copy->offset = null;
$copy->paged = null;
$copy->hierarchical = null;
});

return $comments[0] ?? null;
}

/**
* @return array<int>
*/
public function ids(): array
protected function newWpQuery(): object
{
return array_map('intval', $this->runOnCopy(function (self $copy): void {
$copy->fields = 'ids';
$copy->hierarchical = null;
}));
return new WP_Comment_Query;
}

/**
* The total number of matching comments, whatever the limit, offset or page set on the builder.
* Descendants are ignored by WP for ids and counts, and would hide the record a terminal asks for.
*/
public function count(): int
protected function prepareCopy(self $copy): void
{
$copyArgs = $this->copyWith(function (self $copy): void {
$copy->count = true;
$copy->number = null;
$copy->offset = null;
$copy->paged = null;
$copy->hierarchical = null;
});

return (int) (new WP_Comment_Query)->query($copyArgs);
}

public function exists(): bool
{
return $this->runOnCopy(function (self $copy): void {
$copy->fields = 'ids';
$copy->number = 1;
$copy->offset = null;
$copy->paged = null;
$copy->hierarchical = null;
}) !== [];
}

/**
* @return array<mixed>
*/
private function runOnCopy(callable $configure): array
{
$comments = (new WP_Comment_Query)->query($this->copyWith($configure));

return is_array($comments) ? array_values($comments) : [];
$copy->hierarchical = null;
}
}
18 changes: 18 additions & 0 deletions src/Traits/Concerns/DisablesOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Pollora\Query\Traits\Concerns;

trait DisablesOrder
{
/**
* Disables the ORDER BY clause.
*/
public function withoutOrder(): self
{
$this->orderby = 'none';

return $this;
}
}
Loading
Loading