- 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>
202 lines
6.0 KiB
PHP
202 lines
6.0 KiB
PHP
<?php
|
|
/**
|
|
* [woolist_newsletter] shortcode and AJAX handler.
|
|
*
|
|
* @package WooList
|
|
*/
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
class WooList_Shortcode {
|
|
|
|
/** @var WooList_API */
|
|
private WooList_API $api;
|
|
|
|
public function __construct( WooList_API $api ) {
|
|
$this->api = $api;
|
|
|
|
add_shortcode( 'woolist_newsletter', [ $this, 'render_shortcode' ] );
|
|
|
|
// Register AJAX handlers for logged-in and guest visitors.
|
|
add_action( 'wp_ajax_woolist_newsletter_submit', [ $this, 'handle_ajax' ] );
|
|
add_action( 'wp_ajax_nopriv_woolist_newsletter_submit', [ $this, 'handle_ajax' ] );
|
|
|
|
// Enqueue front-end assets.
|
|
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
|
}
|
|
|
|
/**
|
|
* Enqueue CSS and JS for the newsletter form.
|
|
*/
|
|
public function enqueue_assets(): void {
|
|
wp_enqueue_style(
|
|
'woolist-public',
|
|
WOOLIST_URL . 'assets/css/woolist-public.css',
|
|
[],
|
|
WOOLIST_VERSION
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'woolist-public',
|
|
WOOLIST_URL . 'assets/js/woolist-public.js',
|
|
[ 'jquery' ],
|
|
WOOLIST_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_localize_script(
|
|
'woolist-public',
|
|
'woolist',
|
|
[
|
|
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
|
'nonce' => wp_create_nonce( 'woolist_newsletter_nonce' ),
|
|
'i18n' => [
|
|
'subscribing' => __( 'Subscribing…', 'woolist-phplist' ),
|
|
'subscribe' => __( 'Subscribe', 'woolist-phplist' ),
|
|
'error' => __( 'Something went wrong. Please try again.', 'woolist-phplist' ),
|
|
],
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render the [woolist_newsletter] shortcode.
|
|
*
|
|
* @return string HTML output.
|
|
*/
|
|
public function render_shortcode(): string {
|
|
if ( get_option( 'woolist_sync_newsletter' ) !== 'yes' ) {
|
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && current_user_can( 'manage_options' ) ) {
|
|
return '<!-- WooList: newsletter shortcode is disabled in settings -->';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="woolist-newsletter-wrap">
|
|
<form id="woolist-newsletter-form" novalidate>
|
|
<div class="woolist-form-row">
|
|
<input
|
|
type="email"
|
|
name="woolist_email"
|
|
class="woolist-email-input"
|
|
placeholder="<?php esc_attr_e( 'Your email address', 'woolist-phplist' ); ?>"
|
|
required
|
|
/>
|
|
<button type="submit" class="woolist-submit-btn">
|
|
<?php esc_html_e( 'Subscribe', 'woolist-phplist' ); ?>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<div class="woolist-response" style="display:none;" aria-live="polite"></div>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX newsletter subscription submission.
|
|
*/
|
|
public function handle_ajax(): void {
|
|
// 1. Verify nonce.
|
|
if ( ! check_ajax_referer( 'woolist_newsletter_nonce', 'nonce', false ) ) {
|
|
wp_send_json_error( [ 'message' => __( 'Security check failed. Please refresh and try again.', 'woolist-phplist' ) ], 403 );
|
|
}
|
|
|
|
// 2. Validate email.
|
|
$email = isset( $_POST['woolist_email'] ) ? sanitize_email( wp_unslash( $_POST['woolist_email'] ) ) : '';
|
|
if ( ! is_email( $email ) ) {
|
|
wp_send_json_error( [ 'message' => __( 'Please enter a valid email address.', 'woolist-phplist' ) ], 400 );
|
|
}
|
|
|
|
// 3. Get list ID.
|
|
$list_id = (int) get_option( 'woolist_newsletter_list_id', 0 );
|
|
if ( $list_id < 1 ) {
|
|
wp_send_json_error( [ 'message' => __( 'Newsletter is not configured. Please contact the site administrator.', 'woolist-phplist' ) ], 500 );
|
|
}
|
|
|
|
// 4. Subscribe email to phpList.
|
|
$result = $this->api->subscribe_email_to_list( $email, $list_id );
|
|
if ( ! $result['success'] ) {
|
|
wp_send_json_error( [ 'message' => __( 'Could not subscribe your email. Please try again later.', 'woolist-phplist' ) ], 500 );
|
|
}
|
|
|
|
// 5. Handle coupon generation.
|
|
$coupon_code = '';
|
|
$thankyou_msg = get_option( 'woolist_newsletter_thankyou', __( 'Thank you for subscribing!', 'woolist-phplist' ) );
|
|
|
|
if ( get_option( 'woolist_newsletter_enable_coupon' ) === 'yes' ) {
|
|
$coupon_mode = get_option( 'woolist_coupon_mode', 'fixed' );
|
|
|
|
if ( $coupon_mode === 'fixed' ) {
|
|
$coupon_code = sanitize_text_field( get_option( 'woolist_coupon_fixed_code', '' ) );
|
|
} else {
|
|
$coupon_code = $this->generate_coupon( $email );
|
|
}
|
|
}
|
|
|
|
// Replace {coupon} placeholder in the thank-you message.
|
|
$thankyou_msg = str_replace( '{coupon}', esc_html( $coupon_code ), $thankyou_msg );
|
|
|
|
wp_send_json_success(
|
|
[
|
|
'message' => wp_kses_post( $thankyou_msg ),
|
|
'coupon' => $coupon_code,
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Generate a unique WooCommerce percentage coupon for the subscriber.
|
|
*
|
|
* @param string $email Subscriber email.
|
|
* @return string Generated coupon code, or empty string on failure.
|
|
*/
|
|
private function generate_coupon( string $email ): string {
|
|
if ( ! class_exists( 'WC_Coupon' ) ) {
|
|
error_log( '[WooList] WC_Coupon class not available; cannot generate coupon.' );
|
|
return '';
|
|
}
|
|
|
|
$discount_pct = (int) get_option( 'woolist_coupon_discount_pct', 10 );
|
|
$expiry_days = (int) get_option( 'woolist_coupon_expiry_days', 30 );
|
|
$coupon_code = 'WOOLIST-' . strtoupper( substr( md5( $email . time() ), 0, 8 ) );
|
|
|
|
$expiry_date = '';
|
|
if ( $expiry_days > 0 ) {
|
|
$expiry_date = gmdate( 'Y-m-d', strtotime( '+' . $expiry_days . ' days' ) );
|
|
}
|
|
|
|
$post_id = wp_insert_post(
|
|
[
|
|
'post_title' => $coupon_code,
|
|
'post_name' => $coupon_code,
|
|
'post_status' => 'publish',
|
|
'post_type' => 'shop_coupon',
|
|
'post_excerpt' => 'WooList newsletter signup coupon for ' . $email,
|
|
],
|
|
true
|
|
);
|
|
|
|
if ( is_wp_error( $post_id ) ) {
|
|
error_log( '[WooList] Failed to create coupon post: ' . $post_id->get_error_message() );
|
|
return '';
|
|
}
|
|
|
|
// Set coupon meta via WC functions.
|
|
update_post_meta( $post_id, 'discount_type', 'percent' );
|
|
update_post_meta( $post_id, 'coupon_amount', (string) $discount_pct );
|
|
update_post_meta( $post_id, 'usage_limit', '1' );
|
|
update_post_meta( $post_id, 'usage_limit_per_user', '1' );
|
|
update_post_meta( $post_id, 'individual_use', 'yes' );
|
|
update_post_meta( $post_id, 'customer_email', [ $email ] );
|
|
|
|
if ( $expiry_date ) {
|
|
update_post_meta( $post_id, 'date_expires', strtotime( $expiry_date ) );
|
|
}
|
|
|
|
return $coupon_code;
|
|
}
|
|
}
|