125 lines
3.8 KiB
PHP
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(),
|
|
];
|
|
}
|
|
}
|