$e) ; } } return self::$api; } public function subscribe( Hustle_Module_Model $module, array $data ){ $api = self::api( self::_get_api_key( $module ) ); $list_id = self::_get_list_id( $module ); $sub_status = self::_get_auto_optin( $module ); if ( empty( $api ) ) { $err = new WP_Error(); $err->add( 'server_failed', __( 'API Key is not defined!', Opt_In::TEXT_DOMAIN ) ); return $err; } $email = $data['email']; $merge_vals = array(); $interests = array(); if ( isset( $data['first_name'] ) ) { $merge_vals['MERGE1'] = $data['first_name']; $merge_vals['FNAME'] = $data['first_name']; } elseif ( isset( $data['f_name'] ) ) { $merge_vals['MERGE1'] = $data['f_name']; // Legacy $merge_vals['FNAME'] = $data['f_name']; // Legacy } if ( isset( $data['last_name'] ) ) { $merge_vals['MERGE2'] = $data['last_name']; $merge_vals['LNAME'] = $data['last_name']; } elseif ( isset( $data['l_name'] ) ) { $merge_vals['MERGE2'] = $data['l_name']; // Legacy $merge_vals['LNAME'] = $data['l_name']; // Legacy } // Add extra fields $merge_data = array_diff_key( $data, array( 'email' => '', 'first_name' => '', 'last_name' => '', 'f_name' => '', 'l_name' => '', 'mailchimp_group_id' => '', 'mailchimp_group_interest' => '', ) ); $merge_data = array_filter( $merge_data ); if ( ! empty( $merge_data ) ) { $merge_vals = array_merge( $merge_vals, $merge_data ); } $merge_vals = array_change_key_case($merge_vals, CASE_UPPER); /** * Add args for interest groups */ if( !empty( $data['mailchimp_group_id'] ) && !empty( $data['mailchimp_group_interest'] ) ){ $data_interest = (array) $data['mailchimp_group_interest']; foreach( $data_interest as $interest ) { $interests[$interest] = true; } } try { $subscribe_data = array( 'email_address' => $email, 'status' => $sub_status ); if ( !empty($merge_vals) ) { $subscribe_data['merge_fields'] = $merge_vals; } if ( !empty($interests) ) { $subscribe_data['interests'] = $interests; } $existing_member = $this->get_member( $email, $module, $data ); if ( $existing_member ) { $member_interests = isset($existing_member->interests) ? (array) $existing_member->interests : array(); $can_subscribe = false; if ( isset( $subscribe_data['interests'] ) ){ $local_interest_keys = array_keys( $subscribe_data['interests'] ); if ( !empty( $member_interests ) ) { foreach( $member_interests as $member_interest => $subscribed ){ if( !$subscribed && in_array( $member_interest, $local_interest_keys ) ){ $can_subscribe = true; } } } else { $can_subscribe = true; } } if ( isset( $subscribe_data['interests'] ) && $can_subscribe ) { unset( $subscribe_data['email_address'] ); unset( $subscribe_data['merge_fields'] ); unset( $subscribe_data['status'] ); $response = $api->update_subscription( $list_id, $email, $subscribe_data ); return array( 'message' => $response, 'existing' => true); } else { $err = new WP_Error(); $err->add( 'email_exist', __( 'This email address has already subscribed', Opt_In::TEXT_DOMAIN ) ); return $err; } } else { $result = $api->subscribe( $list_id, $subscribe_data ); return $result; } } catch( Exception $e ) { $data['error'] = $e->getMessage(); $module->log_error( $data ); $err = new WP_Error(); $err->add( 'server_failed', __( 'Something went wrong. Please try again.', Opt_In::TEXT_DOMAIN ) ); return $err; } } /** * @param string $email * @param Hustle_Module_Model $module * @param array $data * * @return Object Returns the member if the email address already exists otherwise false. */ function get_member( $email, Hustle_Module_Model $module, $data ) { $api = self::api( self::_get_api_key( $module ) ); try { $member_info = $api->check_email( self::_get_list_id( $module ), $email); // Mailchimp returns WP error if can't find member on a list if ( is_wp_error( $member_info ) && $member_info->get_error_code() == 404 ) { return false; } return $member_info; } catch( Exception $e ) { $data['error'] = $e->getMessage(); $module->log_error($data); return false; } } function get_options( $module_id ) { //Load more function $load_more = filter_input( INPUT_POST, 'load_more' ); $lists = array(); if ( $load_more ) { $response = $this->lists_pagination( $this->api_key ); list( $lists, $total ) = $response; } else { $response = self::api( $this->api_key )->get_lists(); $_lists = $response->lists; $total = $response->total_items; if( is_array( $_lists ) ) { foreach( $_lists as $list ) { $list = (array) $list; $lists[ $list['id'] ]['value'] = $list['id']; $lists[ $list['id'] ]['label'] = $list['name']; } delete_site_transient( self::LIST_PAGES ); } } $total_lists = count( $lists ); $first = $total_lists > 0 ? reset( $lists ) : ""; if( !empty( $first ) ) $first = $first['value']; $default_options = array( "label" => array( "id" => "optin_email_list_label", "for" => "optin_email_list", "value" => __("Choose email list:", Opt_In::TEXT_DOMAIN), "type" => "label", ), "choose_email_list" => array( "type" => 'select', 'name' => "optin_email_list", 'id' => "wph-email-provider-lists", "default" => "", 'options' => $lists, 'value' => $first, 'selected' => $first, "attributes" => array( "data-nonce" => wp_create_nonce("mailchimp_choose_email_list"), 'class' => "wpmudev-select mailchimp_optin_email_list" ) ), 'loadmore' => array( "id" => "loadmore_mailchimp_lists", "name" => "loadmore_mailchimp_lists", "type" => "button", "value" => __("Load More Lists", Opt_In::TEXT_DOMAIN), 'class' => "wpmudev-button wph-button--spaced wph-button wph-button--filled wph-button--gray mailchimp_optin_load_more_lists" ) ); if ( $total_lists <= 0 ) { //If we have no items, no need to show the button unset( $default_options['loadmore'] ); } else if ( $total <= $total_lists ) { //If we have reached the end, remove the button unset( $default_options['loadmore'] ); } $list_group_options = self::_get_list_group_options( $this->api_key, $first ); return array_merge( $default_options, array( "wph-optin-list-groups-wrapper" => array( "id" => "wph-optin-list-groups", "class" => "wph-optin-list-groups", "type" => "wrapper", "elements" => is_a( $list_group_options, "Mailchimp_Error" ) ? array() : $list_group_options ), "wph-optin-list-group-interests-wrapper" => array( "id" => "wph-optin-list-group-interests-wrap", "class" => "wph-optin-list-group-interests-wrap", "type" => "wrapper", "elements" => array() ) )); } /** * Lists pagination * * @return array */ function lists_pagination( $api_key ) { $lists = array(); $list_pages = get_site_transient( self::LIST_PAGES ); $offset = 2; //Default limit to first page $total = 0; //Default we have 0 if ( $list_pages ) { $total = isset( $list_pages['total'] ) ? $list_pages['total'] : 0; $offset = isset( $list_pages['offset'] ) ? $list_pages['offset'] : 2; } else { $list_pages = array(); } if ( $offset > 0 ) { $response = self::api( $api_key )->get_lists( $offset ); $_lists = $response->lists; $total = $response->total_items; if ( is_array( $_lists ) ) { foreach( $_lists as $list ){ $list = (array) $list; $lists[ $list['id'] ]['value'] = $list['id']; $lists[ $list['id'] ]['label'] = $list['name']; } if ( count( $_lists ) >= $total ) { $offset = 0; //We have reached the end. No more pagination } else { $offset = $offset + 1; } $list_pages['offset'] = $offset; $list_pages['total'] = $total; set_site_transient( self::LIST_PAGES , $list_pages ); } else { delete_site_transient( self::LIST_PAGES ); } } else { delete_site_transient( self::LIST_PAGES ); } return array( $lists, $total ); } function get_account_options( $module_id ){ $module = Hustle_Module_Model::instance()->get( $module_id ); $api_key = self::_get_api_key( $module ); $checked = self::_get_auto_optin( $module ); return array( "label" => array( "id" => "optin_api_key_label", "for" => "optin_api_key", "value" => __("Choose your API key:", Opt_In::TEXT_DOMAIN), "type" => "label", ), "wrapper" => array( "id" => "", "class" => "wpmudev-provider-group", "type" => "wrapper", "elements" => array( "api_key" => array( "id" => "optin_api_key", "name" => "optin_api_key", "type" => "text", "default" => "", "value" => $api_key, "placeholder" => "", "class" => "wpmudev-input_text" ), 'refresh' => array( "id" => "refresh_mailchimp_lists", "name" => "refresh_mailchimp_lists", "type" => "ajax_button", "value" => "" . __( "Fetch Lists", Opt_In::TEXT_DOMAIN ) . "", "class" => "wpmudev-button wpmudev-button-sm optin_refresh_provider_details" ), ) ), "instructions" => array( "id" => "optin_api_instructions", "for" => "", "value" => sprintf( __("Log in to your MailChimp account to get your API Key.", Opt_In::TEXT_DOMAIN), 'https://admin.mailchimp.com/account/api/' ), "type" => "small", ), "subscription_setup" => array( "id" => "", "class" => "wpmudev-switch-labeled", "type" => "wrapper", "elements" => array( "subscription_mode" => array( "id" => "", "class" => "wpmudev-switch", "type" => "wrapper", "elements" => array( "opt_in" => array( "type" => 'checkbox', 'name' => "optin_auto_optin", 'id' => "optin_auto_optin", "default" => "", 'value' => "pending", "attributes" => array( 'class' => "toggle-checkbox", 'checked' => ( $checked != 'pending') ? 'checked' : '' ) ), "label" => array( "id" => "optin_auto_optin_label", "for" => "optin_auto_optin", "value" => "", "type" => "label", "attributes" => array( 'class' => "wpmudev-switch-design" ) ) ), ), "switch_instructions" => array( "id" => "optin_auto_optin_label", "for" => "optin_auto_optin", "value" => __("Automatically opt-in new users to the mailing list", Opt_In::TEXT_DOMAIN), "type" => "label", "attributes" => array( 'class' => "wpmudev-switch-label" ) ), ) ), ); } function is_authorized(){ return true; } function get_args( $data ) { if ( $data && isset( $data['email_services'] ) ) { $email_services = $data['email_services']; $list_id = ( isset( $email_services['mailchimp']['list_id'] ) ) ? $email_services['mailchimp']['list_id'] : ''; $group_id = ( isset( $email_services['mailchimp']['group'] ) ) ? $email_services['mailchimp']['group'] : ''; $groups = $this->_get_group_interests( $list_id, $group_id ); if ( isset( $email_services['mailchimp']['group_interest'] ) ) { $groups['selected'] = $email_services['mailchimp']['group_interest']; } return $groups; } } /** * Returns options for the given $list_id * * @param $api_key * @param $list_id * @return array|Exception */ private static function _get_list_group_options( $api_key, $list_id ){ $group_options = array(); $options = array( -1 => array( "value" => -1, "label" => __( "No group", Opt_In::TEXT_DOMAIN ), "interests" => __("First choose interest group", Opt_In::TEXT_DOMAIN) ) ); $api = self::api( $api_key ); try{ $total_groups = $api->get_interest_categories( $list_id )->total_items; if ( $total_groups < 10 ) { $total_groups = 10; } $groups = (array) $api->get_interest_categories( $list_id, $total_groups )->categories; }catch (Exception $e){ return $e; } if( !is_array( $groups ) ) return $group_options; foreach( $groups as $group_key => $group ){ $group = (array) $group; // get interests for each group category $total_interests = $api->get_interests( $list_id, $group['id'] )->total_items; if ( $total_interests < 10 ) { $total_interests = 10; } $groups[$group_key]->interests = (array) $api->get_interests( $list_id, $group['id'], $total_interests )->interests; $options[ $group['id'] ]['value'] = $group['id']; $options[ $group['id'] ]['label'] = $group['title'] . " ( " . ucfirst( $group['type'] ) . " )"; } set_site_transient( self::GROUP_TRANSIENT . $list_id, $groups ); $first = current( $options ); return array( "mailchimp_groups_label" => array( "id" => "mailchimp_groups_label", "for" => "mailchimp_groups", "value" => __("Choose interest group:", Opt_In::TEXT_DOMAIN), "type" => "label", ), "mailchimp_groups" => array( "type" => 'select', 'name' => "mailchimp_groups", 'id' => "mailchimp_groups", 'class' => "wpmudev-select", "default" => "", 'options' => $options, 'value' => $first, 'selected' => $first, "attributes" => array( "data-nonce" => wp_create_nonce("mailchimp_groups") ) ), "mailchimp_groups_instructions" => array( "id" => "mailchimp_groups_instructions", //"class" => "wpmudev-label--notice", "value" => "", "type" => "label", ) ); } /** * Normalizes api response for groups interests * * * @since 1.0.1 * * @param $interest * @return mixed */ static function normalize_group_interest( $interest ){ $interest = (array) $interest; $interest_arr = array(); $interest_arr["label"] = $interest['name']; $interest_arr["value"] = $interest['id']; return $interest_arr; } /** * Returns interest for given $list_id, $group_id * * @since 1.0.1 * * @param $list_id * @param $group_id * @return array */ private static function _get_group_interests( $list_id, $group_id ){ $interests = array( -1 => array( "id" => -1, "label" => __("No default choice", Opt_In::TEXT_DOMAIN) ) ); $groups = get_site_transient( self::GROUP_TRANSIENT . $list_id ); if( !$groups || !is_array( $groups ) ) return $interests; $the_group = array(); foreach( $groups as $group ){ $group = (array) $group; if( $group["id"] == $group_id ) $the_group = $group; } if( $the_group === array() ) return $interests; if( in_array($the_group['type'], array("radio", "checkboxes", "hidden")) ) $interests = array(); $interests = array_merge( $interests, array_map( array(__CLASS__, "normalize_group_interest" ), $the_group['interests']) ); if( "hidden" === $the_group['type'] && isset( $the_group['interests'][0] ) ) { $interest = $the_group['interests'][0]; if ( is_object( $interest ) ) { $the_group['selected'] = $interest->id; } else { $the_group['selected'] = $interest['id']; } } return array( 'group' => $the_group, "interests" => $interests, "type" => $the_group['type'] ); } /** * @used by array_map in _get_group_interest_args to map interests to their id/value * * @since 1.0.1 * @param $interest * @return mixed */ private function _map_interests_to_ids( $interest ){ return $interest['value']; } /** * Get Provider Details * General function to get provider details from database based on key * * @param Hustle_Module_Model $module * @param String $field - the field name * * @return String */ private static function _get_provider_details( Hustle_Module_Model $module, $field ) { $details = ''; $name = self::ID; if ( !is_null( $module->content->email_services ) && isset( $module->content->email_services[$name] ) && isset( $module->content->email_services[$name][$field] ) ) { $details = $module->content->email_services[$name][$field]; } return $details; } private static function _get_api_key( Hustle_Module_Model $module ) { return self::_get_provider_details( $module, 'api_key' ); } private static function _get_list_id( Hustle_Module_Model $module ) { return self::_get_provider_details( $module, 'list_id' ); } private function _get_auto_optin( Hustle_Module_Model $module ) { $auto_optin = 'pending'; $saved_auto_optin = self::_get_provider_details( $module, 'auto_optin' ); if ( !empty( $saved_auto_optin ) && $saved_auto_optin !== 'pending' ) { $auto_optin = 'subscribed'; } return $auto_optin; } /** * Returns interest args for the given $group_id and $list_id * * @since 1.0.1 * * @param $list_id * @param $group_id * @return array */ private static function _get_group_interest_args( $list_id, $group_id ){ $interests_config = self::_get_group_interests( $list_id, $group_id ); $interests = $interests_config['interests']; $_type = $interests_config['type']; $type = "radio" === $interests_config['type'] ? "radios" : $interests_config['type']; $type = "dropdown" === $type || "hidden" === $type ? "select" : $type; $class = ( $type === 'select' ) ? 'wpmudev-select' : ''; $first = current( $interests ); $interests_config['group']['interests'] = array_map( array(__CLASS__, "normalize_group_interest" ), $interests_config['group']['interests'] ); $name = "mailchimp_groups_interests"; if( $type === "checkboxes" ) $name .= "[]"; $choose_prompt = __("Choose default interest:", Opt_In::TEXT_DOMAIN); if( $_type === "checkboxes" ) $choose_prompt = __("Choose default interest(s):", Opt_In::TEXT_DOMAIN); if( $_type === "hidden" ) $choose_prompt = __("Set default interest:", Opt_In::TEXT_DOMAIN); if( $type === "radios" ) $choose_prompt .= sprintf(" ( %s )", __("clear selection", Opt_In::TEXT_DOMAIN) ); return array( 'group' => $interests_config['group'], "fields" => array( "mailchimp_groups_interest_label" => array( "id" => "mailchimp_groups_interest_label", "for" => "mailchimp_groups_interests", "value" => $choose_prompt, "type" => "label", ), "mailchimp_groups_interests" => array( "type" => $type, 'name' => $name, 'id' => "mailchimp_groups_interests", "default" => "", 'options' => $interests, 'value' => $first, 'selected' => array(), 'class' => $class, "item_attributes" => array() ), "mailchimp_groups_interest_instructions" => array( "id" => "mailchimp_groups_interest_instructions", "for" => "", "value" => __( "What you select here will appear pre-selected for users. If this is a hidden group, the interest will be set but not shown to users.", Opt_In::TEXT_DOMAIN ), "type" => "label", ) ) ); } /** * Ajax endpoint to render html for group options based on given $list_id and $api_key * * @since 1.0.1 */ static function ajax_get_list_groups(){ Opt_In_Utils::validate_ajax_call( 'mailchimp_choose_email_list' ); $list_id = filter_input( INPUT_GET, 'optin_email_list' ); $api_key = filter_input( INPUT_GET, 'optin_api_key' ); $options = self::_get_list_group_options( $api_key, $list_id ); $html = ""; if( is_array( $options ) && !is_a( $options, "Mailchimp_Error" ) ){ foreach( $options as $option ) $html .= Opt_In::static_render("general/option", $option , true); wp_send_json_success( $html ); } wp_send_json_error( $options ); } /** * Ajax call endpoint to return interest options of give list id and group id * * @since 1.0.1 */ static function ajax_get_group_interests(){ Opt_In_Utils::validate_ajax_call( 'mailchimp_groups' ); $list_id = filter_input( INPUT_GET, 'optin_email_list' ); $group_id = filter_input( INPUT_GET, 'mailchimp_groups' ); $groups_config = get_site_transient( self::GROUP_TRANSIENT . $list_id ); if( !$groups_config || !is_array( $groups_config ) ) wp_send_json_error( __("Invalid list id: ", Opt_In::TEXT_DOMAIN) . $list_id ); $args = self::_get_group_interest_args( $list_id, $group_id ); $fields = $args['fields']; $html = ""; if ( is_array( $fields ) ) { foreach( $fields as $field ) { $html .= Opt_In::static_render("general/option", $field , true); } } wp_send_json_success( array( "html" => $html, "group" => $args['group'] ) ); } static function ajax_get_current_settings() { Opt_In_Utils::validate_ajax_call( 'optin_provider_current_settings' ); $list_id = filter_input( INPUT_GET, 'list_id' ); $group = filter_input( INPUT_GET, 'group' ); $groups_config = get_site_transient( self::GROUP_TRANSIENT . $list_id ); $selected = null; if ( $groups_config && is_array( $groups_config ) ) { foreach( $groups_config as $groups ){ if ( $groups->id === $group ) { $selected = $groups; } } } wp_send_json_success( array( "group" => $selected ) ); } static function add_custom_field( $fields, $module_id ) { $module = Hustle_Module_Model::instance()->get( $module_id ); $api_key = self::_get_api_key( $module ); $list_id = self::_get_list_id( $module ); try{ // Mailchimp does not support "email" field type so let's use text // use text as well for name, address and phone // returns either the new MailChimp "merge_field" object or WP error (if already existing) $api = self::api( $api_key ); foreach ( $fields as $field ) { $api->add_custom_field( $list_id, array( 'tag' => strtoupper( $field['name'] ), 'name' => $field['label'], 'type' => ( $field['type'] == 'email' || $field['type'] == 'name' || $field['type'] == 'address' || $field['type'] == 'phone' ) ? 'text' : $field['type'] ) ); } // double check if already on our system /*$current_module_fields = $module->get_design()->__get( 'module_fields' ); foreach( $current_module_fields as $m_field ) { if ( $m_field['name'] == $field['name'] ) { return array( 'error' => true, 'code' => 'custom', 'message' => __( 'Field already exists.', Opt_In::TEXT_DOMAIN ) ); } }*/ }catch (Exception $e){ return array( 'error' => true, 'code' => 'custom', 'message' => $e->getMessage() ); } return array( 'success' => true, 'fields' => $fields ); } } Opt_In_Mailchimp::register_ajax_endpoints(); endif;