ic function get_member( $email, $list_id, $data, $api_key ) { try { $api = $this->get_api( $api_key ); $member_info = $api->check_email( $list_id, $email ); // Mailchimp returns WP error if can't find member on a list. if ( is_wp_error( $member_info ) && 404 === $member_info->get_error_code() ) { return false; } return $member_info; } catch ( Exception $e ) { Hustle_Provider_Utils::maybe_log( __METHOD__, 'Failed to get member from Mailchimp list.', $e->getMessage() ); return false; } } /** * Delete member * * @param string $email Email. * @param string $list_id List ID. * @param array $data Data. * @param string $api_key Api key. * * @return NULL if the member is deleted otherwise false. */ public function delete_member( $email, $list_id, $data, $api_key ) { try { $api = $this->get_api( $api_key ); $delete_status = $api->delete_email( $list_id, $email ); // Mailchimp returns WP error if can't find member on a list. if ( is_wp_error( $delete_status ) && 404 === $delete_status->get_error_code() ) { return false; } return $delete_status; } catch ( Exception $e ) { Hustle_Provider_Utils::maybe_log( __METHOD__, 'Failed to delete member from Mailchimp list.', $e->getMessage() ); return false; } } /** * Get the wizard callbacks for the global settings. * * @since 4.0 * * @return array */ public function settings_wizards() { return array( array( 'callback' => array( $this, 'configure_api_key' ), 'is_completed' => array( $this, 'is_connected' ), ), ); } /** * Configure the API key settings. Global settings. * * @since 4.0 * * @param array $submitted_data Submitted data. * @return array */ public function configure_api_key( $submitted_data ) { $has_errors = false; $default_data = array( 'api_key' => '', 'name' => '', ); $current_data = $this->get_current_data( $default_data, $submitted_data ); $is_submit = isset( $submitted_data['api_key'] ); $global_multi_id = $this->get_global_multi_id( $submitted_data ); $api_key_validated = true; if ( $is_submit ) { $api_key_validated = $this->validate_api_key( $current_data['api_key'] ); if ( ! $api_key_validated ) { $has_errors = true; $error_message = $this->provider_connection_falied(); if ( ! empty( self::$connection_error ) ) { $error_message = self::$connection_error; } } if ( ! $has_errors ) { $settings_to_save = array( 'api_key' => $current_data['api_key'], 'name' => $current_data['name'], ); // If not active, activate it. // TODO: Wrap this in a friendlier method. if ( Hustle_Provider_Utils::is_provider_active( $this->slug ) || Hustle_Providers::get_instance()->activate_addon( $this->slug ) ) { $this->save_multi_settings_values( $global_multi_id, $settings_to_save ); } else { $error_message = __( "Provider couldn't be activated.", 'hustle' ); $has_errors = true; } } if ( ! $has_errors ) { return array( 'html' => Hustle_Provider_Utils::get_integration_modal_title_markup( __( 'Mailchimp Added', 'hustle' ), __( 'You can now go to your pop-ups, slide-ins and embeds and assign them to this integration', 'hustle' ) ), 'buttons' => array( 'close' => array( 'markup' => Hustle_Provider_Utils::get_provider_button_markup( __( 'Close', 'hustle' ), 'sui-button-ghost', 'close' ), ), ), 'redirect' => false, 'has_errors' => false, 'notification' => array( 'type' => 'success', 'text' => '' . $this->get_title() . ' ' . __( 'Successfully connected', 'hustle' ), ), ); } } $options = array( array( 'type' => 'wrapper', 'class' => $api_key_validated ? '' : 'sui-form-field-error', 'elements' => array( 'label' => array( 'type' => 'label', 'for' => 'api_key', 'value' => __( 'API Key', 'hustle' ), ), 'api_key' => array( 'type' => 'text', 'name' => 'api_key', 'value' => $current_data['api_key'], 'placeholder' => __( 'Enter Key', 'hustle' ), 'id' => 'api_key', 'icon' => 'key', ), 'error' => array( 'type' => 'error', 'class' => $api_key_validated ? 'sui-hidden' : '', 'value' => __( 'Please enter a valid Mailchimp API key', 'hustle' ), ), ), ), array( 'type' => 'wrapper', 'style' => 'margin-bottom: 0;', 'elements' => array( 'label' => array( 'type' => 'label', 'for' => 'mailchimp-name-input', 'value' => __( 'Identifier', 'hustle' ), ), 'name' => array( 'type' => 'text', 'name' => 'name', 'value' => $current_data['name'], 'placeholder' => __( 'E.g. Business Account', 'hustle' ), 'id' => 'mailchimp-name-input', ), 'message' => array( 'type' => 'description', 'value' => __( 'Helps to distinguish your integrations if you have connected to the multiple accounts of this integration.', 'hustle' ), ), ), ), array( 'type' => 'hidden', 'name' => 'global_multi_id', 'value' => $global_multi_id, ), ); if ( $has_errors ) { $error_notice = array( 'type' => 'notice', 'icon' => 'info', 'class' => 'sui-notice-error', 'value' => esc_html( $error_message ), ); array_unshift( $options, $error_notice ); } $step_html = Hustle_Provider_Utils::get_integration_modal_title_markup( __( 'Configure Mailchimp', 'hustle' ), sprintf( /* translators: 1. opening 'a' tag to Mailchimp API page, 2. closing 'a' tag */ __( 'Log in to your %1$sMailchimp account%2$s to get your API Key.', 'hustle' ), '', '' ) ); $step_html .= Hustle_Provider_Utils::get_html_for_options( $options ); $is_edit = $this->settings_are_completed( $global_multi_id ); if ( $is_edit ) { $buttons = array( 'disconnect' => array( 'markup' => Hustle_Provider_Utils::get_provider_button_markup( __( 'Disconnect', 'hustle' ), 'sui-button-ghost', 'disconnect', true ), ), 'save' => array( 'markup' => Hustle_Provider_Utils::get_provider_button_markup( __( 'Save', 'hustle' ), '', 'connect', true ), ), ); } else { $buttons = array( 'connect' => array( 'markup' => Hustle_Provider_Utils::get_provider_button_markup( __( 'Connect', 'hustle' ), 'sui-button-right', 'connect', true ), ), ); } $response = array( 'html' => $step_html, 'buttons' => $buttons, 'has_errors' => $has_errors, ); return $response; } /** * Validate the provided API key. * * @since 4.0 * * @param string $api_key Api key. * @return bool */ private function validate_api_key( $api_key ) { if ( empty( trim( $api_key ) ) ) { return false; } // Check API Key by validating it on get_info request. try { $info = $this->get_api( $api_key )->get_info(); if ( is_wp_error( $info ) ) { $error_data = json_decode( $info->get_error_data(), true ); if ( ! empty( $error_data['title'] ) ) { self::$connection_error = $error_data['title']; } if ( ! empty( $error_data['detail'] ) ) { self::$connection_error .= ( ! empty( self::$connection_error ) ? ' - ' : '' ) . $error_data['detail']; } Hustle_Provider_Utils::maybe_log( __METHOD__, $info->get_error_message() ); return false; } $this->connected_account = array( 'account_id' => $info->account_id, 'account_name' => $info->account_name, 'email' => $info->email, ); } catch ( Exception $e ) { Hustle_Provider_Utils::maybe_log( __METHOD__, $e->getMessage() ); return false; } return true; } /** * Get 3.0 provider mappings * * @return array */ protected function get_30_provider_mappings() { return array( 'api_key' => 'api_key', ); } /** * Migrate 3.0 * * @param object $module Module. * @param object $old_module Old module. * @return boolean */ public function migrate_30( $module, $old_module ) { $migrated = parent::migrate_30( $module, $old_module ); if ( ! $migrated ) { return false; } /** * For mailchimp version 3.x used to store a lot of unnecessary crap, let's get rid of it now. */ $redundant = array( 'is_step', 'slug', 'step', 'current_step', 'module_type' ); $module_provider_settings = $module->get_provider_settings( $this->get_slug() ); if ( ! empty( $module_provider_settings ) ) { // Remove redundants. $module_provider_settings = array_diff_key( $module_provider_settings, array_combine( $redundant, $redundant ) ); // Interest options are stored differently so let's try to bridge the differences. $interest_options = $this->transform_interest_options( $module_provider_settings ); $module_provider_settings['interest_options'] = $interest_options; if ( isset( $module_provider_settings['group_interest'] ) ) { // 3.x didn't store group_interest_name so let's see if we can add that. $module_provider_settings['group_interest_name'] = is_array( $interest_options ) && ! empty( $interest_options[ $module_provider_settings['group_interest'] ] ) ? $interest_options[ $module_provider_settings['group_interest'] ] : ''; $module_provider_settings['group_type'] = 'radio'; } $module->set_provider_settings( $this->get_slug(), $module_provider_settings ); } return $migrated; } /** * Transform interest options * * @param array $module_provider_settings Settings. * @return array */ private function transform_interest_options( $module_provider_settings ) { if ( empty( $module_provider_settings['list_id'] ) || empty( $module_provider_settings['interest_options'] ) || empty( $module_provider_settings['group'] ) ) { return array(); } $original = $module_provider_settings['interest_options']; $list_id = $module_provider_settings['list_id']; $transient = get_site_transient( self::GROUP_TRANSIENT . $list_id ); if ( empty( $transient ) ) { return $original; } $group_id = $module_provider_settings['group']; $interests = array(); foreach ( $transient as $group ) { if ( isset( $group->id, $group->list_id, $group->interests ) && $group->id === $group_id && $group->list_id === $list_id ) { $interests = $group->interests; } } if ( empty( $interests ) ) { return $original; } $interest_options = array(); foreach ( $interests as $interest ) { if ( isset( $interest->name ) && strpos( $original . ',', $interest->name . ',' ) !== false ) { $interest_options[ $interest->id ] = $interest->name; } } return $interest_options; } /** * 3.x used to store interest options as a comma-separated string, in later versions we started storing it as an array. * This method returns the interest options in a single, predictable format. * * @param Hustle_Module_Model $module Module model. * * @return array Interest options formatted as id=>name pairs */ public function get_interest_options( Hustle_Module_Model $module ) { $settings = $module->get_provider_settings( $this->get_slug() ); $required = array( 'selected_global_multi_id', 'interest_options', 'list_id', 'group' ); if ( ! $this->array_has_items( $settings, $required ) ) { return array(); } // If we already have the interest options in the correct format, don't bother calling remote. if ( is_array( $settings['interest_options'] ) ) { return $settings['interest_options']; } // No dice, call api. $remote_interest_options = $this->get_remote_interest_options( $settings['selected_global_multi_id'], $settings['list_id'], $settings['group'] ); // Save the new interest_options so we don't have to fetch them remotely again. $settings['interest_options'] = $remote_interest_options; $module->set_provider_settings( $this->get_slug(), $settings ); return $remote_interest_options; } /** * Calls the API to fetch remote interest options * * @param string $global_multi_id Global multi ID. * @param string $list_id List ID. * @param string $group_id Group ID. * @return type */ public function get_remote_interest_options( $global_multi_id, $list_id, $group_id ) { if ( '-1' === $group_id ) { return array(); } $api_key = $this->get_setting( 'api_key', '', $global_multi_id ); try { $api = $this->get_api( $api_key ); $response = $api->get_interests( $list_id, $group_id, PHP_INT_MAX ); if ( is_wp_error( $response ) || ! is_array( $response->interests ) ) { return array(); } $interests = wp_list_pluck( $response->interests, 'name', 'id' ); } catch ( Exception $e ) { return array(); } return $interests; } /** * Maybe add custom field * * @param object $api Api. * @param string $list_id List ID. * @param arry $merge_data Merge data. * @param int $module_id Module ID. * @return boolean|\Hustle_Module_Model */ public function maybe_add_custom_fields( $api, $list_id, $merge_data, $module_id ) { $existed_custom_fields = $api->get_custom_fields( $list_id ); $existed_keys = ! empty( $existed_custom_fields->merge_fields ) ? wp_list_pluck( $existed_custom_fields->merge_fields, 'tag' ) : array(); $new_fields = array(); foreach ( $merge_data as $k => $v ) { if ( ! in_array( strtoupper( $k ), $existed_keys, true ) ) { $new_fields[] = $k; } } if ( ! empty( $new_fields ) ) { $module = new Hustle_Module_Model( $module_id ); if ( is_wp_error( $module ) ) { return $module; } $form_fields = $module->get_form_fields(); $possible_types = array( 'text', 'number', 'phone', 'date', 'url', 'imageurl', 'radio', 'dropdown', 'birthday', 'zip', ); foreach ( $new_fields as $field ) { $tag = strtoupper( $field ); $name = ! empty( $form_fields[ $field ]['label'] ) ? $form_fields[ $field ]['label'] : $field; $type = ! empty( $form_fields[ $field ]['type'] ) ? $form_fields[ $field ]['type'] : ''; $api->add_custom_field( $list_id, array( 'tag' => $tag, 'name' => $name, 'type' => in_array( $type, $possible_types, true ) ? $type : 'text', ) ); } } return true; } /** * Array has item? * * @param array $array Array. * @param type $keys Keys. * @return boolean */ private function array_has_items( $array, $keys ) { foreach ( $keys as $key ) { if ( ! isset( $array[ $key ] ) ) { return false; } } return true; } } endif;