File: /var/www/html/triad-infosec/wp-content/plugins/fusion-builder/inc/class-fusion-mailchimp.php
<?php
/**
* Fusion Mailchimp.
*
* @package Fusion-Builder
* @since 3.5
*/
// Do not allow directly accessing this file.
if ( ! defined( 'ABSPATH' ) ) {
exit( 'Direct script access denied.' );
}
/**
* Fusion Mailchimp class.
*
* @since 3.5
*/
class Fusion_Mailchimp {
/**
* The one, true instance of this object.
*
* @static
* @access private
* @since 3.5
* @var object
*/
private static $instance;
/**
* API key.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $key = null;
/**
* Token data.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $token = null;
/**
* Server prefix.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $dc = null;
/**
* Fields.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $fields = null;
/**
* Lists.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $lists = null;
/**
* Fields.
*
* @static
* @access private
* @since 3.11
* @var mixed
*/
private $group_cats = null;
/**
* Localize status.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $localize_status = null;
/**
* Type of connection.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $type;
/**
* Markup for notices.
*
* @static
* @access private
* @since 3.5
* @var mixed
*/
private $notices = '';
/**
* Class constructor.
*
* @since 3.5
* @access private
*/
private function __construct() {
$fusion_settings = awb_get_fusion_settings();
$this->type = $fusion_settings->get( 'mailchimp_api' );
// Enqueue the OAuth script where required.
$this->oauth_enqueue();
// Add the PO options to the form CPT.
add_filter( 'avada_form_submission_sections', [ $this, 'maybe_add_option' ] );
// This is a redirect from our site with token.
if ( is_admin() && current_user_can( 'manage_options' ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'awb-nonce-mailchimp' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// Trying to save a token.
if ( isset( $_GET['mailchimp'] ) ) {
$this->authenticate();
}
// Trying to revoke a token.
if ( isset( $_GET['revoke_mailchimp'] ) ) {
$this->revoke_access();
}
}
// Render notices if we have any.
add_action( 'avada_dashboard_notices', [ $this, 'render_notices' ] );
// Reset Caches.
add_action( 'wp_ajax_fusion_reset_mailchimp_caches', [ $this, 'reset_caches_handler' ] );
// If not enabled, no need to load anything.
if ( ! apply_filters( 'fusion_load_mailchimp', ( 'off' !== $this->type ) ) ) {
return;
}
// Enqueue the JS script for the PO mapping option.
add_action( 'avada_page_option_scripts', [ $this, 'option_script' ] );
// Add fields list to live editor.
add_filter( 'fusion_app_preview_data', [ $this, 'add_preview_data' ], 10, 3 );
}
/**
* If set, render admin notices.
*
* @access public
* @since 3.5
* @return void
*/
public function render_notices() {
if ( '' !== $this->notices ) {
echo $this->notices; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
/**
* Add note for rendering.
*
* @access public
* @since 3.5
* @param string $message The message to display.
* @param string $type The type of message.
* @return void
*/
public function add_notice( $message = '', $type = 'success' ) {
$this->notices .= '<div id="fusion-mailchimp-notice" class="notice notice-' . esc_attr( $type ) . ' avada-db-card avada-db-' . esc_attr( $type ) . '" style="display:block !important;"><h2>' . esc_html( $message ) . '</h2></div>';
}
/**
* Add fields options to live editor.
*
* @access public
* @since 3.5
* @return void
*/
public function oauth_enqueue() {
// Back-end TO page, enqueue so markup is updated.
if ( is_admin() && current_user_can( 'manage_options' ) && ( ( isset( $_GET['page'] ) && 'avada_options' === $_GET['page'] ) || isset( $_GET['mailchimp'] ) || isset( $_GET['revoke_mailchimp'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_api_script' ] );
}
// Live editor JS script always, in case they change value.
add_action( 'fusion_builder_enqueue_live_scripts', [ $this, 'enqueue_api_script' ] );
}
/**
* Add fields options to live editor.
*
* @access public
* @since 3.5
* @param array $data The data already added.
* @param int $page_id The post ID being edited.
* @param string $post_type The post type being edited.
* @return array $data The data with panel data added.
*/
public function add_preview_data( $data, $page_id = 0, $post_type = 'page' ) {
if ( 'fusion_form' === $post_type ) {
$data['mailchimp'] = [
'fields' => $this->get_all_fields(),
'group_cats' => $this->get_group_cats(),
'automatic' => __( 'Automatic Field', 'fusion-builder' ),
'none' => __( 'No Field', 'fusion-builder' ),
'common' => __( 'Common Fields', 'fusion-builder' ),
'other' => __( 'Other Fields', 'fusion-builder' ),
'group_category' => __( 'Group Category', 'fusion-builder' ),
];
}
return $data;
}
/**
* Enqueue script for handling OAuth.
*
* @since 3.5
* @access public
* @return void
*/
public function enqueue_api_script() {
wp_enqueue_script( 'fusion_mailchimp_oauth', FUSION_BUILDER_PLUGIN_URL . 'assets/admin/js/fusion-mailchimp-oauth.js', [], FUSION_BUILDER_VERSION, true );
wp_localize_script(
'fusion_mailchimp_oauth',
'fusionMailchimpOAuth',
[
'status' => $this->localize_status,
]
);
}
/**
* If we have details to try and connect.
*
* @since 3.5
* @access public
* @return mixed
*/
public function can_connect() {
if ( 'auth' === $this->type ) {
return $this->get_token();
} elseif ( 'key' === $this->type ) {
return $this->get_api_key();
}
return false;
}
/**
* Get the API key
*
* @since 3.5
* @access public
* @return mixed
*/
public function get_api_key() {
// We already have retrieved key.
if ( null !== $this->key ) {
return $this->key;
}
// No transient.
$fusion_settings = awb_get_fusion_settings();
$this->key = $fusion_settings->get( 'mailchimp_key' );
if ( empty( $this->key ) ) {
$this->key = false;
}
return $this->key;
}
/**
* Get the token data.
*
* @since 3.5
* @access public
* @return mixed
*/
public function get_token() {
// We already have retrieved a token, continue to use it.
if ( null !== $this->token ) {
return $this->token;
}
$this->token = get_option( 'fusion_mailchimp_token' );
// No transient.
if ( ! $this->token ) {
$this->token = false;
}
// Return what we have.
return $this->token;
}
/**
* Get the server prefix.
*
* @since 3.5
* @access public
* @return mixed
*/
public function get_server_prefix() {
// We already have retrieved a server prefix, continue to use it.
if ( null !== $this->dc ) {
return $this->dc;
}
if ( 'auth' === $this->type ) {
$this->dc = get_option( 'fusion_mailchimp_dc' );
} elseif ( 'key' === $this->type ) {
$key = $this->get_api_key();
$dc = explode( '-', $this->get_api_key() );
$this->dc = isset( $dc[1] ) ? $dc[1] : false;
}
// Return what we have.
return $this->dc;
}
/**
* Render info about connection status.
*
* @since 3.5
* @access public
* @return string
*/
public function maybe_render_button() {
$wpnonce = wp_create_nonce( 'awb-nonce-mailchimp' );
$auth_url = 'https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id=594428288149&redirect_uri=' . FUSION_UPDATES_URL . '/mailchimp-api&state=' . rawurlencode( admin_url( 'admin.php?page=avada&_wpnonce=' . $wpnonce ) );
$type = 'connected';
if ( isset( $_GET['error'] ) && ! empty( $_GET['error'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
$type = 'error';
} elseif ( ! $this->get_token() ) {
$type = 'no_token';
}
$output = '<div id="fusion-mailchimp-content">';
$output .= '<div data-id="error" style="display:' . ( 'error' === $type ? 'flex' : 'none' ) . '">';
$output .= '<span><strong>' . esc_html__( 'There was a problem when trying to connect. ', 'fusion-builder' ) . '</strong>';
$output .= '<a target="_blank" href="https://avada.com/documentation/how-to-integrate-mailchimp-with-avada-forms/">' . esc_html__( 'Mailchimp integration with Avada Forms documentation.', 'fusion-builder' ) . '</a></span>';
$output .= '<a class="button-primary" target="_blank" href="' . $auth_url . '">' . esc_html__( 'Try again.', 'fusion-builder' ) . '</a>';
$output .= '</div>';
$output .= '<div data-id="no_token" style="display:' . ( 'no_token' === $type ? 'flex' : 'none' ) . '">';
$output .= '<span><strong>' . esc_html__( 'Currently not connected. ', 'fusion-builder' ) . '</strong>';
$output .= '<a target="_blank" href="https://avada.com/documentation/how-to-integrate-mailchimp-with-avada-forms/">' . esc_html__( 'Mailchimp integration with Avada Forms documentation.', 'fusion-builder' ) . '</a></span>';
$output .= '<a class="button-primary" target="_blank" href="' . $auth_url . '">' . esc_html__( 'Connect with Mailchimp', 'fusion-builder' ) . '</a>';
$output .= '</div>';
$output .= '<div data-id="connected" style="display:' . ( 'connected' === $type ? 'flex' : 'none' ) . '">';
$output .= '<strong>' . esc_html__( 'Connected with Mailchimp', 'fusion-builder' ) . '</strong>';
$output .= '<a class="button-primary" target="_blank" href="' . esc_url( admin_url( 'admin.php?page=avada&revoke_mailchimp=1&_wpnonce=' . $wpnonce ) ) . '">' . __( 'Revoke Access', 'fusion-builder' ) . '</a>';
$output .= '</div>';
return $output;
}
/**
* Revoke account access.
*
* @since 3.5
* @access public
* @return void
*/
public function revoke_access() {
$this->reset_token();
$this->localize_response( 'revoke' );
$this->add_notice( __( 'Your Mailchimp account has been disconnected.', 'fusion-builder' ), 'success' );
$this->update_global( 'off' );
}
/**
* Update global Mailchimp option.
*
* @since 3.5
* @access public
* @param string $type Type of Mailchimp api.
* @return void
*/
private function update_global( $type = 'auth' ) {
$fusion_settings = awb_get_fusion_settings();
$fusion_settings->set( 'mailchimp_api', $type );
$this->type = $type;
delete_transient( 'fusion_tos' );
delete_transient( 'fusion_fb_tos' );
}
/**
* Localize the API scripts.
*
* @since 3.5
* @access public
* @param string $status Status type for localization.
* @return void
*/
private function localize_response( $status = 'error' ) {
$this->localize_status = $status;
}
/**
* Reset stored access token.
*
* @since 3.5
* @access public
* @return void
*/
public function reset_token() {
delete_option( 'fusion_mailchimp_token' );
delete_option( 'fusion_mailchimp_dc' );
$this->token = null;
}
/**
* Retrieve API response.
*
* @since 3.5
* @access public
* @param string $action Action/endpoint for API.
* @param array $options Options for request.
* @return mixed
*/
public function api_request( $action = '', $options = [] ) {
if ( '' === $action || ! $this->can_connect() || ! $this->get_server_prefix() ) {
return false;
}
$method = 'GET';
$submission_response = [];
$url = 'https://' . $this->get_server_prefix() . '.api.mailchimp.com/3.0/';
$args = [
'headers' => [
'User-Agent' => 'Fusion Mailchimp',
],
'timeout' => 60,
'headers_data' => false,
];
// Shared args.
if ( 'auth' === $this->type ) {
$args['headers']['Authorization'] = 'Bearer ' . $this->token;
}
// Switch for action, vary url and args.
switch ( $action ) {
case 'get_lists':
$url = $url . 'lists?count=1000&fields=lists.id,lists.name';
break;
case 'get_groups':
$url = $url . 'lists/' . $options['id'] . '/interest-categories/' . $options['groups_category_id'] . '/interests?count=1000&fields=interests.id,interests.name';
break;
case 'get_group_cats':
$url = $url . 'lists/' . $options['id'] . '/interest-categories?count=1000&fields=categories.id,categories.title';
break;
case 'add_group':
$url = $url . 'lists/' . $options['id'] . '/interest-categories/' . $options['groups_category_id'] . '/interests';
$args['body'] = wp_json_encode(
[
'name' => $options['new_group_name'],
]
);
$args['method'] = 'POST';
$method = 'POST';
break;
case 'get_tags':
$url = $url . 'lists/' . $options['id'] . '/segments?count=1000&fields=segments.id,segments.name&type=static';
break;
case 'get_fields':
$url = $url . 'lists/' . $options['id'] . '/merge-fields?count=1000';
break;
case 'update_member':
$url = $url . 'lists/' . $options['id'] . '/members/' . md5( strtolower( $options['email'] ) );
$args['body'] = wp_json_encode( $options['body'] );
$args['method'] = 'PUT';
$method = 'POST';
break;
}
// Check for no URL.
if ( ! $url ) {
return;
}
// If we are connecting via key, add it.
if ( 'key' === $this->type ) {
$args['headers']['Authorization'] = 'apikey: ' . $this->key;
}
// If we are connecting via token, add it.
if ( 'auth' === $this->type ) {
$args['headers']['Authorization'] = 'apikey: ' . $this->token;
}
// We have URL, token, action and args. Send the API request.
if ( 'GET' === $method ) {
$response = wp_remote_get( $url, $args );
} else {
$response = wp_remote_request( $url, $args );
}
// Token invalid, reset token.
if ( 401 === (int) wp_remote_retrieve_response_code( $response ) ) {
$this->reset_token();
$this->api_request( $action, $options );
}
// Check for error.
if ( ! is_wp_error( $response ) && isset( $response['body'] ) ) {
if ( is_array( $response ) && isset( $response['response']['code'] ) && 200 !== $response['response']['code'] ) {
$response = json_decode( $response['body'], true );
$submission_response = [
'status' => $response['status'],
'detail' => isset( $response['detail'] ) ? $response['detail'] : '',
'errors' => isset( $response['errors'] ) ? $response['errors'] : [],
];
return 'update_member' === $action ? wp_json_encode( $submission_response ) : false;
} else {
$submission_response = [
'status' => isset( $response['response']['code'] ) ? $response['response']['code'] : '',
'message' => isset( $response['response']['message'] ) ? $response['response']['message'] : '',
];
return 'update_member' === $action ? wp_json_encode( $submission_response ) : json_decode( $response['body'], true );
}
}
return false;
}
/**
* Add field data.
*
* @since 3.5
* @access public
* @param string $post_type Post type being added to.
* @return void
*/
public function option_script( $post_type ) {
// Not editing a form then we don't need it.
if ( 'fusion_form' !== $post_type ) {
return;
}
// No connection to API then it can't work.
if ( ! $this->can_connect() ) {
return;
}
wp_enqueue_script( 'fusion_mailchimp_option', FUSION_BUILDER_PLUGIN_URL . 'assets/admin/js/fusion-mailchimp-option.js', [], FUSION_BUILDER_VERSION, true );
$fields = $this->get_all_fields();
if ( $fields ) {
// Add field data.
wp_localize_script(
'fusion_mailchimp_option',
'fusionMailchimp',
[
'fields' => $fields,
'group_cats' => $this->get_group_cats(),
'automatic' => __( 'Automatic Field', 'fusion-builder' ),
'none' => __( 'No Field', 'fusion-builder' ),
'common' => __( 'Common Fields', 'fusion-builder' ),
'other' => __( 'Other Fields', 'fusion-builder' ),
'group_category' => __( 'Group Category', 'fusion-builder' ),
]
);
}
}
/**
* Get full array of fields.
*
* @since 3.5
* @access public
* @return mixed
*/
public function get_all_fields() {
// Have already retrieved, return.
if ( null !== $this->fields ) {
return $this->fields;
}
// Retrieve from transient if available.
$fields = get_transient( 'fusion_mailchimp_fields' );
if ( $fields ) {
$this->fields = $fields;
return $this->fields;
}
// Not in transient, need to request it.
$lists = $this->get_lists();
if ( is_array( $lists ) && ! empty( $lists ) ) {
foreach ( $lists['lists'] as $list ) {
$fields_data[] = [
'tag' => 'EMAIL',
'name' => __( 'Email Address', 'fusion-builder' ),
'type' => 'email',
'help_text' => '',
'merge_id' => '0',
];
$fields = $this->api_request( 'get_fields', [ 'id' => $list['id'] ] );
foreach ( $fields['merge_fields'] as $field ) {
$fields_data[] = [
'tag' => $field['tag'],
'name' => $field['name'],
'type' => $field['type'],
'help_text' => $field['help_text'],
'merge_id' => $field['merge_id'],
];
}
$this->fields[ $list['id'] ] = [
'name' => $list['name'],
'fields' => $fields_data,
];
}
}
if ( $this->fields ) {
$this->add_transient_key( 'fusion_mailchimp_fields' );
set_transient( 'fusion_mailchimp_fields', $this->fields, DAY_IN_SECONDS );
}
return $this->fields;
}
/**
* Get full array of lists;
*
* @since 3.5
* @access public
* @return mixed
*/
public function get_lists() {
$key = 'fusion_mailchimp_lists';
// Have already retrieved, return.
if ( null !== $this->lists ) {
return $this->lists;
}
// Retrieve from transient if available.
$lists = get_transient( $key );
if ( $lists ) {
$this->lists = $lists;
return $this->lists;
}
// Not in transient, need to request it.
$this->lists = $this->api_request( 'get_lists' );
if ( $this->lists ) {
$this->add_transient_key( $key );
set_transient( $key, $this->lists, DAY_IN_SECONDS );
}
return $this->lists;
}
/**
* Get the tags from list;
*
* @since 3.10.2
* @access public
* @param int $list_id The id.
* @return mixed
*/
public function get_tags( $list_id ) {
// Retrieve from transient if available.
$key = 'fusion_mailchimp_tags_' . $list_id;
$this->add_transient_key( $key ); // temp.
$tags = get_transient( $key );
if ( $tags ) {
return $tags;
}
// Not in transient, need to request it.
$tags = $this->api_request( 'get_tags', [ 'id' => $list_id ] );
if ( $tags ) {
$this->add_transient_key( $key );
set_transient( $key, $tags, DAY_IN_SECONDS );
}
return $tags;
}
/**
* Get the groups categories from list;
*
* @since 3.10.2
* @access public
* @return mixed
*/
public function get_group_cats() {
// Have already retrieved, return.
if ( null !== $this->group_cats ) {
return $this->group_cats;
}
$key = 'fusion_mailchimp_group_cats';
// Retrieve from transient if available.
$group_cats = get_transient( $key );
if ( $group_cats ) {
$this->group_cats = $group_cats;
return $this->group_cats;
}
// Not in transient, need to request it.
$lists = $this->get_lists();
if ( is_array( $lists ) && ! empty( $lists ) ) {
foreach ( $lists['lists'] as $list ) {
$group_cats = $this->api_request( 'get_group_cats', [ 'id' => $list['id'] ] );
if ( isset( $group_cats['categories'] ) ) {
$this->group_cats[ $list['id'] ] = [
'name' => $list['name'],
'categories' => $group_cats['categories'],
];
}
}
}
if ( $this->group_cats ) {
$this->add_transient_key( $key );
set_transient( $key, $this->group_cats, DAY_IN_SECONDS );
}
return $this->group_cats;
}
/**
* Get the groups categories from list;
*
* @since 3.10.2
* @access public
* @param int $list_id The list id.
* @param int $cat_id The cat id.
* @return mixed
*/
public function get_groups( $list_id, $cat_id ) {
$key = 'fusion_mailchimp_groups_' . $cat_id . $list_id;
// Retrieve from transient if available.
$group_cats = get_transient( $key );
if ( $group_cats ) {
return $group_cats;
}
// Not in transient, need to request it.
$group_cats = $this->api_request(
'get_groups',
[
'id' => $list_id,
'groups_category_id' => $cat_id,
]
);
if ( $group_cats ) {
$this->add_transient_key( $key );
set_transient( $key, DAY_IN_SECONDS );
}
return $group_cats;
}
/**
* Add transient key. this function for save the dynamic transient keys for delete it when using reset cache handler.
*
* @since 3.11
* @access public
* @param string $key The key.
* @return void
*/
public function add_transient_key( $key ) {
$saved_keys = get_transient( 'fusion-mailchimp-transient-keys' );
if ( ! is_array( $saved_keys ) ) {
$saved_keys = [];
}
$saved_keys[] = $key;
set_transient( 'fusion-mailchimp-transient-keys', $saved_keys, DAY_IN_SECONDS );
}
/**
* Get the token data and store it.
*
* @since 3.5
* @access public
* @return void
*/
public function authenticate() {
// Some kind of error reporting here.
if ( ! isset( $_GET['token'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$this->localize_response( 'error' );
$this->add_notice( __( 'There was an error authenticating your Mailchimp token.', 'fusion-builder' ), 'notice' );
return;
}
// Transient with expiry to match.
$token = sanitize_text_field( wp_unslash( $_GET['token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
$dc = sanitize_text_field( wp_unslash( $_GET['dc'] ) ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
update_option( 'fusion_mailchimp_token', $token );
update_option( 'fusion_mailchimp_dc', $dc );
$this->token = $token;
$this->dc = $dc;
$this->localize_response( 'success' );
$this->add_notice( __( 'Your Mailchimp account has been successfully connected.', 'fusion-builder' ), 'success' );
$this->update_global( 'auth' );
}
/**
* Create a Mailchimp contact.
*
* @since 3.5
* @access public
* @param array $form_data Data from form which needs to be stored.
* @param array $form_id The form ID.
* @param array $labels Array of label and field names.
* @return mixed
*/
public function create_contact( $form_data, $form_id, $labels = [] ) {
$list_id = fusion_data()->post_meta( $form_id )->get( 'mailchimp_lists' );
$tags = fusion_data()->post_meta( $form_id )->get( 'mailchimp_tags' );
$groups_cat = fusion_data()->post_meta( $form_id )->get( 'mailchimp_groups_category' );
$groups_field = fusion_data()->post_meta( $form_id )->get( 'mailchimp_groups_field' );
$mapping = fusion_data()->post_meta( $form_id )->get( 'mailchimp_map' );
$opt_in = fusion_data()->post_meta( $form_id )->get( 'mailchimp_double_opt_in' );
$orig_form_data = $form_data;
if ( ! empty( $mapping ) && is_string( $mapping ) ) {
$mapping = json_decode( $mapping, true );
}
// Fields list, try to auto match.
$fields = (array) $this->get_all_fields();
$fields = ! empty( $list_id ) ? $fields[ $list_id ] : [];
$fields = is_array( $fields ) && isset( $fields['fields'] ) ? $fields['fields'] : [];
// Empty starting data.
$mapped_data = [];
// Request options.
$options = [];
// Array of assigned fields.
$used_fields = [];
$group_fields = [];
// Loop each form field to check for mapping match.
foreach ( $form_data['data'] as $field => $value ) {
$field_value = ( is_array( $value ) ) ? implode( ' | ', $value ) : $value;
// Update to correct format.
$form_data['data'][ $field ] = $field_value;
// Check if we have a desired field set in map.
if ( isset( $mapping[ $field ] ) && '' !== $mapping[ $field ] ) {
// If its set to have no field match, entirely exclude from matching.
if ( 'fusion-none' === $mapping[ $field ] ) {
unset( $form_data['data'][ $field ] );
unset( $labels[ $field ] );
continue;
}
// If we are matching to email, set as target contact.
if ( 'EMAIL' === $mapping[ $field ] ) {
$options['email'] = $field_value;
}
// Add to mapped data we will send.
$mapped_data[ $mapping[ $field ] ] = $field_value;
$used_fields[ $mapping[ $field ] ] = true;
if ( strpos( $mapping[ $field ], 'group-category-' ) === 0 ) {
$group_fields[ $field ] = str_replace( 'group-category-', '', $mapping[ $field ] );
}
}
}
// Auto matching if not all are set already.
if ( count( $form_data['data'] ) !== count( $mapped_data ) ) {
foreach ( $fields as $field ) {
$value = false;
// Field is already assigned, do not assign again.
if ( isset( $used_fields[ $field['tag'] ] ) ) {
continue;
}
// Field name matches input name.
if ( isset( $form_data['data'][ $field['name'] ] ) ) {
$value = $form_data['data'][ $field['name'] ];
$mapped_data[ $field['tag'] ] = $value;
// Field tag matches input label.
} elseif ( false !== $field_id = array_search( $field['tag'], $labels, true ) ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments, Generic.CodeAnalysis.AssignmentInCondition
$value = $form_data['data'][ $field_id ];
$mapped_data[ $field['tag'] ] = $value;
// Field name matches input label.
} elseif ( false !== $field_id = array_search( $field['name'], $labels, true ) ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments, Generic.CodeAnalysis.AssignmentInCondition
$value = $form_data['data'][ $field_id ];
$mapped_data[ $field['tag'] ] = $value;
// Field tag matches input name.
} elseif ( isset( $form_data['data'][ str_replace( ' ', '', strtolower( $field['tag'] ) ) ] ) ) {
$field_id = str_replace( ' ', '', strtolower( $field['tag'] ) );
$value = $form_data['data'][ $field_id ];
$mapped_data[ $field['tag'] ] = $value;
}
// If email is one, add to options.
if ( $value && 'email' === $field['name'] ) {
$options['email'] = $value;
}
}
}
// No valid email, contact cannot be created or updated.
if ( ! isset( $options['email'] ) || empty( $options['email'] ) ) {
return;
}
// We made it this far, add data and set request.
$options['body']['merge_fields'] = $mapped_data;
$options['body']['email_address'] = $options['email'];
$options['body']['status_if_new'] = 'yes' === $opt_in ? 'pending' : 'subscribed';
$options['body']['status'] = 'subscribed';
$options['id'] = $list_id;
if ( ! empty( $tags ) ) {
$options['body']['tags'] = $tags;
}
$interests = [];
if ( ! empty( $group_fields ) ) {
foreach ( $group_fields as $field_name => $cat_id ) {
$options['groups_category_id'] = $cat_id;
$groups = $this->api_request( 'get_groups', $options );
$groups = isset( $groups['interests'] ) ? $groups['interests'] : [];
$groups_with_lower_names = [];
foreach ( $groups as $group ) {
$groups_with_lower_names[] = [
'id' => $group['id'],
'name' => strtolower( $group['name'] ),
];
}
$group_field_data = isset( $orig_form_data['data'][ $field_name ] ) ? $orig_form_data['data'][ $field_name ] : [];
if ( ! is_array( $group_field_data ) ) {
$group_field_data = [ $group_field_data ];
}
$group_field_data = array_map( 'strtolower', $group_field_data );
foreach ( $groups_with_lower_names as $group ) {
if ( in_array( $group['name'], $group_field_data, true ) ) {
$interests[ $group['id'] ] = true;
} else {
$interests[ $group['id'] ] = false;
}
}
foreach ( $group_field_data as $group_name ) {
if ( ! in_array( $group_name, array_column( $groups_with_lower_names, 'name' ), true ) ) {
$options['new_group_name'] = ucfirst( $group_name );
$new_group = $this->api_request( 'add_group', $options );
if ( isset( $new_group['id'] ) ) {
$interests[ $new_group['id'] ] = true;
}
}
}
}
}
if ( ! empty( $interests ) ) {
$options['body']['interests'] = $interests;
}
return $this->api_request( 'update_member', $options );
}
/**
* Creates or returns an instance of this class.
*
* @static
* @access public
* @param array $sections Page options.
* @since 3.5
*/
public function maybe_add_option( $sections ) {
if ( 'off' === $this->type ) {
$mailchimp_link = '<a target="_blank" rel="noopener noreferrer" href="http://eepurl.com/hCanr5">Mailchimp account</a>';
$document_link = '<a target="_blank" rel="noopener noreferrer" href="https://avada.com/documentation/how-to-integrate-mailchimp-with-avada-forms/">Mailchimp integration guide</a>';
$sections['form_submission']['fields']['mailchimp_info'] = [
'type' => 'custom',
'label' => '',
/* translators: 1: Mailchimp link. 2: Documentation link. */
'description' => '<div class="fusion-redux-important-notice">' . sprintf( __( 'Sign up for a %1$s and manage your contacts in their free CRM. For more information check out our %2$s. ', 'fusion-builder' ), $mailchimp_link, $document_link ) . '</div>',
'id' => 'mailchimp_info',
'dependency' => [
[
'field' => 'form_type',
'value' => 'ajax',
'comparison' => '==',
],
[
'field' => 'form_actions',
'value' => 'mailchimp',
'comparison' => 'contains',
],
],
];
return $sections;
}
$lists = $this->get_lists();
if ( $this->can_connect() && $lists ) {
$lists_data = [];
$tags_data = [];
$group_cats_data = [];
foreach ( $lists['lists'] as $list ) {
$lists_data[ $list['id'] ] = $list['name'];
$tags = $this->get_tags( $list['id'] );
if ( is_array( $tags ) && isset( $tags['segments'] ) ) {
foreach ( $tags['segments'] as $tag ) {
$tags_data[ $tag['name'] ] = $tag['name'];
}
}
}
$sections['form_submission']['fields']['mailchimp_options'] = [
'type' => 'toggle',
'row_title' => esc_html__( 'Mailchimp', 'fusion-builder' ),
'id' => 'mailchimp_options',
'dependency' => [
[
'field' => 'form_type',
'value' => 'ajax',
'comparison' => '==',
],
[
'field' => 'form_actions',
'value' => 'mailchimp',
'comparison' => 'contains',
],
],
'fields' => [
'mailchimp_info' => [
'type' => 'custom',
'label' => '',
'description' => '<div class="fusion-redux-important-notice">' . __( 'You are currently connected to the Mailchimp API.', 'fusion-builder' ) . '</div>',
'id' => 'mailchimp_info',
],
'mailchimp_action' => [
'type' => 'radio-buttonset',
'label' => esc_html__( 'Mailchimp Action', 'fusion-builder' ),
'description' => esc_html__( 'Select if you want to perform a Mailchimp action after form submission.', 'fusion-builder' ),
'id' => 'mailchimp_action',
'default' => 'no',
'transport' => 'postMessage',
'choices' => [
'no' => esc_html__( 'None', 'fusion-builder' ),
'contact' => esc_html__( 'Create/Update Contact', 'fusion-builder' ),
],
],
'mailchimp_lists' => [
'type' => 'select',
'label' => esc_html__( 'Mailchimp List', 'fusion-builder' ),
'description' => __( 'Select Mailchimp list.', 'fusion-builder' ),
'id' => 'mailchimp_lists',
'choices' => $lists_data,
'transport' => 'postMessage',
'dependency' => [
[
'field' => 'mailchimp_action',
'value' => 'contact',
'comparison' => '==',
],
],
],
'mailchimp_tags' => [
'type' => 'multiple_select',
'label' => esc_html__( 'Mailchimp Tags', 'fusion-builder' ),
'description' => __( 'Select one or more. Selected tags will be added to all subscribers of this form.', 'fusion-builder' ),
'id' => 'mailchimp_tags',
'choices' => $tags_data,
'transport' => 'postMessage',
'dependency' => [
[
'field' => 'mailchimp_action',
'value' => 'contact',
'comparison' => '==',
],
],
],
'mailchimp_double_opt_in' => [
'type' => 'radio-buttonset',
'label' => esc_html__( 'Double Opt-In', 'fusion-builder' ),
'description' => __( 'With double opt-in, everyone who signs up will receive a follow-up email with a confirmation link to verify their subscription.', 'fusion-builder' ),
'id' => 'mailchimp_double_opt_in',
'default' => 'no',
'transport' => 'postMessage',
'choices' => [
'yes' => esc_html__( 'Yes', 'fusion-builder' ),
'no' => esc_html__( 'No', 'fusion-builder' ),
],
'dependency' => [
[
'field' => 'mailchimp_action',
'value' => 'contact',
'comparison' => '==',
],
[
'field' => 'mailchimp_lists',
'value' => '',
'comparison' => '!=',
],
],
],
'mailchimp_consent' => [
'type' => 'select',
'label' => esc_html__( 'Form Consent', 'fusion-builder' ),
'description' => __( 'Select the form consent field which has a description of the communication preference.', 'fusion-builder' ),
'id' => 'mailchimp_consent',
'transport' => 'postMessage',
'choices' => [
'' => esc_html__( 'No Consent', 'fusion-builder' ),
],
'dependency' => [
[
'field' => 'mailchimp_action',
'value' => 'contact',
'comparison' => '==',
],
[
'field' => 'mailchimp_lists',
'value' => '',
'comparison' => '!=',
],
],
],
'mailchimp_map' => [
'type' => 'mailchimp_map',
'label' => esc_html__( 'Mailchimp Mapping', 'fusion-builder' ),
'description' => __( 'Map fields from the form to Mailchimp list merge tags. <strong>NOTE:</strong> The email property is required for creating or updating a contact. When mapping is set to "Automatic", Avada will try to map based on field label, name and tags.', 'fusion-builder' ),
'id' => 'mailchimp_map',
'transport' => 'postMessage',
'dependency' => [
[
'field' => 'mailchimp_action',
'value' => 'contact',
'comparison' => '==',
],
[
'field' => 'mailchimp_lists',
'value' => '',
'comparison' => '!=',
],
],
],
],
];
return $sections;
}
$mailchimp_link = '<a target="_blank" rel="noopener noreferrer" href="' . esc_url( admin_url( 'themes.php?page=avada_options#mailchimp_api' ) ) . '">Mailchimp</a>';
$sections['form_submission']['fields']['mailchimp_info'] = [
'type' => 'custom',
'label' => '',
/* translators: Global link. */
'description' => '<div class="fusion-redux-important-notice">' . sprintf( __( 'Connect to your %s account to create contacts from your form.', 'fusion-builder' ), $mailchimp_link ) . '</div>',
'id' => 'mailchimp_info',
];
return $sections;
}
/**
* Handles resetting caches.
*
* @access public
* @since 3.5
* @return void
*/
public function reset_caches_handler() {
if ( ! is_admin() || ! current_user_can( 'manage_options' ) || ! check_ajax_referer( 'fusionredux_ajax_noncefusion_options', 'nonce' ) ) {
return;
}
if ( is_multisite() && is_main_site() ) {
$sites = get_sites();
foreach ( $sites as $site ) {
switch_to_blog( $site->blog_id );
$this->delete_cache();
restore_current_blog();
}
return;
}
$this->delete_cache();
}
/**
* Delete cache.
*
* @access public
* @since 3.11
* @return void
*/
public function delete_cache() {
$transient_keys = get_transient( 'fusion-mailchimp-transient-keys' );
if ( is_array( $transient_keys ) ) {
foreach ( $transient_keys as $key ) {
delete_transient( $key );
}
delete_transient( 'fusion-mailchimp-transient-keys' );
}
}
/**
* Creates or returns an instance of this class.
*
* @static
* @access public
* @since 3.5
*/
public static function get_instance() {
// If an instance hasn't been created and set to $instance create an instance and set it to $instance.
if ( null === self::$instance ) {
self::$instance = new Fusion_Mailchimp();
}
return self::$instance;
}
}
/**
* Instantiates the Fusion_Mailchimp class.
* Make sure the class is properly set-up.
*
* @since object 3.5
* @return object Fusion_App
*/
function Fusion_Mailchimp() { // phpcs:ignore WordPress.NamingConventions
return Fusion_Mailchimp::get_instance();
}
Fusion_Mailchimp();