Files
wordpress-theme-aksrt/src/Payment/OrderCenterQuery.php
T

125 lines
3.8 KiB
PHP

<?php
/**
* Canonical query state for the knowledge-payment order center.
*
* @package AKSRT
*/
namespace AKSRT\Payment;
use AKSRT\Core\DomainModel;
defined('ABSPATH') || exit;
final class OrderCenterQuery {
public const STATUS_ALL = 'all';
public const STATUS_PENDING = 'pending';
public const STATUS_COMPLETED = 'completed';
public const STATUS_CLOSED = 'closed';
private const STATUS_GROUPS = [
self::STATUS_ALL,
self::STATUS_PENDING,
self::STATUS_COMPLETED,
self::STATUS_CLOSED,
];
/** @var array<string, mixed> */
private array $values;
/**
* @param array<string, mixed> $values
*/
private function __construct(array $values) {
$this->values = $values;
}
/**
* @param array<string, mixed> $raw
*/
public static function from_array(array $raw, int $default_per_page = 20): self {
$status = sanitize_key((string) ($raw['status'] ?? self::STATUS_ALL));
if (!in_array($status, self::STATUS_GROUPS, true)) {
$status = self::STATUS_ALL;
}
$product_type = sanitize_key((string) ($raw['type'] ?? $raw['product_type'] ?? ''));
$types = DomainModel::order_product_type_labels();
if ($product_type !== '' && !isset($types[$product_type])) {
$product_type = '';
}
$order_number = strtoupper(preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($raw['order_number'] ?? '')) ?? '');
$order_number = substr($order_number, 0, 32);
$page = max(1, absint($raw['page'] ?? 1));
$per_page = max(1, min(50, absint($raw['per_page'] ?? $default_per_page)));
return new self([
'status' => $status,
'product_type' => $product_type,
'order_number' => $order_number,
'page' => $page,
'per_page' => $per_page,
]);
}
public function status(): string {
return (string) $this->values['status'];
}
public function product_type(): string {
return (string) $this->values['product_type'];
}
public function order_number(): string {
return (string) $this->values['order_number'];
}
public function page(): int {
return (int) $this->values['page'];
}
public function per_page(): int {
return (int) $this->values['per_page'];
}
/** @return string[] */
public function database_statuses(): array {
return match ($this->status()) {
self::STATUS_PENDING => [Order::STATUS_CREATED, Order::STATUS_PENDING],
self::STATUS_COMPLETED => [Order::STATUS_PAID],
self::STATUS_CLOSED => [Order::STATUS_CANCELLED, Order::STATUS_EXPIRED],
default => [
Order::STATUS_CREATED,
Order::STATUS_PENDING,
Order::STATUS_PAID,
Order::STATUS_CANCELLED,
Order::STATUS_EXPIRED,
],
};
}
/** @return array<string, scalar> */
public function url_values(): array {
return array_filter([
'order_status' => $this->status() !== self::STATUS_ALL ? $this->status() : '',
'order_type' => $this->product_type(),
'order_number' => $this->order_number(),
'order_page' => $this->page() > 1 ? $this->page() : '',
], static fn($value): bool => $value !== '');
}
/** @return array<string, mixed> */
public function repository_args(): array {
return [
'status_in' => $this->database_statuses(),
'product_type' => $this->product_type(),
'order_number_prefix' => $this->order_number(),
'limit' => $this->per_page(),
'offset' => ($this->page() - 1) * $this->per_page(),
];
}
}