diff --git a/woolist-phplist/assets/js/woolist-admin.js b/woolist-phplist/assets/js/woolist-admin.js new file mode 100644 index 0000000..975d003 --- /dev/null +++ b/woolist-phplist/assets/js/woolist-admin.js @@ -0,0 +1,40 @@ +/* global ajaxurl, jQuery */ +( function ( $ ) { + 'use strict'; + + $( document ).on( 'click', '.woolist-manual-subscribe-btn', function () { + var $btn = $( this ); + var $box = $btn.closest( '.woolist-metabox-wrap' ); + var $resp = $box.find( '.woolist-metabox-response' ); + var listId = $box.find( '.woolist-list-select' ).val(); + + $resp.hide().removeClass( 'woolist-mb-success woolist-mb-error' ).html( '' ); + $btn.prop( 'disabled', true ).text( 'Subscribing\u2026' ); + + $.ajax( { + url: ajaxurl, + method: 'POST', + data: { + action: 'woolist_manual_subscribe', + nonce: $btn.data( 'nonce' ), + order_id: $btn.data( 'order-id' ), + list_id: listId, + }, + } ) + .done( function ( response ) { + if ( response.success ) { + $resp.addClass( 'woolist-mb-success' ).html( '✓ ' + response.data.message ); + } else { + $resp.addClass( 'woolist-mb-error' ).html( '✗ ' + response.data.message ); + } + $resp.show(); + } ) + .fail( function () { + $resp.addClass( 'woolist-mb-error' ).html( '✗ Request failed.' ).show(); + } ) + .always( function () { + $btn.prop( 'disabled', false ).text( 'Add to phpList' ); + } ); + } ); + +} )( jQuery ); diff --git a/woolist-phplist/includes/class-woolist-admin.php b/woolist-phplist/includes/class-woolist-admin.php index 7cdaedd..19a5446 100644 --- a/woolist-phplist/includes/class-woolist-admin.php +++ b/woolist-phplist/includes/class-woolist-admin.php @@ -1,6 +1,6 @@ api = $api; - // Register the custom WooCommerce settings tab. + // WooCommerce settings tab. add_filter( 'woocommerce_settings_tabs_array', [ $this, 'add_settings_tab' ], 50 ); add_action( 'woocommerce_settings_tabs_woolist', [ $this, 'render_settings' ] ); add_action( 'woocommerce_update_options_woolist', [ $this, 'save_settings' ] ); @@ -23,50 +23,38 @@ class WooList_Admin { // Test connection admin-post handler. add_action( 'admin_post_woolist_test_connection', [ $this, 'handle_test_connection' ] ); - // Clear log admin-post handler. - add_action( 'admin_post_woolist_clear_log', [ $this, 'handle_clear_log' ] ); + // Order page meta box (classic + HPOS). + add_action( 'add_meta_boxes', [ $this, 'add_order_meta_box' ] ); - // Enqueue admin JS/CSS only on the WC settings page. + // AJAX handler for the manual-subscribe button. + add_action( 'wp_ajax_woolist_manual_subscribe', [ $this, 'handle_manual_subscribe' ] ); + + // Admin assets. add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] ); } - /** - * Add "phpList" tab to WooCommerce → Settings. - * - * @param array $tabs Existing tabs. - * @return array - */ + // ── Settings tab ───────────────────────────────────────────────────────── + public function add_settings_tab( array $tabs ): array { $tabs['woolist'] = __( 'phpList', 'woolist-phplist' ); return $tabs; } - /** - * Render the settings tab content. - */ public function render_settings(): void { woocommerce_admin_fields( $this->get_settings() ); $this->render_test_connection_button(); - $this->render_log_viewer(); } - /** - * Save settings when the form is submitted. - */ public function save_settings(): void { woocommerce_update_options( $this->get_settings() ); } - /** - * Output the "Test Connection" button below the settings form. - */ private function render_test_connection_button(): void { $action_url = wp_nonce_url( admin_url( 'admin-post.php?action=woolist_test_connection' ), 'woolist_test_connection' ); - // Display any stored transient notice. $notice = get_transient( 'woolist_test_connection_notice_' . get_current_user_id() ); if ( $notice ) { delete_transient( 'woolist_test_connection_notice_' . get_current_user_id() ); @@ -80,54 +68,12 @@ class WooList_Admin { echo '
' . esc_html__( 'Test Connection', 'woolist-phplist' ) - . '
'; - } - - /** - * Render the log viewer panel below all settings. - */ - private function render_log_viewer(): void { - $log_content = WooList_Logger::read_recent( 300 ); - $log_path = WooList_Logger::get_log_path(); - $clear_url = wp_nonce_url( - admin_url( 'admin-post.php?action=woolist_clear_log' ), - 'woolist_clear_log' - ); - - $notice = get_transient( 'woolist_clear_log_notice_' . get_current_user_id() ); - if ( $notice ) { - delete_transient( 'woolist_clear_log_notice_' . get_current_user_id() ); - echo '' . esc_html( $notice ) . '
';
- echo esc_html__( 'Log file: ', 'woolist-phplist' );
- echo '' . esc_html( $log_path ) . '';
- echo '
' . esc_html__( 'Log is empty.', 'woolist-phplist' ) . '
'; - } else { - echo ''; - echo '' - . esc_html__( 'Clear Log', 'woolist-phplist' ) . ''; - echo '
'; + echo ' ' + . esc_html__( 'Check WooCommerce → Status → Logs (source: woolist-phplist) to see results.', 'woolist-phplist' ) + . ''; } - /** - * Handle the "Test Connection" form action. - */ public function handle_test_connection(): void { check_admin_referer( 'woolist_test_connection' ); @@ -152,7 +98,7 @@ class WooList_Admin { ); } else { $count = is_array( $result ) ? count( $result ) : '?'; - WooList_Logger::info( 'Test Connection succeeded, found ' . $count . ' list(s).' ); + WooList_Logger::info( 'Test Connection succeeded. Found ' . $count . ' list(s).' ); set_transient( 'woolist_test_connection_notice_' . $user_id, [ @@ -171,44 +117,193 @@ class WooList_Admin { exit; } + // ── Order page meta box ─────────────────────────────────────────────────── + /** - * Handle the "Clear Log" admin-post action. + * Register the meta box on both classic (shop_order) and + * HPOS (woocommerce_page_wc-orders) order screens. */ - public function handle_clear_log(): void { - check_admin_referer( 'woolist_clear_log' ); - - if ( ! current_user_can( 'manage_woocommerce' ) ) { - wp_die( esc_html__( 'You do not have permission to perform this action.', 'woolist-phplist' ) ); + public function add_order_meta_box(): void { + foreach ( [ 'shop_order', 'woocommerce_page_wc-orders' ] as $screen ) { + add_meta_box( + 'woolist_order_metabox', + __( 'phpList Sync', 'woolist-phplist' ), + [ $this, 'render_order_meta_box' ], + $screen, + 'side', + 'default' + ); } - - WooList_Logger::clear(); - WooList_Logger::info( 'Log cleared by user ID ' . get_current_user_id() ); - - set_transient( - 'woolist_clear_log_notice_' . get_current_user_id(), - __( 'Log file cleared.', 'woolist-phplist' ), - 60 - ); - - wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=woolist' ) ); - exit; } /** - * Enqueue admin-side assets on WC Settings → phpList tab. + * Render the "Add to phpList" meta box on the order edit page. + * + * @param WP_Post|WC_Abstract_Order $post_or_order Classic WP_Post or HPOS order object. */ - public function enqueue_admin_assets(): void { - $screen = get_current_screen(); - if ( ! $screen || strpos( $screen->id, 'woocommerce' ) === false ) { + public function render_order_meta_box( $post_or_order ): void { + // Normalise to a WC order object regardless of storage mode. + if ( $post_or_order instanceof WC_Abstract_Order ) { + $order = $post_or_order; + } else { + $order = wc_get_order( $post_or_order->ID ); + } + + if ( ! $order ) { + echo '' . esc_html__( 'Could not load order.', 'woolist-phplist' ) . '
'; return; } + + $order_id = $order->get_id(); + $email = $order->get_billing_email(); + + // Build list of configured lists so the admin can pick one. + $lists = $this->get_configured_lists(); + + if ( empty( $lists ) ) { + echo '' + . esc_html__( 'No phpList lists are configured yet. Add list IDs under WooCommerce → Settings → phpList.', 'woolist-phplist' ) + . '
'; + return; + } + + $nonce = wp_create_nonce( 'woolist_manual_subscribe_' . $order_id ); + ?> + + human label ] for all lists + * that have an ID configured in settings, regardless of whether sync is enabled. * - * @return array + * @return array