feat: initial implementation of WooList phpList Integration plugin v1.0.0
- phpList REST API wrapper with subscriber get-or-create + list assignment - WooCommerce Settings tab (5 sections: connection, orders, signup, newsletter) - Test Connection button via admin-post action - Hooks for order completed/cancelled and user_register events - [woolist_newsletter] shortcode with jQuery AJAX, fixed & auto-generated coupons - Responsive front-end form styles and JS with loading/success/error states Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
341
woolist-phplist/includes/class-woolist-admin.php
Normal file
341
woolist-phplist/includes/class-woolist-admin.php
Normal file
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Settings tab for WooList — phpList Integration.
|
||||
*
|
||||
* @package WooList
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
class WooList_Admin {
|
||||
|
||||
/** @var WooList_API */
|
||||
private WooList_API $api;
|
||||
|
||||
public function __construct( WooList_API $api ) {
|
||||
$this->api = $api;
|
||||
|
||||
// Register the custom 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' ] );
|
||||
|
||||
// Test connection admin-post handler.
|
||||
add_action( 'admin_post_woolist_test_connection', [ $this, 'handle_test_connection' ] );
|
||||
|
||||
// Enqueue admin JS/CSS only on the WC settings page.
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "phpList" tab to WooCommerce → Settings.
|
||||
*
|
||||
* @param array $tabs Existing tabs.
|
||||
* @return array
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() );
|
||||
$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' )
|
||||
. '</a></p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the "Test Connection" form action.
|
||||
*/
|
||||
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' ) );
|
||||
}
|
||||
|
||||
$result = $this->api->lists_get();
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
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 ) : '?';
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin-side assets on WC Settings → phpList tab.
|
||||
*/
|
||||
public function enqueue_admin_assets(): void {
|
||||
$screen = get_current_screen();
|
||||
if ( ! $screen || strpos( $screen->id, 'woocommerce' ) === false ) {
|
||||
return;
|
||||
}
|
||||
// No custom admin JS/CSS needed yet; WC handles the settings form.
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return the WooCommerce settings field definitions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
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',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user