diff --git a/functions.php b/functions.php
index e5e06080..56694bc9 100644
--- a/functions.php
+++ b/functions.php
@@ -315,6 +315,11 @@ if (is_admin() && class_exists('AKSRT_Topic_Admin_List')) {
if (is_admin() && class_exists('AKSRT_Topic_Meta_Box')) {
AKSRT_Topic_Meta_Box::get_instance()->init();
}
+// 论坛版块列表列
+if (is_admin() && class_exists('AKSRT_Plate_Admin_List')) {
+ AKSRT_Plate_Admin_List::get_instance()->init();
+}
+
diff --git a/inc/bootstrap.php b/inc/bootstrap.php
index 21fcc75a..accb5d0f 100644
--- a/inc/bootstrap.php
+++ b/inc/bootstrap.php
@@ -325,6 +325,7 @@ require_once AKSRT_DIR . '/inc/classes/shop/class-aksrt-product-variants-meta-bo
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-plate-meta-box.php';
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-admin-list.php';
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-meta-box.php';
+require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-plate-admin-list.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-1.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-2.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-3.php';
diff --git a/inc/classes/admin/native/class-aksrt-admin-pay-menus.php b/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
index 16a9cf10..34f523b9 100644
--- a/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
+++ b/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
@@ -35,7 +35,9 @@ class AKSRT_Admin_Pay_Menus {
add_action('admin_post_aksrt_pay_disable_charge_card', [$this, 'handle_disable_charge_card']);
add_action('admin_post_aksrt_pay_batch_charge_cards', [$this, 'handle_batch_charge_cards']);
add_action('admin_post_aksrt_pay_update_shipping', [$this, 'handle_update_shipping']);
+ add_action('admin_post_aksrt_pay_create_shipping', [$this, 'handle_create_shipping']);
add_action('admin_post_aksrt_pay_update_after_sale', [$this, 'handle_update_after_sale']);
+ add_action('admin_post_aksrt_pay_create_after_sale', [$this, 'handle_create_after_sale']);
add_action('admin_post_aksrt_pay_create_coupon', [$this, 'handle_create_coupon']);
add_action('admin_post_aksrt_pay_disable_coupon', [$this, 'handle_disable_coupon']);
add_action('admin_post_aksrt_pay_settle_income', [$this, 'handle_settle_income']);
@@ -202,8 +204,12 @@ class AKSRT_Admin_Pay_Menus {
'card_batch_failed' => __('卡密批量生成失败。', 'aksrt'),
'shipping_updated' => __('物流状态已更新。', 'aksrt'),
'shipping_failed' => __('物流状态更新失败。', 'aksrt'),
+ 'shipping_created' => __('发货记录已创建。', 'aksrt'),
+ 'shipping_create_failed' => __('发货记录创建失败。', 'aksrt'),
'after_sale_updated' => __('售后状态已更新。', 'aksrt'),
'after_sale_failed' => __('售后状态更新失败。', 'aksrt'),
+ 'after_sale_created' => __('售后工单已创建。', 'aksrt'),
+ 'after_sale_create_failed' => __('售后工单创建失败。', 'aksrt'),
'coupon_created' => __('优惠码已创建。', 'aksrt'),
'coupon_create_failed'=> __('优惠码创建失败(可能重复)。', 'aksrt'),
'coupon_disabled' => __('优惠码已禁用。', 'aksrt'),
@@ -286,6 +292,13 @@ class AKSRT_Admin_Pay_Menus {
return;
}
+ $detail_order = isset($_GET['order']) ? sanitize_text_field((string) wp_unslash($_GET['order'])) : '';
+ if ($detail_order !== '') {
+ $this->render_order_detail_page($detail_order);
+ $this->render_footer();
+ return;
+ }
+
$status = isset($_GET['status']) ? sanitize_key((string) wp_unslash($_GET['status'])) : '';
$search = isset($_GET['s']) ? sanitize_text_field((string) wp_unslash($_GET['s'])) : '';
$page_num = max(1, (int) ($_GET['paged'] ?? 1));
@@ -353,7 +366,8 @@ class AKSRT_Admin_Pay_Menus {
echo '
' . esc_html(number_format((float) ($row['amount'] ?? 0), 2)) . ' ' . esc_html((string) ($row['currency'] ?? '')) . ' | ';
echo '' . esc_html($status_label) . ' | ';
echo '' . esc_html((string) ($row['created_at'] ?? '')) . ' | ';
- echo '';
+ echo ' | ';
+ echo '' . esc_html__('详情', 'aksrt') . '';
echo '';
+
+ echo '' . esc_html__('物流记录', 'aksrt') . '';
+ echo '';
+ if (!$shipping_items) {
+ echo '' . esc_html__('暂无物流记录。', 'aksrt') . ' ';
+ } else {
+ echo '| ID | ' . esc_html__('承运商', 'aksrt') . ' | ' . esc_html__('运单号', 'aksrt') . ' | ' . esc_html__('状态', 'aksrt') . ' | ' . esc_html__('时间', 'aksrt') . ' | ';
+ foreach ($shipping_items as $item) {
+ echo '';
+ echo '| ' . esc_html((string) ($item['id'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['carrier'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['tracking_no'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['status'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['created_at'] ?? '')) . ' | ';
+ echo ' ';
+ }
+ echo ' ';
+ }
+
+ echo '' . esc_html__('售后工单', 'aksrt') . '';
+ echo '';
+ if (!$after_sale) {
+ echo '' . esc_html__('暂无售后工单。', 'aksrt') . ' ';
+ } else {
+ echo '| ID | ' . esc_html__('类型', 'aksrt') . ' | ' . esc_html__('状态', 'aksrt') . ' | ' . esc_html__('时间', 'aksrt') . ' | ';
+ foreach ($after_sale as $item) {
+ echo '';
+ echo '| ' . esc_html((string) ($item['id'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['type'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['status'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($item['created_at'] ?? '')) . ' | ';
+ echo ' ';
+ }
+ echo ' ';
+ }
+ }
+
public function handle_update_order_status(): void {
if (!current_user_can(self::CAPABILITY)) {
wp_die(esc_html__('权限不足', 'aksrt'));
@@ -406,9 +547,13 @@ class AKSRT_Admin_Pay_Menus {
$ok = AKSRT_Order_Repository::get_instance()->update_status($order_number, $new_status, ['force' => true]);
}
- wp_safe_redirect($this->page_url('aksrt_orders', [
- 'aksrt_pay_msg' => $ok ? 'order_updated' : 'order_failed',
- ]));
+ $args = ['aksrt_pay_msg' => $ok ? 'order_updated' : 'order_failed'];
+ $redirect_order = isset($_POST['redirect_order']) ? sanitize_text_field((string) wp_unslash($_POST['redirect_order'])) : '';
+ if ($redirect_order !== '') {
+ $args['order'] = $redirect_order;
+ }
+
+ wp_safe_redirect($this->page_url('aksrt_orders', $args));
exit;
}
@@ -911,6 +1056,64 @@ class AKSRT_Admin_Pay_Menus {
exit;
}
+ public function handle_create_shipping(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ $order_number = isset($_POST['order_number']) ? sanitize_text_field((string) wp_unslash($_POST['order_number'])) : '';
+ check_admin_referer('aksrt_pay_create_shipping_' . $order_number);
+
+ $ok = false;
+ if ($order_number !== '' && class_exists('AKSRT_Shipping')) {
+ $id = AKSRT_Shipping::get_instance()->create([
+ 'order_number' => $order_number,
+ 'carrier' => sanitize_text_field((string) wp_unslash($_POST['carrier'] ?? '')),
+ 'tracking_no' => sanitize_text_field((string) wp_unslash($_POST['tracking_no'] ?? '')),
+ 'note' => sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')),
+ 'operator_id' => get_current_user_id(),
+ ]);
+ $ok = $id > 0;
+ }
+
+ wp_safe_redirect($this->page_url('aksrt_orders', [
+ 'order' => $order_number,
+ 'aksrt_pay_msg' => $ok ? 'shipping_created' : 'shipping_create_failed',
+ ]));
+ exit;
+ }
+
+ public function handle_create_after_sale(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ $order_number = isset($_POST['order_number']) ? sanitize_text_field((string) wp_unslash($_POST['order_number'])) : '';
+ check_admin_referer('aksrt_pay_create_after_sale_' . $order_number);
+
+ $ok = false;
+ if ($order_number !== '' && class_exists('AKSRT_After_Sale')) {
+ $user_id = isset($_POST['user_id']) ? (int) $_POST['user_id'] : 0;
+ if ($user_id <= 0 && class_exists('AKSRT_Order_Repository')) {
+ $order = AKSRT_Order_Repository::get_instance()->get($order_number);
+ $user_id = (int) ($order['user_id'] ?? 0);
+ }
+ $id = AKSRT_After_Sale::get_instance()->create([
+ 'order_number' => $order_number,
+ 'user_id' => $user_id,
+ 'type' => sanitize_key((string) wp_unslash($_POST['type'] ?? 'refund')),
+ 'reason' => sanitize_textarea_field((string) wp_unslash($_POST['reason'] ?? '')),
+ 'amount' => (float) ($_POST['amount'] ?? 0),
+ 'note' => sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')),
+ ]);
+ $ok = $id > 0;
+ }
+
+ wp_safe_redirect($this->page_url('aksrt_orders', [
+ 'order' => $order_number,
+ 'aksrt_pay_msg' => $ok ? 'after_sale_created' : 'after_sale_create_failed',
+ ]));
+ exit;
+ }
+
/* ------------------------------------------------------------------
* After-sale
* ----------------------------------------------------------------*/
diff --git a/inc/classes/admin/native/class-aksrt-admin-users-menus.php b/inc/classes/admin/native/class-aksrt-admin-users-menus.php
index e0b63f6f..5d7150c1 100644
--- a/inc/classes/admin/native/class-aksrt-admin-users-menus.php
+++ b/inc/classes/admin/native/class-aksrt-admin-users-menus.php
@@ -32,6 +32,8 @@ class AKSRT_Admin_Users_Menus {
add_action('admin_post_aksrt_users_update_report', [$this, 'handle_update_report']);
add_action('admin_post_aksrt_users_add_restriction', [$this, 'handle_add_restriction']);
add_action('admin_post_aksrt_users_remove_restriction', [$this, 'handle_remove_restriction']);
+ add_action('admin_post_aksrt_users_batch_invite_codes', [$this, 'handle_batch_invite_codes']);
+ add_action('admin_post_aksrt_users_disable_invite_code', [$this, 'handle_disable_invite_code']);
}
public function register_menus(): void {
@@ -120,15 +122,19 @@ class AKSRT_Admin_Users_Menus {
}
$code = sanitize_key((string) wp_unslash($_GET['aksrt_users_msg']));
$map = [
- 'message_sent' => __('消息已发送。', 'aksrt'),
- 'message_failed' => __('消息发送失败。', 'aksrt'),
- 'verify_updated' => __('认证状态已更新。', 'aksrt'),
- 'verify_failed' => __('认证审核失败。', 'aksrt'),
- 'report_updated' => __('举报状态已更新。', 'aksrt'),
- 'report_failed' => __('举报更新失败。', 'aksrt'),
- 'restriction_added' => __('限制已添加。', 'aksrt'),
+ 'message_sent' => __('消息已发送。', 'aksrt'),
+ 'message_failed' => __('消息发送失败。', 'aksrt'),
+ 'verify_updated' => __('认证状态已更新。', 'aksrt'),
+ 'verify_failed' => __('认证审核失败。', 'aksrt'),
+ 'report_updated' => __('举报状态已更新。', 'aksrt'),
+ 'report_failed' => __('举报更新失败。', 'aksrt'),
+ 'restriction_added' => __('限制已添加。', 'aksrt'),
'restriction_removed' => __('限制已移除。', 'aksrt'),
- 'restriction_failed'=> __('限制操作失败。', 'aksrt'),
+ 'restriction_failed' => __('限制操作失败。', 'aksrt'),
+ 'invite_batch_ok' => __('邀请码批量生成完成。', 'aksrt'),
+ 'invite_batch_failed' => __('邀请码批量生成失败。', 'aksrt'),
+ 'invite_disabled' => __('邀请码已禁用。', 'aksrt'),
+ 'invite_failed' => __('邀请码操作失败。', 'aksrt'),
];
if (!isset($map[$code])) {
return;
@@ -233,8 +239,68 @@ class AKSRT_Admin_Users_Menus {
echo '' . esc_html__('邀请码管理', 'aksrt') . '';
$this->flash();
- $spa = admin_url('admin.php?page=aksrt-settings#/users/invite-codes');
- echo ' ' . esc_html__('SPA 批量生成(过渡)', 'aksrt') . ' ';
+ echo ' ' . esc_html__('批量生成独立邀请码', 'aksrt') . '';
+ echo ' ';
+
+ if (!empty($_GET['aksrt_generated'])) {
+ echo ' ' . esc_html(sprintf(
+ /* translators: %d count */
+ __('成功生成 %d 个邀请码。', 'aksrt'),
+ (int) $_GET['aksrt_generated']
+ )) . ' ';
+ }
+
+ $standalone = get_option('aksrt_standalone_invite_codes', []);
+ $standalone = is_array($standalone) ? array_reverse(array_values($standalone)) : [];
+
+ echo ' ' . esc_html__('独立邀请码', 'aksrt') . '';
+ echo ' ';
+ echo '| ' . esc_html__('邀请码', 'aksrt') . ' | ' . esc_html__('状态', 'aksrt') . ' | ' . esc_html__('批次', 'aksrt') . ' | ' . esc_html__('备注', 'aksrt') . ' | ' . esc_html__('创建时间', 'aksrt') . ' | ' . esc_html__('操作', 'aksrt') . ' | ';
+ echo ' ';
+ if (!$standalone) {
+ echo '| ' . esc_html__('暂无独立邀请码', 'aksrt') . ' | ';
+ }
+ $shown = 0;
+ foreach ($standalone as $entry) {
+ if ($shown >= 200) {
+ break;
+ }
+ $code = sanitize_key((string) ($entry['code'] ?? ''));
+ if ($code === '') {
+ continue;
+ }
+ $disabled = !empty($entry['disabled']);
+ $used = !empty($entry['used']) || !empty($entry['used_by']);
+ $status = $disabled ? __('已禁用', 'aksrt') : ($used ? __('已使用', 'aksrt') : __('可用', 'aksrt'));
+ echo '';
+ echo '' . esc_html($code) . ' | ';
+ echo '' . esc_html($status) . ' | ';
+ echo '' . esc_html((string) ($entry['batch_id'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($entry['note'] ?? '')) . ' | ';
+ echo '' . esc_html((string) ($entry['created_at'] ?? '')) . ' | ';
+ echo '';
+ if (!$disabled && !$used) {
+ echo '';
+ } else {
+ echo '—';
+ }
+ echo ' | ';
+ $shown++;
+ }
+ echo '
';
global $wpdb;
$rows = $wpdb->get_results(
@@ -269,6 +335,104 @@ class AKSRT_Admin_Users_Menus {
echo ' ';
}
+ public function handle_batch_invite_codes(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ check_admin_referer('aksrt_users_batch_invite_codes');
+
+ $count = isset($_POST['count']) ? max(1, min(100, (int) $_POST['count'])) : 10;
+ $length = isset($_POST['length']) ? max(4, min(12, (int) $_POST['length'])) : 6;
+ $prefix = isset($_POST['prefix']) ? sanitize_key((string) wp_unslash($_POST['prefix'])) : '';
+ $note = isset($_POST['note']) ? sanitize_textarea_field((string) wp_unslash($_POST['note'])) : '';
+ $batch = 'INV-' . gmdate('YmdHis') . '-' . wp_generate_password(4, false, false);
+ $alphabet = 'abcdefghjkmnpqrstuvwxyz23456789';
+
+ $codes = get_option('aksrt_standalone_invite_codes', []);
+ $codes = is_array($codes) ? array_values($codes) : [];
+ $existing = [];
+ foreach ($codes as $entry) {
+ $c = sanitize_key((string) ($entry['code'] ?? ''));
+ if ($c !== '') {
+ $existing[$c] = true;
+ }
+ }
+
+ global $wpdb;
+ $generated = [];
+ for ($i = 0; $i < $count; $i++) {
+ $code = '';
+ for ($attempt = 0; $attempt < 20; $attempt++) {
+ $candidate = $prefix;
+ for ($j = 0; $j < $length; $j++) {
+ $candidate .= $alphabet[random_int(0, strlen($alphabet) - 1)];
+ }
+ $candidate = sanitize_key($candidate);
+ if ($candidate === '' || isset($existing[$candidate])) {
+ continue;
+ }
+ $user_hit = $wpdb->get_var($wpdb->prepare(
+ "SELECT umeta_id FROM {$wpdb->usermeta} WHERE meta_key = 'aksrt_invite_code' AND meta_value = %s LIMIT 1",
+ $candidate
+ ));
+ if ($user_hit) {
+ continue;
+ }
+ $code = $candidate;
+ break;
+ }
+ if ($code === '') {
+ continue;
+ }
+ $existing[$code] = true;
+ $codes[] = [
+ 'code' => $code,
+ 'created_at' => current_time('mysql'),
+ 'used' => false,
+ 'used_by' => 0,
+ 'used_at' => '',
+ 'disabled' => false,
+ 'note' => $note,
+ 'batch_id' => $batch,
+ 'created_by' => get_current_user_id(),
+ ];
+ $generated[] = $code;
+ }
+
+ update_option('aksrt_standalone_invite_codes', array_values($codes), false);
+ $ok = !empty($generated);
+ $this->redirect('aksrt_invite_codes', $ok ? 'invite_batch_ok' : 'invite_batch_failed', [
+ 'aksrt_generated' => count($generated),
+ ]);
+ }
+
+ public function handle_disable_invite_code(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ $code = isset($_POST['code']) ? sanitize_key((string) wp_unslash($_POST['code'])) : '';
+ check_admin_referer('aksrt_users_disable_invite_code_' . $code);
+
+ $ok = false;
+ if ($code !== '') {
+ $codes = get_option('aksrt_standalone_invite_codes', []);
+ $codes = is_array($codes) ? $codes : [];
+ foreach ($codes as $i => $entry) {
+ if (sanitize_key((string) ($entry['code'] ?? '')) !== $code) {
+ continue;
+ }
+ $entry['disabled'] = true;
+ $codes[$i] = $entry;
+ $ok = true;
+ break;
+ }
+ if ($ok) {
+ update_option('aksrt_standalone_invite_codes', array_values($codes), false);
+ }
+ }
+ $this->redirect('aksrt_invite_codes', $ok ? 'invite_disabled' : 'invite_failed');
+ }
+
/* ------------------------------------------------------------------
* Verify
* ----------------------------------------------------------------*/
diff --git a/inc/classes/class-aksrt-shop-term-meta.php b/inc/classes/class-aksrt-shop-term-meta.php
index b6873863..d8f13c57 100644
--- a/inc/classes/class-aksrt-shop-term-meta.php
+++ b/inc/classes/class-aksrt-shop-term-meta.php
@@ -45,6 +45,12 @@ class AKSRT_Shop_Term_Meta {
add_action('aksrt_product_cat_edit_form_fields', [$this, 'render_cat_edit_fields'], 10, 1);
add_action('created_aksrt_product_cat', [$this, 'save_cat_term_fields']);
add_action('edited_aksrt_product_cat', [$this, 'save_cat_term_fields']);
+
+ // Product tag display fields.
+ add_action('aksrt_product_tag_add_form_fields', [$this, 'render_tag_add_fields']);
+ add_action('aksrt_product_tag_edit_form_fields', [$this, 'render_tag_edit_fields'], 10, 1);
+ add_action('created_aksrt_product_tag', [$this, 'save_tag_term_fields']);
+ add_action('edited_aksrt_product_tag', [$this, 'save_tag_term_fields']);
}
// ─── Taxonomy Registration ───────────────────────────────────
@@ -677,4 +683,69 @@ class AKSRT_Shop_Term_Meta {
update_term_meta($term_id, $key, $value);
}
}
+
+ public function render_tag_add_fields(): void {
+ foreach ($this->get_tag_field_definitions() as $key => $def) {
+ echo '';
+ echo '';
+ $this->render_tag_field_control($key, $def['default'] ?? '');
+ echo ' ';
+ }
+ }
+
+ public function render_tag_edit_fields($term): void {
+ if (!($term instanceof WP_Term)) {
+ return;
+ }
+ foreach ($this->get_tag_field_definitions() as $key => $def) {
+ $value = get_term_meta($term->term_id, $key, true);
+ if ($value === '' || $value === false) {
+ $value = $def['default'] ?? '';
+ }
+ echo ' | | ';
+ $this->render_tag_field_control($key, $value);
+ echo ' |
';
+ }
+ }
+
+ /**
+ * @param mixed $value
+ */
+ private function render_tag_field_control(string $key, $value): void {
+ $val = (string) $value;
+ if ($key === 'shop_tag_is_important') {
+ echo '';
+ return;
+ }
+ $type = $key === 'shop_tag_priority' ? 'number' : 'text';
+ printf(
+ '',
+ esc_attr($type),
+ esc_attr($key),
+ esc_attr($key),
+ esc_attr($val)
+ );
+ }
+
+ public function save_tag_term_fields(int $term_id): void {
+ if (!current_user_can('manage_categories')) {
+ return;
+ }
+ foreach ($this->get_tag_field_definitions() as $key => $def) {
+ if ($key === 'shop_tag_is_important') {
+ $raw = isset($_POST[$key]) ? '1' : '';
+ } else {
+ if (!isset($_POST[$key])) {
+ continue;
+ }
+ $raw = wp_unslash($_POST[$key]);
+ }
+ if (isset($def['sanitize']) && is_callable($def['sanitize'])) {
+ $value = call_user_func($def['sanitize'], $raw);
+ } else {
+ $value = sanitize_text_field((string) $raw);
+ }
+ update_term_meta($term_id, $key, $value);
+ }
+ }
}
diff --git a/inc/classes/forum/class-aksrt-plate-admin-list.php b/inc/classes/forum/class-aksrt-plate-admin-list.php
new file mode 100644
index 00000000..5ef7cb95
--- /dev/null
+++ b/inc/classes/forum/class-aksrt-plate-admin-list.php
@@ -0,0 +1,107 @@
+ $label) {
+ $new[$key] = $label;
+ if ($key === 'title') {
+ $new['aksrt_plate_mods'] = __('版主数', 'aksrt');
+ $new['aksrt_plate_posts'] = __('帖子数', 'aksrt');
+ $new['aksrt_plate_reply'] = __('回复数', 'aksrt');
+ $new['aksrt_plate_views'] = __('浏览', 'aksrt');
+ $new['aksrt_plate_follow'] = __('关注', 'aksrt');
+ $new['aksrt_plate_pending_apps'] = __('待审申请', 'aksrt');
+ }
+ }
+ return $new;
+ }
+
+ public function sortable_columns(array $columns): array {
+ $columns['aksrt_plate_posts'] = 'aksrt_posts_count';
+ $columns['aksrt_plate_views'] = 'aksrt_plate_views';
+ return $columns;
+ }
+
+ public function render_column(string $column, int $post_id): void {
+ switch ($column) {
+ case 'aksrt_plate_mods':
+ $mods = get_post_meta($post_id, '_aksrt_moderators', true);
+ $count = is_array($mods) ? count(array_filter(array_map('intval', $mods))) : 0;
+ echo esc_html((string) $count);
+ break;
+ case 'aksrt_plate_posts':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_posts_count', true));
+ break;
+ case 'aksrt_plate_reply':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_reply_count', true));
+ break;
+ case 'aksrt_plate_views':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_plate_views', true));
+ break;
+ case 'aksrt_plate_follow':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_follow_count', true));
+ break;
+ case 'aksrt_plate_pending_apps':
+ $apps = get_post_meta($post_id, '_aksrt_moderator_applications', true);
+ $pending = 0;
+ if (is_array($apps)) {
+ foreach ($apps as $app) {
+ if (is_array($app) && (($app['status'] ?? '') === 'pending')) {
+ $pending++;
+ }
+ }
+ }
+ if ($pending > 0) {
+ echo '' . esc_html((string) $pending) . '';
+ } else {
+ echo '0';
+ }
+ break;
+ }
+ }
+
+ public function apply_orderby(WP_Query $query): void {
+ if (!is_admin() || !$query->is_main_query()) {
+ return;
+ }
+ if ($query->get('post_type') !== 'aksrt_forum_plate') {
+ return;
+ }
+ $orderby = $query->get('orderby');
+ if ($orderby === 'aksrt_posts_count') {
+ $query->set('meta_key', '_aksrt_posts_count');
+ $query->set('orderby', 'meta_value_num');
+ } elseif ($orderby === 'aksrt_plate_views') {
+ $query->set('meta_key', '_aksrt_plate_views');
+ $query->set('orderby', 'meta_value_num');
+ }
+ }
+}