perf(modal): unify cancellable frontend modal flows
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,46 +100,14 @@ trait OrderRepositoryCore {
|
||||
public function get_user_orders(int $user_id, array $args = []): array {
|
||||
global $wpdb;
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if ($user_id > 0) {
|
||||
$where[] = 'user_id = %d';
|
||||
$params[] = $user_id;
|
||||
}
|
||||
|
||||
$statuses = array_values(array_filter(array_map('sanitize_key', (array) ($args['status_in'] ?? []))));
|
||||
if ($statuses !== []) {
|
||||
$where[] = 'status IN (' . implode(', ', array_fill(0, count($statuses), '%s')) . ')';
|
||||
array_push($params, ...$statuses);
|
||||
} else {
|
||||
$status = sanitize_key((string) ($args['status'] ?? ''));
|
||||
if ($status !== '') {
|
||||
$where[] = 'status = %s';
|
||||
$params[] = $status;
|
||||
}
|
||||
}
|
||||
|
||||
$product_type = sanitize_key((string) ($args['product_type'] ?? ''));
|
||||
if ($product_type !== '') {
|
||||
$where[] = 'product_type = %s';
|
||||
$params[] = $product_type;
|
||||
}
|
||||
|
||||
$order_number_prefix = strtoupper(preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($args['order_number_prefix'] ?? '')) ?? '');
|
||||
if ($order_number_prefix !== '') {
|
||||
$where[] = 'order_number LIKE %s';
|
||||
$params[] = $wpdb->esc_like($order_number_prefix) . '%';
|
||||
}
|
||||
|
||||
$limit = max(1, min(100, (int) ($args['limit'] ?? 20)));
|
||||
$parts = $this->get_user_order_query_parts($user_id, $args);
|
||||
$limit = max(1, min(100, (int) ($args['limit'] ?? 20)));
|
||||
$offset = max(0, (int) ($args['offset'] ?? 0));
|
||||
|
||||
$where_sql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
$sql = "SELECT * FROM {$this->table()} {$where_sql} ORDER BY created_at DESC LIMIT %d OFFSET %d";
|
||||
$params = $parts['params'];
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
|
||||
$sql = "SELECT * FROM {$this->table()} {$parts['where']} ORDER BY created_at DESC LIMIT %d OFFSET %d";
|
||||
$rows = $wpdb->get_results($wpdb->prepare($sql, $params), ARRAY_A);
|
||||
|
||||
return array_map([$this, 'normalize_row'], (array) $rows);
|
||||
@@ -175,37 +143,60 @@ trait OrderRepositoryCore {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$where = ['user_id = %d'];
|
||||
$params = [$user_id];
|
||||
$parts = $this->get_user_order_query_parts($user_id, $args);
|
||||
return (int) $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$this->table()} {$parts['where']}",
|
||||
$parts['params']
|
||||
));
|
||||
}
|
||||
|
||||
$statuses = array_values(array_filter(array_map('sanitize_key', (array) ($args['status_in'] ?? []))));
|
||||
if ($statuses !== []) {
|
||||
$where[] = 'status IN (' . implode(', ', array_fill(0, count($statuses), '%s')) . ')';
|
||||
array_push($params, ...$statuses);
|
||||
} else {
|
||||
$status = sanitize_key((string) ($args['status'] ?? ''));
|
||||
if ($status !== '') {
|
||||
$where[] = 'status = %s';
|
||||
$params[] = $status;
|
||||
}
|
||||
/**
|
||||
* Get the filtered list total and the user's order-center counters in one query.
|
||||
*
|
||||
* The filtered total mirrors the list query while the counters intentionally keep
|
||||
* their existing user-wide semantics, so changing a filter does not change the
|
||||
* summary cards. The subquery avoids four independent COUNT statements.
|
||||
*
|
||||
* @return array{total:int,stats:array{total:int,pending:int,completed:int}}
|
||||
*/
|
||||
public function get_user_order_center_summary(int $user_id, array $args = []): array {
|
||||
global $wpdb;
|
||||
|
||||
if ($user_id <= 0) {
|
||||
return [
|
||||
'total' => 0,
|
||||
'stats' => ['total' => 0, 'pending' => 0, 'completed' => 0],
|
||||
];
|
||||
}
|
||||
|
||||
$product_type = sanitize_key((string) ($args['product_type'] ?? ''));
|
||||
if ($product_type !== '') {
|
||||
$where[] = 'product_type = %s';
|
||||
$params[] = $product_type;
|
||||
}
|
||||
$parts = $this->get_user_order_query_parts($user_id, $args);
|
||||
$pending_statuses = [Order::STATUS_CREATED, Order::STATUS_PENDING];
|
||||
$paid_status = Order::STATUS_PAID;
|
||||
$known_statuses = OrderCenterQuery::from_array([])->database_statuses();
|
||||
$known_placeholders = implode(', ', array_fill(0, count($known_statuses), '%s'));
|
||||
$sql = "SELECT
|
||||
(SELECT COUNT(*) FROM {$this->table()} {$parts['where']}) AS filtered_total,
|
||||
COUNT(*) AS known_total,
|
||||
SUM(CASE WHEN status IN (%s, %s) THEN 1 ELSE 0 END) AS pending,
|
||||
SUM(CASE WHEN status = %s THEN 1 ELSE 0 END) AS completed
|
||||
FROM {$this->table()}
|
||||
WHERE user_id = %d AND status IN ({$known_placeholders})";
|
||||
$params = array_merge(
|
||||
$parts['params'],
|
||||
$pending_statuses,
|
||||
[$paid_status, $user_id],
|
||||
$known_statuses
|
||||
);
|
||||
$row = $wpdb->get_row($wpdb->prepare($sql, $params), ARRAY_A);
|
||||
|
||||
$order_number_prefix = strtoupper(preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($args['order_number_prefix'] ?? '')) ?? '');
|
||||
if ($order_number_prefix !== '') {
|
||||
$where[] = 'order_number LIKE %s';
|
||||
$params[] = $wpdb->esc_like($order_number_prefix) . '%';
|
||||
}
|
||||
|
||||
$where_sql = 'WHERE ' . implode(' AND ', $where);
|
||||
$sql = "SELECT COUNT(*) FROM {$this->table()} {$where_sql}";
|
||||
|
||||
return (int) $wpdb->get_var($wpdb->prepare($sql, $params));
|
||||
return [
|
||||
'total' => (int) ($row['filtered_total'] ?? 0),
|
||||
'stats' => [
|
||||
'total' => (int) ($row['known_total'] ?? 0),
|
||||
'pending' => (int) ($row['pending'] ?? 0),
|
||||
'completed' => (int) ($row['completed'] ?? 0),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -515,6 +506,51 @@ trait OrderRepositoryCore {
|
||||
* Internal helpers
|
||||
* ----------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Build the shared list/count predicate without changing caller semantics.
|
||||
*
|
||||
* @return array{where:string,params:array<int,mixed>}
|
||||
*/
|
||||
private function get_user_order_query_parts(int $user_id, array $args = []): array {
|
||||
global $wpdb;
|
||||
|
||||
$where = [];
|
||||
$params = [];
|
||||
if ($user_id > 0) {
|
||||
$where[] = 'user_id = %d';
|
||||
$params[] = $user_id;
|
||||
}
|
||||
|
||||
$statuses = array_values(array_filter(array_map('sanitize_key', (array) ($args['status_in'] ?? []))));
|
||||
if ($statuses !== []) {
|
||||
$where[] = 'status IN (' . implode(', ', array_fill(0, count($statuses), '%s')) . ')';
|
||||
array_push($params, ...$statuses);
|
||||
} else {
|
||||
$status = sanitize_key((string) ($args['status'] ?? ''));
|
||||
if ($status !== '') {
|
||||
$where[] = 'status = %s';
|
||||
$params[] = $status;
|
||||
}
|
||||
}
|
||||
|
||||
$product_type = sanitize_key((string) ($args['product_type'] ?? ''));
|
||||
if ($product_type !== '') {
|
||||
$where[] = 'product_type = %s';
|
||||
$params[] = $product_type;
|
||||
}
|
||||
|
||||
$order_number_prefix = strtoupper(preg_replace('/[^A-Za-z0-9_-]/', '', (string) ($args['order_number_prefix'] ?? '')) ?? '');
|
||||
if ($order_number_prefix !== '') {
|
||||
$where[] = 'order_number LIKE %s';
|
||||
$params[] = $wpdb->esc_like($order_number_prefix) . '%';
|
||||
}
|
||||
|
||||
return [
|
||||
'where' => $where ? 'WHERE ' . implode(' AND ', $where) : '',
|
||||
'params' => $params,
|
||||
];
|
||||
}
|
||||
|
||||
private function normalize_row(array $row): array {
|
||||
$row['id'] = (int) $row['id'];
|
||||
$row['user_id'] = (int) $row['user_id'];
|
||||
|
||||
Reference in New Issue
Block a user