$orderId, ]); $service = new OrderSyncService(); $result = $service->syncOrder($orderId, true); if ($result->isSuccess()) { $this->storeManualSyncNotice( $orderId, 'success', __('Aivie sync completed successfully.', 'aivie-for-woocommerce') ); Logger::info('Manual order sync completed.', [ 'order_id' => $orderId, 'status' => $result->status, 'event_id' => $result->eventId, ]); } elseif ('skipped' === $result->status) { $this->storeManualSyncNotice( $orderId, 'warning', sprintf( /* translators: %s is the sync result message. */ __('Aivie sync skipped: %s', 'aivie-for-woocommerce'), $result->message ) ); Logger::info('Manual order sync skipped.', [ 'order_id' => $orderId, 'message' => $result->message, ]); } else { $this->storeManualSyncNotice( $orderId, 'error', sprintf( /* translators: %s is the sync error message. */ __('Aivie sync failed: %s', 'aivie-for-woocommerce'), $result->message ) ); Logger::error('Manual order sync did not complete successfully.', [ 'order_id' => $orderId, 'status' => $result->status, 'message' => $result->message, ]); } wp_safe_redirect($this->getOrderEditUrl($orderId)); exit; } private function storeManualSyncNotice(int $orderId, string $type, string $message): void { set_transient(self::MANUAL_SYNC_NOTICE_PREFIX . $orderId, [ 'type' => $type, 'message' => $message, ], MINUTE_IN_SECONDS); } public function renderManualSyncNotice(): void { $orderId = $this->getCurrentOrderId(); if ($orderId <= 0) { return; } $transientKey = self::MANUAL_SYNC_NOTICE_PREFIX . $orderId; $notice = get_transient($transientKey); if (! is_array($notice)) { return; } delete_transient($transientKey); $type = in_array($notice['type'] ?? '', ['success', 'warning', 'error'], true) ? $notice['type'] : 'info'; printf( '
%s
' . esc_html__('Not synced yet.', 'aivie-for-woocommerce') . '
'; } else { $statusLabels = [ 'success' => __('Success', 'aivie-for-woocommerce'), 'duplicate' => __('Duplicate (OK)', 'aivie-for-woocommerce'), 'error' => __('Error', 'aivie-for-woocommerce'), 'skipped' => __('Skipped', 'aivie-for-woocommerce'), ]; $label = $statusLabels[$status] ?? esc_html($status); echo '' . esc_html__('Sync to Aivie', 'aivie-for-woocommerce') . '
'; if ($aivieOrderId > 0 && in_array($status, ['success', 'duplicate'], true)) { echo ''; } } public function renderMetaBoxRepositionScript(): void { $screen = get_current_screen(); if (! $screen instanceof \WP_Screen) { return; } $orderScreenId = Compatibility::isHposEnabled() ? wc_get_page_screen_id('shop-order') : 'shop_order'; if ($screen->id !== $orderScreenId) { return; } echo ''; } private function getOrderEditUrl(int $orderId): string { if (Compatibility::isHposEnabled()) { return admin_url('admin.php?page=wc-orders&action=edit&id=' . $orderId); } return get_edit_post_link($orderId, 'raw') ?: admin_url('edit.php?post_type=shop_order'); } private function resolveOrderFromMetaBoxArgument(object|int $orderOrId): \WC_Order|false { if ($orderOrId instanceof \WC_Order) { return $orderOrId; } if (is_int($orderOrId)) { return wc_get_order($orderOrId); } if ($orderOrId instanceof \WP_Post) { return wc_get_order((int) $orderOrId->ID); } return false; } private function buildAivieOrderUrl(int $aivieOrderId): string { return trailingslashit(Options::getBaseUrl()) . 's/commerce/orders/view/' . $aivieOrderId; } private function formatAdminDateTime(string $value): string { $timestamp = strtotime($value); if (false === $timestamp) { return $value; } $format = trim((string) get_option('date_format') . ' ' . (string) get_option('time_format')); if (function_exists('wp_date')) { return wp_date($format, $timestamp); } return date_i18n($format, $timestamp); } }