fix: meta box visibility + add WooCommerce Order Actions dropdown entries
Meta box:
- Replace generic add_meta_boxes hook with screen-specific
add_meta_boxes_shop_order and add_meta_boxes_woocommerce_page_wc-orders
so the box reliably appears on both classic and HPOS order edit pages
Order Actions dropdown:
- Hook woocommerce_order_actions filter to inject "phpList: Add to X list"
entries for every configured list (only lists with a saved ID appear)
- Register individual woocommerce_order_action_woolist_sync_{list_id}
handlers via closures at init time so WooCommerce can process them
- Shared do_sync() used by both the dropdown action and the meta box AJAX;
appends an order note (visible in order timeline) on success or failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,10 +23,17 @@ class WooList_Admin {
|
|||||||
// Test connection admin-post handler.
|
// Test connection admin-post handler.
|
||||||
add_action( 'admin_post_woolist_test_connection', [ $this, 'handle_test_connection' ] );
|
add_action( 'admin_post_woolist_test_connection', [ $this, 'handle_test_connection' ] );
|
||||||
|
|
||||||
// Order page meta box (classic + HPOS).
|
// Order page meta box — use screen-specific hooks so both classic and
|
||||||
add_action( 'add_meta_boxes', [ $this, 'add_order_meta_box' ] );
|
// HPOS order edit pages are reliably targeted.
|
||||||
|
add_action( 'add_meta_boxes_shop_order', [ $this, 'register_meta_box' ] );
|
||||||
|
add_action( 'add_meta_boxes_woocommerce_page_wc-orders', [ $this, 'register_meta_box' ] );
|
||||||
|
|
||||||
// AJAX handler for the manual-subscribe button.
|
// WooCommerce Order Actions dropdown (works with classic + HPOS).
|
||||||
|
add_filter( 'woocommerce_order_actions', [ $this, 'add_order_actions' ] );
|
||||||
|
// Register one action handler per configured list (list IDs from options).
|
||||||
|
$this->register_order_action_handlers();
|
||||||
|
|
||||||
|
// AJAX handler for the manual-subscribe meta box button.
|
||||||
add_action( 'wp_ajax_woolist_manual_subscribe', [ $this, 'handle_manual_subscribe' ] );
|
add_action( 'wp_ajax_woolist_manual_subscribe', [ $this, 'handle_manual_subscribe' ] );
|
||||||
|
|
||||||
// Admin assets.
|
// Admin assets.
|
||||||
@@ -120,20 +127,98 @@ class WooList_Admin {
|
|||||||
// ── Order page meta box ───────────────────────────────────────────────────
|
// ── Order page meta box ───────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the meta box on both classic (shop_order) and
|
* Called by add_meta_boxes_shop_order and add_meta_boxes_woocommerce_page_wc-orders.
|
||||||
* HPOS (woocommerce_page_wc-orders) order screens.
|
* The $post_or_order argument is passed by WC but not needed here.
|
||||||
*/
|
*/
|
||||||
public function add_order_meta_box(): void {
|
public function register_meta_box( $post_or_order = null ): void {
|
||||||
foreach ( [ 'shop_order', 'woocommerce_page_wc-orders' ] as $screen ) {
|
// Determine the correct screen ID from the current hook name.
|
||||||
add_meta_box(
|
$screen = did_action( 'add_meta_boxes_shop_order' )
|
||||||
'woolist_order_metabox',
|
? 'shop_order'
|
||||||
__( 'phpList Sync', 'woolist-phplist' ),
|
: 'woocommerce_page_wc-orders';
|
||||||
[ $this, 'render_order_meta_box' ],
|
|
||||||
$screen,
|
add_meta_box(
|
||||||
'side',
|
'woolist_order_metabox',
|
||||||
'default'
|
__( 'phpList Sync', 'woolist-phplist' ),
|
||||||
|
[ $this, 'render_order_meta_box' ],
|
||||||
|
$screen,
|
||||||
|
'side',
|
||||||
|
'default'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── WooCommerce Order Actions dropdown ────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject a "phpList: …" entry for each configured list into the
|
||||||
|
* WooCommerce Order Actions dropdown (the select in the order sidebar).
|
||||||
|
*
|
||||||
|
* @param array $actions Existing order actions.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function add_order_actions( array $actions ): array {
|
||||||
|
foreach ( $this->get_configured_lists() as $list_id => $label ) {
|
||||||
|
$actions[ 'woolist_sync_' . $list_id ] = sprintf(
|
||||||
|
/* translators: %s: list label e.g. "Completed Orders" */
|
||||||
|
__( 'phpList: Add to %s list', 'woolist-phplist' ),
|
||||||
|
$label
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a woocommerce_order_action_{slug} handler for every
|
||||||
|
* configured list at init time so WooCommerce can call them.
|
||||||
|
*/
|
||||||
|
private function register_order_action_handlers(): void {
|
||||||
|
foreach ( $this->get_configured_lists() as $list_id => $label ) {
|
||||||
|
$list_id_captured = $list_id; // explicit capture for the closure
|
||||||
|
add_action(
|
||||||
|
'woocommerce_order_action_woolist_sync_' . $list_id,
|
||||||
|
function ( $order ) use ( $list_id_captured ) {
|
||||||
|
$this->do_sync( $order, $list_id_captured );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared subscribe logic used by both the Order Action and the meta box AJAX.
|
||||||
|
*
|
||||||
|
* @param WC_Abstract_Order $order The order.
|
||||||
|
* @param int $list_id Target phpList list ID.
|
||||||
|
* @return bool True on success.
|
||||||
|
*/
|
||||||
|
private function do_sync( WC_Abstract_Order $order, int $list_id ): bool {
|
||||||
|
$email = $order->get_billing_email();
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
|
||||||
|
if ( ! is_email( $email ) ) {
|
||||||
|
WooList_Logger::error( 'do_sync: order #' . $order_id . ' has no valid billing email.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WooList_Logger::info( 'do_sync: order #' . $order_id . ' email=' . $email . ' list_id=' . $list_id );
|
||||||
|
$result = $this->api->subscribe_email_to_list( $email, $list_id );
|
||||||
|
|
||||||
|
if ( $result['success'] ) {
|
||||||
|
// Add a visible note on the order so it's traceable in the order timeline.
|
||||||
|
$order->add_order_note( sprintf(
|
||||||
|
/* translators: 1: email, 2: list ID */
|
||||||
|
__( 'WooList: %1$s added to phpList list %2$d.', 'woolist-phplist' ),
|
||||||
|
$email,
|
||||||
|
$list_id
|
||||||
|
) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order->add_order_note( sprintf(
|
||||||
|
/* translators: 1: email, 2: list ID */
|
||||||
|
__( 'WooList: failed to add %1$s to phpList list %2$d. Check WooCommerce → Status → Logs.', 'woolist-phplist' ),
|
||||||
|
$email,
|
||||||
|
$list_id
|
||||||
|
) );
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,19 +332,11 @@ class WooList_Admin {
|
|||||||
wp_send_json_error( [ 'message' => __( 'Order not found.', 'woolist-phplist' ) ] );
|
wp_send_json_error( [ 'message' => __( 'Order not found.', 'woolist-phplist' ) ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
$email = $order->get_billing_email();
|
WooList_Logger::info( 'Meta box manual subscribe: order #' . $order_id . ' list_id=' . $list_id . ' user#' . get_current_user_id() );
|
||||||
if ( ! is_email( $email ) ) {
|
|
||||||
wp_send_json_error( [ 'message' => __( 'Order has no valid billing email.', 'woolist-phplist' ) ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
WooList_Logger::info(
|
$ok = $this->do_sync( $order, $list_id );
|
||||||
'Manual subscribe: order #' . $order_id . ' email=' . $email . ' list_id=' . $list_id
|
|
||||||
. ' triggered_by=user#' . get_current_user_id()
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = $this->api->subscribe_email_to_list( $email, $list_id );
|
if ( ! $ok ) {
|
||||||
|
|
||||||
if ( ! $result['success'] ) {
|
|
||||||
wp_send_json_error( [
|
wp_send_json_error( [
|
||||||
'message' => __( 'Subscription failed. Check WooCommerce → Status → Logs for details.', 'woolist-phplist' ),
|
'message' => __( 'Subscription failed. Check WooCommerce → Status → Logs for details.', 'woolist-phplist' ),
|
||||||
] );
|
] );
|
||||||
@@ -269,7 +346,7 @@ class WooList_Admin {
|
|||||||
'message' => sprintf(
|
'message' => sprintf(
|
||||||
/* translators: 1: email address, 2: list ID */
|
/* translators: 1: email address, 2: list ID */
|
||||||
__( '%1$s added to list %2$d.', 'woolist-phplist' ),
|
__( '%1$s added to list %2$d.', 'woolist-phplist' ),
|
||||||
esc_html( $email ),
|
esc_html( $order->get_billing_email() ),
|
||||||
$list_id
|
$list_id
|
||||||
),
|
),
|
||||||
] );
|
] );
|
||||||
|
|||||||
Reference in New Issue
Block a user