├── mailchimp-api ├── 2.0 │ ├── Mailchimp │ │ ├── Mailchimp.php │ │ ├── Mobile.php │ │ ├── Neapolitan.php │ │ ├── Folders.php │ │ ├── Goal.php │ │ ├── Conversations.php │ │ ├── Gallery.php │ │ ├── Users.php │ │ ├── Ecomm.php │ │ ├── Vip.php │ │ ├── Templates.php │ │ └── Exceptions.php │ ├── mailchimp-api-2.0.php │ ├── webhooks.php │ └── Mailchimp.php └── 3.0 │ ├── Mailchimp │ ├── Webhook.php │ ├── Batch.php │ └── MailChimp.php │ ├── webhooks.php │ └── mailchimp-api-3.0.php ├── assets ├── spinner.gif ├── tinymceicon.png ├── jquery-ui │ ├── images │ │ ├── animated-overlay.gif │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_228ef1_256x240.png │ │ ├── ui-icons_ef8c08_256x240.png │ │ ├── ui-icons_ffd27a_256x240.png │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ └── ui-bg_highlight-soft_100_eeeeee_1x100.png │ └── jquery.ui.progressbar.js ├── shortcode-editor.css ├── form.js ├── form.css └── tiny-mce-button.js ├── .gitignore ├── .gitmodules ├── integration.php ├── package.json ├── dev-README.md ├── admin ├── user-profile.php ├── class-admin.php └── assets │ └── mailchimp-admin.js ├── front ├── form-template.php ├── form.class.php ├── widget.php └── shortcode.php ├── Gruntfile.js ├── README.md ├── changelog.txt ├── deprecated.php └── mailchimp-sync.php /mailchimp-api/2.0/Mailchimp/Mailchimp.php: -------------------------------------------------------------------------------- 1 | sdfsdf -------------------------------------------------------------------------------- /assets/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/spinner.gif -------------------------------------------------------------------------------- /assets/tinymceicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/tinymceicon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | .sass-cache/ 3 | node_modules/ 4 | npm-debug.log 5 | .DS_Store 6 | build/ 7 | tmp/ -------------------------------------------------------------------------------- /assets/jquery-ui/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/animated-overlay.gif -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "externals"] 2 | path = externals 3 | url = git@bitbucket.org:incsub/wpmudev-dashboard-notification.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /assets/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/mailchimp-sync/master/assets/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /assets/shortcode-editor.css: -------------------------------------------------------------------------------- 1 | .mailchimp-editor-icon { 2 | text-indent:-9999px; 3 | background:url("tinymceicon.png") no-repeat scroll center top transparent; 4 | width:188px; 5 | height:70px; 6 | } 7 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Mobile.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Neapolitan.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /integration.php: -------------------------------------------------------------------------------- 1 | $user->user_email, 23 | 'first_name' => $me['first_name'], 24 | 'last_name' => $me['last_name'] 25 | ); 26 | 27 | $mailchimp_sync->mailchimp_add_user( $user_arr ); 28 | } 29 | add_action( 'wdfb-user_registered-postprocess', 'mailchimp_ultimate_fb_add_user', 10, 3 ); 30 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mailchimp-sync", 3 | "version": "1.9.7", 4 | "main": "mailchimp-sync.php", 5 | "projectEditUrl": "https://premium.wpmudev.org/wp-admin/edit.php?post_type=project&page=projects-manage&manage_files=73", 6 | "description": "", 7 | "scripts": { 8 | "build": "grunt build", 9 | "release": "grunt version-compare && git-branch-is master && git submodule update --remote && grunt build && grunt finish" 10 | }, 11 | "dependencies": {}, 12 | "devDependencies": { 13 | "git-branch-is": "^0.1.0", 14 | "grunt": "~0.4.5", 15 | "grunt-checktextdomain": "^0.1.1", 16 | "grunt-contrib-clean": "~0.5.0", 17 | "grunt-contrib-compress": "~0.8.0", 18 | "grunt-contrib-copy": "~0.5.0", 19 | "grunt-contrib-jshint": "^1.0.0", 20 | "grunt-contrib-uglify": "^1.0.1", 21 | "grunt-contrib-watch": "^1.0.0", 22 | "grunt-exec": "~0.4.5", 23 | "grunt-open": "^0.2.3", 24 | "grunt-phpunit": "^0.3.6", 25 | "grunt-potomo": "~2.1.0", 26 | "grunt-search": "^0.1.8", 27 | "grunt-wp-i18n": "~0.5.0", 28 | "load-grunt-tasks": "~0.2.0" 29 | }, 30 | "author": "WPMU DEV", 31 | "license": "GPLv2" 32 | } 33 | -------------------------------------------------------------------------------- /dev-README.md: -------------------------------------------------------------------------------- 1 | # MailChimp Sync 2 | 3 | ## Development guide 4 | 5 | ### Branches 6 | There are two main branches: 7 | 8 | * `development`: Every development work should be done here first 9 | * `master`: Whenever a new version is ready, merge `development` branch into this one and push 10 | 11 | ### Development workflow 12 | 13 | MailChimp Sync contains a few automated tasks that helps the developer to make faster and less buggy releases. 14 | 15 | #### Requirements: 16 | 17 | 1. Install nodejs: [https://github.com/joyent/node/wiki/installing-node.js-via-package-manager] 18 | 2. Install Grunt globally `sudo npm install -g grunt` 19 | 3. Execute `git submodule update --init --recursive` to download every submodule 20 | 21 | #### Dependencies installation 22 | 23 | MailChimp Sync requires a few node dependencies for development. Use `npm install` to install all of them. 24 | 25 | #### Releasing versions 26 | 27 | 1. Make sure that the version in `mailchimp-sync.php` matches with the version in `package.json`, otherwise the build will fail. 28 | 2. Update all Git submodules with `git submodule update --remote` 29 | 3. Now execute `npm run build`. A new folder called `build` will be created where you can grab the zip file for the new version. 30 | 4. Language files, JS Lint and text domains verification are done during the execution of this script so developer doesn't need to worry about these tasks. 31 | 32 | Don't forget to create a new tag in Git! 33 | -------------------------------------------------------------------------------- /admin/user-profile.php: -------------------------------------------------------------------------------- 1 | user_email ); 14 | $is_subscribed = $subscribed && ( $subscribed['status'] === 'subscribed' ); 15 | ?> 16 |

17 | 18 | 19 | 20 | 31 | 32 |
21 | 22 |
23 |

24 |
25 | 26 |
27 |

28 |
29 | 30 |
33 | 53 | ').text( data.data.errors[i] ); 42 | errors_container.append( error ); 43 | } 44 | errors_container.slideDown(); 45 | } 46 | 47 | 48 | 49 | }); 50 | 51 | return false; 52 | } 53 | } 54 | 55 | mailchimp_form.init(); 56 | }); -------------------------------------------------------------------------------- /assets/form.css: -------------------------------------------------------------------------------- 1 | .incsub-mailchimp-form { 2 | margin-bottom:1em; 3 | } 4 | .incsub-mailchimp-label { 5 | display:block; 6 | } 7 | .incsub-mailchimp-field-wrap { 8 | margin-bottom:1em; 9 | } 10 | .mailchimp-spinner { 11 | background: url('spinner.gif') no-repeat top left transparent; 12 | height: 25px; 13 | width: 25px; 14 | display: inline-block; 15 | vertical-align: middle; 16 | visibility:hidden; 17 | } 18 | ul.incsub-mailchimp-error, 19 | p.incsub-mailchimp-updated { 20 | box-sizing:border-box; 21 | list-style:none; 22 | padding: 6px 10px; 23 | -webkit-transition: border .25s linear, color .25s linear, background-color .25s linear; 24 | transition: border .25s linear, color .25s linear, background-color .25s linear; 25 | box-shadow: none; 26 | -webkit-box-shadow: none; 27 | border:1px solid transparent; 28 | background:white; 29 | margin-left:0; 30 | } 31 | p.incsub-mailchimp-updated { 32 | color: #2E9459; 33 | border-color: #3BA869; 34 | } 35 | ul.incsub-mailchimp-error { 36 | color: #E74C3C; 37 | border-color: #E74C3C; 38 | } 39 | ul.incsub-mailchimp-error li { 40 | color: #E74C3C; 41 | } 42 | .incsub-mailchimp-field { 43 | box-sizing:border-box; 44 | width:100%; 45 | } 46 | 47 | .incsub-mailchimp-submit:hover, 48 | .incsub-mailchimp-submit:focus, 49 | .incsub-mailchimp-submit:active, 50 | .incsub-mailchimp-submit.active { 51 | color: #FFF; 52 | background-color: #818181; 53 | border-color: #4E4E4E; 54 | outline: none; 55 | } 56 | 57 | .incsub-mailchimp-submit { 58 | background: #CCC; 59 | padding: 10px 19px; 60 | font-size: 17px; 61 | line-height: 1.471; 62 | border-radius: 2px; 63 | border: none; 64 | font-size: 15px; 65 | font-weight: normal; 66 | line-height: 1.4; 67 | padding: 8px 10px; 68 | -webkit-font-smoothing: subpixel-antialiased; 69 | -webkit-transition: border .25s linear, color .25s linear, background-color .25s linear; 70 | transition: border .25s linear, color .25s linear, background-color .25s linear; 71 | cursor:pointer; 72 | } -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Folders.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Add a new folder to file campaigns, autoresponders, or templates in 10 | * @param string $name 11 | * @param string $type 12 | * @return associative_array with a single value: 13 | * - folder_id int the folder_id of the newly created folder. 14 | */ 15 | public function add($name, $type) { 16 | $_params = array("name" => $name, "type" => $type); 17 | return $this->master->call('folders/add', $_params); 18 | } 19 | 20 | /** 21 | * Delete a campaign, autoresponder, or template folder. Note that this will simply make whatever was in the folder appear unfiled, no other data is removed 22 | * @param int $fid 23 | * @param string $type 24 | * @return associative_array with a single entry: 25 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 26 | */ 27 | public function del($fid, $type) { 28 | $_params = array("fid" => $fid, "type" => $type); 29 | return $this->master->call('folders/del', $_params); 30 | } 31 | 32 | /** 33 | * List all the folders of a certain type 34 | * @param string $type 35 | * @return array structs for each folder, including: 36 | * - folder_id int Folder Id for the given folder, this can be used in the campaigns/list() function to filter on. 37 | * - name string Name of the given folder 38 | * - date_created string The date/time the folder was created 39 | * - type string The type of the folders being returned, just to make sure you know. 40 | * - cnt int number of items in the folder. 41 | */ 42 | public function getList($type) { 43 | $_params = array("type" => $type); 44 | return $this->master->call('folders/list', $_params); 45 | } 46 | 47 | /** 48 | * Update the name of a folder for campaigns, autoresponders, or templates 49 | * @param int $fid 50 | * @param string $name 51 | * @param string $type 52 | * @return associative_array with a single entry: 53 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 54 | */ 55 | public function update($fid, $name, $type) { 56 | $_params = array("fid" => $fid, "name" => $name, "type" => $type); 57 | return $this->master->call('folders/update', $_params); 58 | } 59 | 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /mailchimp-api/3.0/Mailchimp/Webhook.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Mailchimp_Sync_Webhook 11 | { 12 | private static $eventSubscriptions = array(); 13 | private static $receivedWebhook = null; 14 | 15 | /** 16 | * Subscribe to an incoming webhook request. The callback will be invoked when a matching webhook is received. 17 | * @param string $event Name of the webhook event, e.g. subscribe, unsubscribe, campaign 18 | * @param callable $callback A callable function to invoke with the data from the received webhook 19 | * @return void 20 | */ 21 | public static function subscribe($event, callable $callback) 22 | { 23 | if (!isset(self::$eventSubscriptions[$event])) self::$eventSubscriptions[$event] = array(); 24 | self::$eventSubscriptions[$event][] = $callback; 25 | 26 | self::receive(); 27 | } 28 | 29 | /** 30 | * Retrieve the incoming webhook request as sent. 31 | * @param string $input An optional raw POST body to use instead of php://input - mainly for unit testing. 32 | * @return array|false An associative array containing the details of the received webhook 33 | */ 34 | public static function receive($input = null) 35 | { 36 | if (is_null($input)) { 37 | if (self::$receivedWebhook !== null) { 38 | $input = self::$receivedWebhook; 39 | } else { 40 | $input = file_get_contents("php://input"); 41 | } 42 | } 43 | 44 | if (!is_null($input) && $input != '') { 45 | return self::processWebhook($input); 46 | } 47 | 48 | return false; 49 | } 50 | 51 | /** 52 | * Process the raw request into a PHP array and dispatch any matching subscription callbacks 53 | * @param string $input The raw HTTP POST request 54 | * @return array|false An associative array containing the details of the received webhook 55 | */ 56 | private static function processWebhook($input) 57 | { 58 | self::$receivedWebhook = $input; 59 | parse_str($input, $result); 60 | if ($result && isset($result['type'])) { 61 | self::dispatchWebhookEvent($result['type'], $result['data']); 62 | return $result; 63 | } 64 | 65 | return false; 66 | } 67 | 68 | /** 69 | * Call any subscribed callbacks for this event 70 | * @param string $event The name of the callback event 71 | * @param array $data An associative array of the webhook data 72 | * @return void 73 | */ 74 | private static function dispatchWebhookEvent($event, $data) 75 | { 76 | if (isset(self::$eventSubscriptions[$event])) { 77 | foreach(self::$eventSubscriptions[$event] as $callback) { 78 | $callback($data); 79 | } 80 | // reset subscriptions 81 | self::$eventSubscriptions[$event] = array(); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Goal.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Retrieve goal event data for a particular list member. Note: only unique events are returned. If a user triggers 10 | a particular event multiple times, you will still only receive one entry for that event. 11 | * @param string $list_id 12 | * @param associative_array $email 13 | * - email string an email address 14 | * - euid string the unique id for an email address (not list related) - the email "id" returned from listMemberInfo, Webhooks, Campaigns, etc. 15 | * - leid string the list email id (previously called web_id) for a list-member-info type call. this doesn't change when the email address changes 16 | * @param int $start 17 | * @param int $limit 18 | * @return associative_array Event data and metadata 19 | * - data array An array of goal data structs for the specified list member in the following format 20 | * - event string The URL or name of the event that was triggered 21 | * - last_visited_at string A timestamp in the format 'YYYY-MM-DD HH:MM:SS' that represents the last time this event was seen. 22 | * - total int The total number of events that match your criteria. 23 | */ 24 | public function events($list_id, $email, $start=0, $limit=25) { 25 | $_params = array("list_id" => $list_id, "email" => $email, "start" => $start, "limit" => $limit); 26 | return $this->master->call('goal/events', $_params); 27 | } 28 | 29 | /** 30 | * This allows programmatically trigger goal event collection without the use of front-end code. 31 | * @param string $list_id 32 | * @param associative_array $email 33 | * - email string an email address 34 | * - euid string the unique id for an email address (not list related) - the email "id" returned from listMemberInfo, Webhooks, Campaigns, etc. 35 | * - leid string the list email id (previously called web_id) for a list-member-info type call. this doesn't change when the email address changes 36 | * @param string $campaign_id 37 | * @param string $event 38 | * @return associative_array Event data for the submitted event 39 | * - event string The URL or name of the event that was triggered 40 | * - last_visited_at string A timestamp in the format 'YYYY-MM-DD HH:MM:SS' that represents the last time this event was seen. 41 | */ 42 | public function recordEvent($list_id, $email, $campaign_id, $event) { 43 | $_params = array("list_id" => $list_id, "email" => $email, "campaign_id" => $campaign_id, "event" => $event); 44 | return $this->master->call('goal/record-event', $_params); 45 | } 46 | 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /front/form-template.php: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 |

5 | 6 | 7 |
8 | 9 | 10 | 11 |

12 | 13 |

14 | 15 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 | 32 |
33 | 34 | 35 |
36 | 37 |
38 | 39 | 40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /admin/class-admin.php: -------------------------------------------------------------------------------- 1 | '' . __( 'Settings', 'mailchimp' ) . '' 42 | ), 43 | $links 44 | ); 45 | } 46 | 47 | /** 48 | * Show plugin admin notices 49 | */ 50 | public function admin_notices() { 51 | if ( ( is_multisite() && ! current_user_can( 'manage_network' ) ) || ( ! is_multisite() && ! current_user_can( 'manage_options' ) ) ) { 52 | return; 53 | } 54 | 55 | if ( get_site_option( 'mailchimp_sync_set_groups_again_notice' ) ) { 56 | ?> 57 |
58 |

click here to set the groups again.', 'mailchimp' ), 60 | is_multisite() ? network_admin_url('settings.php') . '?page=mailchimp' : admin_url('options-general.php') . '?page=mailchimp' 61 | ); ?> 62 | 63 |

64 |
65 | 69 | 83 | " ) 42 | .appendTo( this.element ); 43 | 44 | this._refreshValue(); 45 | }, 46 | 47 | _destroy: function() { 48 | this.element 49 | .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 50 | .removeAttr( "role" ) 51 | .removeAttr( "aria-valuemin" ) 52 | .removeAttr( "aria-valuemax" ) 53 | .removeAttr( "aria-valuenow" ); 54 | 55 | this.valueDiv.remove(); 56 | }, 57 | 58 | value: function( newValue ) { 59 | if ( newValue === undefined ) { 60 | return this.options.value; 61 | } 62 | 63 | this.options.value = this._constrainedValue( newValue ); 64 | this._refreshValue(); 65 | }, 66 | 67 | _constrainedValue: function( newValue ) { 68 | if ( newValue === undefined ) { 69 | newValue = this.options.value; 70 | } 71 | 72 | this.indeterminate = newValue === false; 73 | 74 | // sanitize value 75 | if ( typeof newValue !== "number" ) { 76 | newValue = 0; 77 | } 78 | 79 | return this.indeterminate ? false : 80 | Math.min( this.options.max, Math.max( this.min, newValue ) ); 81 | }, 82 | 83 | _setOptions: function( options ) { 84 | // Ensure "value" option is set after other values (like max) 85 | var value = options.value; 86 | delete options.value; 87 | 88 | this._super( options ); 89 | 90 | this.options.value = this._constrainedValue( value ); 91 | this._refreshValue(); 92 | }, 93 | 94 | _setOption: function( key, value ) { 95 | if ( key === "max" ) { 96 | // Don't allow a max less than min 97 | value = Math.max( this.min, value ); 98 | } 99 | 100 | this._super( key, value ); 101 | }, 102 | 103 | _percentage: function() { 104 | return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 105 | }, 106 | 107 | _refreshValue: function() { 108 | var value = this.options.value, 109 | percentage = this._percentage(); 110 | 111 | this.valueDiv 112 | .toggle( this.indeterminate || value > this.min ) 113 | .toggleClass( "ui-corner-right", value === this.options.max ) 114 | .width( percentage.toFixed(0) + "%" ); 115 | 116 | this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 117 | 118 | if ( this.indeterminate ) { 119 | this.element.removeAttr( "aria-valuenow" ); 120 | if ( !this.overlayDiv ) { 121 | this.overlayDiv = $( "
" ).appendTo( this.valueDiv ); 122 | } 123 | } else { 124 | this.element.attr({ 125 | "aria-valuemax": this.options.max, 126 | "aria-valuenow": value 127 | }); 128 | if ( this.overlayDiv ) { 129 | this.overlayDiv.remove(); 130 | this.overlayDiv = null; 131 | } 132 | } 133 | 134 | if ( this.oldValue !== value ) { 135 | this.oldValue = value; 136 | this._trigger( "change" ); 137 | } 138 | if ( value === this.options.max ) { 139 | this._trigger( "complete" ); 140 | } 141 | } 142 | }); 143 | })( jQuery ); -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Conversations.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Retrieve conversation metadata, includes message data for the most recent message in the conversation 10 | * @param string $list_id 11 | * @param string $leid 12 | * @param string $campaign_id 13 | * @param int $start 14 | * @param int $limit 15 | * @return associative_array Conversation data and metadata 16 | * - count int Total number of conversations, irrespective of pagination. 17 | * - data array An array of structs representing individual conversations 18 | * - unique_id string A string identifying this particular conversation 19 | * - message_count int The total number of messages in this conversation 20 | * - campaign_id string The unique identifier of the campaign this conversation is associated with (will be null if the campaign has been deleted) 21 | * - list_id string The unique identifier of the list this conversation is associated with 22 | * - unread_messages int The number of messages in this conversation which have not yet been read. 23 | * - from_label string A label representing the sender of this message. 24 | * - from_email string The email address of the sender of this message. 25 | * - subject string The subject of the message. 26 | * - timestamp string Date the message was either sent or received. 27 | * - last_message associative_array The most recent message in the conversation 28 | * - from_label string A label representing the sender of this message. 29 | * - from_email string The email address of the sender of this message. 30 | * - subject string The subject of the message. 31 | * - message string The plain-text content of the message. 32 | * - read boolean Whether or not this message has been marked as read. 33 | * - timestamp string Date the message was either sent or received. 34 | */ 35 | public function getList($list_id=null, $leid=null, $campaign_id=null, $start=0, $limit=25) { 36 | $_params = array("list_id" => $list_id, "leid" => $leid, "campaign_id" => $campaign_id, "start" => $start, "limit" => $limit); 37 | return $this->master->call('conversations/list', $_params); 38 | } 39 | 40 | /** 41 | * Retrieve conversation messages 42 | * @param string $conversation_id 43 | * @param boolean $mark_as_read 44 | * @param int $start 45 | * @param int $limit 46 | * @return associative_array Message data and metadata 47 | * - count int The number of messages in this conversation, irrespective of paging. 48 | * - data array An array of structs representing each message in a conversation 49 | * - from_label string A label representing the sender of this message. 50 | * - from_email string The email address of the sender of this message. 51 | * - subject string The subject of the message. 52 | * - message string The plain-text content of the message. 53 | * - read boolean Whether or not this message has been marked as read. 54 | * - timestamp string Date the message was either sent or received. 55 | */ 56 | public function messages($conversation_id, $mark_as_read=false, $start=0, $limit=25) { 57 | $_params = array("conversation_id" => $conversation_id, "mark_as_read" => $mark_as_read, "start" => $start, "limit" => $limit); 58 | return $this->master->call('conversations/messages', $_params); 59 | } 60 | 61 | /** 62 | * Reply to a conversation 63 | * @param string $conversation_id 64 | * @param string $message 65 | * @return associative_array Message data from the created message 66 | * - from_label string A label representing the sender of this message. 67 | * - from_email string The email address of the sender of this message. 68 | * - subject string The subject of the message. 69 | * - message string The plain-text content of the message. 70 | * - read boolean Whether or not this message has been marked as read. 71 | * - timestamp string Date the message was either sent or received. 72 | */ 73 | public function reply($conversation_id, $message) { 74 | $_params = array("conversation_id" => $conversation_id, "message" => $message); 75 | return $this->master->call('conversations/reply', $_params); 76 | } 77 | 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Gallery.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Return a section of the image gallery 10 | * @param associative_array $opts 11 | * - type string optional the gallery type to return - images or files - default to images 12 | * - start int optional for large data sets, the page number to start at - defaults to 1st page of data (page 0) 13 | * - limit int optional for large data sets, the number of results to return - defaults to 25, upper limit set at 100 14 | * - sort_by string optional field to sort by - one of size, time, name - defaults to time 15 | * - sort_dir string optional field to sort by - one of asc, desc - defaults to desc 16 | * - search_term string optional a term to search for in names 17 | * - folder_id int optional to return files that are in a specific folder. id returned by the list-folders call 18 | * @return associative_array the matching gallery items 19 | * - total int the total matching items 20 | * - data array structs for each item included in the set, including: 21 | * - id int the id of the file 22 | * - name string the file name 23 | * - time string the creation date for the item 24 | * - size int the file size in bytes 25 | * - full string the url to the actual item in the gallery 26 | * - thumb string a url for a thumbnail that can be used to represent the item, generally an image thumbnail or an icon for a file type 27 | */ 28 | public function getList($opts=array()) { 29 | $_params = array("opts" => $opts); 30 | return $this->master->call('gallery/list', $_params); 31 | } 32 | 33 | /** 34 | * Return a list of the folders available to the file gallery 35 | * @param associative_array $opts 36 | * - start int optional for large data sets, the page number to start at - defaults to 1st page of data (page 0) 37 | * - limit int optional for large data sets, the number of results to return - defaults to 25, upper limit set at 100 38 | * - search_term string optional a term to search for in names 39 | * @return associative_array the matching gallery folders 40 | * - total int the total matching folders 41 | * - data array structs for each folder included in the set, including: 42 | * - id int the id of the folder 43 | * - name string the file name 44 | * - file_count int the number of files in the folder 45 | */ 46 | public function listFolders($opts=array()) { 47 | $_params = array("opts" => $opts); 48 | return $this->master->call('gallery/list-folders', $_params); 49 | } 50 | 51 | /** 52 | * Adds a folder to the file gallery 53 | * @param string $name 54 | * @return associative_array the new data for the created folder 55 | * - data.id int the id of the new folder 56 | */ 57 | public function addFolder($name) { 58 | $_params = array("name" => $name); 59 | return $this->master->call('gallery/add-folder', $_params); 60 | } 61 | 62 | /** 63 | * Remove a folder 64 | * @param int $folder_id 65 | * @return boolean true/false for success/failure 66 | */ 67 | public function removeFolder($folder_id) { 68 | $_params = array("folder_id" => $folder_id); 69 | return $this->master->call('gallery/remove-folder', $_params); 70 | } 71 | 72 | /** 73 | * Add a file to a folder 74 | * @param int $file_id 75 | * @param int $folder_id 76 | * @return boolean true/false for success/failure 77 | */ 78 | public function addFileToFolder($file_id, $folder_id) { 79 | $_params = array("file_id" => $file_id, "folder_id" => $folder_id); 80 | return $this->master->call('gallery/add-file-to-folder', $_params); 81 | } 82 | 83 | /** 84 | * Remove a file from a folder 85 | * @param int $file_id 86 | * @param int $folder_id 87 | * @return boolean true/false for success/failure 88 | */ 89 | public function removeFileFromFolder($file_id, $folder_id) { 90 | $_params = array("file_id" => $file_id, "folder_id" => $folder_id); 91 | return $this->master->call('gallery/remove-file-from-folder', $_params); 92 | } 93 | 94 | /** 95 | * Remove all files from a folder (Note that the files are not deleted, they are only removed from the folder) 96 | * @param int $folder_id 97 | * @return boolean true/false for success/failure 98 | */ 99 | public function removeAllFilesFromFolder($folder_id) { 100 | $_params = array("folder_id" => $folder_id); 101 | return $this->master->call('gallery/remove-all-files-from-folder', $_params); 102 | } 103 | 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /mailchimp-api/3.0/Mailchimp/Batch.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | class Mailchimp_Sync_Batch 10 | { 11 | /** 12 | * @var MailChimp_Sync_Mailchimp 13 | */ 14 | private $MailChimp; 15 | 16 | private $operations = array(); 17 | private $batch_id; 18 | 19 | public function __construct($MailChimp, $batch_id = null) 20 | { 21 | $this->MailChimp = $MailChimp; 22 | $this->batch_id = $batch_id; 23 | } 24 | 25 | /** 26 | * Add an HTTP DELETE request operation to the batch - for deleting data 27 | * @param string $id ID for the operation within the batch 28 | * @param string $method URL of the API request method 29 | * @return void 30 | */ 31 | public function delete($id, $method) 32 | { 33 | $this->queueOperation('DELETE', $id, $method); 34 | } 35 | 36 | /** 37 | * Add an HTTP GET request operation to the batch - for retrieving data 38 | * @param string $id ID for the operation within the batch 39 | * @param string $method URL of the API request method 40 | * @param array $args Assoc array of arguments (usually your data) 41 | * @return void 42 | */ 43 | public function get($id, $method, $args = array()) 44 | { 45 | $this->queueOperation('GET', $id, $method, $args); 46 | } 47 | 48 | /** 49 | * Add an HTTP PATCH request operation to the batch - for performing partial updates 50 | * @param string $id ID for the operation within the batch 51 | * @param string $method URL of the API request method 52 | * @param array $args Assoc array of arguments (usually your data) 53 | * @return void 54 | */ 55 | public function patch($id, $method, $args = array()) 56 | { 57 | $this->queueOperation('PATCH', $id, $method, $args); 58 | } 59 | 60 | /** 61 | * Add an HTTP POST request operation to the batch - for creating and updating items 62 | * @param string $id ID for the operation within the batch 63 | * @param string $method URL of the API request method 64 | * @param array $args Assoc array of arguments (usually your data) 65 | * @return void 66 | */ 67 | public function post($id, $method, $args = array()) 68 | { 69 | $this->queueOperation('POST', $id, $method, $args); 70 | } 71 | 72 | /** 73 | * Add an HTTP PUT request operation to the batch - for creating new items 74 | * @param string $id ID for the operation within the batch 75 | * @param string $method URL of the API request method 76 | * @param array $args Assoc array of arguments (usually your data) 77 | * @return void 78 | */ 79 | public function put($id, $method, $args = array()) 80 | { 81 | $this->queueOperation('PUT', $id, $method, $args); 82 | } 83 | 84 | /** 85 | * Execute the batch request 86 | * @param int $timeout Request timeout in seconds (optional) 87 | * @return array|false Assoc array of API response, decoded from JSON 88 | */ 89 | public function execute($timeout = 10) 90 | { 91 | $req = array('operations' => $this->operations); 92 | 93 | $result = $this->MailChimp->post('batches', $req, $timeout); 94 | 95 | if ($result && isset($result['id'])) { 96 | $this->batch_id = $result['id']; 97 | } 98 | 99 | return $result; 100 | } 101 | 102 | /** 103 | * Check the status of a batch request. If the current instance of the Batch object 104 | * was used to make the request, the batch_id is already known and is therefore optional. 105 | * @param string $batch_id ID of the batch about which to enquire 106 | * @return array|false Assoc array of API response, decoded from JSON 107 | */ 108 | public function check_status($batch_id = null) 109 | { 110 | if ($batch_id === null && $this->batch_id) { 111 | $batch_id = $this->batch_id; 112 | } 113 | 114 | return $this->MailChimp->get('batches/' . $batch_id); 115 | } 116 | 117 | /** 118 | * Add an operation to the internal queue. 119 | * @param string $http_verb GET, POST, PUT, PATCH or DELETE 120 | * @param string $id ID for the operation within the batch 121 | * @param string $method URL of the API request method 122 | * @param array $args Assoc array of arguments (usually your data) 123 | * @return void 124 | */ 125 | private function queueOperation($http_verb, $id, $method, $args = null) 126 | { 127 | $operation = array( 128 | 'operation_id' => $id, 129 | 'method' => $http_verb, 130 | 'path' => $method, 131 | ); 132 | 133 | if ($args) { 134 | $key = ($http_verb == 'GET' ? 'params' : 'body'); 135 | $operation[$key] = json_encode($args); 136 | } 137 | 138 | $this->operations[] = $operation; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Users.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Invite a user to your account 10 | * @param string $email 11 | * @param string $role 12 | * @param string $msg 13 | * @return associative_array the method completion status 14 | * - status string The status (success) of the call if it completed. Otherwise an error is thrown. 15 | */ 16 | public function invite($email, $role='viewer', $msg='') { 17 | $_params = array("email" => $email, "role" => $role, "msg" => $msg); 18 | return $this->master->call('users/invite', $_params); 19 | } 20 | 21 | /** 22 | * Resend an invite a user to your account. Note, if the same address has been invited multiple times, this will simpy re-send the most recent invite 23 | * @param string $email 24 | * @return associative_array the method completion status 25 | * - status string The status (success) of the call if it completed. Otherwise an error is thrown. 26 | */ 27 | public function inviteResend($email) { 28 | $_params = array("email" => $email); 29 | return $this->master->call('users/invite-resend', $_params); 30 | } 31 | 32 | /** 33 | * Revoke an invitation sent to a user to your account. Note, if the same address has been invited multiple times, this will simpy revoke the most recent invite 34 | * @param string $email 35 | * @return associative_array the method completion status 36 | * - status string The status (success) of the call if it completed. Otherwise an error is thrown. 37 | */ 38 | public function inviteRevoke($email) { 39 | $_params = array("email" => $email); 40 | return $this->master->call('users/invite-revoke', $_params); 41 | } 42 | 43 | /** 44 | * Retrieve the list of pending users invitations have been sent for. 45 | * @return array structs for each invitation, including: 46 | * - email string the email address the invitation was sent to 47 | * - role string the role that will be assigned if they accept 48 | * - sent_at string the time the invitation was sent. this will change if it's resent. 49 | * - expiration string the expiration time for the invitation. this will change if it's resent. 50 | * - msg string the welcome message included with the invitation 51 | */ 52 | public function invites() { 53 | $_params = array(); 54 | return $this->master->call('users/invites', $_params); 55 | } 56 | 57 | /** 58 | * Revoke access for a specified login 59 | * @param string $username 60 | * @return associative_array the method completion status 61 | * - status string The status (success) of the call if it completed. Otherwise an error is thrown. 62 | */ 63 | public function loginRevoke($username) { 64 | $_params = array("username" => $username); 65 | return $this->master->call('users/login-revoke', $_params); 66 | } 67 | 68 | /** 69 | * Retrieve the list of active logins. 70 | * @return array structs for each user, including: 71 | * - id int the login id for this login 72 | * - username string the username used to log in 73 | * - name string a display name for the account - empty first/last names will return the username 74 | * - email string the email tied to the account used for passwords resets and the ilk 75 | * - role string the role assigned to the account 76 | * - avatar string if available, the url for the login's avatar 77 | * - global_user_id int the globally unique user id for the user account connected to 78 | * - dc_unique_id string the datacenter unique id for the user account connected to, like helper/account-details 79 | */ 80 | public function logins() { 81 | $_params = array(); 82 | return $this->master->call('users/logins', $_params); 83 | } 84 | 85 | /** 86 | * Retrieve the profile for the login owning the provided API Key 87 | * @return associative_array the current user's details, including: 88 | * - id int the login id for this login 89 | * - username string the username used to log in 90 | * - name string a display name for the account - empty first/last names will return the username 91 | * - email string the email tied to the account used for passwords resets and the ilk 92 | * - role string the role assigned to the account 93 | * - avatar string if available, the url for the login's avatar 94 | * - global_user_id int the globally unique user id for the user account connected to 95 | * - dc_unique_id string the datacenter unique id for the user account connected to, like helper/account-details 96 | * - account_name string The name of the account to which the API key belongs 97 | */ 98 | public function profile() { 99 | $_params = array(); 100 | return $this->master->call('users/profile', $_params); 101 | } 102 | 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /front/form.class.php: -------------------------------------------------------------------------------- 1 | 22 | 25 | 30 | 32 | admin_url( 'admin-ajax.php' ), 45 | 'nonce' => wp_create_nonce( "mailchimp_subscribe_user" ) 46 | ); 47 | wp_localize_script( 'mailchimp-form-js', 'mailchimp_form_captions', $l10n ); 48 | 49 | add_action( 'wp_footer', array( 'WPMUDEV_MailChimp_Form', 'enqueue_scripts' ) ); 50 | 51 | } 52 | 53 | 54 | public static function enqueue_scripts() { 55 | wp_enqueue_script( 'mailchimp-form-js' ); 56 | } 57 | 58 | 59 | public static function render_form( $args ) { 60 | $defaults = array( 61 | 'submit_name' => 'submit-subscribe-user', 62 | 'button_text' => '', 63 | 'form_id' => '', 64 | 'subscribed_placeholder' => '', 65 | 'text' => '', 66 | 'subscribed' => false, 67 | 'firstname' => '', 68 | 'lastname' => '', 69 | 'email' => '', 70 | 'errors' => array(), 71 | 'form_class' => '', 72 | 'require_fn' => false, 73 | 'require_ln' => false 74 | ); 75 | 76 | $args = wp_parse_args( $args, $defaults ); 77 | extract( $args ); 78 | 79 | $require_fn = $require_fn ? 1 : 0; 80 | $require_ln = $require_ln ? 1 : 0; 81 | include( apply_filters( 'mailchimp_form_template_location', MAILCHIMP_PLUGIN_DIR . 'front/form-template.php' ) ); 82 | } 83 | 84 | public static function validate_ajax_form() { 85 | 86 | check_ajax_referer( 'mailchimp_subscribe_user_' . $_POST['form_id'] . $_POST['require_fn'] . $_POST['require_ln'] ); 87 | 88 | $errors = self::validate_subscription_form( 89 | $_POST, 90 | array( 91 | 'require_firstname' => (bool)$_POST['require_fn'], 92 | 'require_lastname' => (bool)$_POST['require_ln'] 93 | ) 94 | ); 95 | 96 | if ( ! empty( $errors ) ) 97 | wp_send_json_error( array( 'errors' => $errors ) ); 98 | 99 | 100 | $user['email'] = sanitize_email( $_POST['subscription-email'] ); 101 | $user['first_name'] = sanitize_text_field( $_POST['subscription-firstname'] ); 102 | $user['last_name'] = sanitize_text_field( $_POST['subscription-lastname'] ); 103 | 104 | $results = mailchimp_sync()->mailchimp_add_user( $user ); 105 | 106 | wp_send_json_success( $results ); 107 | 108 | die(); 109 | } 110 | 111 | public static function validate_subscription_form( $input, $settings ) { 112 | $default_settings = array( 113 | 'require_firstname' => false, 114 | 'require_lastname' => false 115 | ); 116 | 117 | 118 | $errors = array(); 119 | 120 | $settings = wp_parse_args( $settings, $default_settings ); 121 | 122 | $email = sanitize_email( $input['subscription-email'] ); 123 | if ( ! is_email( $email ) ) 124 | $errors[] = ( __( 'Please, insert a valid email', MAILCHIMP_LANG_DOMAIN ) ); 125 | 126 | $firstname = sanitize_text_field( $input['subscription-firstname'] ); 127 | $firstname = ! empty( $firstname ) ? $firstname : ''; 128 | if ( empty( $firstname ) && $settings['require_firstname'] ) 129 | $errors[] = ( __( 'First name is required', MAILCHIMP_LANG_DOMAIN ) ); 130 | 131 | 132 | $lastname = sanitize_text_field( $input['subscription-lastname'] ); 133 | $lastname = ! empty( $lastname ) ? $lastname : ''; 134 | if ( empty( $lastname ) && $settings['require_lastname'] ) 135 | $errors[] = ( __( 'Last name is required', MAILCHIMP_LANG_DOMAIN ) ); 136 | 137 | // Check if user is already subscribed and confirmed 138 | $is_subscribed = mailchimp_30_get_user_info( $email ); 139 | if ( $is_subscribed && $is_subscribed['status'] === 'subscribed' ) 140 | $errors[] = ( __( 'The email is already in the subscription list', MAILCHIMP_LANG_DOMAIN ) ); 141 | 142 | return apply_filters( 'mailchimp_form_validate', $errors ); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/mailchimp-api-2.0.php: -------------------------------------------------------------------------------- 1 | apikey = $apikey; 37 | $dc = "us1"; 38 | 39 | if ( strstr( $this->apikey, "-" ) ) { 40 | list( $key, $dc ) = explode( "-", $this->apikey, 2 ); 41 | if ( ! $dc ) 42 | $dc = "us1"; 43 | } 44 | 45 | $this->root = str_replace('https://api', 'https://' . $dc . '.api', $this->root); 46 | $this->root = rtrim($this->root, '/') . '/'; 47 | 48 | $defaults = array( 49 | 'debug' => false, 50 | 'ssl_verifypeer' => true, 51 | 'ssl_verifyhost' => 2, 52 | 'ssl_cainfo' => null 53 | ); 54 | 55 | $opts = wp_parse_args( $opts, $defaults ); 56 | 57 | $this->debug = $opts['debug']; 58 | 59 | if ( isset( $opts['timeout'] ) ) 60 | $this->timeout = absint( $opts['timeout'] ); 61 | 62 | $this->ssl_verifypeer = $opts['ssl_verifypeer']; 63 | $this->ssl_verifyhost = $opts['ssl_verifyhost']; 64 | $this->ssl_cainfo = $opts['ssl_cainfo']; 65 | 66 | $this->folders = new Mailchimp_Folders($this); 67 | $this->templates = new Mailchimp_Templates($this); 68 | $this->users = new Mailchimp_Users($this); 69 | $this->helper = new Mailchimp_Helper($this); 70 | $this->mobile = new Mailchimp_Mobile($this); 71 | $this->conversations = new Mailchimp_Conversations($this); 72 | $this->ecomm = new Mailchimp_Ecomm($this); 73 | $this->neapolitan = new Mailchimp_Neapolitan($this); 74 | $this->lists = new Mailchimp_Lists($this); 75 | $this->campaigns = new Mailchimp_Campaigns($this); 76 | $this->vip = new Mailchimp_Vip($this); 77 | $this->reports = new Mailchimp_Reports($this); 78 | $this->gallery = new Mailchimp_Gallery($this); 79 | $this->goal = new Mailchimp_Goal($this); 80 | } 81 | 82 | public function call( $url, $params ) { 83 | $params['apikey'] = $this->apikey; 84 | 85 | $params = json_encode($params); 86 | 87 | $args = array( 88 | 'timeout' => $this->timeout, 89 | 'user-agent' => 'MailChimp-PHP/2.0.4', 90 | 'blocking' => true, 91 | 'headers' => array( 'Content-Type' => 'application/json' ), 92 | 'body' => $params, 93 | 'sslverify' => $this->ssl_verifypeer, 94 | 'filename' => null 95 | ); 96 | 97 | $args = apply_filters( 'mailchimp_request_args', $args ); 98 | 99 | if ( $this->ssl_cainfo ) 100 | $args['sslcertificates'] = $this->ssl_cainfo; 101 | 102 | $response = wp_remote_post( $this->root . $url . '.json', $args ); 103 | 104 | if ( is_wp_error( $response ) ) { 105 | $this->log_errors( 106 | array( array( 107 | 'code' => $response->get_error_code(), 108 | 'message' => $response->get_error_message() 109 | ) ) 110 | ); 111 | return $response; 112 | } 113 | 114 | $response_body = wp_remote_retrieve_body( $response ); 115 | 116 | $result = json_decode($response_body, true); 117 | 118 | if( floor( $response['response']['code'] / 100 ) >= 4 ) { 119 | $error = $this->castError($result); 120 | $this->log_errors( 121 | array( array( 122 | 'code' => $error->getCode(), 123 | 'message' => $error->getMessage() 124 | ) ) 125 | ); 126 | return new WP_Error( $error->getCode(), $error->getMessage() ); 127 | } 128 | 129 | return $result; 130 | } 131 | 132 | public function log_errors( $errors ) { 133 | if ( ! is_array( $errors ) ) 134 | $errors = array( $errors ); 135 | 136 | $current_log = get_site_option( 'mailchimp_error_log' ); 137 | $new_log = array(); 138 | 139 | 140 | foreach ( $errors as $error ) { 141 | 142 | $code = isset( $error['code'] ) ? $error['code'] : 0; 143 | $message = isset( $error['message'] ) ? $error['message'] : ''; 144 | $email = isset( $error['email'] ) ? $error['email'] : ''; 145 | $date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) ); 146 | 147 | $new_log[] = compact( 'code', 'message', 'email', 'date' ); 148 | 149 | } 150 | 151 | 152 | if ( $current_log ) { 153 | 154 | $new_log = array_merge( $current_log, $new_log ); 155 | 156 | // We'll only saved the last X lines of the log 157 | $count = count( $new_log ); 158 | if ( $count > MAILCHIMP_MAX_LOG_LINES ) { 159 | $new_log = array_slice( $new_log, $count - $offset - 1 ); 160 | } 161 | 162 | } 163 | 164 | update_site_option( 'mailchimp_error_log', $new_log ); 165 | } 166 | } -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Ecomm.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Import Ecommerce Order Information to be used for Segmentation. This will generally be used by ecommerce package plugins 10 | provided by us or by 3rd part system developers. 11 | * @param associative_array $order 12 | * - id string the Order Id 13 | * - campaign_id string optional the Campaign Id to track this order against (see the "mc_cid" query string variable a campaign passes) 14 | * - email_id string optional (kind of) the Email Id of the subscriber we should attach this order to (see the "mc_eid" query string variable a campaign passes) - required if campaign_id is passed, otherwise either this or email is required. If both are provided, email_id takes precedence 15 | * - email string optional (kind of) the Email Address we should attach this order to - either this or email_id is required. If both are provided, email_id takes precedence 16 | * - total double The Order Total (ie, the full amount the customer ends up paying) 17 | * - order_date string optional the date of the order - if this is not provided, we will default the date to now. Should be in the format of 2012-12-30 18 | * - shipping double optional the total paid for Shipping Fees 19 | * - tax double optional the total tax paid 20 | * - store_id string a unique id for the store sending the order in (32 bytes max) 21 | * - store_name string optional a "nice" name for the store - typically the base web address (ie, "store.mailchimp.com"). We will automatically update this if it changes (based on store_id) 22 | * - items array structs for each individual line item including: 23 | * - line_num int optional the line number of the item on the order. We will generate these if they are not passed 24 | * - product_id int the store's internal Id for the product. Lines that do no contain this will be skipped 25 | * - sku string optional the store's internal SKU for the product. (max 30 bytes) 26 | * - product_name string the product name for the product_id associated with this item. We will auto update these as they change (based on product_id) (max 500 bytes) 27 | * - category_id int (required) the store's internal Id for the (main) category associated with this product. Our testing has found this to be a "best guess" scenario 28 | * - category_name string (required) the category name for the category_id this product is in. Our testing has found this to be a "best guess" scenario. Our plugins walk the category heirarchy up and send "Root - SubCat1 - SubCat4", etc. 29 | * - qty double optional the quantity of the item ordered - defaults to 1 30 | * - cost double optional the cost of a single item (ie, not the extended cost of the line) - defaults to 0 31 | * @return associative_array with a single entry: 32 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 33 | */ 34 | public function orderAdd($order) { 35 | $_params = array("order" => $order); 36 | return $this->master->call('ecomm/order-add', $_params); 37 | } 38 | 39 | /** 40 | * Delete Ecommerce Order Information used for segmentation. This will generally be used by ecommerce package plugins 41 | that we provide or by 3rd part system developers. 42 | * @param string $store_id 43 | * @param string $order_id 44 | * @return associative_array with a single entry: 45 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 46 | */ 47 | public function orderDel($store_id, $order_id) { 48 | $_params = array("store_id" => $store_id, "order_id" => $order_id); 49 | return $this->master->call('ecomm/order-del', $_params); 50 | } 51 | 52 | /** 53 | * Retrieve the Ecommerce Orders for an account 54 | * @param string $cid 55 | * @param int $start 56 | * @param int $limit 57 | * @param string $since 58 | * @return associative_array the total matching orders and the specific orders for the requested page 59 | * - total int the total matching orders 60 | * - data array structs for each order being returned 61 | * - store_id string the store id generated by the plugin used to uniquely identify a store 62 | * - store_name string the store name collected by the plugin - often the domain name 63 | * - order_id string the internal order id the store tracked this order by 64 | * - email string the email address that received this campaign and is associated with this order 65 | * - order_total double the order total 66 | * - tax_total double the total tax for the order (if collected) 67 | * - ship_total double the shipping total for the order (if collected) 68 | * - order_date string the date the order was tracked - from the store if possible, otherwise the GMT time we received it 69 | * - items array structs for each line item on this order.: 70 | * - line_num int the line number 71 | * - product_id int the product id 72 | * - product_name string the product name 73 | * - product_sku string the sku for the product 74 | * - product_category_id int the category id for the product 75 | * - product_category_name string the category name for the product 76 | * - qty int the quantity ordered 77 | * - cost double the cost of the item 78 | */ 79 | public function orders($cid=null, $start=0, $limit=100, $since=null) { 80 | $_params = array("cid" => $cid, "start" => $start, "limit" => $limit, "since" => $since); 81 | return $this->master->call('ecomm/orders', $_params); 82 | } 83 | 84 | } 85 | 86 | 87 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Vip.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Retrieve all Activity (opens/clicks) for VIPs over the past 10 days 10 | * @return array structs for each activity recorded. 11 | * - action string The action taken - either "open" or "click" 12 | * - timestamp string The datetime the action occurred in GMT 13 | * - url string IF the action is a click, the url that was clicked 14 | * - unique_id string The campaign_id of the List the Member appears on 15 | * - title string The campaign title 16 | * - list_name string The name of the List the Member appears on 17 | * - list_id string The id of the List the Member appears on 18 | * - email string The email address of the member 19 | * - fname string IF a FNAME merge field exists on the list, that value for the member 20 | * - lname string IF a LNAME merge field exists on the list, that value for the member 21 | * - member_rating int the rating of the subscriber. This will be 1 - 5 as described here 22 | * - member_since string the datetime the member was added and/or confirmed 23 | * - geo associative_array the geographic information if we have it. including: 24 | * - latitude string the latitude 25 | * - longitude string the longitude 26 | * - gmtoff string GMT offset 27 | * - dstoff string GMT offset during daylight savings (if DST not observered, will be same as gmtoff 28 | * - timezone string the timezone we've place them in 29 | * - cc string 2 digit ISO-3166 country code 30 | * - region string generally state, province, or similar 31 | */ 32 | public function activity() { 33 | $_params = array(); 34 | return $this->master->call('vip/activity', $_params); 35 | } 36 | 37 | /** 38 | * Add VIPs (previously called Golden Monkeys) 39 | * @param string $id 40 | * @param array $emails 41 | * - email string an email address - for new subscribers obviously this should be used 42 | * - euid string the unique id for an email address (not list related) - the email "id" returned from listMemberInfo, Webhooks, Campaigns, etc. 43 | * - leid string the list email id (previously called web_id) for a list-member-info type call. this doesn't change when the email address changes 44 | * @return associative_array of data and success/error counts 45 | * - success_count int the number of successful adds 46 | * - error_count int the number of unsuccessful adds 47 | * - errors array array of error structs including: 48 | * - email associative_array whatever was passed in the email parameter 49 | * - email string the email address added 50 | * - euid string the email unique id 51 | * - leid string the list member's truly unique id 52 | * - code string the error code 53 | * - error string the error message 54 | * - data array array of structs for each member added 55 | * - email associative_array whatever was passed in the email parameter 56 | * - email string the email address added 57 | * - euid string the email unique id 58 | * - leid string the list member's truly unique id 59 | */ 60 | public function add($id, $emails) { 61 | $_params = array("id" => $id, "emails" => $emails); 62 | return $this->master->call('vip/add', $_params); 63 | } 64 | 65 | /** 66 | * Remove VIPs - this does not affect list membership 67 | * @param string $id 68 | * @param array $emails 69 | * - email string an email address - for new subscribers obviously this should be used 70 | * - euid string the unique id for an email address (not list related) - the email "id" returned from listMemberInfo, Webhooks, Campaigns, etc. 71 | * - leid string the list email id (previously called web_id) for a list-member-info type call. this doesn't change when the email address changes 72 | * @return associative_array of data and success/error counts 73 | * - success_count int the number of successful deletions 74 | * - error_count int the number of unsuccessful deletions 75 | * - errors array array of error structs including: 76 | * - email associative_array whatever was passed in the email parameter 77 | * - email string the email address 78 | * - euid string the email unique id 79 | * - leid string the list member's truly unique id 80 | * - code string the error code 81 | * - msg string the error message 82 | * - data array array of structs for each member deleted 83 | * - email associative_array whatever was passed in the email parameter 84 | * - email string the email address 85 | * - euid string the email unique id 86 | * - leid string the list member's truly unique id 87 | */ 88 | public function del($id, $emails) { 89 | $_params = array("id" => $id, "emails" => $emails); 90 | return $this->master->call('vip/del', $_params); 91 | } 92 | 93 | /** 94 | * Retrieve all Golden Monkey(s) for an account 95 | * @return array structs for each Golden Monkey, including: 96 | * - list_id string The id of the List the Member appears on 97 | * - list_name string The name of the List the Member appears on 98 | * - email string The email address of the member 99 | * - fname string IF a FNAME merge field exists on the list, that value for the member 100 | * - lname string IF a LNAME merge field exists on the list, that value for the member 101 | * - member_rating int the rating of the subscriber. This will be 1 - 5 as described here 102 | * - member_since string the datetime the member was added and/or confirmed 103 | */ 104 | public function members() { 105 | $_params = array(); 106 | return $this->master->call('vip/members', $_params); 107 | } 108 | 109 | } 110 | 111 | 112 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | require('load-grunt-tasks')(grunt); 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | 6 | checktextdomain: { 7 | options:{ 8 | report_missing: false, 9 | text_domain: 'mailchimp', 10 | keywords: [ 11 | '__:1,2d', 12 | '_e:1,2d', 13 | '_x:1,2c,3d', 14 | 'esc_html__:1,2d', 15 | 'esc_html_e:1,2d', 16 | 'esc_html_x:1,2c,3d', 17 | 'esc_attr__:1,2d', 18 | 'esc_attr_e:1,2d', 19 | 'esc_attr_x:1,2c,3d', 20 | '_ex:1,2c,3d', 21 | '_n:1,2,4d', 22 | '_nx:1,2,4c,5d', 23 | '_n_noop:1,2,3d', 24 | '_nx_noop:1,2,3c,4d' 25 | ] 26 | }, 27 | files: { 28 | src: [ 29 | '**/*.php', // Include all files 30 | '!node_modules/**', // Exclude node_modules/ 31 | '!tests/**', // Exclude tests/ 32 | '!admin/assets/shared-ui/**', // Exclude WPMU DEV Shared UI 33 | '!externals/**', 34 | '!tmp/**' 35 | ], 36 | expand: true 37 | } 38 | }, 39 | 40 | copy: { 41 | main: { 42 | src: [ 43 | '**', 44 | '!npm-debug.log', 45 | '!node_modules/**', 46 | '!build/**', 47 | '!bin/**', 48 | '!.git/**', 49 | '!Gruntfile.js', 50 | '!package.json', 51 | '!.gitignore', 52 | '!.gitmodules', 53 | '!sourceMap.map', 54 | '!phpunit.xml.dist', 55 | '!travis.yml', 56 | '!tests/**', 57 | '!**/Gruntfile.js', 58 | '!**/package.json', 59 | '!**/README.md', 60 | '!lite-vs-pro.txt', 61 | '!composer.json', 62 | '!vendor/**', 63 | '!tmp/**', 64 | '!**/*~' 65 | ], 66 | dest: 'build/<%= pkg.name %>/' 67 | } 68 | }, 69 | 70 | // Generate POT files. 71 | makepot: { 72 | options: { 73 | type: 'wp-plugin', 74 | domainPath: 'languages', 75 | potHeaders: { 76 | 'report-msgid-bugs-to': 'https://wpmudev.org', 77 | 'language-team': 'LANGUAGE ' 78 | } 79 | }, 80 | dist: { 81 | options: { 82 | potFilename: 'mailchimp.pot', 83 | exclude: [ 84 | 'tests/.*', 85 | 'node_modules/.*', 86 | 'includes/external/*' 87 | ] 88 | } 89 | } 90 | }, 91 | 92 | clean: { 93 | main: ['build/*'] 94 | }, 95 | 96 | compress: { 97 | main: { 98 | options: { 99 | mode: 'zip', 100 | archive: './build/<%= pkg.name %>-<%= pkg.version %>.zip' 101 | }, 102 | expand: true, 103 | cwd: 'build/<%= pkg.name %>/', 104 | src: ['**/*'], 105 | dest: '<%= pkg.name %>/' 106 | } 107 | }, 108 | 109 | search: { 110 | files: { 111 | src: ['<%= pkg.main %>'] 112 | }, 113 | options: { 114 | logFile: 'tmp/log-search.log', 115 | searchString: /^[ \t\/*#@]*Version:(.*)$/mig, 116 | onMatch: function(match) { 117 | var regExp = /^[ \t\/*#@]*Version:(.*)$/mig; 118 | var groupedMatches = regExp.exec( match.match ); 119 | var versionFound = groupedMatches[1].trim(); 120 | if ( versionFound != grunt.file.readJSON('package.json').version ) { 121 | grunt.fail.fatal("Plugin version does not match with package.json version. Please, fix."); 122 | } 123 | }, 124 | onComplete: function( matches ) { 125 | if ( ! matches.numMatches ) { 126 | if ( ! grunt.file.readJSON('package.json').main ) { 127 | grunt.fail.fatal("main field is not defined in package.json. Please, add the plugin main file on that field."); 128 | } 129 | else { 130 | grunt.fail.fatal("Version Plugin header not found in " + grunt.file.readJSON('package.json').main + " file or the file does not exist" ); 131 | } 132 | 133 | } 134 | } 135 | } 136 | }, 137 | 138 | open: { 139 | dev : { 140 | path: '<%= pkg.projectEditUrl %>', 141 | app: 'Google Chrome' 142 | } 143 | } 144 | }); 145 | 146 | grunt.loadNpmTasks('grunt-search'); 147 | 148 | grunt.registerTask( 'finish', function() { 149 | var json = grunt.file.readJSON('package.json'); 150 | var file = './build/' + json.name + '-' + json.version + '.zip'; 151 | grunt.log.writeln( 'Process finished. Browse now to: ' + json.projectEditUrl['green'].bold ); 152 | grunt.log.writeln( 'And upload the zip file under: ' + file['green'].bold); 153 | grunt.log.writeln('----------'); 154 | grunt.log.writeln(''); 155 | grunt.log.writeln( 'Remember to tag this new version:' ); 156 | 157 | var tagMessage = 'git tag -a ' + json.version + ' -m "$CHANGELOG"'; 158 | var pushMessage = 'git push -u origin ' + json.version; 159 | grunt.log.writeln( tagMessage['green'] ); 160 | grunt.log.writeln( pushMessage['green'] ); 161 | grunt.log.writeln('----------'); 162 | }); 163 | 164 | grunt.registerTask('version-compare', [ 'search' ] ); 165 | 166 | grunt.registerTask('build', [ 167 | 'version-compare', 168 | 'clean', 169 | 'checktextdomain', 170 | 'makepot', 171 | 'copy', 172 | 'compress' 173 | ]); 174 | }; 175 | -------------------------------------------------------------------------------- /admin/assets/mailchimp-admin.js: -------------------------------------------------------------------------------- 1 | window.MailChimp = { 2 | options: {}, 3 | 4 | /** 5 | * Save the responses in every iteration so 6 | * bulk status can be checked at the end of the process 7 | */ 8 | bulkActions: [], 9 | progressbar:null, 10 | $progressLabel:null, 11 | processing: false, 12 | page: 1, 13 | stats: { 14 | added:0, 15 | updated:0, 16 | errors:0, 17 | total:0 18 | }, 19 | init: function( options ) { 20 | if ( this.processing ) { 21 | // We are already processing 22 | return this; 23 | } 24 | 25 | var labels = jQuery.extend( { 26 | }, options.labels || { 27 | initializing: 'Initializing...', 28 | processed: 'Processed %s / %s', 29 | checkOperation: 'Checking bulk action result, operation: %s', 30 | downloadMoreInfo: 'Download more info about bulk operation', 31 | results: 'Results: Total: %s. Errors: %s' 32 | } ); 33 | 34 | this.options = jQuery.extend( { 35 | total: 0, 36 | nonce: '', 37 | progressbar: '', 38 | labels: labels, 39 | progressLabel: '' 40 | }, options ); 41 | 42 | this.$el = jQuery( this.options.progressbar ); 43 | this.$progressLabel = jQuery( this.options.progressLabel ); 44 | 45 | this.processing = true; 46 | this.showProgressBar(); 47 | this.process(); 48 | return this; 49 | }, 50 | showProgressBar: function() { 51 | this.progressbar = this.$el.progressbar(); 52 | this.progressbar.progressbar('option', 'value',false); 53 | this.setLabel( this.options.labels.initializing ); 54 | this.$progressLabel.show(); 55 | }, 56 | 57 | process() { 58 | if ( this.getStat( 'total' ) >= this.options.total ) { 59 | // Check bulks and finish the process 60 | this.checkBulkResults(); 61 | return false; 62 | } 63 | 64 | var mc = this; 65 | 66 | this.call( { 67 | action:'mailchimp_import', 68 | page: mc.page 69 | }) 70 | .done( function(response) { 71 | if ( ! response.success ) { 72 | alert( response.data.message ); 73 | mc.stop(); 74 | } 75 | else { 76 | mc.page++; 77 | mc.updateStat( 'total', mc.getStat( 'total' ) + response.data.processed ); 78 | mc.addBulkAction(response.data.bulkInfo.operation, response.data.bulkInfo.users ); 79 | 80 | var total = mc.getStat( 'total' ); 81 | mc.setLabel( mc.options.labels.processed, Math.min( total, mc.options.total ), mc.options.total ); 82 | mc.process(); 83 | } 84 | }); 85 | }, 86 | 87 | checkBulkResults: function() { 88 | var action = this.getNextUncheckedBulkAction(); 89 | if ( ! action ) { 90 | this.finish(); 91 | return; 92 | } 93 | 94 | this.setLabel( this.options.labels.checkOperation, action.operation ); 95 | var mc = this; 96 | 97 | this.call({ 98 | action: 'mailchimp_check_bulk_results', 99 | operation: action.operation 100 | }) 101 | .done( function( response ) { 102 | if ( response.data.finished ) { 103 | // MailChimp has finished with the bulk process 104 | var result = response.data.result; 105 | mc.updateBulkAction( action.operation, result ); 106 | 107 | // Update stats 108 | mc.updateStat( 'errors', mc.getStat( 'errors' ) + result.errored_operations ); 109 | mc.checkBulkResults(); 110 | } 111 | else { 112 | // MailChimp is still processing, let's wait a little 113 | setTimeout(function(){ 114 | mc.checkBulkResults(); 115 | }, 5000); 116 | } 117 | }); 118 | }, 119 | 120 | finish: function() { 121 | var actions = this.getBulkActions(); 122 | console.log(actions); 123 | this.progressbar.progressbar( 'destroy' ); 124 | 125 | // Show a list of URL links where the user can download extra information 126 | var urlLinks = jQuery( ''); 127 | var link; 128 | var listElem; 129 | for ( operation in actions ) { 130 | listElem = jQuery( '
  • ' ); 131 | link = jQuery( '' ) 132 | .attr( 'href', actions[operation].result.response_body_url ) 133 | .text( this.options.labels.downloadMoreInfo + ' ' + operation, operation ); 134 | 135 | listElem.append( link ); 136 | urlLinks.append( listElem ); 137 | } 138 | this.setLabel( this.options.labels.results, this.options.total, this.getStat( 'errors' ) ); 139 | this.$progressLabel.append( urlLinks ); 140 | }, 141 | 142 | call: function( data, callback ) { 143 | var mc = this; 144 | data.nonce = this.options.nonce; 145 | return jQuery.post( ajaxurl, data ) 146 | .error( function( response ) { 147 | console.log( response ); 148 | mc.stop(); 149 | }); 150 | }, 151 | 152 | updateStat: function( type, value ) { 153 | this.stats[ type ] = value; 154 | }, 155 | 156 | getStat: function( type ) { 157 | if ( this.stats[ type ] ) { 158 | return this.stats[ type ]; 159 | } 160 | 161 | return 0; 162 | }, 163 | 164 | addBulkAction: function( operation, userIds ) { 165 | this.bulkActions[operation] = { 166 | userIds: userIds, 167 | checked: false, 168 | result: false, 169 | operation: operation 170 | }; 171 | }, 172 | 173 | updateBulkAction: function( operation, result ) { 174 | this.bulkActions[operation].checked = true; 175 | this.bulkActions[operation].result = result; 176 | 177 | // Update stats 178 | }, 179 | 180 | getBulkActions: function() { 181 | return this.bulkActions; 182 | }, 183 | 184 | getNextUncheckedBulkAction: function() { 185 | var actions = this.getBulkActions(); 186 | for ( var operation in actions ) { 187 | if ( ! actions[ operation ].checked ) { 188 | return actions[ operation ]; 189 | } 190 | } 191 | return false; 192 | }, 193 | 194 | /** 195 | * Interrupt the process 196 | */ 197 | stop: function() { 198 | this.progressbar.progressbar( 'destroy' ); 199 | this.setLabel( '' ); 200 | }, 201 | 202 | setLabel: function( label ) { 203 | for (var i = 1; i < arguments.length; i++) { 204 | label = label.replace( '%s', arguments[i] ); 205 | } 206 | this.$progressLabel.html( label ); 207 | } 208 | }; 209 | -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Templates.php: -------------------------------------------------------------------------------- 1 | master = $master; 6 | } 7 | 8 | /** 9 | * Create a new user template, NOT campaign content. These templates can then be applied while creating campaigns. 10 | * @param string $name 11 | * @param string $html 12 | * @param int $folder_id 13 | * @return associative_array with a single element: 14 | * - template_id int the new template id, otherwise an error is thrown. 15 | */ 16 | public function add($name, $html, $folder_id=null) { 17 | $_params = array("name" => $name, "html" => $html, "folder_id" => $folder_id); 18 | return $this->master->call('templates/add', $_params); 19 | } 20 | 21 | /** 22 | * Delete (deactivate) a user template 23 | * @param int $template_id 24 | * @return associative_array with a single entry: 25 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 26 | */ 27 | public function del($template_id) { 28 | $_params = array("template_id" => $template_id); 29 | return $this->master->call('templates/del', $_params); 30 | } 31 | 32 | /** 33 | * Pull details for a specific template to help support editing 34 | * @param int $template_id 35 | * @param string $type 36 | * @return associative_array info to be used when editing 37 | * - default_content associative_array the default content broken down into the named editable sections for the template - dependant upon template, so not documented 38 | * - sections associative_array the valid editable section names - dependant upon template, so not documented 39 | * - source string the full source of the template as if you exported it via our template editor 40 | * - preview string similar to the source, but the rendered version of the source from our popup preview 41 | */ 42 | public function info($template_id, $type='user') { 43 | $_params = array("template_id" => $template_id, "type" => $type); 44 | return $this->master->call('templates/info', $_params); 45 | } 46 | 47 | /** 48 | * Retrieve various templates available in the system, allowing some thing similar to our template gallery to be created. 49 | * @param associative_array $types 50 | * - user boolean Custom templates for this user account. Defaults to true. 51 | * - gallery boolean Templates from our Gallery. Note that some templates that require extra configuration are withheld. (eg, the Etsy template). Defaults to false. 52 | * - base boolean Our "start from scratch" extremely basic templates. Defaults to false. As of the 9.0 update, "base" templates are no longer available via the API because they are now all saved Drag & Drop templates. 53 | * @param associative_array $filters 54 | * - category string optional for Gallery templates only, limit to a specific template category 55 | * - folder_id string user templates, limit to this folder_id 56 | * - include_inactive boolean user templates are not deleted, only set inactive. defaults to false. 57 | * - inactive_only boolean only include inactive user templates. defaults to false. 58 | * - include_drag_and_drop boolean Include templates created and saved using the new Drag & Drop editor. Note: You will not be able to edit or create new drag & drop templates via this API. This is useful only for creating a new campaign based on a drag & drop template. 59 | * @return associative_array for each type 60 | * - user array matching user templates, if requested. 61 | * - id int Id of the template 62 | * - name string Name of the template 63 | * - layout string General description of the layout of the template 64 | * - category string The category for the template, if there is one. 65 | * - preview_image string If we've generated it, the url of the preview image for the template. We do out best to keep these up to date, but Preview image urls are not guaranteed to be available 66 | * - date_created string The date/time the template was created 67 | * - active boolean whether or not the template is active and available for use. 68 | * - edit_source boolean Whether or not you are able to edit the source of a template. 69 | * - folder_id boolean if it's in one, the folder id 70 | * - gallery array matching gallery templates, if requested. 71 | * - id int Id of the template 72 | * - name string Name of the template 73 | * - layout string General description of the layout of the template 74 | * - category string The category for the template, if there is one. 75 | * - preview_image string If we've generated it, the url of the preview image for the template. We do out best to keep these up to date, but Preview image urls are not guaranteed to be available 76 | * - date_created string The date/time the template was created 77 | * - active boolean whether or not the template is active and available for use. 78 | * - edit_source boolean Whether or not you are able to edit the source of a template. 79 | * - base array matching base templates, if requested. (Will always be empty as of 9.0) 80 | */ 81 | public function getList($types=array(), $filters=array()) { 82 | $_params = array("types" => $types, "filters" => $filters); 83 | return $this->master->call('templates/list', $_params); 84 | } 85 | 86 | /** 87 | * Undelete (reactivate) a user template 88 | * @param int $template_id 89 | * @return associative_array with a single entry: 90 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 91 | */ 92 | public function undel($template_id) { 93 | $_params = array("template_id" => $template_id); 94 | return $this->master->call('templates/undel', $_params); 95 | } 96 | 97 | /** 98 | * Replace the content of a user template, NOT campaign content. 99 | * @param int $template_id 100 | * @param associative_array $values 101 | * - name string the name for the template - names must be unique and a max of 50 bytes 102 | * - html string a string specifying the entire template to be created. This is NOT campaign content. They are intended to utilize our template language. 103 | * - folder_id int the folder to put this template in - 0 or a blank values will remove it from a folder. 104 | * @return associative_array with a single entry: 105 | * - complete bool whether the call worked. reallistically this will always be true as errors will be thrown otherwise. 106 | */ 107 | public function update($template_id, $values) { 108 | $_params = array("template_id" => $template_id, "values" => $values); 109 | return $this->master->call('templates/update', $_params); 110 | } 111 | 112 | } 113 | 114 | 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MailChimp Integration 2 | 3 | **INACTIVE NOTICE: This plugin is unsupported by WPMUDEV, we've published it here for those technical types who might want to fork and maintain it for their needs.** 4 | 5 | ## Translations 6 | 7 | Translation files can be found at https://github.com/wpmudev/translations 8 | 9 | ## Mailchimp Integration ties WordPress to MailChimp for seriously powerful email marketing, growing a subscriber base and list syncing. 10 | 11 | Get far more than just easy-embed signup forms. Tap core features of MailChimp that allow you to not only build your email subscriber list – but integrates to manage your site's user database. 12 | 13 | ### Build a Massive Following 14 | 15 | MailChimp Integration helps you effectively capture new subscribers from anywhere on your site using simple customizable signup forms. The included MailChimp widget and shortcode generator make it possible to add subscription forms anywhere on your site in under 60 seconds. 16 | 17 | ### Smart Subscription Management 18 | 19 | Eliminate the frustrations associated with managing users across multiple lists. Quickly establish a fluid communication stream with MailChimp and make sure your site user list and email list are always a perfect match. Automatically subscribe new users to your mailing list, add subscribers to your site user list and trigger user removal when unsubscribing from your mailing list. 20 | 21 | ### Merge and Grow Your User Base 22 | 23 | Merge existing Subscriber and User lists with a single click. Import makes it easy to sync existing lists and works to complete missing user information, eliminate duplicates, and remove spammed and deleted users from your selected MailChimp list. 24 | 25 | ### Make Room to Expand 26 | 27 | From our simple subscription form generator to managing user lists of hundreds or even thousands, MailChimp Integration is the right fit for sites both large and small. If you’re serious about email and building a huge following, create a powerful marketing machine by expanding WordPress with MailChimp. 28 | 29 | ## Usage 30 | 31 | For help with installing plugins please refer to our [Plugin installation guide](https://premium.wpmudev.org/wpmu-manual/installing-regular-plugins-on-wpmu/). Once installed, login to your admin panel for WordPress or Multisite and activate the plugin: 32 | 33 | * On regular WordPress installs – visit **Plugins** and **Activate** the plugin. The plugin options will appear in your Settings menu. [ 34 | 35 | ![Plugin options in single site installs of WordPress.](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-single-menu.png) 36 | 37 | ](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-single-menu.png) 38 | 39 | Plugin options in single site installs of WordPress. 40 | 41 | * For WordPress Multisite installs – Visit **Network Admin -> Plugins** and **Network Activate** the plugin. The plugin options will appear in your Network Settings menu. **Note:** When used on a multisite install, MailChimp Integration _**must**_ be network activated to work. 42 | 43 | ![Plugin options on multisite installs of WordPress.](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-network-menu.png) 44 | 45 | Plugin options on multisite installs of WordPress. 46 | 47 | ### To use: 48 | 49 | First, set up an account with [MailChimp](http://www.mailchimp.com/) (unless you already have one of course). Then you can either create a new MailChimp list for your users, e.g. Edublogs.org users, or use an existing one. 50 | 51 | ![mailchimp-integration-1300-create-list](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-create-list.png) 52 | 53 | Login into your WordPress dashboard, and go to the MailChimp settings. Once you enter your MailChimp API key and click Save Changes, additional settings will become available. 54 | 55 | ![1\. Allow sub-sites to use the widget. 2\. Your MailChimp API key. 3\. Select whether users should be opted in automatically. 4\. Ignore duplicate email accounts. 5\. Select your mailing list.](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-settings-1.png) 56 | 57 | 1\. Allow sub-sites to use the widget. 58 | 2\. Your MailChimp API key. 59 | 3\. Select whether users should be opted in automatically. 60 | 4\. Ignore duplicate email accounts. 61 | 5\. Select your mailing list. 62 | 63 | 1\. The _Allow widget in all subsites_ checkbox is only available when network-activated. Checking it will allow sub-site admins to place the MailChimp signup widget on their sites too. 2\. _MailChimp API Key_ is, well, your key. :) 3\. If you set _Auto Opt-in_ to "Yes", your users will not receive an email confirmation. Be careful with this: some locales have anti-spam regulations that require the double-optin. 4\. You can set _Ignore email addresses including + signs_ to "Yes" if some of your subscribers have duplicate accounts using the "+" sign. Don't want to annoy them with duplicate emails. 5\. _Mailing List_ is where you select the MailChimp list you want to sync. You can also sync all your existing WordPress users to your MailChimp list. 64 | 65 | ![1\. Select your MailChimp mailing list. 2\. Select whether users should be opted in automatically.](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-settings-2.png) 66 | 67 | 1\. Select your MailChimp mailing list. 68 | 2\. Select whether users should be opted in automatically. 69 | 70 | 1\. Select your Mailing List. 2\. Select whether to _Auto Opt-in_ your users or not. 3\. Click _Import_ to synchronize your WordPress users to your MailChimp list. The bottom section of your MailChimp settings page is a very handy excerpt of the error log. It will display the most recent 100 lines right in your admin to help you with troubleshooting. It even tells you if email addresses have been banned. 71 | 72 | ![mailchimp-integration-1300-errorlog](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-errorlog.png) 73 | 74 | Finally, if you want your users to be able to subscribe directly to your MailChimp list, you can customize how the widget form should appear under Appearance > Widgets. 75 | 76 | ![mailchimp-integration-1300-widget](https://premium.wpmudev.org/wp-content/uploads/2009/04/mailchimp-integration-1300-widget.png) 77 | 78 | ### Using MailChimp Webhooks 79 | 80 | With MailChimp webhooks, you can synchronize your MailChimp lists and WordPress users. Yes, you read that right, whenever someone subscribes to your MailChimp list, they can be automatically added as a user on your WordPress site. Booya! The settings to get this done on your WordPress site are quite simple, and appear once you have configured & saved the previous settings (eg - you have entered your MailChimp API key, selected the list you want use & saved changes): 81 | 82 | ![mailchimp-integration-1711-webhooks](https://premium.wpmudev.org/wp-content/uploads/2014/12/mailchimp-integration-1711-webhooks.png) 83 | 84 | 1\. First, enter any name you would like your webhook to have in _Specify a unique webhook key_ field. Then click _Save Changes_ at the bottom of your screen. 2\. _Your Webhook URL_ will then appear right beneath the field where you just entered the key name. That is what you must enter in your MailChimp account. 3\. Select the _Action to take when user unsubscribes from list_. You can select to either mark them as unsubscribed, or to delete them from your WordPress install. _Save Changes_ again. Now, head on over to your MailChimp account page and follow the simple directions you'll find [on this page](http://kb.mailchimp.com/integrations/other-integrations/what-are-webhooks-and-how-can-i-set-them-up) to set up your webhook. The URL you'll be entering in the Callback URL field is the one you just generated with your unique key name. 85 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | Plugin Name: MailChimp Sync 2 | Author: WPMU DEV 3 | Requires at least: 3.5 4 | Tested up to: 4.8 5 | 6 | Change Log: 7 | ---------------------------------------------------------------------- 8 | ---------------------------------------------------------------------- 9 | 1.9.7 - 2017-11-01 10 | - Fix: Deprecated code 11 | 12 | 1.9.6 - 2017-09-04 13 | ---------------------------------------------------------------------- 14 | - Fix: conflict with WooCommerce plugin 15 | 16 | 1.9.4 - 2017-07-11 17 | ---------------------------------------------------------------------- 18 | - Fix: Fatal error when using widget/shortcode 19 | 20 | 1.9.3 - 2017-01-13 21 | ---------------------------------------------------------------------- 22 | - Added filter to modify the MailChimp API request parameters 23 | 24 | 1.9.2 - 2016-12-22 25 | ---------------------------------------------------------------------- 26 | - Fix: Fatal error when inserting a wrong API Key 27 | 28 | 1.9.1 - 2016-12-21 29 | ---------------------------------------------------------------------- 30 | - Fix: Capabilities issue in single installations 31 | 32 | 1.9.0 - 2016-12-19 33 | ---------------------------------------------------------------------- 34 | - Enhance: Updated MailChimp API to 3.0 35 | - Updated WPMU DEV Dashboard notification 36 | 37 | 1.8.2 - 2015-08-29 38 | ---------------------------------------------------------------------- 39 | - Fix: Webhook URL not working on subfolder installation 40 | - Fix: Warning on activation 41 | 42 | 1.8.1 - 2015-11-25 43 | ---------------------------------------------------------------------- 44 | - Fixed: Deprecated widget notice 45 | 46 | 1.8 - 2015-08-20 47 | ---------------------------------------------------------------------- 48 | - Enhance: Removed user meta to check if it's subscribed to the list in the profile page. Using API instead. 49 | - Enhance: User Profile Admin styles 50 | 51 | 1.7.3 - 2015-05-29 52 | ---------------------------------------------------------------------- 53 | - Fixed: Warning when bulk subscribing users. 54 | - Added default arguments for shortcode. 55 | 56 | 1.7.2 - 2015-03-10 57 | ---------------------------------------------------------------------- 58 | - Fixed: Added message error when a user is already subscribed and confirmed 59 | 60 | 1.7.1.1 - 2014-12-09 61 | ---------------------------------------------------------------------- 62 | - Fixed: Undefined constant warning. 63 | 64 | 1.7.1 - 2014-12-09 65 | ---------------------------------------------------------------------- 66 | - Fixed: Shortcode was always appearing on the top of the content. 67 | 68 | 1.7 - 2014-12-05 69 | ---------------------------------------------------------------------- 70 | - New: Mailchimp Webhooks. 71 | 72 | 1.6.6 - 2014-11-10 73 | ---------------------------------------------------------------------- 74 | - Fixed: Users details were not updated in Mailchimp List. 75 | 76 | 1.6.5 - 2014-08-28 77 | ---------------------------------------------------------------------- 78 | - Enhanced: Added option that saves the last list imported. 79 | - Fixed: Fixed typo in Exception classes. 80 | 81 | 1.6.4 - 2014-08-25 82 | ---------------------------------------------------------------------- 83 | - Fixed: MailChimp API errors were causing a fatal error. 84 | 85 | 1.6.3 - 2014-08-18 86 | ---------------------------------------------------------------------- 87 | - Enhanced: added prefix to Mailchimp API classes. 88 | - Enhanced: Added Settings link in plugins list. 89 | 90 | 1.6.2 - 2014-05-15 91 | ---------------------------------------------------------------------- 92 | - Fixed fatal error 93 | 94 | 1.6.1 - 2014-05-15 95 | ---------------------------------------------------------------------- 96 | - Fixed: Widgets issues when there were more than one in the same screen 97 | - Improved forms validation 98 | - Tiny MCE plugin improved 99 | - Other minor fixes 100 | 101 | 1.6 - 2014-05-02 102 | ---------------------------------------------------------------------- 103 | - curl functions replaced by wp_remote_* functions in Maiclhimp API 104 | - Better errors management 105 | - Fixed Javascript conflict 106 | - Fixed redirection in import tab to 404 page in single sites 107 | 108 | 1.5.1 - 2014-04-26 109 | ---------------------------------------------------------------------- 110 | - Plugin triggered a fatal error if the API key was blank 111 | 112 | 1.5 - 2014-04-25 113 | ---------------------------------------------------------------------- 114 | - Mailchimp API updated to 2.0 115 | - Better errors management 116 | - Other minor improvements 117 | 118 | 1.4 - 2014-02-11- Ignacio Cruz 119 | ---------------------------------------------------------------------- 120 | - Added shortcode. 121 | - Ultimate Facebook Integration 122 | - Code refactored 123 | - Settings splitted into tabs 124 | 125 | 1.3 - 2013/10/03 - Ignacio Cruz 126 | ---------------------------------------------------------------------- 127 | - Added new widget. 128 | 129 | 1.2.4 - 2013/05/14 - Ignacio Cruz 130 | ---------------------------------------------------------------------- 131 | - Fixed error when error log was empty. 132 | 133 | 1.2.3 - 2013/05/10 - Ignacio Cruz 134 | ---------------------------------------------------------------------- 135 | - Added an additional control when subscribing users on a list. If the 136 | user was already unsubscribed (from the mail link) it won't be subscribed again 137 | - Added a log for MailChimp API calls 138 | 139 | 1.2.2 - 2013/05/06 - Ignacio Cruz 140 | ---------------------------------------------------------------------- 141 | - The import feature was using the list on the settings instead the list on the import section 142 | 143 | 1.2.1 - 14/03/2013 - Ignacio Cruz 144 | ---------------------------------------------------------------------- 145 | - Fixed some PHP notices when displaying the settings and saving 146 | http://premium.wpmudev.org/forums/topic/basic-php-errors-turn-on-wp_edbug-to-see 147 | - Added styles to submit buttons 148 | 149 | 1.2 - 12/19/2012 - Aaron Edwards 150 | ---------------------------------------------------------------------- 151 | - Make deleting WP users remove them from mailchimp: http://wp.mu/77 152 | 153 | 1.1.4 - 7/23/2012 - Paul Menard 154 | ---------------------------------------------------------------------- 155 | - Patched error returned from MailChimp API when user already is present in MailChimp 156 | http://premium.wpmudev.org/forums/topic/mailchimp-integration#post-249269 157 | 158 | 1.1.3 - 4/15/2012 - Aaron Edwards 159 | ---------------------------------------------------------------------- 160 | - Limit bulk import query to scale better for large user databases 161 | 162 | 1.1.2 - 8/05/2011 - Aaron Edwards 163 | ---------------------------------------------------------------------- 164 | - Add filters for merging additional fields 165 | - Fix entity problems with bulk import of names 166 | 167 | 1.1.1 - 1/05/2011 - Aaron Edwards 168 | ---------------------------------------------------------------------- 169 | - WP 3.1 Compatibility 170 | 171 | 1.1 - 12/20/2010 - Aaron Edwards 172 | ---------------------------------------------------------------------- 173 | - Updated to the latest API to fix bugs 174 | - Now removes users when they or their blogs are spammed/deleted 175 | - Imports Names to MailChimp now on creation and profile updates 176 | - Works with BuddyPress now 177 | - Auto-update capable 178 | 179 | 1.0.4 - 07/20/2010 - Aaron Edwards 180 | ---------------------------------------------------------------------- 181 | - Fixed compatibility with WP installs running BP (for good this time hopefully) 182 | 183 | 1.0.3 - 06/01/2010 184 | ---------------------------------------------------------------------- 185 | - 3.0+ compatibility update 186 | 187 | 1.0.2 - 05/18/2010 188 | ---------------------------------------------------------------------- 189 | - Now comaptible with WP installs running BP 190 | 191 | 1.0.1 - 07/13/2009 192 | ---------------------------------------------------------------------- 193 | - Added option to ignore email address including a + sign. 194 | 195 | 1.0.0 - 04/29/2009 196 | ---------------------------------------------------------------------- 197 | - Initial Release. 198 | -------------------------------------------------------------------------------- /deprecated.php: -------------------------------------------------------------------------------- 1 | api ) ) 23 | return $mailchimp_sync->api; 24 | 25 | require_once( 'mailchimp-api/2.0/mailchimp-api-2.0.php' ); 26 | $mailchimp_apikey = get_site_option('mailchimp_apikey'); 27 | 28 | $options = array( 29 | 'timeout' => apply_filters( 'mailchimp_sync_api_timeout', false ) 30 | ); 31 | 32 | $ssl_verifypeer = apply_filters( 'mailchimp_sync_api_ssl_verifypeer', false ); 33 | if ( $ssl_verifypeer ) { 34 | $options['ssl_verifypeer'] = $ssl_verifypeer; 35 | } 36 | 37 | $ssl_verifyhost = apply_filters( 'mailchimp_sync_api_ssl_verifyhost', false ); 38 | if ( $ssl_verifyhost ) { 39 | $options['ssl_verifyhost'] = $ssl_verifyhost; 40 | } 41 | 42 | $ssl_cainfo = apply_filters( 'mailchimp_sync_api_ssl_cainfo', false ); 43 | if ( $ssl_cainfo ) { 44 | $options['ssl_cainfo'] = $ssl_cainfo; 45 | } 46 | 47 | $debug = apply_filters( 'mailchimp_sync_api_debug', false ); 48 | if ( $debug ) { 49 | $options['debug'] = $debug; 50 | } 51 | 52 | try { 53 | $api = new WPMUDEV_Mailchimp_Sync_API_20( $mailchimp_apikey, $options ); 54 | } 55 | catch ( Exception $e ) { 56 | return new WP_Error( $e->getCode(), $e->getMessage() ); 57 | } 58 | 59 | // Pinging the server 60 | $ping = $api->helper->ping(); 61 | 62 | if ( is_wp_error( $ping ) ) 63 | return $ping; 64 | 65 | $mailchimp_sync->api = $api; 66 | 67 | return $api; 68 | } 69 | 70 | /** 71 | * Get the lists of a Mailchimp account 72 | * 73 | * @return array Lists info 74 | * @deprecated 75 | */ 76 | function mailchimp_get_lists() { 77 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_get_lists()' ); 78 | return mailchimp_30_get_lists(); 79 | } 80 | 81 | /** 82 | * @param $list_id 83 | * @deprecated 84 | * @return array 85 | */ 86 | function mailchimp_get_list_groups( $list_id ) { 87 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_get_list_groups()' ); 88 | return mailchimp_30_get_list_groups( $list_id ); 89 | } 90 | 91 | /** 92 | * Subscribe a user to a Mailchimp list 93 | * 94 | * @param String $user_email 95 | * @param String $list_id 96 | * @param Boolean $autopt 97 | * @param Array $extra Extra data 98 | * Array( 99 | * 'FNAME' => First name, 100 | * 'LNAME' => Last Name 101 | * ) 102 | * @return Array Result from the server 103 | * @deprecated 104 | */ 105 | function mailchimp_subscribe_user( $user_email, $list_id, $autopt = false, $merge = array(), $update = false ) { 106 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_subscribe_user()' ); 107 | $api = mailchimp_load_API(); 108 | 109 | if ( ! $update ) { 110 | return mailchimp_30_subscribe_user( $user_email, $list_id, array( 'merge_fields' => $merge, 'autopt' => $autopt ) ); 111 | } 112 | else { 113 | } 114 | } 115 | 116 | /** 117 | * Check if a user is subscribed in the list 118 | * 119 | * @param String $user_email 120 | * @param String $list_id 121 | * @return bool. True if the user is subscribed already to the list 122 | * @deprecated 123 | */ 124 | function mailchimp_is_user_subscribed( $user_email, $list_id = '' ) { 125 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_is_user_subscribed()' ); 126 | return mailchimp_30_is_user_subscribed( $user_email, $list_id ); 127 | } 128 | 129 | /** 130 | * Unsubscribe a user from a list 131 | * 132 | * @param String $user_email 133 | * @param String $list_id 134 | * @param Boolean $delete True if the user is gonna be deleted from the list (not only unsubscribed) 135 | * 136 | * @deprecated 137 | */ 138 | function mailchimp_unsubscribe_user( $user_email, $list_id, $delete = false ) { 139 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_unsubscribe_user()' ); 140 | return mailchimp_30_unsubscribe_user( $user_email, $list_id, $delete ); 141 | } 142 | 143 | /** 144 | * Update a user data in a list 145 | * @param String $user_email 146 | * @param String $list_id 147 | * @param Array $merge_vars 148 | * Array( 149 | * 'FNAME' => First name, 150 | * 'LNAME' => Last Name 151 | * ) 152 | * @deprecated 153 | */ 154 | function mailchimp_update_user( $user_email, $list_id, $merge_vars ) { 155 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_update_user()' ); 156 | return mailchimp_30_update_user( $user_email, $list_id, array( 'merge_fields' => $merge_vars ) ); 157 | } 158 | 159 | /** 160 | * Return the groups that the user has selected in Settings 161 | * 162 | * @return array Array of groups 163 | * @deprecated 164 | */ 165 | function mailchimp_get_interest_groups() { 166 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_get_interest_groups()' ); 167 | $mailchimp_mailing_list = get_site_option( 'mailchimp_mailing_list', '' ); 168 | $groups = get_site_option( 'mailchimp_groups', array() ); 169 | 170 | $vars = array(); 171 | $merge_groups = array(); 172 | if ( ! empty( $groups[ $mailchimp_mailing_list ] ) ) { 173 | 174 | foreach ( $groups[ $mailchimp_mailing_list ] as $group_id => $subgroups ) { 175 | if ( is_array( $subgroups ) && ! empty( $subgroups ) ) { 176 | $merge_groups[] = array( 177 | 'id' => $group_id, 178 | 'groups' => $subgroups 179 | ); 180 | } 181 | elseif ( ! empty( $subgroups ) ) { 182 | $merge_groups[] = array( 183 | 'id' => $group_id, 184 | 'groups' => array( $subgroups ) 185 | ); 186 | } 187 | } 188 | 189 | $vars = $merge_groups; 190 | } 191 | 192 | return $vars; 193 | } 194 | 195 | /** 196 | * Return user data from a list 197 | * 198 | * @param String $user_email 199 | * @param String $list_id 200 | * @return Array User data / False if the user do not exist 201 | * @deprecated 202 | */ 203 | function mailchimp_get_user_info( $user_email, $list_id ) { 204 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_get_user_info()' ); 205 | return mailchimp_30_get_user_info( $user_email, $list_id ); 206 | } 207 | 208 | function mailchimp_bulk_subscribe_users( $emails, $list_id, $autopt = false, $update = false ) { 209 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_bulk_subscribe_users()' ); 210 | return mailchimp_30_bulk_subscribe_users( $emails ); 211 | $api = mailchimp_load_API(); 212 | 213 | if ( is_wp_error( $api ) ) 214 | return $api; 215 | 216 | $merge_vars = array(); 217 | if ( $autopt ) { 218 | $merge_vars['optin_ip'] = $_SERVER['REMOTE_ADDR']; 219 | $merge_vars['optin_time'] = current_time( 'mysql', true ); 220 | } 221 | 222 | $results = $api->lists->batchSubscribe( $list_id, $emails, ! $autopt, $update ); 223 | 224 | $return = array(); 225 | $return['added'] = $results['adds']; 226 | $return['updated'] = $results['updates']; 227 | $return['errors'] = array(); 228 | 229 | if ( $results['error_count'] ) { 230 | foreach( $results['errors'] as $error ) { 231 | $return['errors'][] = new WP_Error( $error['code'], '{' . $error['email']['email'] . '} ' . $error['error'] ); 232 | } 233 | } 234 | 235 | return $return; 236 | 237 | } 238 | 239 | /** 240 | * Unsubscribe a list of users 241 | * @param Array $emails 242 | * Array( 243 | * array( 244 | * 'email' => Email 245 | * ), 246 | * ... 247 | * ) 248 | * @param String $list_id 249 | * @param Boolean $autopt 250 | * @param Array $merge Array of merge vars 251 | * @return type 252 | * @deprecated 253 | */ 254 | function mailchimp_bulk_unsubscribe_users( $emails, $list_id, $delete = false ) { 255 | _deprecated_function( __FUNCTION__, '1.9', 'mailchimp_30_bulk_unsubscribe_users()' ); 256 | $api = mailchimp_load_API(); 257 | 258 | if ( is_wp_error( $api ) ) 259 | return $api; 260 | 261 | $results = $api->lists->batchUnsubscribe( $list_id, $emails, $delete ); 262 | 263 | $return = array(); 264 | $return['success_count'] = $results['success_count']; 265 | $return['errors'] = array(); 266 | 267 | if ( $results['error_count'] ) { 268 | foreach( $results['errors'] as $error ) { 269 | $return['errors'][] = new WP_Error( $error['code'], '{' . $error['email'] . '} ' . $error['error'] ); 270 | } 271 | } 272 | 273 | return $return; 274 | 275 | } 276 | -------------------------------------------------------------------------------- /mailchimp-api/3.0/webhooks.php: -------------------------------------------------------------------------------- 1 | 1, 38 | 'mckey' => $webhooks_settings['webhook_key'] 39 | ), 40 | home_url() 41 | ); 42 | } 43 | else { 44 | $url = trailingslashit( site_url() ) . 'mailchimp-sync/' . $webhooks_settings['webhook_key']; 45 | } 46 | 47 | 48 | return $url; 49 | } 50 | 51 | public function parse_request() { 52 | global $wp_query; 53 | if ( ! self::is_webhooks_active() ) 54 | return; 55 | 56 | $webhooks_settings = mailchimp_get_webhooks_settings(); 57 | 58 | if ( get_query_var( 'mailchimp-sync' ) == 1 ) { 59 | if ( get_query_var( 'mckey' ) != $webhooks_settings['webhook_key'] ) { 60 | $this->log( sprintf( __( 'Security key specified, but not correct: %s', MAILCHIMP_LANG_DOMAIN ), get_query_var( 'mckey' ) ) ); 61 | exit(); 62 | } 63 | 64 | $this->trigger_webhook_action(); 65 | exit(); 66 | } 67 | } 68 | 69 | private function trigger_webhook_action() { 70 | $req = $_POST; 71 | 72 | if ( ! isset( $req['type'] ) ) { 73 | $this->log( __( 'Request type not defined', MAILCHIMP_LANG_DOMAIN ) ); 74 | return; 75 | } 76 | 77 | $list_id = get_site_option( 'mailchimp_mailing_list' ); 78 | if ( $list_id != $req['data']['list_id'] ) { 79 | $this->log( sprintf( __( 'Requested list ID [%s] is not the same than the selected one in Mailchimp Settings [%s]', MAILCHIMP_LANG_DOMAIN ), $req['data']['list_id'], $list_id ) ); 80 | return; 81 | } 82 | 83 | $allowed_types = apply_filters( 'mailchimp_webhooks_allowed_types', array( 'subscribe', 'unsubscribe', 'profile', 'upemail' ) ); 84 | 85 | if ( ! in_array( $req['type'], $allowed_types ) ) 86 | $this->log( sprintf( __( 'Request type "%s" unknown, ignoring.', MAILCHIMP_LANG_DOMAIN ), $req['type'] ) ); 87 | 88 | $function = array( $this, $req['type'] ); 89 | $function = apply_filters( 'mailchimp_webhook_action_function', $function, $req ); 90 | 91 | $result = call_user_func_array( $function, array( $req['data'] ) ); 92 | 93 | if ( is_wp_error( $result ) ) 94 | $this->log( strtoupper( $req['type'] ) . ': ' . $result->get_error_message() ); 95 | 96 | } 97 | 98 | private function log( $message, $echo = true ) { 99 | mi_mailchimp_log( array( 'message' => $message ), 'webhooks' ); 100 | if ( $echo ) { 101 | echo $message; 102 | } 103 | } 104 | 105 | private function subscribe( $data ) { 106 | $user_email = $data['email']; 107 | 108 | $user = get_user_by( 'email', $user_email ); 109 | 110 | if ( $user ) 111 | return new WP_Error( 'user_exists', sprintf( __( 'Existing user found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 112 | 113 | $login = explode( '@', $user_email ); 114 | $login = $login[0]; 115 | $login = sanitize_user( $login ); 116 | 117 | $user = get_user_by( 'login', $login ); 118 | 119 | if ( $user ) 120 | return new WP_Error( 'user_exists', sprintf( __( 'Existing user found with this user login: "%s"', MAILCHIMP_LANG_DOMAIN ), $login ) ); 121 | 122 | $userdata = array( 123 | 'user_pass' => wp_generate_password( 12, false ), 124 | 'user_login' => $login, 125 | 'user_email' => $user_email, 126 | 'first_name' => $data['merges']['FNAME'], 127 | 'last_name' => $data['merges']['LNAME'], 128 | 'role' => 'subscriber' 129 | ); 130 | 131 | $userdata = apply_filters( 'mailchimp_webhooks_subscribe_user', $userdata ); 132 | 133 | $user_id = wp_insert_user( $userdata ); 134 | 135 | if ( is_wp_error( $user_id ) ) 136 | return new WP_Error( 'user_exists', sprintf( __( 'FAILED! Problem encountered trying to create new user: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 137 | 138 | $list_id = get_site_option( 'mailchimp_mailing_list' ); 139 | 140 | $this->log( sprintf( __( 'SUBSCRIBE: New user created: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 141 | 142 | return true; 143 | } 144 | 145 | private function unsubscribe( $data ) { 146 | $user_email = $data['email']; 147 | 148 | $user = get_user_by( 'email', $user_email ); 149 | 150 | if ( ! $user ) 151 | return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 152 | 153 | $settings = mailchimp_get_webhooks_settings(); 154 | if ( 'mark' === $settings['delete_user'] ) { 155 | $this->log( sprintf( __( 'UNSUBSCRIBE: user unsubscribed from list: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 156 | } 157 | else { 158 | if ( is_multisite() ) { 159 | if ( ! function_exists( 'wp_delete_user' ) ) 160 | require_once(ABSPATH . 'wp-admin/includes/ms.php'); 161 | 162 | if ( is_super_admin() ) 163 | return new WP_Error( 'user_not_exists', sprintf( __( 'Deleting Super Admins is not allowed: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 164 | 165 | $result = wpmu_delete_user( $user->ID ); 166 | } 167 | else { 168 | if ( ! function_exists( 'wp_delete_user' ) ) 169 | require_once(ABSPATH . 'wp-admin/includes/user.php'); 170 | 171 | if ( current_user_can( 'manage_options' ) ) 172 | return new WP_Error( 'user_not_exists', sprintf( __( 'Deleting Administrators is not allowed: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 173 | 174 | $result = wp_delete_user( $user->ID, false ); 175 | } 176 | 177 | if ( ! $result ) 178 | return new WP_Error( 'error_deleting_user', sprintf( __( 'FAILED: Something went wrong while trying to delete user: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 179 | 180 | $this->log( sprintf( __( 'UNSUBSCRIBE: user deleted: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 181 | } 182 | 183 | return true; 184 | 185 | } 186 | 187 | private function upemail( $data ) { 188 | $user_email = $data['old_email']; 189 | 190 | $user = get_user_by( 'email', $user_email ); 191 | 192 | if ( ! $user ) 193 | return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 194 | 195 | $new_email = $data['new_email']; 196 | 197 | if ( ! is_email( $new_email ) ) 198 | return new WP_Error( 'wrong_email', sprintf( __( 'The new email is not a valid one: "%s"', MAILCHIMP_LANG_DOMAIN ), $new_email ) ); 199 | 200 | $userdata = array( 201 | 'ID' => $user->ID, 202 | 'user_email' => $new_email 203 | ); 204 | 205 | $result = wp_update_user( $userdata ); 206 | 207 | if ( ! $result ) 208 | return new WP_Error( 'error_updating_email', sprintf( __( 'FAILED: Something went wrong while trying to update user email: "%s"', MAILCHIMP_LANG_DOMAIN ), $new_email ) ); 209 | 210 | $this->log( sprintf( __( 'UPEMAIL: email updated: "%s" to "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email, $new_email ) ); 211 | 212 | return true; 213 | 214 | } 215 | 216 | private function profile( $data ) { 217 | $user_email = $data['email']; 218 | 219 | $user = get_user_by( 'email', $user_email ); 220 | 221 | if ( ! $user ) 222 | return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 223 | 224 | $userdata = array( 225 | 'ID' => $user->ID, 226 | 'first_name' => $data['merges']['FNAME'], 227 | 'last_name' => $data['merges']['LNAME'], 228 | ); 229 | 230 | $result = wp_update_user( $userdata ); 231 | 232 | if ( ! $result ) 233 | return new WP_Error( 'error_updating_profile', sprintf( __( 'FAILED: Something went wrong while trying to update user profile: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 234 | 235 | 236 | $this->log( sprintf( __( 'PROFILE: profile updated: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 237 | 238 | return true; 239 | 240 | } 241 | 242 | 243 | } -------------------------------------------------------------------------------- /front/widget.php: -------------------------------------------------------------------------------- 1 | success = false; 18 | 19 | /* Widget settings. */ 20 | $widget_ops = array( 21 | 'classname' => 'incsub-mailchimp-widget' , 22 | 'description' => __( 'This widget allows visitors to subscribe to a MailChimp email list (set by the network administrator).', MAILCHIMP_LANG_DOMAIN ) 23 | ); 24 | 25 | /* Create the widget. */ 26 | parent::__construct( 'incsub-mailchimp-widget' , __( 'MailChimp', MAILCHIMP_LANG_DOMAIN ), $widget_ops ); 27 | 28 | add_filter( 'mailchimp_form_require_field', array( &$this, 'set_require_field' ), 10, 3 ); 29 | add_filter( 'mailchimp_form_success_redirect', array( &$this, 'set_form_success_redirect' ) ); 30 | add_filter( 'mailchimp_form_subscribed_placeholder', array( &$this, 'set_form_success_placeholder' ), 10, 2 ); 31 | 32 | add_action( 'init', array( $this, 'init' ) ); 33 | add_action( 'init', array( $this, 'validate_widget' ) ); 34 | 35 | 36 | } 37 | 38 | function init() { 39 | WPMUDEV_MailChimp_Form::enqueue_dependencies(); 40 | } 41 | 42 | 43 | function validate_widget() { 44 | if ( isset( $_POST['submit-subscribe-widget-user'] ) ) { 45 | 46 | global $mailchimp_sync; 47 | 48 | $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX; 49 | $errors = array(); 50 | 51 | if ( ! $doing_ajax ) { 52 | if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'mailchimp_subscribe_user' ) ) 53 | return false; 54 | } 55 | else { 56 | check_ajax_referer( 'mailchimp_subscribe_user', 'nonce' ); 57 | } 58 | 59 | $_form_id = $_POST['form_id']; 60 | $form_id = explode( '-', $_form_id ); 61 | $number = $form_id[ count( $form_id ) -1 ]; 62 | 63 | $settings = $this->get_settings(); 64 | 65 | if ( ! isset( $settings[ $number ] ) ) 66 | return; 67 | 68 | $settings = $settings[ $number ]; 69 | 70 | $errors = WPMUDEV_MailChimp_Form::validate_subscription_form( $_POST, $settings ); 71 | 72 | if ( empty( $errors ) ) { 73 | $user['email'] = sanitize_email( $_POST['subscription-email'] ); 74 | $user['first_name'] = sanitize_text_field( $_POST['subscription-firstname'] ); 75 | $user['last_name'] = sanitize_text_field( $_POST['subscription-lastname'] ); 76 | 77 | $mailchimp_sync->mailchimp_add_user( $user ); 78 | 79 | if ( ! $doing_ajax ) { 80 | $redirect_to = add_query_arg( 'mailchimp-subscribed-' . $number, 'true' ) . '#' . $_form_id; 81 | wp_redirect( $redirect_to ); 82 | exit; 83 | } 84 | else { 85 | $text = apply_filters( 'mailchimp_form_subscribed_placeholder', $this->args['subscribed_placeholder'], $_POST['form_id'] ); 86 | wp_send_json_success( array( 'message' => $text ) ); 87 | } 88 | } 89 | elseif ( ! empty( $errors ) && $doing_ajax ) { 90 | wp_send_json_error( $errors ); 91 | } 92 | 93 | $this->errors[ $number ] = $errors; 94 | 95 | 96 | } 97 | } 98 | 99 | 100 | /** 101 | * How to display the widget on the screen. 102 | */ 103 | function widget( $args, $instance ) { 104 | 105 | extract( $args ); 106 | 107 | $title = apply_filters( 'widget_title', $instance['title'] ); 108 | 109 | echo $before_widget; 110 | 111 | if ( $title ) 112 | echo $before_title . $title . $after_title; 113 | 114 | 115 | $firstname = ! empty( $_POST['subscription-firstname'] ) ? stripslashes( $_POST['subscription-firstname'] ) : ''; 116 | $lastname = ! empty( $_POST['subscription-lastname'] ) ? stripslashes( $_POST['subscription-lastname'] ) : ''; 117 | $email = ! empty( $_POST['subscription-email'] ) ? stripslashes( $_POST['subscription-email'] ) : ''; 118 | 119 | $form_id = 'incsub-mailchimp-widget-form-' . $this->number; 120 | $subscribed = isset( $_GET[ 'mailchimp-subscribed-' . $this->number ] ); 121 | 122 | $submit_name = 'submit-subscribe-widget-user'; 123 | $errors = isset( $this->errors[ $this->number ] ) ? $this->errors[ $this->number ] : array(); 124 | 125 | $args = compact( 'submit_name', 'form_id', 'subscribed', 'firstname', 'lastname', 'email', 'errors' ); 126 | $args['button_text'] = $instance['button_text']; 127 | $args['subscribed_placeholder'] = $instance['subscribed_placeholder']; 128 | $args['text'] = $instance['text']; 129 | $args['require_fn'] = $instance['require_firstname']; 130 | $args['require_ln'] = $instance['require_lastname']; 131 | 132 | WPMUDEV_MailChimp_Form::render_form( $args ); 133 | 134 | echo $after_widget; 135 | } 136 | 137 | /** 138 | * Update the widget settings. 139 | */ 140 | function update( $new_instance, $old_instance ) { 141 | $instance = $old_instance; 142 | 143 | /* Strip tags for title and name to remove HTML (important for text inputs). */ 144 | $instance['title'] = sanitize_text_field( $new_instance['title'] ); 145 | $instance['text'] = sanitize_text_field( $new_instance['text'] ); 146 | $instance['button_text'] = sanitize_text_field( $new_instance['button_text'] ); 147 | $instance['subscribed_placeholder'] = sanitize_text_field( $new_instance['subscribed_placeholder'] ); 148 | $instance['require_firstname'] = ! empty( $new_instance['require_firstname'] ) ? true : false; 149 | $instance['require_lastname'] = ! empty( $new_instance['require_lastname'] ) ? true : false; 150 | 151 | return $instance; 152 | } 153 | 154 | /** 155 | * Displays the widget settings controls on the widget panel. 156 | * Make use of the get_field_id() and get_field_name() function 157 | * when creating your form elements. This handles the confusing stuff. 158 | */ 159 | function form( $instance ) { 160 | 161 | /* Set up some default widget settings. */ 162 | $defaults = array( 163 | 'title' => __( 'Subscribe to MailChimp', MAILCHIMP_LANG_DOMAIN ), 164 | 'text' => __( 'Subscribe to our MailChimp list.', MAILCHIMP_LANG_DOMAIN ), 165 | 'button_text' => __( 'Subscribe', MAILCHIMP_LANG_DOMAIN ), 166 | 'subscribed_placeholder' => __( 'Thank you, your email has been added to the list.', MAILCHIMP_LANG_DOMAIN ), 167 | 'require_firstname' => false, 168 | 'require_lastname' => false 169 | ); 170 | 171 | $instance = wp_parse_args( (array) $instance, $defaults ); ?> 172 |

    173 | 174 | 175 |

    176 |

    177 | 178 | 179 |

    180 |

    181 | 182 | 183 |

    184 |

    185 | 186 | 187 |

    188 |

    189 | /> 190 | 191 |

    192 |

    193 | /> 194 | 195 |

    196 | 1, 39 | // 'mckey' => $webhooks_settings['webhook_key'] 40 | // ), 41 | // home_url() 42 | // ); 43 | // } 44 | // else { 45 | // $url = trailingslashit( site_url() ) . 'mailchimp-sync/' . $webhooks_settings['webhook_key']; 46 | // } 47 | // 48 | // 49 | // return $url; 50 | // } 51 | // 52 | // public function parse_request() { 53 | // global $wp_query; 54 | // if ( ! self::is_webhooks_active() ) 55 | // return; 56 | // 57 | // $webhooks_settings = mailchimp_get_webhooks_settings(); 58 | // 59 | // if ( get_query_var( 'mailchimp-sync' ) == 1 ) { 60 | // if ( get_query_var( 'mckey' ) != $webhooks_settings['webhook_key'] ) { 61 | // $this->log( sprintf( __( 'Security key specified, but not correct: %s', MAILCHIMP_LANG_DOMAIN ), get_query_var( 'mckey' ) ) ); 62 | // exit(); 63 | // } 64 | // 65 | // $this->trigger_webhook_action(); 66 | // exit(); 67 | // } 68 | // } 69 | // 70 | // private function trigger_webhook_action() { 71 | // $req = $_POST; 72 | // 73 | // if ( ! isset( $req['type'] ) ) { 74 | // $this->log( __( 'Request type not defined', MAILCHIMP_LANG_DOMAIN ) ); 75 | // return; 76 | // } 77 | // 78 | // $list_id = get_site_option( 'mailchimp_mailing_list' ); 79 | // if ( $list_id != $req['data']['list_id'] ) { 80 | // $this->log( sprintf( __( 'Requested list ID [%s] is not the same than the selected one in Mailchimp Settings [%s]', MAILCHIMP_LANG_DOMAIN ), $req['data']['list_id'], $list_id ) ); 81 | // return; 82 | // } 83 | // 84 | // $allowed_types = apply_filters( 'mailchimp_webhooks_allowed_types', array( 'subscribe', 'unsubscribe', 'profile', 'upemail' ) ); 85 | // 86 | // if ( ! in_array( $req['type'], $allowed_types ) ) 87 | // $this->log( sprintf( __( 'Request type "%s" unknown, ignoring.', MAILCHIMP_LANG_DOMAIN ), $req['type'] ) ); 88 | // 89 | // $function = array( $this, $req['type'] ); 90 | // $function = apply_filters( 'mailchimp_webhook_action_function', $function, $req ); 91 | // 92 | // $result = call_user_func_array( $function, array( $req['data'] ) ); 93 | // 94 | // if ( is_wp_error( $result ) ) 95 | // $this->log( strtoupper( $req['type'] ) . ': ' . $result->get_error_message() ); 96 | // 97 | // } 98 | // 99 | // private function log( $message, $echo = true ) { 100 | // 101 | // $current_log = get_site_option( 'mailchimp_webhooks_log' ); 102 | // $new_log = array(); 103 | // 104 | // $date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) ); 105 | // 106 | // $message = '[' . $date . '] ' . $message; 107 | // $new_log[] = $message; 108 | // 109 | // 110 | // if ( $current_log ) { 111 | // 112 | // $new_log = array_merge( $current_log, $new_log ); 113 | // 114 | // // We'll only saved the last X lines of the log 115 | // $count = count( $new_log ); 116 | // if ( $count > MAILCHIMP_MAX_LOG_LINES ) { 117 | // $new_log = array_slice( $new_log, $count - $offset - 1 ); 118 | // } 119 | // 120 | // } 121 | // 122 | // update_site_option( 'mailchimp_webhooks_log', $new_log ); 123 | // 124 | // if ( $echo ) 125 | // echo $message; 126 | // } 127 | // 128 | // private function subscribe( $data ) { 129 | // $user_email = $data['email']; 130 | // 131 | // $user = get_user_by( 'email', $user_email ); 132 | // 133 | // if ( $user ) 134 | // return new WP_Error( 'user_exists', sprintf( __( 'Existing user found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 135 | // 136 | // $login = explode( '@', $user_email ); 137 | // $login = $login[0]; 138 | // $login = sanitize_user( $login ); 139 | // 140 | // $user = get_user_by( 'login', $login ); 141 | // 142 | // if ( $user ) 143 | // return new WP_Error( 'user_exists', sprintf( __( 'Existing user found with this user login: "%s"', MAILCHIMP_LANG_DOMAIN ), $login ) ); 144 | // 145 | // $userdata = array( 146 | // 'user_pass' => wp_generate_password( 12, false ), 147 | // 'user_login' => $login, 148 | // 'user_email' => $user_email, 149 | // 'first_name' => $data['merges']['FNAME'], 150 | // 'last_name' => $data['merges']['LNAME'], 151 | // 'role' => 'subscriber' 152 | // ); 153 | // 154 | // $userdata = apply_filters( 'mailchimp_webhooks_subscribe_user', $userdata ); 155 | // 156 | // $user_id = wp_insert_user( $userdata ); 157 | // 158 | // if ( is_wp_error( $user_id ) ) 159 | // return new WP_Error( 'user_exists', sprintf( __( 'FAILED! Problem encountered trying to create new user: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 160 | // 161 | // $list_id = get_site_option( 'mailchimp_mailing_list' ); 162 | // 163 | // $this->log( sprintf( __( 'SUBSCRIBE: New user created: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 164 | // 165 | // return true; 166 | // } 167 | // 168 | // private function unsubscribe( $data ) { 169 | // $user_email = $data['email']; 170 | // 171 | // $user = get_user_by( 'email', $user_email ); 172 | // 173 | // if ( ! $user ) 174 | // return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 175 | // 176 | // $settings = mailchimp_get_webhooks_settings(); 177 | // if ( 'mark' === $settings['delete_user'] ) { 178 | // $this->log( sprintf( __( 'UNSUBSCRIBE: user unsubscribed from list: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 179 | // } 180 | // else { 181 | // if ( is_multisite() ) { 182 | // if ( ! function_exists( 'wp_delete_user' ) ) 183 | // require_once(ABSPATH . 'wp-admin/includes/ms.php'); 184 | // 185 | // if ( is_super_admin() ) 186 | // return new WP_Error( 'user_not_exists', sprintf( __( 'Deleting Super Admins is not allowed: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 187 | // 188 | // $result = wpmu_delete_user( $user->ID, false ); 189 | // } 190 | // else { 191 | // if ( ! function_exists( 'wp_delete_user' ) ) 192 | // require_once(ABSPATH . 'wp-admin/includes/user.php'); 193 | // 194 | // if ( current_user_can( 'manage_options' ) ) 195 | // return new WP_Error( 'user_not_exists', sprintf( __( 'Deleting Administrators is not allowed: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 196 | // 197 | // $result = wp_delete_user( $user->ID, false ); 198 | // } 199 | // 200 | // if ( ! $result ) 201 | // return new WP_Error( 'error_deleting_user', sprintf( __( 'FAILED: Something went wrong while trying to delete user: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 202 | // 203 | // $this->log( sprintf( __( 'UNSUBSCRIBE: user deleted: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 204 | // } 205 | // 206 | // return true; 207 | // 208 | // } 209 | // 210 | // private function upemail( $data ) { 211 | // $user_email = $data['old_email']; 212 | // 213 | // $user = get_user_by( 'email', $user_email ); 214 | // 215 | // if ( ! $user ) 216 | // return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 217 | // 218 | // $new_email = $data['new_email']; 219 | // 220 | // if ( ! is_email( $new_email ) ) 221 | // return new WP_Error( 'wrong_email', sprintf( __( 'The new email is not a valid one: "%s"', MAILCHIMP_LANG_DOMAIN ), $new_email ) ); 222 | // 223 | // $userdata = array( 224 | // 'ID' => $user->ID, 225 | // 'user_email' => $new_email 226 | // ); 227 | // 228 | // $result = wp_update_user( $userdata ); 229 | // 230 | // if ( ! $result ) 231 | // return new WP_Error( 'error_updating_email', sprintf( __( 'FAILED: Something went wrong while trying to update user email: "%s"', MAILCHIMP_LANG_DOMAIN ), $new_email ) ); 232 | // 233 | // $this->log( sprintf( __( 'UPEMAIL: email updated: "%s" to "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email, $new_email ) ); 234 | // 235 | // return true; 236 | // 237 | // } 238 | // 239 | // private function profile( $data ) { 240 | // $user_email = $data['email']; 241 | // 242 | // $user = get_user_by( 'email', $user_email ); 243 | // 244 | // if ( ! $user ) 245 | // return new WP_Error( 'user_not_exists', sprintf( __( 'User not found with this email address: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 246 | // 247 | // $userdata = array( 248 | // 'ID' => $user->ID, 249 | // 'first_name' => $data['merges']['FNAME'], 250 | // 'last_name' => $data['merges']['LNAME'], 251 | // ); 252 | // 253 | // $result = wp_update_user( $userdata ); 254 | // 255 | // if ( ! $result ) 256 | // return new WP_Error( 'error_updating_profile', sprintf( __( 'FAILED: Something went wrong while trying to update user profile: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 257 | // 258 | // 259 | // $this->log( sprintf( __( 'PROFILE: profile updated: "%s"', MAILCHIMP_LANG_DOMAIN ), $user_email ) ); 260 | // 261 | // return true; 262 | // 263 | // } 264 | // 265 | // 266 | //} -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp/Exceptions.php: -------------------------------------------------------------------------------- 1 | 9 | * @version 2.2 10 | */ 11 | class MailChimp_Sync_Mailchimp 12 | { 13 | private $api_key; 14 | private $api_endpoint = 'https://.api.mailchimp.com/3.0'; 15 | 16 | /* SSL Verification 17 | Read before disabling: 18 | http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/ 19 | */ 20 | public $verify_ssl = true; 21 | 22 | private $request_successful = false; 23 | private $last_error = ''; 24 | private $last_response = array(); 25 | private $last_request = array(); 26 | 27 | /** 28 | * Create a new instance 29 | * @param string $api_key Your MailChimp API key 30 | * @throws Exception 31 | */ 32 | public function __construct($api_key) 33 | { 34 | $this->api_key = $api_key; 35 | 36 | if (strpos($this->api_key, '-') === false) { 37 | throw new Exception("Invalid MailChimp API key `{$api_key}` supplied."); 38 | } 39 | 40 | list(, $data_center) = explode('-', $this->api_key); 41 | $this->api_endpoint = str_replace('', $data_center, $this->api_endpoint); 42 | 43 | $this->last_response = array('headers' => null, 'body' => null); 44 | } 45 | 46 | /** 47 | * Create a new instance of a Batch request. Optionally with the ID of an existing batch. 48 | * 49 | *@param string $batch_id Optional ID of an existing batch, if you need to check its status for example. 50 | * 51 | *@return Mailchimp_Sync_Batch New Batch object. 52 | */ 53 | public function new_batch($batch_id = null) 54 | { 55 | return new Mailchimp_Sync_Batch($this, $batch_id); 56 | } 57 | 58 | /** 59 | * Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL 60 | * @param string $email The subscriber's email address 61 | * @return string Hashed version of the input 62 | */ 63 | public function subscriberHash($email) 64 | { 65 | return md5(strtolower($email)); 66 | } 67 | 68 | /** 69 | * Was the last request successful? 70 | * @return bool True for success, false for failure 71 | */ 72 | public function success() 73 | { 74 | return $this->request_successful; 75 | } 76 | 77 | /** 78 | * Get the last error returned by either the network transport, or by the API. 79 | * If something didn't work, this should contain the string describing the problem. 80 | * @return array|false describing the error 81 | */ 82 | public function getLastError() 83 | { 84 | return $this->last_error ?: false; 85 | } 86 | 87 | /** 88 | * Get an array containing the HTTP headers and the body of the API response. 89 | * @return array Assoc array with keys 'headers' and 'body' 90 | */ 91 | public function getLastResponse() 92 | { 93 | return $this->last_response; 94 | } 95 | 96 | /** 97 | * Get an array containing the HTTP headers and the body of the API request. 98 | * @return array Assoc array 99 | */ 100 | public function getLastRequest() 101 | { 102 | return $this->last_request; 103 | } 104 | 105 | /** 106 | * Make an HTTP DELETE request - for deleting data 107 | * @param string $method URL of the API request method 108 | * @param array $args Assoc array of arguments (if any) 109 | * @param int $timeout Timeout limit for request in seconds 110 | * @return array|false Assoc array of API response, decoded from JSON 111 | */ 112 | public function delete($method, $args = array(), $timeout = 10) 113 | { 114 | return $this->makeRequest('delete', $method, $args, $timeout); 115 | } 116 | 117 | /** 118 | * Make an HTTP GET request - for retrieving data 119 | * @param string $method URL of the API request method 120 | * @param array $args Assoc array of arguments (usually your data) 121 | * @param int $timeout Timeout limit for request in seconds 122 | * @return array|false Assoc array of API response, decoded from JSON 123 | */ 124 | public function get($method, $args = array(), $timeout = 10) 125 | { 126 | return $this->makeRequest('get', $method, $args, $timeout); 127 | } 128 | 129 | /** 130 | * Make an HTTP PATCH request - for performing partial updates 131 | * @param string $method URL of the API request method 132 | * @param array $args Assoc array of arguments (usually your data) 133 | * @param int $timeout Timeout limit for request in seconds 134 | * @return array|false Assoc array of API response, decoded from JSON 135 | */ 136 | public function patch($method, $args = array(), $timeout = 10) 137 | { 138 | return $this->makeRequest('patch', $method, $args, $timeout); 139 | } 140 | 141 | /** 142 | * Make an HTTP POST request - for creating and updating items 143 | * @param string $method URL of the API request method 144 | * @param array $args Assoc array of arguments (usually your data) 145 | * @param int $timeout Timeout limit for request in seconds 146 | * @return array|false Assoc array of API response, decoded from JSON 147 | */ 148 | public function post($method, $args = array(), $timeout = 10) 149 | { 150 | return $this->makeRequest('post', $method, $args, $timeout); 151 | } 152 | 153 | /** 154 | * Make an HTTP PUT request - for creating new items 155 | * @param string $method URL of the API request method 156 | * @param array $args Assoc array of arguments (usually your data) 157 | * @param int $timeout Timeout limit for request in seconds 158 | * @return array|false Assoc array of API response, decoded from JSON 159 | */ 160 | public function put($method, $args = array(), $timeout = 10) 161 | { 162 | return $this->makeRequest('put', $method, $args, $timeout); 163 | } 164 | 165 | /** 166 | * Performs the underlying HTTP request. Not very exciting. 167 | * @param string $http_verb The HTTP verb to use: get, post, put, patch, delete 168 | * @param string $method The API method to be called 169 | * @param array $args Assoc array of parameters to be passed 170 | * @param int $timeout 171 | * @return array|false Assoc array of decoded result 172 | * @throws Exception 173 | */ 174 | private function makeRequest($http_verb, $method, $args = array(), $timeout = 10) 175 | { 176 | $url = $this->api_endpoint . '/' . $method; 177 | 178 | $this->last_error = ''; 179 | $this->request_successful = false; 180 | $response = array('headers' => null, 'body' => null); 181 | $this->last_response = $response; 182 | 183 | $this->last_request = array( 184 | 'method' => $http_verb, 185 | 'path' => $method, 186 | 'url' => $url, 187 | 'body' => '', 188 | 'timeout' => $timeout, 189 | ); 190 | 191 | $request_args = array( 192 | 'headers' => array( 193 | 'Accept' => 'application/vnd.api+json', 194 | 'Content-Type' => 'application/vnd.api+json', 195 | 'Authorization' => 'apikey ' . $this->api_key 196 | ), 197 | 'user-agent' => 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)', 198 | 'timeout' => apply_filters( 'mailchimp_sync_api_timeout', $timeout ), 199 | 'sslverify' => $this->verify_ssl, 200 | 'method' => strtoupper( $http_verb ) 201 | ); 202 | 203 | $args = apply_filters( 'mailchimp_api_request_args', $args, $method, $request_args ); 204 | 205 | if ( 'get' !== $http_verb ) { 206 | $request_args['body'] = wp_json_encode( $args ); 207 | } 208 | else { 209 | $request_args['body'] = $args; 210 | } 211 | 212 | $wp_response = wp_remote_request( $url, $request_args ); 213 | if ( is_wp_error( $wp_response ) ) { 214 | $this->last_error = $wp_response->get_error_code() . ': ' . $wp_response->get_error_message(); 215 | } 216 | 217 | $response['body'] = wp_remote_retrieve_body( $wp_response ); 218 | $response['headers'] = wp_remote_retrieve_headers( $wp_response ); 219 | $this->last_request['headers'] = $request_args['headers']; 220 | 221 | $formattedResponse = $this->formatResponse($wp_response); 222 | 223 | $this->determineSuccess($wp_response, $formattedResponse); 224 | 225 | return $formattedResponse; 226 | } 227 | 228 | /** 229 | * Encode the data and attach it to the request 230 | * @param resource $ch cURL session handle, used by reference 231 | * @param array $data Assoc array of data to attach 232 | */ 233 | private function attachRequestPayload(&$ch, $data) 234 | { 235 | $encoded = json_encode($data); 236 | $this->last_request['body'] = $encoded; 237 | curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded); 238 | } 239 | 240 | /** 241 | * Decode the response and format any error messages for debugging 242 | * @param array $response The response from the curl request 243 | * @return array|false The JSON decoded into an array 244 | */ 245 | private function formatResponse($response) 246 | { 247 | $this->last_response = $response; 248 | 249 | if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) { 250 | return json_decode( $response['body'], true ); 251 | } 252 | 253 | return false; 254 | } 255 | 256 | /** 257 | * Check if the response was successful or a failure. If it failed, store the error. 258 | * @param array $response The response from the curl request 259 | * @param array|false $formattedResponse The response body payload from the curl request 260 | * @return bool If the request was successful 261 | */ 262 | private function determineSuccess($response, $formattedResponse) 263 | { 264 | $status = $this->findHTTPStatus($response, $formattedResponse); 265 | 266 | if ($status >= 200 && $status <= 299) { 267 | $this->request_successful = true; 268 | return true; 269 | } 270 | 271 | if (isset($formattedResponse['detail'])) { 272 | $this->last_error = sprintf('%d: %s', $formattedResponse['status'], $formattedResponse['detail']); 273 | return false; 274 | } 275 | 276 | $this->last_error = 'Unknown error, call getLastResponse() to find out what happened.'; 277 | return false; 278 | } 279 | 280 | /** 281 | * Find the HTTP status code from the headers or API response body 282 | * @param array $response The response from the curl request 283 | * @param array|false $formattedResponse The response body payload from the curl request 284 | * @return int HTTP status code 285 | */ 286 | private function findHTTPStatus($response, $formattedResponse) 287 | { 288 | $status = wp_remote_retrieve_response_code( $response ); 289 | if ( is_wp_error( $response ) ) { 290 | if ( empty( $status ) ) { 291 | return 418; 292 | } 293 | return $status; 294 | } 295 | 296 | if ( ! empty( $status ) ) { 297 | return $status; 298 | } 299 | elseif ( !empty($response['body']) && isset($formattedResponse['status']) ) { 300 | return (int) $formattedResponse['status']; 301 | } 302 | 303 | return 418; 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /front/shortcode.php: -------------------------------------------------------------------------------- 1 | mailchimp_add_user( $user ); 46 | } 47 | 48 | $this->errors[ $number ] = $errors; 49 | 50 | 51 | } 52 | 53 | } 54 | 55 | public function set_form_success_redirect( $redirect_to ) { 56 | $instance = $this->get_settings(); 57 | if ( false !== $instance && $form_id == 'incsub-mailchimp-widget-form-' . $this->number ) { 58 | $widget_settings = $instance [ $this->number ]; 59 | $redirect_to .= 'incsub-mailchimp-shortcode-form-' . self::$number; 60 | } 61 | 62 | return $redirect_to; 63 | } 64 | 65 | public function register_scripts() { 66 | if ( $this->enqueue_styles ) { 67 | WPMUDEV_MailChimp_Form::enqueue_dependencies(); 68 | } 69 | } 70 | 71 | 72 | public function add_tinymce_buttons() { 73 | if ( get_user_option( 'rich_editing' ) == 'true' ) { 74 | add_filter( 'mce_external_plugins', array( &$this, 'add_buttons' ) ); 75 | add_filter( 'mce_buttons', array( &$this, 'register_buttons' ) ); 76 | add_editor_style( MAILCHIMP_ASSETS_URL . 'shortcode-editor.css' ); 77 | } 78 | } 79 | 80 | public function add_buttons( $plugin_array ) { 81 | global $wp_version; 82 | 83 | if ( version_compare( $wp_version, '3.9', '<' ) ) 84 | $suffix = ''; 85 | else 86 | $suffix = '_39'; 87 | 88 | $plugin_array['mailchimpshortcode'] = MAILCHIMP_ASSETS_URL . 'tiny-mce-button.js'; 89 | 90 | return $plugin_array; 91 | } 92 | 93 | 94 | public function register_buttons( $buttons ) { 95 | array_push( $buttons, 'mailchimpform' ); 96 | return $buttons; 97 | } 98 | 99 | 100 | public function render_form( $atts ) { 101 | $defaults = array( 102 | 'title' => __( 'Subscribe to our MailChimp list.', MAILCHIMP_LANG_DOMAIN ), 103 | 'success_text' => __( 'Thank you, your email has been added to the list.', MAILCHIMP_LANG_DOMAIN ), 104 | 'button_text' => __( 'Subscribe!', MAILCHIMP_LANG_DOMAIN ), 105 | 'lastname' => 1, 106 | 'firstname' => 1 107 | ); 108 | 109 | $atts = wp_parse_args( $atts, $defaults ); 110 | extract( $atts ); 111 | 112 | $args['text'] = $title; 113 | $args['subscribed_placeholder'] = $success_text; 114 | $args['button_text'] = $button_text; 115 | $args['form_id'] = 'incsub-mailchimp-shortcode-form-' . self::$number; 116 | $args['submit_name'] = 'submit-subscribe-shortcode-user'; 117 | $args['firstname'] = ! empty( $_POST['subscription-firstname'] ) ? stripslashes( $_POST['subscription-firstname'] ) : ''; 118 | $args['lastname'] = ! empty( $_POST['subscription-lastname'] ) ? stripslashes( $_POST['subscription-lastname'] ) : ''; 119 | $args['email'] = ! empty( $_POST['subscription-email'] ) ? stripslashes( $_POST['subscription-email'] ) : ''; 120 | 121 | $settings = array( 122 | 'require_firstname' => isset( $firstname ) ? (bool)$firstname : false, 123 | 'require_lastname' => isset( $lastname ) ? (bool)$lastname : false, 124 | ); 125 | $this->validate_shortcode( $settings ); 126 | 127 | $args['errors'] = isset( $this->errors[ self::$number ] ) ? $this->errors[ self::$number ] : array(); 128 | $args['subscribed'] = isset( $_POST[ 'submit-subscribe-shortcode-user' ] ) && empty( $this->errors[ self::$number ] ); 129 | $args['require_fn'] = $settings['require_firstname']; 130 | $args['require_ln'] = $settings['require_lastname']; 131 | 132 | self::$number++; 133 | $this->enqueue_styles = true; 134 | 135 | ob_start(); 136 | WPMUDEV_MailChimp_Form::render_form( $args ); 137 | return ob_get_clean(); 138 | } 139 | 140 | public function display_shortcode_admin_form() { 141 | 142 | global $wp_scripts; 143 | ?> 144 | 145 | 146 | 147 | <?php _e( 'Mailchimp Shortcode', MAILCHIMP_LANG_DOMAIN ); ?> 148 | 149 | 150 | 151 | 152 | /wp-admin/load-styles.php?c=1&dir=ltr&load=widgets,global,wp-admin' type='text/css' media='all' /> 153 | 154 | 157 | 158 | 159 | 160 | 210 | 211 | 212 | 213 |
    214 |
    215 |
    216 | 220 |
    221 |
    222 | 226 |
    227 |
    228 | 232 |
    233 |
    234 | 238 |
    239 |
    240 | 244 |
    245 | 246 |
    247 |
    248 | 249 |
    250 | 251 |
    252 | 253 |
    254 |
    255 |
    256 |
    257 | 258 | 259 | 291 | 292 | post( $path, $args ); 22 | break; 23 | } 24 | case 'delete': { 25 | $result = $api->delete( $path, $args ); 26 | break; 27 | } 28 | case 'patch': { 29 | $result = $api->patch( $path, $args ); 30 | break; 31 | } 32 | default: { 33 | $result = $api->get( $path, $args ); 34 | } 35 | } 36 | } 37 | catch ( Exception $e ) { 38 | $error = new WP_Error( $e->getCode(), $e->getMessage() ); 39 | mi_mailchimp_log( $error->get_error_message() ); 40 | return $error; 41 | } 42 | 43 | if ( ! $api->success() ) { 44 | $response = $api->getLastResponse(); 45 | if ( is_wp_error( $response ) ) { 46 | /** @var WP_Error $response */ 47 | mi_mailchimp_log( array( 48 | 'message' => $response->get_error_message(), 49 | 'code' => $response->get_error_code() 50 | ) ); 51 | return $response; 52 | } 53 | 54 | $status = wp_remote_retrieve_response_code( $api->getLastResponse() ); 55 | // Log here 56 | mi_mailchimp_log( array( 57 | 'message' => $api->getLastError(), 58 | 'code' => $status 59 | ) ); 60 | return new WP_Error( $status, $api->getLastError() ); 61 | } 62 | 63 | return $result; 64 | } 65 | 66 | /** 67 | * A wrapper method for Batch API calls 68 | * 69 | * @param array $operations A list of operations 70 | * [ 71 | * method string Request method 72 | * path string Request path 73 | * args array List of arguments to pass 74 | * ] 75 | * 76 | * @return WP_Error|array 77 | */ 78 | function mailchimp_api_30_make_batch_request( $operations ) { 79 | $api = mailchimp_load_api_30(); 80 | if ( is_wp_error( $api ) ) { 81 | return $api; 82 | } 83 | 84 | $batch = $api->new_batch(); 85 | 86 | foreach ( $operations as $key => $operation ) { 87 | $op_number = 'op_' . time(); 88 | switch ( $operation['method'] ) { 89 | case 'post': { 90 | $batch->post( $op_number, $operation['path'], $operation['args'] ); 91 | break; 92 | } 93 | case 'delete': { 94 | $batch->delete( $op_number, $operation['path'] ); 95 | break; 96 | } 97 | case 'patch': { 98 | $batch->patch( $op_number, $operation['path'], $operation['args'] ); 99 | break; 100 | } 101 | default: { 102 | $batch->get( $op_number, $operation['path'], $operation['args'] ); 103 | } 104 | } 105 | } 106 | 107 | try { 108 | $result = $batch->execute(); 109 | } 110 | catch ( Exception $e ) { 111 | return new WP_Error( $e->getCode(), $e->getMessage() ); 112 | } 113 | 114 | if ( ! $api->success() ) { 115 | $status = wp_remote_retrieve_response_code( $api->getLastResponse() ); 116 | // Log here 117 | mi_mailchimp_log( array( 118 | 'message' => $api->getLastError(), 119 | 'code' => $status 120 | ) ); 121 | return new WP_Error( $status, $api->getLastError() ); 122 | } 123 | 124 | return $result['id']; 125 | } 126 | 127 | function mailchimp_api_30_get_batch_operation_result( $batch_id ) { 128 | $api = mailchimp_load_api_30(); 129 | if ( is_wp_error( $api ) ) { 130 | return $api; 131 | } 132 | 133 | $batch = $api->new_batch( $batch_id ); 134 | $result = $batch->check_status(); 135 | if ( is_wp_error( $result ) ) { 136 | mi_mailchimp_log( array( 137 | 'message' => $result->get_error_message(), 138 | 'code' => $result->get_error_code() 139 | ) ); 140 | } 141 | 142 | return $result; 143 | } 144 | 145 | /** 146 | * Load the Mailchimp API 147 | * 148 | * @return MailChimp_Sync_Mailchimp|WP_Error Object 149 | */ 150 | function mailchimp_load_api_30() { 151 | global $mailchimp_sync_api; 152 | 153 | include_once( 'Mailchimp/MailChimp.php' ); 154 | include_once( 'Mailchimp/Batch.php' ); 155 | include_once( 'Mailchimp/Webhook.php' ); 156 | 157 | if ( is_a( $mailchimp_sync_api, 'MailChimp_Sync_Mailchimp' ) ) { 158 | return $mailchimp_sync_api; 159 | } 160 | 161 | 162 | $mailchimp_apikey = get_site_option('mailchimp_apikey'); 163 | 164 | try { 165 | $api = new MailChimp_Sync_Mailchimp( $mailchimp_apikey ); 166 | } 167 | catch ( Exception $e ) { 168 | return new WP_Error( $e->getCode(), $e->getMessage() ); 169 | } 170 | 171 | $mailchimp_sync_api = $api; 172 | 173 | return $mailchimp_sync_api; 174 | } 175 | 176 | /** 177 | * Return a list of API options like timeout, ssl verify... 178 | * 179 | * @return array 180 | */ 181 | function mailchimp_api_options() { 182 | $options = array( 183 | 'timeout' => apply_filters( 'mailchimp_sync_api_timeout', false ) 184 | ); 185 | 186 | $ssl_verifypeer = apply_filters( 'mailchimp_sync_api_ssl_verifypeer', false ); 187 | if ( $ssl_verifypeer ) { 188 | $options['ssl_verifypeer'] = $ssl_verifypeer; 189 | } 190 | 191 | $ssl_verifyhost = apply_filters( 'mailchimp_sync_api_ssl_verifyhost', false ); 192 | if ( $ssl_verifyhost ) { 193 | $options['ssl_verifyhost'] = $ssl_verifyhost; 194 | } 195 | 196 | $ssl_cainfo = apply_filters( 'mailchimp_sync_api_ssl_cainfo', false ); 197 | if ( $ssl_cainfo ) { 198 | $options['ssl_cainfo'] = $ssl_cainfo; 199 | } 200 | 201 | $debug = apply_filters( 'mailchimp_sync_api_debug', false ); 202 | if ( $debug ) { 203 | $options['debug'] = $debug; 204 | } 205 | 206 | return $options; 207 | } 208 | 209 | function mi_mailchimp_log( $details, $type = 'error' ) { 210 | if ( ! is_array( $details ) ) { 211 | return; 212 | } 213 | 214 | $option_name = 'mailchimp_' . $type . '_log'; 215 | 216 | $current_log = get_site_option( $option_name ); 217 | $new_log = array(); 218 | 219 | $code = isset( $details['code'] ) ? $details['code'] : 0; 220 | $message = isset( $details['message'] ) ? $details['message'] : ''; 221 | $date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) ); 222 | 223 | $new_log[] = compact( 'code', 'message', 'email', 'date' ); 224 | 225 | if ( $current_log ) { 226 | 227 | $new_log = array_merge( $current_log, $new_log ); 228 | 229 | // We'll only saved the last X lines of the log 230 | $count = count( $new_log ); 231 | if ( $count > MAILCHIMP_MAX_LOG_LINES ) { 232 | $new_log = array_slice( $new_log, $count - 1 ); 233 | } 234 | 235 | } 236 | 237 | update_site_option( $option_name, $new_log ); 238 | } 239 | 240 | // 241 | //class WPMUDEV_Mailchimp_Sync_API_30 extends Mailchimp { 242 | // 243 | // /** 244 | // * CURLOPT_SSL_VERIFYPEER setting 245 | // * @var bool 246 | // */ 247 | // public $ssl_verifypeer = true; 248 | // /** 249 | // * CURLOPT_SSL_VERIFYHOST setting 250 | // * @var bool 251 | // */ 252 | // public $ssl_verifyhost = 2; 253 | // /** 254 | // * CURLOPT_CAINFO 255 | // * @var string 256 | // */ 257 | // public $ssl_cainfo = null; 258 | // 259 | // /** 260 | // * Timeout setting 261 | // * @var bool 262 | // */ 263 | // public $timeout = 600; 264 | // 265 | // public function __construct( $apikey, $opts ) { 266 | // if( ! $apikey ) 267 | // $apikey = getenv('MAILCHIMP_APIKEY'); 268 | // 269 | // if( ! $apikey ) 270 | // throw new Mailchimp_Error( 'You must provide a MailChimp API key' ); 271 | // 272 | // $this->apikey = $apikey; 273 | // $dc = "us1"; 274 | // 275 | // if ( strstr( $this->apikey, "-" ) ) { 276 | // list( $key, $dc ) = explode( "-", $this->apikey, 2 ); 277 | // if ( ! $dc ) 278 | // $dc = "us1"; 279 | // } 280 | // 281 | // $this->root = str_replace('https://api', 'https://' . $dc . '.api', $this->root); 282 | // $this->root = rtrim($this->root, '/') . '/'; 283 | // 284 | // $defaults = array( 285 | // 'debug' => false, 286 | // 'ssl_verifypeer' => true, 287 | // 'ssl_verifyhost' => 2, 288 | // 'ssl_cainfo' => null 289 | // ); 290 | // 291 | // $opts = wp_parse_args( $opts, $defaults ); 292 | // 293 | // $this->debug = $opts['debug']; 294 | // 295 | // if ( isset( $opts['timeout'] ) ) 296 | // $this->timeout = absint( $opts['timeout'] ); 297 | // 298 | // $this->ssl_verifypeer = $opts['ssl_verifypeer']; 299 | // $this->ssl_verifyhost = $opts['ssl_verifyhost']; 300 | // $this->ssl_cainfo = $opts['ssl_cainfo']; 301 | // 302 | // $this->folders = new Mailchimp_Folders($this); 303 | // $this->templates = new Mailchimp_Templates($this); 304 | // $this->users = new Mailchimp_Users($this); 305 | // $this->helper = new Mailchimp_Helper($this); 306 | // $this->mobile = new Mailchimp_Mobile($this); 307 | // $this->conversations = new Mailchimp_Conversations($this); 308 | // $this->ecomm = new Mailchimp_Ecomm($this); 309 | // $this->neapolitan = new Mailchimp_Neapolitan($this); 310 | // $this->lists = new Mailchimp_Lists($this); 311 | // $this->campaigns = new Mailchimp_Campaigns($this); 312 | // $this->vip = new Mailchimp_Vip($this); 313 | // $this->reports = new Mailchimp_Reports($this); 314 | // $this->gallery = new Mailchimp_Gallery($this); 315 | // $this->goal = new Mailchimp_Goal($this); 316 | // } 317 | // 318 | // public function call( $url, $params ) { 319 | // $params['apikey'] = $this->apikey; 320 | // 321 | // $params = json_encode($params); 322 | // 323 | // $args = array( 324 | // 'timeout' => $this->timeout, 325 | // 'user-agent' => 'MailChimp-PHP/2.0.4', 326 | // 'blocking' => true, 327 | // 'headers' => array( 'Content-Type' => 'application/json' ), 328 | // 'body' => $params, 329 | // 'sslverify' => $this->ssl_verifypeer, 330 | // 'filename' => null 331 | // ); 332 | // 333 | // $args = apply_filters( 'mailchimp_request_args', $args ); 334 | // 335 | // if ( $this->ssl_cainfo ) 336 | // $args['sslcertificates'] = $this->ssl_cainfo; 337 | // 338 | // $response = wp_remote_post( $this->root . $url . '.json', $args ); 339 | // 340 | // if ( is_wp_error( $response ) ) { 341 | // $this->log_errors( 342 | // array( array( 343 | // 'code' => $response->get_error_code(), 344 | // 'message' => $response->get_error_message() 345 | // ) ) 346 | // ); 347 | // return $response; 348 | // } 349 | // 350 | // $response_body = wp_remote_retrieve_body( $response ); 351 | // 352 | // $result = json_decode($response_body, true); 353 | // 354 | // if( floor( $response['response']['code'] / 100 ) >= 4 ) { 355 | // $error = $this->castError($result); 356 | // $this->log_errors( 357 | // array( array( 358 | // 'code' => $error->getCode(), 359 | // 'message' => $error->getMessage() 360 | // ) ) 361 | // ); 362 | // return new WP_Error( $error->getCode(), $error->getMessage() ); 363 | // } 364 | // 365 | // return $result; 366 | // } 367 | // 368 | // public function log_errors( $errors ) { 369 | // if ( ! is_array( $errors ) ) 370 | // $errors = array( $errors ); 371 | // 372 | // $current_log = get_site_option( 'mailchimp_error_log' ); 373 | // $new_log = array(); 374 | // 375 | // 376 | // foreach ( $errors as $error ) { 377 | // 378 | // $code = isset( $error['code'] ) ? $error['code'] : 0; 379 | // $message = isset( $error['message'] ) ? $error['message'] : ''; 380 | // $email = isset( $error['email'] ) ? $error['email'] : ''; 381 | // $date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) ); 382 | // 383 | // $new_log[] = compact( 'code', 'message', 'email', 'date' ); 384 | // 385 | // } 386 | // 387 | // 388 | // if ( $current_log ) { 389 | // 390 | // $new_log = array_merge( $current_log, $new_log ); 391 | // 392 | // // We'll only saved the last X lines of the log 393 | // $count = count( $new_log ); 394 | // if ( $count > MAILCHIMP_MAX_LOG_LINES ) { 395 | // $new_log = array_slice( $new_log, $count - $offset - 1 ); 396 | // } 397 | // 398 | // } 399 | // 400 | // update_site_option( 'mailchimp_error_log', $new_log ); 401 | // } 402 | //} -------------------------------------------------------------------------------- /mailchimp-api/2.0/Mailchimp.php: -------------------------------------------------------------------------------- 1 | "Mailchimp_ValidationError", 28 | "ServerError_MethodUnknown" => "Mailchimp_ServerError_MethodUnknown", 29 | "ServerError_InvalidParameters" => "Mailchimp_ServerError_InvalidParameters", 30 | "Unknown_Exception" => "Mailchimp_Unknown_Exception", 31 | "Request_TimedOut" => "Mailchimp_Request_TimedOut", 32 | "Zend_Uri_Exception" => "Mailchimp_Zend_Uri_Exception", 33 | "PDOException" => "Mailchimp_PDOException", 34 | "Avesta_Db_Exception" => "Mailchimp_Avesta_Db_Exception", 35 | "XML_RPC2_Exception" => "Mailchimp_XML_RPC2_Exception", 36 | "XML_RPC2_FaultException" => "Mailchimp_XML_RPC2_FaultException", 37 | "Too_Many_Connections" => "Mailchimp_Too_Many_Connections", 38 | "Parse_Exception" => "Mailchimp_Parse_Exception", 39 | "User_Unknown" => "Mailchimp_User_Unknown", 40 | "User_Disabled" => "Mailchimp_User_Disabled", 41 | "User_DoesNotExist" => "Mailchimp_User_DoesNotExist", 42 | "User_NotApproved" => "Mailchimp_User_NotApproved", 43 | "Invalid_ApiKey" => "Mailchimp_Invalid_ApiKey", 44 | "User_UnderMaintenance" => "Mailchimp_User_UnderMaintenance", 45 | "Invalid_AppKey" => "Mailchimp_Invalid_AppKey", 46 | "Invalid_IP" => "Mailchimp_Invalid_IP", 47 | "User_DoesExist" => "Mailchimp_User_DoesExist", 48 | "User_InvalidRole" => "Mailchimp_User_InvalidRole", 49 | "User_InvalidAction" => "Mailchimp_User_InvalidAction", 50 | "User_MissingEmail" => "Mailchimp_User_MissingEmail", 51 | "User_CannotSendCampaign" => "Mailchimp_User_CannotSendCampaign", 52 | "User_MissingModuleOutbox" => "Mailchimp_User_MissingModuleOutbox", 53 | "User_ModuleAlreadyPurchased" => "Mailchimp_User_ModuleAlreadyPurchased", 54 | "User_ModuleNotPurchased" => "Mailchimp_User_ModuleNotPurchased", 55 | "User_NotEnoughCredit" => "Mailchimp_User_NotEnoughCredit", 56 | "MC_InvalidPayment" => "Mailchimp_MC_InvalidPayment", 57 | "List_DoesNotExist" => "Mailchimp_List_DoesNotExist", 58 | "List_InvalidInterestFieldType" => "Mailchimp_List_InvalidInterestFieldType", 59 | "List_InvalidOption" => "Mailchimp_List_InvalidOption", 60 | "List_InvalidUnsubMember" => "Mailchimp_List_InvalidUnsubMember", 61 | "List_InvalidBounceMember" => "Mailchimp_List_InvalidBounceMember", 62 | "List_AlreadySubscribed" => "Mailchimp_List_AlreadySubscribed", 63 | "List_NotSubscribed" => "Mailchimp_List_NotSubscribed", 64 | "List_InvalidImport" => "Mailchimp_List_InvalidImport", 65 | "MC_PastedList_Duplicate" => "Mailchimp_MC_PastedList_Duplicate", 66 | "MC_PastedList_InvalidImport" => "Mailchimp_MC_PastedList_InvalidImport", 67 | "Email_AlreadySubscribed" => "Mailchimp_Email_AlreadySubscribed", 68 | "Email_AlreadyUnsubscribed" => "Mailchimp_Email_AlreadyUnsubscribed", 69 | "Email_NotExists" => "Mailchimp_Email_NotExists", 70 | "Email_NotSubscribed" => "Mailchimp_Email_NotSubscribed", 71 | "List_MergeFieldRequired" => "Mailchimp_List_MergeFieldRequired", 72 | "List_CannotRemoveEmailMerge" => "Mailchimp_List_CannotRemoveEmailMerge", 73 | "List_Merge_InvalidMergeID" => "Mailchimp_List_Merge_InvalidMergeID", 74 | "List_TooManyMergeFields" => "Mailchimp_List_TooManyMergeFields", 75 | "List_InvalidMergeField" => "Mailchimp_List_InvalidMergeField", 76 | "List_InvalidInterestGroup" => "Mailchimp_List_InvalidInterestGroup", 77 | "List_TooManyInterestGroups" => "Mailchimp_List_TooManyInterestGroups", 78 | "Campaign_DoesNotExist" => "Mailchimp_Campaign_DoesNotExist", 79 | "Campaign_StatsNotAvailable" => "Mailchimp_Campaign_StatsNotAvailable", 80 | "Campaign_InvalidAbsplit" => "Mailchimp_Campaign_InvalidAbsplit", 81 | "Campaign_InvalidContent" => "Mailchimp_Campaign_InvalidContent", 82 | "Campaign_InvalidOption" => "Mailchimp_Campaign_InvalidOption", 83 | "Campaign_InvalidStatus" => "Mailchimp_Campaign_InvalidStatus", 84 | "Campaign_NotSaved" => "Mailchimp_Campaign_NotSaved", 85 | "Campaign_InvalidSegment" => "Mailchimp_Campaign_InvalidSegment", 86 | "Campaign_InvalidRss" => "Mailchimp_Campaign_InvalidRss", 87 | "Campaign_InvalidAuto" => "Mailchimp_Campaign_InvalidAuto", 88 | "MC_ContentImport_InvalidArchive" => "Mailchimp_MC_ContentImport_InvalidArchive", 89 | "Campaign_BounceMissing" => "Mailchimp_Campaign_BounceMissing", 90 | "Campaign_InvalidTemplate" => "Mailchimp_Campaign_InvalidTemplate", 91 | "Invalid_EcommOrder" => "Mailchimp_Invalid_EcommOrder", 92 | "Absplit_UnknownError" => "Mailchimp_Absplit_UnknownError", 93 | "Absplit_UnknownSplitTest" => "Mailchimp_Absplit_UnknownSplitTest", 94 | "Absplit_UnknownTestType" => "Mailchimp_Absplit_UnknownTestType", 95 | "Absplit_UnknownWaitUnit" => "Mailchimp_Absplit_UnknownWaitUnit", 96 | "Absplit_UnknownWinnerType" => "Mailchimp_Absplit_UnknownWinnerType", 97 | "Absplit_WinnerNotSelected" => "Mailchimp_Absplit_WinnerNotSelected", 98 | "Invalid_Analytics" => "Mailchimp_Invalid_Analytics", 99 | "Invalid_DateTime" => "Mailchimp_Invalid_DateTime", 100 | "Invalid_Email" => "Mailchimp_Invalid_Email", 101 | "Invalid_SendType" => "Mailchimp_Invalid_SendType", 102 | "Invalid_Template" => "Mailchimp_Invalid_Template", 103 | "Invalid_TrackingOptions" => "Mailchimp_Invalid_TrackingOptions", 104 | "Invalid_Options" => "Mailchimp_Invalid_Options", 105 | "Invalid_Folder" => "Mailchimp_Invalid_Folder", 106 | "Invalid_URL" => "Mailchimp_Invalid_URL", 107 | "Module_Unknown" => "Mailchimp_Module_Unknown", 108 | "MonthlyPlan_Unknown" => "Mailchimp_MonthlyPlan_Unknown", 109 | "Order_TypeUnknown" => "Mailchimp_Order_TypeUnknown", 110 | "Invalid_PagingLimit" => "Mailchimp_Invalid_PagingLimit", 111 | "Invalid_PagingStart" => "Mailchimp_Invalid_PagingStart", 112 | "Max_Size_Reached" => "Mailchimp_Max_Size_Reached", 113 | "MC_SearchException" => "Mailchimp_MC_SearchException", 114 | "Goal_SaveFailed" => "Mailchimp_Goal_SaveFailed", 115 | "Conversation_DoesNotExist" => "Mailchimp_Conversation_DoesNotExist", 116 | "Conversation_ReplySaveFailed" => "Mailchimp_Conversation_ReplySaveFailed", 117 | "File_Not_Found_Exception" => "Mailchimp_File_Not_Found_Exception", 118 | "Folder_Not_Found_Exception" => "Mailchimp_Folder_Not_Found_Exception", 119 | "Folder_Exists_Exception" => "Mailchimp_Folder_Exists_Exception" 120 | ); 121 | 122 | public function __construct($apikey=null, $opts=array()) { 123 | if (!$apikey) { 124 | $apikey = getenv('MAILCHIMP_APIKEY'); 125 | } 126 | 127 | if (!$apikey) { 128 | $apikey = $this->readConfigs(); 129 | } 130 | 131 | if (!$apikey) { 132 | throw new Mailchimp_Error('You must provide a MailChimp API key'); 133 | } 134 | 135 | $this->apikey = $apikey; 136 | $dc = "us1"; 137 | 138 | if (strstr($this->apikey, "-")){ 139 | list($key, $dc) = explode("-", $this->apikey, 2); 140 | if (!$dc) { 141 | $dc = "us1"; 142 | } 143 | } 144 | 145 | $this->root = str_replace('https://api', 'https://' . $dc . '.api', $this->root); 146 | $this->root = rtrim($this->root, '/') . '/'; 147 | 148 | if (!isset($opts['timeout']) || !is_int($opts['timeout'])){ 149 | $opts['timeout'] = 600; 150 | } 151 | if (isset($opts['debug'])){ 152 | $this->debug = true; 153 | } 154 | 155 | 156 | $this->ch = curl_init(); 157 | 158 | if (isset($opts['CURLOPT_FOLLOWLOCATION']) && $opts['CURLOPT_FOLLOWLOCATION'] === true) { 159 | curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true); 160 | } 161 | 162 | curl_setopt($this->ch, CURLOPT_USERAGENT, 'MailChimp-PHP/2.0.6'); 163 | curl_setopt($this->ch, CURLOPT_POST, true); 164 | curl_setopt($this->ch, CURLOPT_HEADER, false); 165 | curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); 166 | curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, 30); 167 | curl_setopt($this->ch, CURLOPT_TIMEOUT, $opts['timeout']); 168 | 169 | 170 | $this->folders = new Mailchimp_Folders($this); 171 | $this->templates = new Mailchimp_Templates($this); 172 | $this->users = new Mailchimp_Users($this); 173 | $this->helper = new Mailchimp_Helper($this); 174 | $this->mobile = new Mailchimp_Mobile($this); 175 | $this->conversations = new Mailchimp_Conversations($this); 176 | $this->ecomm = new Mailchimp_Ecomm($this); 177 | $this->neapolitan = new Mailchimp_Neapolitan($this); 178 | $this->lists = new Mailchimp_Lists($this); 179 | $this->campaigns = new Mailchimp_Campaigns($this); 180 | $this->vip = new Mailchimp_Vip($this); 181 | $this->reports = new Mailchimp_Reports($this); 182 | $this->gallery = new Mailchimp_Gallery($this); 183 | $this->goal = new Mailchimp_Goal($this); 184 | } 185 | 186 | public function __destruct() { 187 | if(is_resource($this->ch)) { 188 | curl_close($this->ch); 189 | } 190 | } 191 | 192 | public function call($url, $params) { 193 | $params['apikey'] = $this->apikey; 194 | 195 | $params = json_encode($params); 196 | $ch = $this->ch; 197 | 198 | curl_setopt($ch, CURLOPT_URL, $this->root . $url . '.json'); 199 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 200 | curl_setopt($ch, CURLOPT_POSTFIELDS, $params); 201 | curl_setopt($ch, CURLOPT_VERBOSE, $this->debug); 202 | 203 | $start = microtime(true); 204 | $this->log('Call to ' . $this->root . $url . '.json: ' . $params); 205 | if($this->debug) { 206 | $curl_buffer = fopen('php://memory', 'w+'); 207 | curl_setopt($ch, CURLOPT_STDERR, $curl_buffer); 208 | } 209 | 210 | $response_body = curl_exec($ch); 211 | 212 | $info = curl_getinfo($ch); 213 | $time = microtime(true) - $start; 214 | if($this->debug) { 215 | rewind($curl_buffer); 216 | $this->log(stream_get_contents($curl_buffer)); 217 | fclose($curl_buffer); 218 | } 219 | $this->log('Completed in ' . number_format($time * 1000, 2) . 'ms'); 220 | $this->log('Got response: ' . $response_body); 221 | 222 | if(curl_error($ch)) { 223 | throw new Mailchimp_HttpError("API call to $url failed: " . curl_error($ch)); 224 | } 225 | $result = json_decode($response_body, true); 226 | 227 | if(floor($info['http_code'] / 100) >= 4) { 228 | throw $this->castError($result); 229 | } 230 | 231 | return $result; 232 | } 233 | 234 | public function readConfigs() { 235 | $paths = array('~/.mailchimp.key', '/etc/mailchimp.key'); 236 | foreach($paths as $path) { 237 | if(file_exists($path)) { 238 | $apikey = trim(file_get_contents($path)); 239 | if ($apikey) { 240 | return $apikey; 241 | } 242 | } 243 | } 244 | return false; 245 | } 246 | 247 | public function castError($result) { 248 | if ($result['status'] !== 'error' || !$result['name']) { 249 | throw new Mailchimp_Error('We received an unexpected error: ' . json_encode($result)); 250 | } 251 | 252 | $class = (isset(self::$error_map[$result['name']])) ? self::$error_map[$result['name']] : 'Mailchimp_Error'; 253 | return new $class($result['error'], $result['code']); 254 | } 255 | 256 | public function log($msg) { 257 | if ($this->debug) { 258 | error_log($msg); 259 | } 260 | } 261 | } 262 | 263 | 264 | -------------------------------------------------------------------------------- /mailchimp-sync.php: -------------------------------------------------------------------------------- 1 | set_globals(); 50 | $this->includes(); 51 | self::$basename = plugin_basename( plugin_dir_path( __FILE__ )) . '/mailchimp-sync.php'; 52 | 53 | add_action( 'plugins_loaded', array( $this, 'mailchimp_localization' ) ); 54 | 55 | add_action( 'init', array( $this, 'init' ), 1 ); 56 | add_action( 'admin_init', array( $this, 'maybe_upgrade' ), 1 ); 57 | 58 | add_action( 'wpmu_new_user', array( $this, 'mailchimp_add_user' ) ); 59 | add_action( 'user_register', array( $this, 'mailchimp_add_user' ) ); 60 | add_action( 'make_ham_user', array( $this, 'mailchimp_add_user' ) ); 61 | add_action( 'profile_update', array( $this, 'mailchimp_edit_user' ) ); 62 | add_action( 'xprofile_updated_profile', array( $this, 'mailchimp_edit_user' ) ); //for buddypress 63 | 64 | add_action( 'make_spam_user', array( $this, 'mailchimp_user_remove' ) ); 65 | add_action( 'delete_user', array( $this, 'mailchimp_user_remove' ) ); 66 | add_action( 'wpmu_delete_user', array( $this, 'mailchimp_user_remove' ) ); 67 | add_action( 'bp_core_action_set_spammer_status', array( $this, 'mailchimp_bp_spamming' ) , 10, 2); //for buddypress 68 | 69 | add_action( 'widgets_init', array( $this, 'mailchimp_widget_init' ) ); 70 | 71 | new WPMUDEV_MailChimp_Sync_Webhooks_30(); 72 | 73 | if ( is_admin() ) { 74 | include_once( 'admin/class-admin.php' ); 75 | new Mailchimp_Sync_Admin(); 76 | } 77 | 78 | } 79 | 80 | private function set_globals() { 81 | define( 'MAILCHIMP_MAX_LOG_LINES', 100 ); 82 | define( 'MAILCHIMP_LANG_DOMAIN', 'mailchimp' ); 83 | define( 'MAILCHIMP_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 84 | define( 'MAILCHIMP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 85 | 86 | define( 'MAILCHIMP_ASSETS_URL', MAILCHIMP_PLUGIN_URL . 'assets/' ); 87 | define( 'MAILCHIMP_FRONT_DIR', MAILCHIMP_PLUGIN_DIR . 'front/' ); 88 | } 89 | 90 | private function includes() { 91 | require_once( 'deprecated.php' ); 92 | require_once( 'helpers.php' ); 93 | require_once( 'integration.php' ); 94 | require_once( 'mailchimp-api/3.0/webhooks.php' ); 95 | 96 | // WPMUDEV Dashboard class 97 | if ( is_admin() ) { 98 | global $wpmudev_notices; 99 | $wpmudev_notices[] = array( 100 | 'id'=> 73, 101 | 'name'=> 'MailChimp Sync', 102 | 'screens' => array( 103 | 'settings_page_mailchimp-network' 104 | ) 105 | ); 106 | include_once( 'externals/wpmudev-dash-notification.php' ); 107 | } 108 | 109 | } 110 | 111 | public function init() { 112 | if ( ! is_multisite() || ( is_multisite() && get_site_option( 'mailchimp_allow_shortcode', false ) ) ) { 113 | require_once( MAILCHIMP_FRONT_DIR . 'shortcode.php' ); 114 | new WPMUDEV_MailChimp_Shortcode(); 115 | } 116 | 117 | require_once( MAILCHIMP_FRONT_DIR . 'form.class.php' ); 118 | add_action( 'wp_ajax_incsub_mailchimp_subscribe_user', array( 'WPMUDEV_MailChimp_Form', 'validate_ajax_form' ) ); 119 | add_action( 'wp_ajax_nopriv_incsub_mailchimp_subscribe_user', array( 'WPMUDEV_MailChimp_Form', 'validate_ajax_form' ) ); 120 | 121 | 122 | } 123 | 124 | 125 | function mailchimp_localization() { 126 | // Load up the localization file if we're using WordPress in a different language 127 | // Place it in this plugin's "languages" folder and name it "mailchimp-[value in wp-config].mo" 128 | load_plugin_textdomain( 'mailchimp', false, '/mailchimp-sync/languages/' ); 129 | } 130 | 131 | 132 | 133 | function mailchimp_widget_init() { 134 | if ( ! is_multisite() || ( is_multisite() && get_site_option( 'mailchimp_allow_widget', false ) ) ) { 135 | require_once( MAILCHIMP_FRONT_DIR . 'widget.php' ); 136 | register_widget( 'Incsub_Mailchimp_Widget' ); 137 | } 138 | } 139 | 140 | 141 | function mailchimp_add_user($uid) { 142 | 143 | if ( is_integer( $uid ) ) { 144 | $user = get_userdata( $uid ); 145 | } 146 | elseif ( is_array( $uid ) ) { 147 | $user = new stdClass; 148 | $user->spam = false; 149 | $user->deleted = false; 150 | $user->user_email = $uid['email']; 151 | $user->user_firstname = $uid['first_name']; 152 | $user->user_lastname = $uid['last_name']; 153 | } 154 | else { 155 | return false; 156 | } 157 | 158 | // If we have recently added this email, don't do anything 159 | $transient_key = 'mailchimp_sync_' . md5( $user->user_email ); 160 | if ( get_site_transient( $transient_key ) ) { 161 | return false; 162 | } 163 | 164 | //check for spam 165 | if ( $user->spam || $user->deleted ) 166 | return false; 167 | 168 | //remove + sign emails 169 | if ( get_site_option('mailchimp_ignore_plus') == 'yes' && strstr( $user->user_email, '+' ) ) 170 | return false; 171 | 172 | $mailchimp_auto_opt_in = get_site_option('mailchimp_auto_opt_in'); 173 | 174 | $autopt = $mailchimp_auto_opt_in == 'yes' ? true : false; 175 | $merge_vars = array( 'FNAME' => $user->user_firstname, 'LNAME' => $user->user_lastname ); 176 | 177 | $merge_vars = apply_filters( 'mailchimp_merge_vars', $merge_vars, $user ); 178 | do_action( 'mailchimp_subscribe_user', $merge_vars, $user ); 179 | 180 | $interests = mailchimp_30_get_interest_groups(); 181 | $results = mailchimp_30_subscribe_user( $user->user_email, '', array( 'interests' => $interests, 'autopt' => $autopt, 'merge_fields' => $merge_vars ) ); 182 | 183 | if ( ! is_wp_error( $results ) ) { 184 | // There could be other plugins triggering this function twice for a single user. 185 | // MailChimp does not refresh the list such fast. 186 | // We'll save the subscriber user data in order to avoid that. 187 | $transient_key = 'mailchimp_sync_' . md5( $results['email_address'] ); 188 | set_site_transient( $transient_key, true, 30 ); // Set it only to 30 seconds, should be enough for most cases 189 | } 190 | 191 | return $results; 192 | } 193 | 194 | 195 | 196 | function mailchimp_edit_user($uid) { 197 | 198 | $user = get_userdata( $uid ); 199 | 200 | //check for spam 201 | if ( $user->spam || $user->deleted ) 202 | return false; 203 | 204 | $merge_vars = array( 'FNAME' => $user->user_firstname, 'LNAME' => $user->user_lastname ); 205 | 206 | $merge_vars = apply_filters('mailchimp_merge_vars', $merge_vars, $user); 207 | do_action( 'mailchimp_update_user', $merge_vars, $user ); 208 | 209 | $result = mailchimp_30_update_user( $user->user_email, '', array( 'merge_fields' => $merge_vars ) ); 210 | 211 | return $result; 212 | } 213 | 214 | function mailchimp_user_remove( $uid ) { 215 | 216 | $user = get_userdata( $uid ); 217 | 218 | if ( ! $user ) 219 | return; 220 | 221 | $results = mailchimp_30_unsubscribe_user( $user->user_email, '', true ); 222 | } 223 | 224 | 225 | function mailchimp_bp_spamming( $user_id, $is_spam ) { 226 | if ($is_spam) 227 | $this->mailchimp_user_remove( $user_id ); 228 | else 229 | $this->mailchimp_add_user( $user_id ); 230 | } 231 | 232 | //------------------------------------------------------------------------// 233 | //---Page Output Functions------------------------------------------------// 234 | //------------------------------------------------------------------------// 235 | 236 | 237 | /** 238 | * Log MailChimp errors 239 | * @param Array $errors 240 | * @return type 241 | */ 242 | function mailchimp_log_errors( $errors ) { 243 | 244 | if ( ! is_array( $errors ) ) 245 | $errors = array( $errors ); 246 | 247 | $current_log = get_site_option( 'mailchimp_error_log' ); 248 | $new_log = array(); 249 | 250 | 251 | foreach ( $errors as $error ) { 252 | 253 | $code = isset( $error['code'] ) ? $error['code'] : 0; 254 | $message = isset( $error['message'] ) ? $error['message'] : ''; 255 | $email = isset( $error['email'] ) ? $error['email'] : ''; 256 | $date = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), current_time( 'timestamp' ) ); 257 | 258 | $new_log[] = compact( 'code', 'message', 'email', 'date' ); 259 | 260 | } 261 | 262 | 263 | if ( $current_log ) { 264 | 265 | $new_log = array_merge( $current_log, $new_log ); 266 | 267 | // We'll only saved the last X lines of the log 268 | $count = count( $new_log ); 269 | if ( $count > MAILCHIMP_MAX_LOG_LINES ) { 270 | $new_log = array_slice( $new_log, $count - $offset - 1 ); 271 | } 272 | 273 | } 274 | 275 | update_site_option( 'mailchimp_error_log', $new_log ); 276 | 277 | } 278 | 279 | public function maybe_upgrade() { 280 | $saved_version = get_site_option( 'mailchimp_sync_version', '1.8.5' ); 281 | if ( $saved_version === self::$version ) { 282 | return; 283 | } 284 | 285 | if ( version_compare( $saved_version, '1.9', '<' ) ) { 286 | // Show a notice so the user can set the groups again 287 | $mailchimp_apikey = get_site_option('mailchimp_apikey', ''); 288 | $mailchimp_mailing_list = get_site_option('mailchimp_mailing_list'); 289 | $groups = get_site_option( 'mailchimp_groups' ); 290 | 291 | if ( $mailchimp_apikey && $mailchimp_mailing_list && $groups ) { 292 | update_site_option( 'mailchimp_sync_set_groups_again_notice', true ); 293 | } 294 | } 295 | 296 | update_site_option( 'mailchimp_sync_version', self::$version ); 297 | 298 | } 299 | } 300 | 301 | global $mailchimp_sync; 302 | $mailchimp_sync = WPMUDEV_MailChimp_Sync::get_instance(); 303 | 304 | function mailchimp_sync() { 305 | return WPMUDEV_MailChimp_Sync::get_instance(); 306 | } 307 | 308 | add_action( 'wp_ajax_mailchimp_dismiss_notice', 'mailchimp_dismiss_notice' ); 309 | function mailchimp_dismiss_notice() { 310 | if ( 311 | ( is_multisite() && current_user_can( 'manage_network' ) ) 312 | || ( ! is_multisite() && current_user_can( 'manage_options' ) ) 313 | ) { 314 | $option = $_POST['option']; 315 | $allowed_options = array( 316 | 'mailchimp_sync_set_groups_again_notice' 317 | ); 318 | if ( in_array( $option, $allowed_options ) ) { 319 | delete_site_option( $option ); 320 | } 321 | } 322 | } 323 | 324 | register_uninstall_hook(__FILE__, 'mailchimp_sync_uninstall' ); 325 | function mailchimp_sync_uninstall() { 326 | global $wpdb; 327 | delete_site_option( 'mailchimp_apikey' ); 328 | delete_site_option( 'mailchimp_mailing_list' ); 329 | delete_site_option( 'mailchimp_auto_opt_in' ); 330 | delete_site_option( 'mailchimp_ignore_plus' ); 331 | delete_site_option( 'mailchimp_webhooks_settings' ); 332 | delete_site_option( 'mailchimp_groups' ); 333 | delete_site_option( 'mailchimp_sync_version' ); 334 | 335 | $wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_mailchimp_list_groups%'" ); 336 | $wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_timeout_mailchimp_list_groups%'" ); 337 | 338 | $wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_mailchimp_category_interests%'" ); 339 | $wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_timeout_mailchimp_category_interests%'" ); 340 | 341 | //$wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_mailchimp_list_groups%'" ); 342 | //$wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_timeout_mailchimp_list_groups%'" ); 343 | 344 | //$wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_mailchimp_list_groups%'" ); 345 | //$wpdb->query( "DELETE FROM $wpdb->sitemeta WHERE meta_key LIKE '%transient_timeout_mailchimp_list_groups%'" ); 346 | } 347 | --------------------------------------------------------------------------------