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>
This commit is contained in:
@@ -12,7 +12,7 @@ class WooList_API {
|
||||
/**
|
||||
* Retrieve a saved plugin option.
|
||||
*
|
||||
* @param string $key Option key (without prefix).
|
||||
* @param string $key Option key (without woolist_ prefix).
|
||||
* @param mixed $default Default value.
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -63,38 +63,45 @@ class WooList_API {
|
||||
$url = $this->build_url( $cmd, $extra );
|
||||
|
||||
if ( is_wp_error( $url ) ) {
|
||||
WooList_Logger::error( 'Cannot build URL for cmd=' . $cmd . ': ' . $url->get_error_message() );
|
||||
return $url;
|
||||
}
|
||||
|
||||
WooList_Logger::debug( '→ API request cmd=' . $cmd . ' url=' . WooList_Logger::redact_url( $url ) );
|
||||
|
||||
$response = wp_remote_post( $url, [ 'timeout' => 15 ] );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
error_log( '[WooList] API request failed for cmd=' . $cmd . ': ' . $response->get_error_message() );
|
||||
WooList_Logger::error( 'HTTP request failed cmd=' . $cmd . ' error=' . $response->get_error_message() );
|
||||
return $response;
|
||||
}
|
||||
|
||||
$code = wp_remote_retrieve_response_code( $response );
|
||||
$body = wp_remote_retrieve_body( $response );
|
||||
|
||||
// Log the raw response at debug level (truncated to 2 KB to avoid huge entries).
|
||||
WooList_Logger::debug( '← API response cmd=' . $cmd . ' http=' . $code . ' body=' . substr( $body, 0, 2048 ) );
|
||||
|
||||
if ( $code < 200 || $code >= 300 ) {
|
||||
error_log( '[WooList] API returned HTTP ' . $code . ' for cmd=' . $cmd );
|
||||
WooList_Logger::error( 'API returned HTTP ' . $code . ' cmd=' . $cmd );
|
||||
return new WP_Error( 'woolist_http_error', 'HTTP error ' . $code );
|
||||
}
|
||||
|
||||
$data = json_decode( $body, true );
|
||||
|
||||
if ( json_last_error() !== JSON_ERROR_NONE ) {
|
||||
error_log( '[WooList] API returned invalid JSON for cmd=' . $cmd . ': ' . $body );
|
||||
WooList_Logger::error( 'Invalid JSON response cmd=' . $cmd . ' body=' . substr( $body, 0, 500 ) );
|
||||
return new WP_Error( 'woolist_json_error', 'Invalid JSON response from phpList.' );
|
||||
}
|
||||
|
||||
// phpList REST API signals errors via a "status" field.
|
||||
if ( isset( $data['status'] ) && strtolower( $data['status'] ) === 'error' ) {
|
||||
$message = $data['errormessage'] ?? $data['message'] ?? 'Unknown API error';
|
||||
error_log( '[WooList] API error for cmd=' . $cmd . ': ' . $message );
|
||||
WooList_Logger::error( 'API error cmd=' . $cmd . ' message=' . $message );
|
||||
return new WP_Error( 'woolist_api_error', $message );
|
||||
}
|
||||
|
||||
WooList_Logger::debug( 'API call succeeded cmd=' . $cmd );
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -118,9 +125,9 @@ class WooList_API {
|
||||
return $this->call(
|
||||
'subscriberAdd',
|
||||
[
|
||||
'email' => rawurlencode( $email ),
|
||||
'confirmed' => 1,
|
||||
'htmlemail' => 1,
|
||||
'email' => rawurlencode( $email ),
|
||||
'confirmed' => 1,
|
||||
'htmlemail' => 1,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -152,35 +159,45 @@ class WooList_API {
|
||||
* @return array{success: bool, subscriber_id: int|null}
|
||||
*/
|
||||
public function subscribe_email_to_list( string $email, int $list_id ): array {
|
||||
// Try to find existing subscriber.
|
||||
WooList_Logger::debug( 'subscribe_email_to_list email=' . $email . ' list_id=' . $list_id );
|
||||
|
||||
// Step 1: look up existing subscriber.
|
||||
$subscriber_id = null;
|
||||
$existing = $this->subscriber_get_by_email( $email );
|
||||
|
||||
if ( ! is_wp_error( $existing ) && ! empty( $existing['id'] ) ) {
|
||||
$subscriber_id = (int) $existing['id'];
|
||||
WooList_Logger::debug( 'Found existing subscriber id=' . $subscriber_id . ' email=' . $email );
|
||||
} else {
|
||||
// Create new subscriber.
|
||||
// Step 2: create a new subscriber.
|
||||
WooList_Logger::debug( 'Subscriber not found, creating new email=' . $email );
|
||||
$added = $this->subscriber_add( $email );
|
||||
|
||||
if ( is_wp_error( $added ) ) {
|
||||
error_log( '[WooList] Could not add subscriber ' . $email . ': ' . $added->get_error_message() );
|
||||
WooList_Logger::error( 'Could not create subscriber email=' . $email . ' error=' . $added->get_error_message() );
|
||||
return [ 'success' => false, 'subscriber_id' => null ];
|
||||
}
|
||||
|
||||
$subscriber_id = isset( $added['id'] ) ? (int) $added['id'] : null;
|
||||
|
||||
if ( $subscriber_id ) {
|
||||
WooList_Logger::info( 'Created new subscriber id=' . $subscriber_id . ' email=' . $email );
|
||||
} else {
|
||||
WooList_Logger::error( 'API returned no subscriber ID after add email=' . $email . ' response=' . wp_json_encode( $added ) );
|
||||
return [ 'success' => false, 'subscriber_id' => null ];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $subscriber_id ) {
|
||||
error_log( '[WooList] Could not determine subscriber ID for ' . $email );
|
||||
return [ 'success' => false, 'subscriber_id' => null ];
|
||||
}
|
||||
|
||||
// Add subscriber to the list.
|
||||
// Step 3: add subscriber to the list.
|
||||
WooList_Logger::debug( 'Adding subscriber ' . $subscriber_id . ' to list ' . $list_id );
|
||||
$result = $this->list_subscriber_add( $list_id, $subscriber_id );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
error_log( '[WooList] Could not add subscriber ' . $subscriber_id . ' to list ' . $list_id . ': ' . $result->get_error_message() );
|
||||
WooList_Logger::error( 'Could not add subscriber to list subscriber_id=' . $subscriber_id . ' list_id=' . $list_id . ' error=' . $result->get_error_message() );
|
||||
return [ 'success' => false, 'subscriber_id' => $subscriber_id ];
|
||||
}
|
||||
|
||||
WooList_Logger::info( 'Subscribed email=' . $email . ' subscriber_id=' . $subscriber_id . ' list_id=' . $list_id );
|
||||
return [ 'success' => true, 'subscriber_id' => $subscriber_id ];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user