first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
<?php
/**
* Abstract action class to send an email to provided email address.
*
* @since 4.5.3
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Abstract class for send email workflow action
*
* @class ES_Action_Send_Email_Abstract
*
* @since 4.5.3
*/
abstract class ES_Action_Send_Email_Abstract extends ES_Workflow_Action {
/**
* Load admin props.
*
* @since 4.5.3
*/
public function load_admin_details() {
$this->group = __( 'Email', 'email-subscribers' );
}
/**
* Load fields.
*
* @since 4.5.3
*/
public function load_fields() {
$send_to = new ES_Text();
$send_to->set_name( 'ig-es-send-to' );
$send_to->set_title( __( 'Send to', 'email-subscribers' ) );
$send_to->set_description( __( 'Enter emails here or use variable such as {{EMAIL}}. Multiple emails can be separated by commas.', 'email-subscribers' ) );
$send_to->set_placeholder( __( 'E.g. {{EMAIL}}, admin@example.com', 'email-subscribers' ) );
$send_to->set_required();
$subject = new ES_Text();
$subject->set_name( 'ig-es-email-subject' );
$subject->set_title( __( 'Email subject', 'email-subscribers' ) );
$subject->set_required();
$this->add_field( $send_to );
$this->add_field( $subject );
}
}

View File

@@ -0,0 +1,209 @@
<?php
/**
* Action to add contact to the selected list
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Action_Add_To_List' ) ) {
/**
* Class to add contact to the selected list
*
* @class ES_Action_Add_To_List
*
* @since 4.4.1
*/
class ES_Action_Add_To_List extends ES_Workflow_Action {
/**
* Load action admin details.
*
* @since 4.4.1
*/
public function load_admin_details() {
$this->title = __( 'Add to list', 'email-subscribers' );
$this->group = __( 'List', 'email-subscribers' );
}
/**
* Load action fields
*
* @since 4.4.1
*/
public function load_fields() {
$lists = ES()->lists_db->get_list_id_name_map();
$list_field = new ES_Select();
$list_field->set_name( 'ig-es-list' );
$list_field->set_title( __( 'Select List', 'email-subscribers' ) );
$list_field->set_options( $lists );
$list_field->set_required();
$this->add_field( $list_field );
}
/**
* Called when an action should be run
*
* @since 4.4.1
*/
public function run() {
$list_id = $this->get_option( 'ig-es-list' );
$user_list_status = $this->get_option( 'ig-es-user-list-status' );
$user_list_status = empty( $user_list_status ) ? 'subscribed' : $user_list_status;
if ( ! $list_id ) {
return;
}
$raw_data = $this->workflow->data_layer()->get_raw_data();
if ( ! empty( $raw_data ) ) {
foreach ( $raw_data as $data_type_id => $data_item ) {
$data_type = ES_Workflow_Data_Types::get( $data_type_id );
if ( ! $data_type || ! $data_type->validate( $data_item ) ) {
continue;
}
$data = array();
if ( is_callable( array( $data_type, 'get_data' ) ) ) {
$data = $data_type->get_data( $data_item );
}
if ( ! empty( $data['email'] ) ) {
$this->add_contact( $list_id, $data, $user_list_status );
}
}
}
}
/**
* Add contact data to given list
*
* @param int $list_id List id to add the contact's data.
* @param array $data Contact's data.
*
* @modify 5.6.7
*/
public function add_contact( $list_id = 0, $data = array(), $user_list_status = '' ) {
// Don't know where to add contact? please find it first.
if ( empty( $list_id ) ) {
return;
}
// Email not found? Say good bye.
if ( empty( $data['email'] ) || ! filter_var( $data['email'], FILTER_VALIDATE_EMAIL ) ) {
return;
}
$is_domain_blocked = ES_Common::is_domain_blocked( $data['email'] );
// Store it blocked emails
if ( $is_domain_blocked ) {
$data = array(
'email' => $data['email'],
'ip' => ig_es_get_ip(),
);
ES()->blocked_emails_db->insert( $data );
return;
}
// Source not set? Say bye.
if ( empty( $data['source'] ) ) {
return;
}
$email = trim( $data['email'] );
$source = trim( $data['source'] );
$status = ! empty( $data['status'] ) ? trim( $data['status'] ) : 'verified';
$wp_user_id = ! empty( $data['wp_user_id'] ) ? trim( $data['wp_user_id'] ) : 0;
// If first name is set, get the first name and last name from $data.
// Else prepare the first name and last name from $data['name'] field or $data['email'] field.
if ( ! empty( $data['first_name'] ) ) {
$first_name = $data['first_name'];
$last_name = ! empty( $data['last_name'] ) ? $data['last_name'] : '';
} else {
$name = ! empty( $data['name'] ) ? trim( $data['name'] ) : '';
$first_name = '';
$last_name = '';
if ( ! empty( $name ) ) {
$name_parts = ES_Common::prepare_first_name_last_name( $name );
$first_name = $name_parts['first_name'];
$last_name = $name_parts['last_name'];
}
}
$guid = ES_Common::generate_guid();
$contact_data = array(
'first_name' => $first_name,
'last_name' => $last_name,
'email' => $email,
'source' => $source,
'status' => $status,
'user_list_status' => $user_list_status,
'hash' => $guid,
'created_at' => ig_get_current_date_time(),
'wp_user_id' => $wp_user_id,
);
do_action( 'ig_es_add_contact', $contact_data, $list_id );
}
/**
* Create contact list from product
*
* @param WC_Product $product Product object.
*
* @return int $list_id List ID.
*
* @since 4.4.3
*/
public function create_list_from_product( $product ) {
$list_id = 0;
if ( ! ( $product instanceof WC_Product ) ) {
return $list_id;
}
$product_name = $product->get_name();
$product_sku = $product->get_sku();
$list_name = $product_name;
if ( empty( $product_sku ) ) {
$list_slug = $product_name;
} else {
$list_slug = $product_sku;
}
$list = ES()->lists_db->get_list_by_slug( $list_slug );
if ( ! empty( $list ) ) {
$list_id = $list['id'];
} else {
$list_id = ES()->lists_db->add_list( $list_name, $list_slug );
}
return $list_id;
}
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Action to add contact to the selected list
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Action_Delete_Contact' ) ) {
/**
* Class to add contact to the selected list
*
* @class ES_Action_Delete_Contact
*
* @since 4.4.1
*/
class ES_Action_Delete_Contact extends ES_Workflow_Action {
/**
* Load action admin details.
*
* @since 4.4.1
*/
public function load_admin_details() {
$this->title = __( 'Delete Contact', 'email-subscribers' );
$this->group = __( 'Contact', 'email-subscribers' );
}
/**
* Called when an action should be run
*
* @since 4.4.1
*/
public function run() {
global $wpdb;
$raw_data = $this->workflow->data_layer()->get_raw_data();
if ( ! empty( $raw_data ) ) {
foreach ( $raw_data as $data_type_id => $data_item ) {
$data_type = ES_Workflow_Data_Types::get( $data_type_id );
if ( ! $data_type || ! $data_type->validate( $data_item ) ) {
continue;
}
$data = array();
if ( is_callable( array( $data_type, 'get_data' ) ) ) {
$data = $data_type->get_data( $data_item );
}
$email = ! empty( $data['email'] ) ? $data['email'] : '';
if ( ! empty( $email ) ) {
$where = $wpdb->prepare( 'email = %s', $email );
$contact_id = ES()->contacts_db->get_column_by_condition( 'id', $where );
if ( $contact_id ) {
ES()->contacts_db->delete_contacts_by_ids( $contact_id );
}
}
}
}
}
}
}

View File

@@ -0,0 +1,251 @@
<?php
/**
* Action to send an email to provided email address.
*
* @since 4.5.3
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class to handle send email action
*
* @class ES_Action_Send_Email
*
* @since 4.5.3
*/
if ( ! class_exists( 'ES_Action_Send_Email' ) ) {
class ES_Action_Send_Email extends ES_Action_Send_Email_Abstract {
/**
* Load action admin details.
*
* @since 4.5.3
*/
public function load_admin_details() {
$this->group = __( 'Email', 'email-subscribers' );
$this->title = __( 'Send Email', 'email-subscribers' );
}
/**
* Load action fields
*
* @since 4.5.3
*/
public function load_fields() {
global $ig_es_tracker;
parent::load_fields();
$is_woocommerce_active = $ig_es_tracker::is_plugin_activated( 'woocommerce/woocommerce.php' );
if ( $is_woocommerce_active ) {
$email_template_field = new ES_Select( false );
$email_template_field->set_name( 'ig-es-email-template' );
$email_template_field->set_title( __( 'Email styling', 'email-subscribers' ) );
$email_template_field->set_description( __( 'Select which style to use when formatting the email.', 'email-subscribers' ) );
$email_template_field_options = array(
'none' => __( 'None', 'email-subscribers' ),
'woocommerce' => 'WooCommerce email styling',
);
$email_template_field->set_options( $email_template_field_options );
$email_template_field->set_required();
$this->add_field( $email_template_field );
$email_heading_field = new ES_Text();
$email_heading_field->set_name( 'ig-es-email-heading' );
$email_heading_field->set_title( __( 'Email heading', 'email-subscribers' ) );
$email_heading_field->set_description( __( 'Enter text to be shown in email header area.', 'email-subscribers' ) );
$email_template = $this->get_option( 'ig-es-email-template', false );
$is_wocoomerce_template = 'woocommerce' === $email_template;
if ( ! $is_wocoomerce_template ) {
$email_heading_field->add_container_classes( 'hidden' );
}
$this->add_field( $email_heading_field );
}
$tracking_campaign_id = $this->get_option( 'ig-es-tracking-campaign-id', false );
if ( empty( $tracking_campaign_id ) ) {
$tracking_campaign_id = uniqid();
}
$email_content = new ES_WP_Editor();
$email_content->set_id( 'ig-es-workflow-email-content-' . $tracking_campaign_id );
$email_content->set_name( 'ig-es-email-content' );
$email_content->set_title( __( 'Email content', 'email-subscribers' ) );
$email_content->set_required();
$this->add_field( $email_content );
$tracking_field = new ES_Checkbox();
$tracking_field->set_name( 'ig-es-email-tracking-enabled' );
$tracking_field->set_title( __( 'Track opens and clicks', 'email-subscribers' ) );
$tracking_field->add_classes( 'form-checkbox text-indigo-600' );
$tracking_field->default_to_checked = false;
$this->add_field( $tracking_field );
$tracking_campaign_id = new ES_Hidden_Field();
$tracking_campaign_id->set_name( 'ig-es-tracking-campaign-id' );
$this->add_field( $tracking_campaign_id );
}
/**
* Create content for showing preview
*
* @return mixed|null
*/
public function load_preview() {
$email_content = $this->get_option( 'ig-es-email-content', true, true );
$email_template = $this->get_option( 'ig-es-email-template', false );
$email_heading = $this->get_option( 'ig-es-email-heading', false );
$email_content = wpautop( $email_content );
$email_content = $this->add_template_styling( $email_content, $email_heading, $email_template );
$current_user = wp_get_current_user();
$email_content = ES_Common::replace_keywords_with_fallback( $email_content, array(
'subscriber.first_name' => $current_user->first_name,
'subscriber.name' => $current_user->display_name,
'subscriber.last_name' => $current_user->last_name,
'subscriber.email' => $current_user->user_email
) );
return ES_Common::replace_keywords_with_fallback( $email_content, array(
'EMAIL' => $current_user->user_email,
'NAME' => $current_user->display_name,
'FIRSTNAME' => $current_user->first_name,
'LASTNAME' => $current_user->last_name,
) );
}
/**
* Called when an action should be run
*
* @since 4.5.3
*/
public function run() {
$recipients = $this->get_option( 'ig-es-send-to', true );
$subject = $this->get_option( 'ig-es-email-subject', true );
$email_template = $this->get_option( 'ig-es-email-template', false );
$email_heading = $this->get_option( 'ig-es-email-heading', false );
$email_content = $this->get_option( 'ig-es-email-content', true, true );
$tracking_enabled = $this->get_option( 'ig-es-email-tracking-enabled', false );
$tracking_campaign_id = $this->get_option( 'ig-es-tracking-campaign-id', false );
$recipients = explode(',', $recipients );
$recipients = array_map( 'trim', $recipients );
// Check if we have all required data to send the email.
if ( empty( $recipients ) || empty( $email_content ) || empty( $subject ) ) {
return;
}
// Replace line breaks with paragraphs in email body.
$email_content = wpautop( $email_content );
$raw_data = $this->workflow->data_layer()->get_raw_data();
if ( ! empty( $raw_data ) ) {
foreach ( $raw_data as $data_type_id => $data_item ) {
$data_type = ES_Workflow_Data_Types::get( $data_type_id );
if ( ! $data_type || ! $data_type->validate( $data_item ) ) {
continue;
}
$data = array();
if ( method_exists( $data_type, 'get_data' ) ) {
$data = $data_type->get_data( $data_item );
if ( ! empty( $data['email'] ) ) {
foreach ( $recipients as $index => $recipient_email ) {
// Replace placeholder tags with the got data from the triggerred event.
$recipients[$index] = str_replace( '{{EMAIL}}', $data['email'], $recipient_email );
}
// If source is 'es, it means it is from ES subscriber form, replace {{EMAIL}}, {{NAME}} placeholders with subscriber's email, name
// If we don't replace it here then for workflow configured to be sent to admins, {{EMAIL}}, {{NAME}} gets replaced with admin email and names which is not desired for subscriber based workflows.
if ( 'es' === $data['source'] ) {
$subject = str_replace( '{{EMAIL}}', $data['email'], $subject );
$subject = str_replace( '{{NAME}}', $data['name'], $subject );
$email_content = str_replace( '{{EMAIL}}', $data['email'], $email_content );
$email_content = str_replace( '{{NAME}}', $data['name'], $email_content );
$email_content = str_replace( '{{LIST}}', $data['list_name'], $email_content );
}
}
if ( 'campaign' === $data_type_id && ! empty( $data['notification_guid'] ) ) {
$notification = ES_DB_Mailing_Queue::get_notification_by_hash( $data['notification_guid'] );
$subject = str_replace( '{{SUBJECT}}', $notification['subject'], $subject );
$email_count = $notification['count'];
$campaign_subject = $notification['subject'];
$cron_date = gmdate( 'Y-m-d H:i:s' );
$cron_local_date = get_date_from_gmt( $cron_date ); // Convert from GMT to local date/time based on WordPress time zone setting.
$cron_date = ES_Common::convert_date_to_wp_date( $cron_local_date ); // Get formatted date from WordPress date/time settings.
$email_content = str_replace( '{{DATE}}', $cron_date, $email_content );
$email_content = str_replace( '{{COUNT}}', $email_count, $email_content );
$email_content = str_replace( '{{SUBJECT}}', $campaign_subject, $email_content );
}
}
}
$email_content = $this->add_template_styling( $email_content, $email_heading, $email_template );
$es_mailer = ES()->mailer;
if ( ! empty( $tracking_campaign_id ) ) {
$data['campaign_id'] = $tracking_campaign_id;
}
if ( $tracking_enabled ) {
$es_mailer->can_track_open_clicks = true;
} else {
$es_mailer->can_track_open_clicks = false;
}
$es_mailer->add_unsubscribe_link = false;
$es_mailer->send( $subject, $email_content, $recipients, $data );
}
}
/**
* Add template styling to email content.
*/
public function add_template_styling( $email_content, $email_heading = '', $email_template = 'none' ) {
if ( 'woocommerce' === $email_template ) {
// Make sure WC function exisists before calling it.
if ( function_exists( 'WC' ) ) {
$email_content = WC()->mailer()->wrap_message( $email_heading, $email_content );
$wc_email = new WC_Email();
$email_content = $wc_email->style_inline( $email_content );
// When inlining CSS, curly braces {{UNSUBSCRIBE-LINK}} gets converted to following characters. We are reverting them back
$email_content = str_replace( array( '%5C%7B', '%5C%7D' ), array( '{', '}' ), $email_content );
$email_content = str_replace( array( '%7B', '%7D' ), array( '{', '}' ), $email_content );
}
}
return $email_content;
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Action to add contact to the selected list
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'ES_Action_Update_Contact' ) ) {
/**
* Class to add contact to the selected list
*
* @class ES_Action_Update_Contact
*
* @since 4.4.1
*/
class ES_Action_Update_Contact extends ES_Workflow_Action {
/**
* Load action admin details.
*
* @since 4.4.1
*/
public function load_admin_details() {
$this->title = __( 'Update Contact', 'email-subscribers' );
$this->group = __( 'Contact', 'email-subscribers' );
}
/**
* Called when an action should be run
*
* @since 4.4.1
*/
public function run() {
$raw_data = $this->workflow->data_layer()->get_raw_data();
if ( ! empty( $raw_data ) ) {
foreach ( $raw_data as $data_type_id => $data_item ) {
$data_type = ES_Workflow_Data_Types::get( $data_type_id );
if ( ! $data_type || ! $data_type->validate( $data_item ) ) {
continue;
}
$data = array();
if ( is_callable( array( $data_type, 'get_data' ) ) ) {
$data = $data_type->get_data( $data_item );
}
$user_id = ! empty( $data['wp_user_id'] ) ? $data['wp_user_id'] : 0;
if ( ! empty( $user_id ) ) {
$user = get_user_by( 'ID', $user_id );
if ( $user instanceof WP_User ) {
// Check if user exist with this email.
$es_contact_id = ES()->contacts_db->get_contact_id_by_wp_user_id( $user_id );
if ( ! $es_contact_id ) {
$es_contact_id = ES()->contacts_db->get_contact_id_by_email( $user->user_email );
}
if ( ! empty( $es_contact_id ) ) {
$first_name = get_user_meta( $user_id, 'first_name', true );
$last_name = get_user_meta( $user_id, 'last_name', true );
if ( empty( $first_name ) && empty( $last_name ) ) {
$first_name = $user->display_name;
}
$contact = array(
'email' => $user->user_email,
'first_name' => $first_name,
'last_name' => $last_name,
'wp_user_id' => $user->ID,
);
ES()->contacts_db->update_contact( $es_contact_id, $contact );
}
}
} else {
$email = ! empty( $data['email'] ) ? $data['email'] : '';
$es_contact_id = ES()->contacts_db->get_contact_id_by_email( $email );
if ( ! empty( $es_contact_id ) ) {
$first_name = ! empty( $data['first_name'] ) ? $data['first_name'] : '';
$last_name = ! empty( $data['last_name'] ) ? $data['last_name'] : '';
// Check if we are getting the name field.
if ( empty( $first_name ) && empty( $last_name ) && ! empty( $data['name'] ) ) {
$name = explode( ' ', $data['name'] );
$first_name = $name[0];
if ( isset( $name[1] ) ) {
$last_name = $name[1];
}
}
$contact = array(
'email' => $email,
'first_name' => $first_name,
'last_name' => $last_name,
);
ES()->contacts_db->update_contact( $es_contact_id, $contact );
}
}
}
}
}
}
}