2026-02-19 11:51:12 +01:00
< ? php
/**
2026-02-20 08:00:05 +01:00
* WooCommerce Settings tab and order - page meta box for WooList .
2026-02-19 11:51:12 +01:00
*
* @ package WooList
*/
defined ( 'ABSPATH' ) || exit ;
class WooList_Admin {
/** @var WooList_API */
private WooList_API $api ;
public function __construct ( WooList_API $api ) {
$this -> api = $api ;
2026-02-20 08:00:05 +01:00
// WooCommerce settings tab.
2026-02-19 11:51:12 +01:00
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' ] );
// Test connection admin-post handler.
add_action ( 'admin_post_woolist_test_connection' , [ $this , 'handle_test_connection' ] );
2026-02-20 08:00:05 +01:00
// Order page meta box (classic + HPOS).
add_action ( 'add_meta_boxes' , [ $this , 'add_order_meta_box' ] );
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
2026-02-20 08:00:05 +01:00
// AJAX handler for the manual-subscribe button.
add_action ( 'wp_ajax_woolist_manual_subscribe' , [ $this , 'handle_manual_subscribe' ] );
// Admin assets.
2026-02-19 11:51:12 +01:00
add_action ( 'admin_enqueue_scripts' , [ $this , 'enqueue_admin_assets' ] );
}
2026-02-20 08:00:05 +01:00
// ── Settings tab ─────────────────────────────────────────────────────────
2026-02-19 11:51:12 +01:00
public function add_settings_tab ( array $tabs ) : array {
$tabs [ 'woolist' ] = __ ( 'phpList' , 'woolist-phplist' );
return $tabs ;
}
public function render_settings () : void {
woocommerce_admin_fields ( $this -> get_settings () );
$this -> render_test_connection_button ();
}
public function save_settings () : void {
woocommerce_update_options ( $this -> get_settings () );
}
private function render_test_connection_button () : void {
$action_url = wp_nonce_url (
admin_url ( 'admin-post.php?action=woolist_test_connection' ),
'woolist_test_connection'
);
$notice = get_transient ( 'woolist_test_connection_notice_' . get_current_user_id () );
if ( $notice ) {
delete_transient ( 'woolist_test_connection_notice_' . get_current_user_id () );
$type = $notice [ 'success' ] ? 'updated' : 'error' ;
printf (
'<div class="notice notice-%s inline"><p>%s</p></div>' ,
esc_attr ( $type ),
esc_html ( $notice [ 'message' ] )
);
}
echo '<p><a href="' . esc_url ( $action_url ) . '" class="button button-secondary">'
. esc_html__ ( 'Test Connection' , 'woolist-phplist' )
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
. '</a>' ;
2026-02-20 08:00:05 +01:00
echo ' <span style="color:#646970;font-size:13px;margin-left:8px;">'
. esc_html__ ( 'Check WooCommerce → Status → Logs (source: woolist-phplist) to see results.' , 'woolist-phplist' )
. '</span></p>' ;
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
}
2026-02-19 11:51:12 +01:00
public function handle_test_connection () : void {
check_admin_referer ( 'woolist_test_connection' );
if ( ! current_user_can ( 'manage_woocommerce' ) ) {
wp_die ( esc_html__ ( 'You do not have permission to perform this action.' , 'woolist-phplist' ) );
}
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
WooList_Logger :: info ( 'Test Connection triggered by user ID ' . get_current_user_id () );
2026-02-19 11:51:12 +01:00
$result = $this -> api -> lists_get ();
$user_id = get_current_user_id ();
if ( is_wp_error ( $result ) ) {
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
WooList_Logger :: error ( 'Test Connection failed: ' . $result -> get_error_message () );
2026-02-19 11:51:12 +01:00
set_transient (
'woolist_test_connection_notice_' . $user_id ,
[
'success' => false ,
'message' => __ ( 'Connection failed: ' , 'woolist-phplist' ) . $result -> get_error_message (),
],
60
);
} else {
$count = is_array ( $result ) ? count ( $result ) : '?' ;
2026-02-20 08:00:05 +01:00
WooList_Logger :: info ( 'Test Connection succeeded. Found ' . $count . ' list(s).' );
2026-02-19 11:51:12 +01:00
set_transient (
'woolist_test_connection_notice_' . $user_id ,
[
'success' => true ,
'message' => sprintf (
/* translators: %d: number of lists found */
__ ( 'Connection successful! Found %d list(s) in phpList.' , 'woolist-phplist' ),
$count
),
],
60
);
}
wp_safe_redirect ( admin_url ( 'admin.php?page=wc-settings&tab=woolist' ) );
exit ;
}
2026-02-20 08:00:05 +01:00
// ── Order page meta box ───────────────────────────────────────────────────
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
/**
2026-02-20 08:00:05 +01:00
* Register the meta box on both classic ( shop_order ) and
* HPOS ( woocommerce_page_wc - orders ) order screens .
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
*/
2026-02-20 08:00:05 +01:00
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'
);
}
}
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
2026-02-20 08:00:05 +01:00
/**
* 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 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 );
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
}
2026-02-20 08:00:05 +01:00
if ( ! $order ) {
echo '<p>' . esc_html__ ( 'Could not load order.' , 'woolist-phplist' ) . '</p>' ;
return ;
}
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
2026-02-20 08:00:05 +01:00
$order_id = $order -> get_id ();
$email = $order -> get_billing_email ();
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
2026-02-20 08:00:05 +01:00
// Build list of configured lists so the admin can pick one.
$lists = $this -> get_configured_lists ();
if ( empty ( $lists ) ) {
echo '<p style="color:#d63638;">'
. esc_html__ ( 'No phpList lists are configured yet. Add list IDs under WooCommerce → Settings → phpList.' , 'woolist-phplist' )
. '</p>' ;
return ;
}
$nonce = wp_create_nonce ( 'woolist_manual_subscribe_' . $order_id );
?>
< div class = " woolist-metabox-wrap " >
< p style = " margin:0 0 8px; " >
< strong >< ? php esc_html_e ( 'Email:' , 'woolist-phplist' ); ?> </strong>
< ? php echo esc_html ( $email ? : __ ( '(none)' , 'woolist-phplist' ) ); ?>
</ p >
< p style = " margin:0 0 6px; " >
< label for = " woolist-list-select-<?php echo esc_attr( $order_id ); ?> " style = " display:block;margin-bottom:4px;font-weight:600; " >
< ? php esc_html_e ( 'Target list:' , 'woolist-phplist' ); ?>
</ label >
< select id = " woolist-list-select-<?php echo esc_attr( $order_id ); ?> "
class = " woolist-list-select "
style = " width:100%; " >
< ? php foreach ( $lists as $list_id => $label ) : ?>
< option value = " <?php echo esc_attr( $list_id ); ?> " >
< ? php echo esc_html ( $label . ' (ID: ' . $list_id . ')' ); ?>
</ option >
< ? php endforeach ; ?>
</ select >
</ p >
< button type = " button "
class = " button woolist-manual-subscribe-btn "
style = " width:100%;margin-top:4px; "
data - order - id = " <?php echo esc_attr( $order_id ); ?> "
data - nonce = " <?php echo esc_attr( $nonce ); ?> " >
< ? php esc_html_e ( 'Add to phpList' , 'woolist-phplist' ); ?>
</ button >
< div class = " woolist-metabox-response " style = " display:none;margin-top:8px;padding:6px 8px;border-radius:3px;font-size:13px; " ></ div >
</ div >
< ? php
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
}
2026-02-19 11:51:12 +01:00
/**
2026-02-20 08:00:05 +01:00
* Build an associative array of [ list_id => human label ] for all lists
* that have an ID configured in settings , regardless of whether sync is enabled .
*
* @ return array < int , string >
2026-02-19 11:51:12 +01:00
*/
2026-02-20 08:00:05 +01:00
private function get_configured_lists () : array {
$map = [
( int ) get_option ( 'woolist_completed_list_id' , 0 ) => __ ( 'Completed Orders' , 'woolist-phplist' ),
( int ) get_option ( 'woolist_cancelled_list_id' , 0 ) => __ ( 'Cancelled Orders' , 'woolist-phplist' ),
( int ) get_option ( 'woolist_signup_list_id' , 0 ) => __ ( 'Account Signup' , 'woolist-phplist' ),
( int ) get_option ( 'woolist_newsletter_list_id' , 0 ) => __ ( 'Newsletter' , 'woolist-phplist' ),
];
// Remove entries where no list ID has been set.
unset ( $map [ 0 ] );
return $map ;
}
/**
* AJAX handler for the " Add to phpList " order meta box button .
*/
public function handle_manual_subscribe () : void {
$order_id = ( int ) ( $_POST [ 'order_id' ] ? ? 0 );
if ( ! check_ajax_referer ( 'woolist_manual_subscribe_' . $order_id , 'nonce' , false ) ) {
wp_send_json_error ( [ 'message' => __ ( 'Security check failed.' , 'woolist-phplist' ) ], 403 );
}
if ( ! current_user_can ( 'manage_woocommerce' ) ) {
wp_send_json_error ( [ 'message' => __ ( 'Permission denied.' , 'woolist-phplist' ) ], 403 );
}
$list_id = ( int ) ( $_POST [ 'list_id' ] ? ? 0 );
if ( $list_id < 1 ) {
wp_send_json_error ( [ 'message' => __ ( 'No list selected.' , 'woolist-phplist' ) ] );
}
$order = wc_get_order ( $order_id );
if ( ! $order ) {
wp_send_json_error ( [ 'message' => __ ( 'Order not found.' , 'woolist-phplist' ) ] );
}
$email = $order -> get_billing_email ();
if ( ! is_email ( $email ) ) {
wp_send_json_error ( [ 'message' => __ ( 'Order has no valid billing email.' , 'woolist-phplist' ) ] );
}
WooList_Logger :: info (
'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 ( ! $result [ 'success' ] ) {
wp_send_json_error ( [
'message' => __ ( 'Subscription failed. Check WooCommerce → Status → Logs for details.' , 'woolist-phplist' ),
] );
}
wp_send_json_success ( [
'message' => sprintf (
/* translators: 1: email address, 2: list ID */
__ ( '%1$s added to list %2$d.' , 'woolist-phplist' ),
esc_html ( $email ),
$list_id
),
] );
}
// ── Admin assets ─────────────────────────────────────────────────────────
2026-02-19 11:51:12 +01:00
public function enqueue_admin_assets () : void {
$screen = get_current_screen ();
2026-02-20 08:00:05 +01:00
if ( ! $screen ) {
2026-02-19 11:51:12 +01:00
return ;
}
2026-02-20 08:00:05 +01:00
// Enqueue button JS on both classic and HPOS order edit screens.
if ( in_array ( $screen -> id , [ 'shop_order' , 'woocommerce_page_wc-orders' ], true ) ) {
wp_enqueue_script (
'woolist-admin' ,
WOOLIST_URL . 'assets/js/woolist-admin.js' ,
[ 'jquery' ],
WOOLIST_VERSION ,
true
);
// Inline styles for the meta box response area.
wp_add_inline_style (
'woocommerce_admin_styles' ,
'.woolist-mb-success{background:#edfaf1;color:#2d6a0f;border:1px solid #52c41a;}'
. '.woolist-mb-error{background:#fff1f0;color:#a8071a;border:1px solid #ff4d4f;}'
);
}
2026-02-19 11:51:12 +01:00
}
2026-02-20 08:00:05 +01:00
// ── Settings definitions ─────────────────────────────────────────────────
2026-02-19 11:51:12 +01:00
private function get_settings () : array {
return [
// ── Section 1: Connection ────────────────────────────────────────
[
'title' => __ ( 'phpList Connection' , 'woolist-phplist' ),
'type' => 'title' ,
'id' => 'woolist_section_connection' ,
],
[
'title' => __ ( 'phpList Base URL' , 'woolist-phplist' ),
'desc' => __ ( 'e.g. https://newsletter.example.com' , 'woolist-phplist' ),
'id' => 'woolist_phplist_url' ,
'type' => 'text' ,
'default' => '' ,
'desc_tip' => true ,
],
[
'title' => __ ( 'Login' , 'woolist-phplist' ),
'desc' => __ ( 'phpList admin username.' , 'woolist-phplist' ),
'id' => 'woolist_phplist_login' ,
'type' => 'text' ,
'default' => '' ,
'desc_tip' => true ,
],
[
'title' => __ ( 'Password' , 'woolist-phplist' ),
'desc' => __ ( 'phpList admin password.' , 'woolist-phplist' ),
'id' => 'woolist_phplist_password' ,
'type' => 'password' ,
'default' => '' ,
'desc_tip' => true ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_connection' ,
],
// ── Section 2: Completed Orders ──────────────────────────────────
[
'title' => __ ( 'Completed Orders' , 'woolist-phplist' ),
'type' => 'title' ,
'id' => 'woolist_section_completed' ,
],
[
'title' => __ ( 'Enable sync' , 'woolist-phplist' ),
'desc' => __ ( 'Subscribe customers to phpList when an order is completed.' , 'woolist-phplist' ),
'id' => 'woolist_sync_completed' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'title' => __ ( 'List ID' , 'woolist-phplist' ),
'desc' => __ ( 'phpList list ID to subscribe completed-order customers to.' , 'woolist-phplist' ),
'id' => 'woolist_completed_list_id' ,
'type' => 'number' ,
'default' => '' ,
'custom_attributes' => [ 'min' => '1' ],
'desc_tip' => true ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_completed' ,
],
// ── Section 3: Cancelled Orders ──────────────────────────────────
[
'title' => __ ( 'Cancelled Orders' , 'woolist-phplist' ),
'type' => 'title' ,
'id' => 'woolist_section_cancelled' ,
],
[
'title' => __ ( 'Enable sync' , 'woolist-phplist' ),
'desc' => __ ( 'Subscribe customers to phpList when an order is cancelled.' , 'woolist-phplist' ),
'id' => 'woolist_sync_cancelled' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'title' => __ ( 'List ID' , 'woolist-phplist' ),
'desc' => __ ( 'phpList list ID to subscribe cancelled-order customers to.' , 'woolist-phplist' ),
'id' => 'woolist_cancelled_list_id' ,
'type' => 'number' ,
'default' => '' ,
'custom_attributes' => [ 'min' => '1' ],
'desc_tip' => true ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_cancelled' ,
],
// ── Section 4: Account Signup ────────────────────────────────────
[
'title' => __ ( 'Account Signup' , 'woolist-phplist' ),
'type' => 'title' ,
'id' => 'woolist_section_signup' ,
],
[
'title' => __ ( 'Enable sync' , 'woolist-phplist' ),
'desc' => __ ( 'Subscribe new WordPress users to phpList when they register.' , 'woolist-phplist' ),
'id' => 'woolist_sync_signup' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'title' => __ ( 'List ID' , 'woolist-phplist' ),
'desc' => __ ( 'phpList list ID for new account signups.' , 'woolist-phplist' ),
'id' => 'woolist_signup_list_id' ,
'type' => 'number' ,
'default' => '' ,
'custom_attributes' => [ 'min' => '1' ],
'desc_tip' => true ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_signup' ,
],
// ── Section 5: Newsletter Shortcode ──────────────────────────────
[
'title' => __ ( 'Newsletter Shortcode' , 'woolist-phplist' ),
'type' => 'title' ,
'desc' => __ ( 'Settings for the [woolist_newsletter] shortcode.' , 'woolist-phplist' ),
'id' => 'woolist_section_newsletter' ,
],
[
'title' => __ ( 'Enable sync' , 'woolist-phplist' ),
'desc' => __ ( 'Enable the [woolist_newsletter] shortcode.' , 'woolist-phplist' ),
'id' => 'woolist_sync_newsletter' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'title' => __ ( 'List ID' , 'woolist-phplist' ),
'desc' => __ ( 'phpList list ID for newsletter shortcode subscribers.' , 'woolist-phplist' ),
'id' => 'woolist_newsletter_list_id' ,
'type' => 'number' ,
'default' => '' ,
'custom_attributes' => [ 'min' => '1' ],
'desc_tip' => true ,
],
[
'title' => __ ( 'Enable incentive coupon' , 'woolist-phplist' ),
'desc' => __ ( 'Send a WooCommerce coupon after newsletter signup.' , 'woolist-phplist' ),
'id' => 'woolist_newsletter_enable_coupon' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'title' => __ ( 'Coupon mode' , 'woolist-phplist' ),
'desc' => __ ( 'Choose how the coupon is provided.' , 'woolist-phplist' ),
'id' => 'woolist_coupon_mode' ,
'type' => 'select' ,
'default' => 'fixed' ,
'options' => [
'fixed' => __ ( 'Fixed code' , 'woolist-phplist' ),
'autogenerate' => __ ( 'Auto-generate unique code' , 'woolist-phplist' ),
],
'desc_tip' => true ,
],
[
'title' => __ ( 'Fixed coupon code' , 'woolist-phplist' ),
'desc' => __ ( 'The coupon code to show when mode is set to "Fixed code".' , 'woolist-phplist' ),
'id' => 'woolist_coupon_fixed_code' ,
'type' => 'text' ,
'default' => '' ,
'desc_tip' => true ,
],
[
'title' => __ ( 'Discount (%)' , 'woolist-phplist' ),
'desc' => __ ( 'Percentage discount for auto-generated coupons.' , 'woolist-phplist' ),
'id' => 'woolist_coupon_discount_pct' ,
'type' => 'number' ,
'default' => '10' ,
'custom_attributes' => [ 'min' => '1' , 'max' => '100' ],
'desc_tip' => true ,
],
[
'title' => __ ( 'Expiry (days)' , 'woolist-phplist' ),
'desc' => __ ( 'Days until auto-generated coupon expires. Use 0 for no expiry.' , 'woolist-phplist' ),
'id' => 'woolist_coupon_expiry_days' ,
'type' => 'number' ,
'default' => '30' ,
'custom_attributes' => [ 'min' => '0' ],
'desc_tip' => true ,
],
[
'title' => __ ( 'Thank-you message' , 'woolist-phplist' ),
'desc' => __ ( 'Message shown after signup. Use {coupon} as a placeholder for the coupon code.' , 'woolist-phplist' ),
'id' => 'woolist_newsletter_thankyou' ,
'type' => 'textarea' ,
'default' => __ ( 'Thank you for subscribing! Use coupon {coupon} for 10% off your first order.' , 'woolist-phplist' ),
'css' => 'width:100%;height:80px;' ,
'desc_tip' => true ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_newsletter' ,
],
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
// ── Section 6: Logging ───────────────────────────────────────────
[
'title' => __ ( 'Logging' , 'woolist-phplist' ),
'type' => 'title' ,
2026-02-20 08:00:05 +01:00
'desc' => __ ( 'Logs are written to WooCommerce → Status → Logs (source: woolist-phplist).' , 'woolist-phplist' ),
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
'id' => 'woolist_section_logging' ,
],
[
'title' => __ ( 'Enable debug logging' , 'woolist-phplist' ),
2026-02-20 08:00:05 +01:00
'desc' => __ ( 'Log full API request URLs (password redacted) and raw responses. Useful for diagnosing API issues; disable on production once confirmed working.' , 'woolist-phplist' ),
feat: add structured file-based logging with admin log viewer
- New WooList_Logger class writes to wp-content/uploads/woolist-logs/woolist.log
- INFO level: subscription events, test connection results (always recorded)
- ERROR level: API failures, config problems (always recorded + php error_log fallback)
- DEBUG level: full request URLs (password redacted), raw responses, step-by-step
flow (only when "Enable debug logging" is checked in settings)
- Auto-rotates at 1 MB; log directory protected by .htaccess
- API class: logs every request URL (redacted) and raw response body at DEBUG,
errors at ERROR; subscribe_email_to_list logs each step (lookup/create/add)
- Hooks class: logs hook fire, skip reasons, and sync intent at DEBUG/INFO/ERROR
- Shortcode class: logs AJAX submissions, coupon generation, and failures
- Admin: new Logging section with "Enable debug logging" checkbox;
log viewer textarea (last 300 lines, dark theme) + Clear Log button
both visible at bottom of WooCommerce → Settings → phpList tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:25:33 +01:00
'id' => 'woolist_enable_debug_log' ,
'type' => 'checkbox' ,
'default' => 'no' ,
],
[
'type' => 'sectionend' ,
'id' => 'woolist_section_logging' ,
],
2026-02-19 11:51:12 +01:00
];
}
}