1309 lines
37 KiB
PHP
1309 lines
37 KiB
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();
|