MailChimp for WordPress - Version 1.2.1

Version Description

  • Improved: total revamp of the form field wizard, many improvements.
  • Improved: some textual improvements in the setting pages
  • Added: debug message to sign-up checkbox for WP administrators
Download this release

Release Info

Developer DvanKooten
Plugin Icon 128x128 MailChimp for WordPress
Version 1.2.1
Comparing to
See all releases

Code changes from version 1.1.5 to 1.2.1

assets/css/admin.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #mc4wp-content{ float:left; width:65%; margin-right:0; }
2
+ #mc4wp-sidebar{ float:right; width:32%; margin:0; padding:9px 0 0; }
3
+ #mc4wp-sidebar .mc4wp-box{ margin-bottom:20px; }
4
+
5
+ #mc4wp-upgrade-box { background:#efefef; border:1px solid #cecece; padding:20px; }
6
+ #mc4wp-upgrade-box h3{ margin:0; }
7
+
8
+ #mc4wp-fw h4{ margin-top:0; }
9
+ #mc4wp-fw-fields { display:none; }
10
+ #mc4wp-fw-preview { font-family: "Courier New", Courier, monospace; font-size:11px; }
11
+ #mc4wp-lists{ margin:0; }
12
+ #mc4wp-lists input{ margin-right:5px; }
13
+
14
+ .mc4wp-settings tr.pro-feature th, .mc4wp-settings tr.pro-feature td{ color:#999; }
15
+
16
+ .mc4wp-settings span.status{ display:inline-block; padding:3px 6px; color:white; font-size:12px; font-weight:bold; }
17
+ .mc4wp-settings span.positive{ background-color:green; }
18
+ .mc4wp-settings span.negative{ background-color:lightGrey; }
19
+ .mc4wp-settings table th{ text-align:left; }
20
+ .mc4wp-settings table.form-table tr td:first-child, .mc4wp-settings table.form-table tr th:first-child{ padding-left:0; }
21
+ .mc4wp-settings p.copyright-notice{ font-style:italic; }
22
+ .mc4wp-settings td.nowrap{ white-space: nowrap }
23
+ .mc4wp-settings td.desc{ font-style:italic; font-size:11px; }
24
+
25
+ .mc4wp-settings .mc4wp-wrapper{ clear:both; width:100%; display:block; }
26
+ .mc4wp-settings .mc4wp-col { float:left; margin:0 1%; padding:0; }
27
+ .mc4wp-settings .mc4wp-col-2-3{ width:64%; }
28
+ .mc4wp-settings .mc4wp-col-1-3{ width:34%; }
29
+ .mc4wp-settings .mc4wp-first{ margin-left:0; }
30
+ .mc4wp-settings .mc4wp-last{ margin-right:0; }
31
+ .mc4wp-settings .mc4wp-well{ background:#efefef; padding:10px;
32
+ border:1px solid #ccc;
33
+ -webkit-border-radius: 3px; border-radius: 3px;
34
+ -moz-border-radius: 3px; }
35
+
36
+ table.mc4wp-help, table.mc4wp-help th, table.mc4wp-help td { border: 1px solid #ddd; border-collapse: collapse; font-size: 12px; }
37
+ table.mc4wp-help th, table.mc4wp-help td { vertical-align: text-top; text-align: left; padding: 5px 10px; }
38
+ table.mc4wp-help tr:hover { background-color: #ddd; }
{css → assets/css}/checkbox.css RENAMED
File without changes
{css → assets/css}/form.css RENAMED
File without changes
{img → assets/img}/menu-icon.png RENAMED
File without changes
assets/js/admin.js ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+
3
+ $("tr.pro-feature td :radio").change(function() {
4
+ this.checked = false;
5
+ alert("This option is only available in the premium version of MailChimp for WordPress.");
6
+ });
7
+
8
+ $("tr.pro-feature label").click(function() {
9
+ alert("This option is only available in the premium version of MailChimp for WordPress.");
10
+ });
11
+
12
+
13
+ /**
14
+ * MailChimp for WordPress Field Wizard
15
+ * Created by Danny van Kooten
16
+ */
17
+ (function() {
18
+ // setup variables
19
+ var $lists = $("#mc4wp-lists input");
20
+ var $mailchimpFields = $("#mc4wp-fw-mailchimp-fields");
21
+ var $mailchimpMergeFields = $("#mc4wp-fw-mailchimp-fields .merge-fields");
22
+ var $mailchimpGroupings = $("#mc4wp-fw-mailchimp-fields .groupings");
23
+ var $wizardFields = $("#mc4wp-fw-fields");
24
+ var $value = $("#mc4wp-fw-value");
25
+ var $valueLabel = $("#mc4wp-fw-value-label");
26
+ var $multipleValues = $("#mc4wp-fw-values");
27
+ var $label = $("#mc4wp-fw-label");
28
+ var $placeholder = $("#mc4wp-fw-placeholder");
29
+ var $required = $("#mc4wp-fw-required");
30
+ var $wrapp = $("#mc4wp-fw-wrap-p");
31
+ var field = {
32
+ 'type': 'text',
33
+ 'name': ''
34
+ };
35
+ var $codePreview = $("#mc4wp-fw-preview");
36
+ // functions
37
+
38
+ // set the fields the user can choose from
39
+ function setFields()
40
+ {
41
+ // empty field select
42
+ $mailchimpFields.find('option').not('.default').remove();
43
+
44
+ // loop through checked lists
45
+ $lists.filter(':checked').each(function() {
46
+ var fields = $(this).data('fields');
47
+ var groupings = $(this).data('groupings');
48
+
49
+ // loop through merge fields from this list
50
+ for(var i = 0, fieldCount = fields.length; i < fieldCount; i++) {
51
+ var field = fields[i];
52
+
53
+ // add field to select if no similar option exists yet
54
+ if($mailchimpMergeFields.find("option[value='"+ field.tag +"']").length == 0) {
55
+
56
+ var text = (field.name.length > 40) ? field.name.substring(0, 40) + '..' : field.name;
57
+ if(field.req) { text += '*'; }
58
+
59
+ var include = false;
60
+ var triggers = [ 'name', 'email', 'website' ];
61
+ for(var i = 0; i < triggers.length; i++) {
62
+ if(field.tag.toLowerCase().indexOf(triggers[i]) != -1) {
63
+ include = true;
64
+ break;
65
+ }
66
+ }
67
+
68
+ if(include) {
69
+ var $option = $("<option />").text(text).val(field.tag).data('field', field);
70
+ } else {
71
+ var $option = $("<option />").text(text + " (Pro only)").val(field.tag).attr('disabled', 'disabled');
72
+ }
73
+
74
+ $mailchimpMergeFields.append($option);
75
+ }
76
+ }
77
+
78
+ // loop through interest groupings
79
+ for(var i = 0, groupingsCount = groupings.length; i < groupingsCount; i++) {
80
+ var grouping = groupings[i];
81
+
82
+ // add field to select if no similar option exists yet
83
+ if($mailchimpGroupings.find("option[value='"+ grouping.id +"']").length == 0) {
84
+ var text = (grouping.name.length > 40) ? grouping.name.substring(0, 40) + '..' : grouping.name;
85
+ var $option = $("<option />").text(text + " (Pro only)").val(grouping.id).attr('disabled', 'disabled');
86
+ $mailchimpGroupings.append($option);
87
+ }
88
+ }
89
+
90
+
91
+ });
92
+ }
93
+
94
+ function setPresets()
95
+ {
96
+ resetFields();
97
+
98
+ var selected = $(this).find(':selected');
99
+ if(selected.val() == 'submit') {
100
+ // setup values for submit field
101
+ field['type'] = 'submit';
102
+ $valueLabel.text("Button text");
103
+ $wizardFields.find('p.row').filter('.value, .wrap-p').show();
104
+ updateCodePreview();
105
+ } else {
106
+ var data = selected.data('field');
107
+ if(data) { return setPresetsForField(data); }
108
+ }
109
+
110
+ return;
111
+ }
112
+
113
+ function resetFields() {
114
+ $wizardFields.find('.row :input').each(function() {
115
+ if($(this).is(":checkbox")) { this.checked = false; } else { this.value = ''; }
116
+ });
117
+
118
+ $wizardFields.find('p.row').hide();
119
+ $multipleValues.find(':input').remove();
120
+ $wizardFields.show();
121
+
122
+ field['type'] = 'text';
123
+ field['name'] = '';
124
+ $valueLabel.html("Initial value <small>(optional)</small>");
125
+ }
126
+
127
+ // show available fields and fill it with some values
128
+ function setPresetsForField(data)
129
+ {
130
+
131
+ // show fields for this field type
132
+ var visibleRowsMap = {
133
+ 'default': [ 'label', 'value', 'placeholder', 'required', 'wrap-p' ],
134
+ 'select': [ 'label', 'required', 'wrap-p', 'values'],
135
+ 'radio': [ 'label', 'required', 'wrap-p', 'values'],
136
+ 'date': [ 'label', 'required', 'wrap-p', 'value']
137
+ }
138
+
139
+ var fieldTypesMap = {
140
+ 'text': 'text', 'email': 'email', 'phone': 'tel', 'address': 'text', 'number': 'number', 'url': 'url',
141
+ 'dropdown': 'select', 'date': 'date', 'birthday': 'date', 'radio': 'radio', 'checkbox': 'checkbox'
142
+ }
143
+
144
+ if(fieldTypesMap[data.field_type] != undefined) {
145
+ var fieldType = fieldTypesMap[data.field_type];
146
+ } else {
147
+ var fieldType = 'text';
148
+ }
149
+
150
+ if(visibleRowsMap[fieldType] != undefined) {
151
+ var visibleRows = visibleRowsMap[fieldType];
152
+ } else {
153
+ var visibleRows = visibleRowsMap["default"];
154
+ }
155
+
156
+ for(var i = 0, count = visibleRows.length; i < count; i++) {
157
+ $wizardFields.find('p.row.' + visibleRows[i]).show();
158
+ }
159
+
160
+ // populate fields with preset values
161
+ field['type'] = fieldType;
162
+ field['name'] = data.tag;
163
+ $placeholder.val("Your " + data.name.toLowerCase());
164
+ $label.val(data.name + ":");
165
+ if(data.req) { $required.attr('checked', true); }
166
+
167
+ // update code preview
168
+ updateCodePreview();
169
+ }
170
+
171
+ function updateCodePreview()
172
+ {
173
+ var $code = $("<div></div>");
174
+ var inputs = [];
175
+ var $input;
176
+
177
+ // build input / select / textarea element
178
+ $input = $("<input />").attr('type', field['type']);
179
+
180
+ // set name attribute
181
+ if(field.name.length > 0) {
182
+ $input.attr('name', field.name);
183
+ }
184
+
185
+ // set value
186
+ if($value.is(":visible") && $value.val().length > 0) {
187
+ if(field['type'] == 'textarea') {
188
+ $input.text($value.val());
189
+ } else {
190
+ $input.attr('value', $value.val());
191
+ }
192
+ }
193
+
194
+ // add placeholder to element
195
+ if($placeholder.is(":visible") && $placeholder.val().length > 0) {
196
+ $input.attr('placeholder', $placeholder.val());
197
+ }
198
+
199
+ // add required attribute
200
+ if($required.is(':visible:checked')) {
201
+ $input.attr('required', 'required');
202
+ }
203
+
204
+ $code.append($input);
205
+
206
+
207
+
208
+
209
+ // build label
210
+ if($label.is(":visible") && $label.val().length > 0) {
211
+ var labelTag = (field['type'] == 'radio' || field['type'] == 'checkbox') ? 'h5' : 'label';
212
+ $("<"+ labelTag +" />").text($label.val()).prependTo($code);
213
+ }
214
+
215
+ // start indenting and tabbing of code
216
+ var codePreview = $code.html();
217
+
218
+ if($wrapp.is(':visible:checked')) {
219
+ $code.wrapInner($("<p />"));
220
+
221
+ // indent code inside paragraphs (double tab)
222
+ codePreview = $code.html()
223
+ .replace(/<p>/gi, "<p>\n\t")
224
+ .replace(/<label><input /gi, "\n\t<label><input ")
225
+ .replace(/<\/label><input/gi, "</label> \n\t<input");
226
+ }
227
+
228
+ // newline after every closed element
229
+ codePreview = codePreview.replace(/></g, "> \n<");
230
+
231
+ // add code to codePreview textarea
232
+ $codePreview.val(codePreview);
233
+ }
234
+
235
+ function addCodeToFormMarkup() {
236
+
237
+ var result = false;
238
+
239
+ // try to insert in QuickTags editor at cursor position
240
+ if(typeof QTags !='undefined' && QTags.insertContent) {
241
+ result = QTags.insertContent($codePreview.val());
242
+ }
243
+
244
+ // fallback
245
+ if(!result) {
246
+ $("#mc4wpformmarkup").val($("#mc4wpformmarkup").val() + "\n" + $codePreview.val());
247
+ }
248
+ }
249
+
250
+ // setup events
251
+ $lists.change(setFields);
252
+ $mailchimpFields.change(setPresets);
253
+ $wizardFields.change(updateCodePreview);
254
+ $("#mc4wp-fw-add-to-form").click(addCodeToFormMarkup);
255
+
256
+ // init
257
+ $lists.change();
258
+
259
+ })();
260
+
261
+ })(jQuery);
262
+
css/admin.css DELETED
@@ -1,67 +0,0 @@
1
- #mc4wp_admin hr{ margin:20px 0; background-color:lightGray; border:0; height:1px; }
2
- #mc4wp_admin h2{ padding-bottom: 0; }
3
- #mc4wp_admin span.status{ padding:3px; color:white; font-size:12px; }
4
- #mc4wp_admin span.status.connected{ background-color:green; }
5
- #mc4wp_admin span.status.not_connected{ background-color:lightGrey; }
6
- #mc4wp_admin td.desc{ font-style:italic; font-size:10px; }
7
-
8
- #mc4wp_admin .alert{ border:1px solid black; padding:5px; width:auto; }
9
- #mc4wp_admin .alert.warning{ background:#FCF8E3; color:#C09853; border:1px solid #FBEED5; }
10
-
11
- #mc4wp-main-column{ float:left; width:65%; margin-right:0; }
12
- #mc4wp-secondary-column{ float:right; width:32%; margin-left:2.5%; }
13
- #mc4wp-secondary-column .mc4wp-box{ margin-bottom:20px; }
14
-
15
- /* tabs */
16
- #mc4wp-nav { clear:both; padding:0; margin:20px 0; border-bottom: 1px solid lightGray; }
17
- #mc4wp-nav li { list-style: none; margin: 0; padding:0; display: inline-block; }
18
- #mc4wp-nav li a { font-weight:bold; display:block; padding: 6px 12px; margin:0 10px -1px 0; border:1px solid lightGray; text-decoration: none; font-size:14px; }
19
- #mc4wp-nav li a.active { background: white; border-bottom: 1px solid white; color:black; }
20
- #mc4wp-tabs .mc4wp-tab{ display:none !important; }
21
- #mc4wp-tabs .mc4wp-tab.active{ display:block !important; }
22
- /* end tabs */
23
-
24
- #mc4wp-upgrade-box { border:1px solid black; background:#efefef; padding:20px; -moz-box-shadow: 0 0 5px 5px #888; -webkit-box-shadow: 0 0 5px 5px#888; box-shadow: 0 0 5px 5px #888; }
25
- #mc4wp-upgrade-box h3{ margin:0; }
26
- #mc4wp-upgrade-box ul{ list-style:square; margin-left:25px; }
27
- #mc4wp-upgrade-box li{ margin:0; }
28
-
29
- #mc4wp-fw h4{ margin-top:0; }
30
- #mc4wp-fw .mc4wp-fields { display:none; }
31
- #mc4wp-fw-preview { font-size:11px; }
32
-
33
- #mc4wp_admin table th{ text-align:left; }
34
- #mc4wp_admin table.form-table tr td:first-child, #mc4wp_admin table.form-table tr th:first-child{ padding-left:0; }
35
- #mc4wp_admin p.copyright-notice{ font-style:italic; }
36
-
37
- #mc4wp_admin .mc4wp-wrapper{ clear:both; width:100%; display:block; }
38
- #mc4wp_admin .mc4wp-col { float:left; margin:0 1%; padding:0; }
39
- #mc4wp_admin .mc4wp-col-2-3{ width:64%; }
40
- #mc4wp_admin .mc4wp-col-1-3{ width:34%; }
41
- #mc4wp_admin .mc4wp-first{ margin-left:0; }
42
- #mc4wp_admin .mc4wp-last{ margin-right:0; }
43
- #mc4wp_admin .mc4wp-well{ background:#efefef; padding:10px; border:1px solid #666; }
44
-
45
- #mc4wp_admin .upgrade-button{
46
- border:1px solid #ffad41;-webkit-box-shadow: #999999 1px 1px 1px ;-moz-box-shadow: #999999 1px 1px 1px ; box-shadow: #999999 1px 1px 1px ; -webkit-border-radius: 3px; -moz-border-radius: 3px;border-radius: 3px;padding: 12px 16px; text-decoration:none; display:inline-block;text-shadow: 1px 1px 0 rgba(51,51,51,0.3);font-weight:bold; color: #000000;
47
- background-color: #ffc579; background-image: -webkit-gradient(linear, left top, left bottom, from(#ffc579), to(#fb9d23));
48
- background-image: -webkit-linear-gradient(top, #ffc579, #fb9d23);
49
- background-image: -moz-linear-gradient(top, #ffc579, #fb9d23);
50
- background-image: -ms-linear-gradient(top, #ffc579, #fb9d23);
51
- background-image: -o-linear-gradient(top, #ffc579, #fb9d23);
52
- background-image: linear-gradient(to bottom, #ffc579, #fb9d23);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#ffc579, endColorstr=#fb9d23);
53
- }
54
-
55
- #mc4wp_admin .upgrade-button:hover{
56
- border:1px solid #ff9913;
57
- background-color: #ffaf46; background-image: -webkit-gradient(linear, left top, left bottom, from(#ffaf46), to(#e78404));
58
- background-image: -webkit-linear-gradient(top, #ffaf46, #e78404);
59
- background-image: -moz-linear-gradient(top, #ffaf46, #e78404);
60
- background-image: -ms-linear-gradient(top, #ffaf46, #e78404);
61
- background-image: -o-linear-gradient(top, #ffaf46, #e78404);
62
- background-image: linear-gradient(to bottom, #ffaf46, #e78404);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#ffaf46, endColorstr=#e78404);
63
- }
64
-
65
- table.mc4wp-help, table.mc4wp-help th, table.mc4wp-help td { border: 1px solid #ddd; border-collapse: collapse; font-size: 12px; }
66
- table.mc4wp-help th, table.mc4wp-help td { vertical-align: text-top; text-align: left; padding: 5px 10px; }
67
- table.mc4wp-help tr:hover { background-color: #ddd; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/MC4WP_Lite.php CHANGED
@@ -3,8 +3,7 @@
3
  class MC4WP_Lite
4
  {
5
  private $options = array();
6
- private $mailchimp_api = null;
7
- private static $instance, $checkbox = null, $form = null;
8
 
9
  public static function instance()
10
  {
@@ -29,74 +28,152 @@ class MC4WP_Lite
29
  return self::$form;
30
  }
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  public function __construct()
33
  {
34
  self::$instance = $this;
35
 
 
36
  $opts = $this->get_options();
37
 
 
38
  self::checkbox();
39
  self::form();
40
 
41
- if(defined('DOING_AJAX') && DOING_AJAX) {
42
- // ajax only
43
-
44
- } else {
45
  // non-ajax only
46
-
47
  if(is_admin()) {
48
- // backend non-ajax only
49
- require_once 'MC4WP_Lite_Admin.php';
50
- new MC4WP_Lite_Admin();
51
  } else {
52
- // frontend non-ajax only
53
  require 'functions.php';
54
  }
55
  }
56
  }
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  public function get_options()
59
  {
60
  if(empty($this->options)) {
61
- $defaults = array(
62
- 'mailchimp_api_key' => '',
63
- 'checkbox_label' => 'Sign me up for the newsletter!', 'checkbox_precheck' => 1, 'checkbox_css' => 0,
64
- 'checkbox_show_at_comment_form' => 0, 'checkbox_show_at_registration_form' => 0, 'checkbox_show_at_ms_form' => 0, 'checkbox_show_at_bp_form' => 0, 'checkbox_show_at_other_forms' => 0,
65
- 'checkbox_lists' => array(), 'checkbox_double_optin' => 1, 'checkbox_show_at_bbpress_forms' => 0,
66
- 'form_css' => 1, 'form_markup' => "<p>\n\t<label for=\"mc4wp_email\">Email address: </label>\n\t<input type=\"email\" id=\"mc4wp_email\" name=\"EMAIL\" required placeholder=\"Your email address\" />\n</p>\n\n<p>\n\t<input type=\"submit\" value=\"Sign up\" />\n</p>",
67
- 'form_text_success' => 'Thank you, your sign-up request was successful! Please check your e-mail inbox.', 'form_text_error' => 'Oops. Something went wrong. Please try again later.',
68
- 'form_text_invalid_email' => 'Please provide a valid email address.', 'form_text_already_subscribed' => "Given email address is already subscribed, thank you!",
69
- 'form_redirect' => '', 'form_lists' => array(), 'form_double_optin' => 1, 'form_hide_after_success' => 0
70
- );
71
-
72
- $options = get_option('mc4wp_lite');
73
- if(!$options) {
74
- // using old option key?
75
- if(($options = get_option('mc4wp')) != false) {
76
- add_option('mc4wp_lite', $options);
77
- }
78
- }
79
 
80
- $this->options = $opts = array_merge($defaults, (array) $options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
  return $this->options;
84
  }
85
 
86
- public function get_mailchimp_api()
87
- {
88
- if(!$this->mailchimp_api) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
- // Only load MailChimp API if it has not been loaded yet
91
- // other plugins may have already at this point.
92
- if(!class_exists("MCAPI")) {
93
- require_once 'MCAPI.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
-
96
- $this->mailchimp_api = new MCAPI($this->options['mailchimp_api_key']);
97
- }
98
 
99
- return $this->mailchimp_api;
 
 
 
100
  }
101
 
102
  }
3
  class MC4WP_Lite
4
  {
5
  private $options = array();
6
+ private static $instance, $checkbox = null, $form = null, $api = null, $admin = null;
 
7
 
8
  public static function instance()
9
  {
28
  return self::$form;
29
  }
30
 
31
+ public static function api()
32
+ {
33
+ if(!self::$api) {
34
+ require 'MC4WP_Lite_API.php';
35
+ $opts = self::instance()->get_options();
36
+ self::$api = new MC4WP_Lite_API($opts['general']['api_key']);
37
+ }
38
+ return self::$api;
39
+ }
40
+
41
+ public static function admin()
42
+ {
43
+ if(!self::$admin) {
44
+ require_once 'MC4WP_Lite_Admin.php';
45
+ self::$admin = new MC4WP_Lite_Admin();
46
+ }
47
+ return self::$admin;
48
+ }
49
  public function __construct()
50
  {
51
  self::$instance = $this;
52
 
53
+ $this->backwards_compatibility();
54
  $opts = $this->get_options();
55
 
56
+ // setup the code
57
  self::checkbox();
58
  self::form();
59
 
60
+ if(!defined('DOING_AJAX') || !DOING_AJAX) {
 
 
 
61
  // non-ajax only
 
62
  if(is_admin()) {
63
+ // backend non-ajax only
64
+ self::admin();
 
65
  } else {
66
+ // frontend non-ajax only
67
  require 'functions.php';
68
  }
69
  }
70
  }
71
 
72
+ private function get_default_options()
73
+ {
74
+ return array(
75
+ 'general' => array(
76
+ 'api_key' => ''
77
+ ),
78
+ 'checkbox' => array(
79
+ 'label' => 'Sign me up for the newsletter!',
80
+ 'precheck' => 1,
81
+ 'css' => 1,
82
+ 'show_at_comment_form' => 0,
83
+ 'show_at_registration_form' => 0,
84
+ 'show_at_multisite_form' => 0,
85
+ 'show_at_buddypress_form' => 0,
86
+ 'show_at_bbpress_forms' => 0,
87
+ 'show_at_other_forms' => 0,
88
+ 'lists' => array(),
89
+ 'double_optin' => 1
90
+ ),
91
+ 'form' => array(
92
+ 'css' => 1,
93
+ 'markup' => "<p>\n\t<label for=\"mc4wp_email\">Email address: </label>\n\t<input type=\"email\" id=\"mc4wp_email\" name=\"EMAIL\" required placeholder=\"Your email address\" />\n</p>\n\n<p>\n\t<input type=\"submit\" value=\"Sign up\" />\n</p>",
94
+ 'text_success' => 'Thank you, your sign-up request was successful! Please check your e-mail inbox.',
95
+ 'text_error' => 'Oops. Something went wrong. Please try again later.',
96
+ 'text_invalid_email' => 'Please provide a valid email address.',
97
+ 'text_already_subscribed' => "Given email address is already subscribed, thank you!",
98
+ 'redirect' => '',
99
+ 'lists' => array(),
100
+ 'double_optin' => 1,
101
+ 'hide_after_success' => 0
102
+ )
103
+ );
104
+ }
105
+
106
  public function get_options()
107
  {
108
  if(empty($this->options)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
+ $defaults = $this->get_default_options();
111
+ $db_keys_option_keys = array(
112
+ 'mc4wp_lite' => 'general',
113
+ 'mc4wp_lite_checkbox' => 'checkbox',
114
+ 'mc4wp_lite_form' => 'form'
115
+ );
116
+
117
+ foreach($db_keys_option_keys as $db_key => $option_key) {
118
+ $option = get_option($db_key);
119
+
120
+ // add option to database to prevent query on every pageload
121
+ if($option == false) { add_option($db_key, $defaults[$option_key]); }
122
+
123
+ $this->options[$option_key] = array_merge($defaults[$option_key], (array) $option);
124
+ }
125
  }
126
 
127
  return $this->options;
128
  }
129
 
130
+ private function backwards_compatibility()
131
+ {
132
+ $options = get_option('mc4wp_lite');
133
+
134
+ // transfer old options to new option system
135
+ if(isset($options['mailchimp_api_key'])) {
136
+
137
+ // delete transients
138
+ delete_transient('mc4wp_mailchimp_lists');
139
+ delete_transient('mc4wp_mailchimp_lists_fallback');
140
+
141
+ $new_options = array(
142
+ 'general' => array(),
143
+ 'checkbox' => array(),
144
+ 'form' => array()
145
+ );
146
+
147
+ $new_options['general']['api_key'] = $options['mailchimp_api_key'];
148
 
149
+ foreach($options as $key => $value) {
150
+ $_pos = strpos($key, '_');
151
+
152
+ $first_key = substr($key, 0, $_pos);
153
+ $second_key = substr($key, $_pos + 1);
154
+
155
+ if(isset($new_options[$first_key])) {
156
+
157
+ // change option name
158
+ if($second_key == 'show_at_bp_form') {
159
+ $second_key = 'show_at_buddypress_form';
160
+ }
161
+
162
+ // change option name
163
+ if($second_key == 'show_at_ms_form') {
164
+ $second_key = 'show_at_multisite_form';
165
+ }
166
+
167
+ // set value into new option name
168
+ $new_options[$first_key][$second_key] = $value;
169
+ }
170
+
171
  }
 
 
 
172
 
173
+ update_option('mc4wp_lite', $new_options['general']);
174
+ update_option('mc4wp_lite_checkbox', $new_options['checkbox']);
175
+ update_option('mc4wp_lite_form', $new_options['form']);
176
+ }
177
  }
178
 
179
  }
includes/MC4WP_Lite_API.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class MC4WP_Lite_API {
4
+
5
+ private $api_url = 'https://api.mailchimp.com/2.0/';
6
+ private $api_key = '';
7
+ private $error_message = '';
8
+ private $connected = null;
9
+
10
+ public function __construct($api_key)
11
+ {
12
+ $this->api_key = $api_key;
13
+
14
+ if(strpos($api_key, '-') !== false) {
15
+ $this->api_url = 'https://' . substr($api_key, -3) . '.api.mailchimp.com/2.0/';
16
+ }
17
+ }
18
+
19
+ public function is_connected()
20
+ {
21
+ if($this->connected === null) {
22
+ $result = $this->call('helper/ping');
23
+ $this->connected = ($result && isset($result->msg) && $result->msg === "Everything's Chimpy!");
24
+ }
25
+
26
+ return $this->connected;
27
+ }
28
+
29
+ public function subscribe($list_id, $email, array $merge_vars = array(), $email_type = 'html', $double_optin = true, $update_existing = false, $replace_interests = true, $send_welcome = false )
30
+ {
31
+ $data = array(
32
+ 'id' => $list_id,
33
+ 'email' => array( 'email' => $email),
34
+ 'merge_vars' => $merge_vars,
35
+ 'email_type' => $email_type,
36
+ 'double_optin' => $double_optin,
37
+ 'update_existing' => $update_existing,
38
+ 'replace_interests' => $replace_interests,
39
+ 'send_welcome' => $send_welcome
40
+ );
41
+
42
+ $result = $this->call('lists/subscribe', $data);
43
+
44
+ if($result) {
45
+
46
+ if(!isset($result->error)) {
47
+ return true;
48
+ } else {
49
+ // check error
50
+ if($result->code == 214) { return 'already_subscribed'; }
51
+
52
+ // store error message
53
+ $this->error_message = $result->error;
54
+ return 'error';
55
+ }
56
+
57
+ } else {
58
+ return 'error';
59
+ }
60
+ }
61
+
62
+ public function get_list_groupings($list_id)
63
+ {
64
+ $result = $this->call('lists/interest-groupings', array('id' => $list_id) );
65
+ if($result && is_array($result)) {
66
+ return $result;
67
+ } else {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ public function get_lists()
73
+ {
74
+ $result = $this->call('lists/list');
75
+
76
+ if($result && isset($result->data)) {
77
+ return $result->data;
78
+ } else {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ public function get_lists_with_merge_vars($list_ids)
84
+ {
85
+ $result = $this->call('lists/merge-vars', array('id' => $list_ids));
86
+
87
+ if($result && isset($result->data)) {
88
+ return $result->data;
89
+ } else {
90
+ return false;
91
+ }
92
+ }
93
+
94
+ private function call($method, array $data = array())
95
+ {
96
+
97
+ $data['apikey'] = $this->api_key;
98
+
99
+ $response = wp_remote_post($this->api_url . $method . '.json', array(
100
+ 'body' => json_encode($data),
101
+ 'timeout' => 10,
102
+ 'headers' => array('Accept-Encoding' => ''),
103
+ 'sslverify' => false
104
+ )
105
+ );
106
+
107
+ if(is_wp_error($response)) {
108
+ return false;
109
+ } else {
110
+ // dirty fix for older WP version
111
+ if($method == 'helper/ping' && isset($response['headers']['content-length']) && (int) $response['headers']['content-length'] == '44') {
112
+ return (object) array( 'msg' => "Everything's Chimpy!");
113
+ }
114
+
115
+ $body = wp_remote_retrieve_body($response);
116
+ return json_decode($body);
117
+ }
118
+ }
119
+
120
+ public function has_error()
121
+ {
122
+ return (!empty($this->error_message));
123
+ }
124
+
125
+ public function get_error_message()
126
+ {
127
+ return $this->error_message;
128
+ }
129
+
130
+ }
includes/MC4WP_Lite_Admin.php CHANGED
@@ -12,12 +12,19 @@ class MC4WP_Lite_Admin
12
  add_action('admin_menu', array($this, 'build_menu'));
13
  add_action( 'admin_enqueue_scripts', array($this, 'load_css_and_js') );
14
 
15
- register_activation_hook( 'mailchimp-for-wp-pro/mailchimp-for-wp-pro.php', array($this, 'on_activation') );
 
16
 
17
  add_filter("plugin_action_links_mailchimp-for-wp/mailchimp-for-wp.php", array($this, 'add_settings_link'));
 
 
 
 
 
 
18
  }
19
 
20
- public function on_activation()
21
  {
22
  delete_transient('mc4wp_mailchimp_lists');
23
  delete_transient('mc4wp_mailchimp_lists_fallback');
@@ -25,7 +32,7 @@ class MC4WP_Lite_Admin
25
 
26
  public function add_settings_link($links)
27
  {
28
- $settings_link = '<a href="admin.php?page=mailchimp-for-wp">Settings</a>';
29
  $upgrade_link = '<a href="http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/">Upgrade to Pro</a>';
30
  array_unshift($links, $upgrade_link, $settings_link);
31
  return $links;
@@ -33,7 +40,9 @@ class MC4WP_Lite_Admin
33
 
34
  public function register_settings()
35
  {
36
- register_setting('mc4wp_options_group', 'mc4wp_lite', array($this, 'validate_options'));
 
 
37
  }
38
 
39
  public function validate_options($opts)
@@ -43,22 +52,24 @@ class MC4WP_Lite_Admin
43
 
44
  public function build_menu()
45
  {
46
- $page = add_menu_page('MailChimp for WP Lite', 'MailChimp for WP Lite', 'manage_options', 'mailchimp-for-wp', array($this, 'page_dashboard'), plugins_url('mailchimp-for-wp/img/menu-icon.png'));
 
 
 
 
 
47
  }
48
 
49
  public function load_css_and_js($hook)
50
  {
51
- if($hook != 'toplevel_page_mailchimp-for-wp') { return false; }
52
-
53
- wp_register_script('mc4wp-admin-js', plugins_url('mailchimp-for-wp/js/admin.js'), array('jquery'), false, true);
54
 
55
  // css
56
- wp_enqueue_style( 'mc4wp-admin-css', plugins_url('mailchimp-for-wp/css/admin.css') );
57
 
58
  // js
 
59
  wp_enqueue_script( array('jquery', 'mc4wp-admin-js') );
60
- $translation_array = array( 'admin_page' => get_admin_url(null, 'admin.php?page=mailchimp-for-wp') );
61
- wp_localize_script( 'mc4wp-admin-js', 'mc4wp_urls', $translation_array );
62
  }
63
 
64
  public function get_checkbox_compatible_plugins()
@@ -75,72 +86,107 @@ class MC4WP_Lite_Admin
75
  return $checkbox_plugins;
76
  }
77
 
78
- public function page_dashboard()
79
  {
80
- $opts = $this->options;
81
- $api = $this->get_mailchimp_api();
82
 
83
- if(empty($opts['mailchimp_api_key'])) {
 
 
 
 
 
84
  $connected = false;
85
  } else {
86
- $connected = ($api->ping() === "Everything's Chimpy!");
87
  }
88
 
89
- if($connected) {
90
- $lists = $this->get_mailchimp_lists();
91
- }
92
-
93
- // tab shit
94
- $tabs = array('api-settings', 'checkbox-settings', 'form-settings');
95
- $tab = (isset($_GET['tab'])) ? $_GET['tab'] : 'api-settings';
96
 
97
- require 'views/dashboard.php';
 
 
 
 
 
98
  }
99
 
100
- private function get_mailchimp_api()
101
  {
102
- return MC4WP_Lite::instance()->get_mailchimp_api();
 
 
 
103
  }
104
 
105
- public function get_mailchimp_lists($refresh_cache = false)
 
 
 
 
106
  {
107
- $lists = get_transient( 'mc4wp_mailchimp_lists' );
108
-
109
- $refresh_cache = (isset($_REQUEST['renew-cached-data'])) ? true : $refresh_cache;
110
 
111
- if($refresh_cache || !$lists) {
 
 
 
112
 
 
113
  // make api request for lists
114
- $api = $this->get_mailchimp_api();
115
- $lists_data = $api->lists();
116
- $lists = array();
 
 
 
 
 
 
 
 
 
 
 
117
 
118
- if($lists_data && isset($lists_data['data'])) {
 
 
 
119
 
120
- foreach($lists_data['data'] as $l) {
121
- $lists[$l['id']] = array(
122
- 'id' => $l['id'],
123
- 'name' => $l['name']
124
- );
125
  }
126
 
 
127
  if(isset($_REQUEST['renew-cached-data'])) {
128
- // add notice
129
- add_settings_error("mc4wp", "cache-renewed", 'MailChimp cache renewed.', 'updated' );
 
 
 
130
  }
131
 
132
  // store lists in transients
133
- set_transient('mc4wp_mailchimp_lists', $lists, 3600); // 1 hour
134
  set_transient('mc4wp_mailchimp_lists_fallback', $lists, 1209600); // 2 weeks
 
135
  } else {
136
  // api request failed, get fallback data (with longer lifetime)
137
- $lists = get_transient('mc4wp_mailchimp_lists_fallback');
138
- if(!$lists) { return array(); }
139
  }
140
 
141
  }
142
 
143
- return $lists;
144
  }
145
 
146
  }
12
  add_action('admin_menu', array($this, 'build_menu'));
13
  add_action( 'admin_enqueue_scripts', array($this, 'load_css_and_js') );
14
 
15
+ register_activation_hook( 'mailchimp-for-wp/mailchimp-for-wp.php', array($this, 'delete_transients') );
16
+ register_deactivation_hook( 'mailchimp-for-wp-pro/mailchimp-for-wp-pro.php', array($this, 'delete_transients') );
17
 
18
  add_filter("plugin_action_links_mailchimp-for-wp/mailchimp-for-wp.php", array($this, 'add_settings_link'));
19
+
20
+ // did the user click on upgrade to pro link?
21
+ if(isset($_GET['page']) && $_GET['page'] == 'mc4wp-lite-upgrade' && !headers_sent()) {
22
+ header("Location: http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/");
23
+ exit;
24
+ }
25
  }
26
 
27
+ public function delete_transients()
28
  {
29
  delete_transient('mc4wp_mailchimp_lists');
30
  delete_transient('mc4wp_mailchimp_lists_fallback');
32
 
33
  public function add_settings_link($links)
34
  {
35
+ $settings_link = '<a href="admin.php?page=mc4wp-lite">Settings</a>';
36
  $upgrade_link = '<a href="http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/">Upgrade to Pro</a>';
37
  array_unshift($links, $upgrade_link, $settings_link);
38
  return $links;
40
 
41
  public function register_settings()
42
  {
43
+ register_setting('mc4wp_lite_settings', 'mc4wp_lite', array($this, 'validate_options'));
44
+ register_setting('mc4wp_lite_checkbox_settings', 'mc4wp_lite_checkbox', array($this, 'validate_options'));
45
+ register_setting('mc4wp_lite_form_settings', 'mc4wp_lite_form', array($this, 'validate_options'));
46
  }
47
 
48
  public function validate_options($opts)
52
 
53
  public function build_menu()
54
  {
55
+ add_menu_page('MailChimp for WP Lite', 'MailChimp for WP Lite', 'manage_options', 'mc4wp-lite', array($this, 'show_api_settings'), plugins_url('mailchimp-for-wp/assets/img/menu-icon.png'));
56
+ add_submenu_page('mc4wp-lite', 'API Settings - MailChimp for WP Lite', 'MailChimp Settings', 'manage_options', 'mc4wp-lite', array($this, 'show_api_settings'));
57
+ add_submenu_page('mc4wp-lite', 'Checkbox Settings - MailChimp for WP Lite', 'Checkboxes', 'manage_options', 'mc4wp-lite-checkbox-settings', array($this, 'show_checkbox_settings'));
58
+ add_submenu_page('mc4wp-lite', 'Form Settings - MailChimp for WP Lite', 'Forms', 'manage_options', 'mc4wp-lite-form-settings', array($this, 'show_form_settings'));
59
+ add_submenu_page('mc4wp-lite', 'Upgrade to Pro - MailChimp for WP Lite', 'Upgrade to Pro', 'manage_options', 'mc4wp-lite-upgrade', array($this, 'redirect_to_pro'));
60
+
61
  }
62
 
63
  public function load_css_and_js($hook)
64
  {
65
+ if(!isset($_GET['page']) || stristr($_GET['page'], 'mc4wp-lite') == false) { return; }
 
 
66
 
67
  // css
68
+ wp_enqueue_style( 'mc4wp-admin-css', plugins_url('mailchimp-for-wp/assets/css/admin.css') );
69
 
70
  // js
71
+ wp_register_script('mc4wp-admin-js', plugins_url('mailchimp-for-wp/assets/js/admin.js'), array('jquery'), false, true);
72
  wp_enqueue_script( array('jquery', 'mc4wp-admin-js') );
 
 
73
  }
74
 
75
  public function get_checkbox_compatible_plugins()
86
  return $checkbox_plugins;
87
  }
88
 
89
+ public function redirect_to_pro()
90
  {
91
+ ?><script>window.location.replace('http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/'); </script><?php
92
+ }
93
 
94
+ public function show_api_settings()
95
+ {
96
+ $opts = $this->options['general'];
97
+ $tab = 'api-settings';
98
+
99
+ if(empty($opts['api_key'])) {
100
  $connected = false;
101
  } else {
102
+ $connected = (MC4WP_Lite::api()->is_connected());
103
  }
104
 
105
+ $lists = $this->get_mailchimp_lists();
106
+ require 'views/api-settings.php';
107
+ }
 
 
 
 
108
 
109
+ public function show_checkbox_settings()
110
+ {
111
+ $opts = $this->options['checkbox'];
112
+ $lists = $this->get_mailchimp_lists();
113
+ $tab = 'checkbox-settings';
114
+ require 'views/checkbox-settings.php';
115
  }
116
 
117
+ public function show_form_settings()
118
  {
119
+ $opts = $this->options['form'];
120
+ $lists = $this->get_mailchimp_lists();
121
+ $tab = 'form-settings';
122
+ require 'views/form-settings.php';
123
  }
124
 
125
+ /**
126
+ * Get MailChimp lists
127
+ * Try cache first, then try API, then try fallback cache.
128
+ */
129
+ private function get_mailchimp_lists()
130
  {
131
+ $cached_lists = get_transient( 'mc4wp_mailchimp_lists' );
132
+ $refresh_cache = (isset($_REQUEST['renew-cached-data']));
 
133
 
134
+ // force cache refresh if merge_vars are not set
135
+ if($cached_lists && !isset($cached_lists[0]->merge_vars)) {
136
+ $refresh_cache = true;
137
+ }
138
 
139
+ if($refresh_cache || !$cached_lists) {
140
  // make api request for lists
141
+ $api = MC4WP_Lite::api();
142
+ $lists = $api->get_lists();
143
+
144
+ if($lists) {
145
+
146
+ $list_ids = array();
147
+ foreach($lists as $key => $list) {
148
+ $list_ids[] = $list->id;
149
+ $lists[$key]->merge_vars = array();
150
+ $lists[$key]->interest_groupings = array();
151
+ }
152
+
153
+ // get lists including merge vars
154
+ $lists = $api->get_lists_with_merge_vars($list_ids);
155
 
156
+ // get interest groupings for each list
157
+ if($lists) {
158
+ foreach($lists as $key => $list) {
159
+ $lists[$key]->interest_groupings = array();
160
 
161
+ $result = $api->get_list_groupings($list->id);
162
+ if($result) {
163
+ $lists[$key]->interest_groupings = $result;
164
+ }
165
+ }
166
  }
167
 
168
+ // cache renewal triggered manually?
169
  if(isset($_REQUEST['renew-cached-data'])) {
170
+ if($lists) {
171
+ add_settings_error("mc4wp", "cache-renewed", 'Renewed MailChimp cache.', 'updated' );
172
+ } else {
173
+ add_settings_error("mc4wp", "cache-renew-failed", 'Failed to renew MailChimp cache - please try again later.' );
174
+ }
175
  }
176
 
177
  // store lists in transients
178
+ set_transient('mc4wp_mailchimp_lists', $lists, (24 * 3600)); // 1 day
179
  set_transient('mc4wp_mailchimp_lists_fallback', $lists, 1209600); // 2 weeks
180
+ return $lists;
181
  } else {
182
  // api request failed, get fallback data (with longer lifetime)
183
+ $cached_lists = get_transient('mc4wp_mailchimp_lists_fallback');
184
+ if(!$cached_lists) { return array(); }
185
  }
186
 
187
  }
188
 
189
+ return $cached_lists;
190
  }
191
 
192
  }
includes/MC4WP_Lite_Checkbox.php CHANGED
@@ -2,23 +2,22 @@
2
 
3
  class MC4WP_Lite_Checkbox
4
  {
5
- private $options = array();
6
  private $showed_checkbox = false;
7
 
8
  public function __construct()
9
  {
10
- $this->options = $opts = MC4WP_Lite::instance()->get_options();
11
 
12
  add_action('init', array($this, 'on_init'));
13
 
14
  // load checkbox css if necessary
15
- if($this->options['checkbox_css'] == 1) {
16
  add_action( 'wp_enqueue_scripts', array($this, 'load_stylesheet') );
17
  add_action( 'login_enqueue_scripts', array($this, 'load_stylesheet') );
18
  }
19
 
20
  /* Comment Form Actions */
21
- if($opts['checkbox_show_at_comment_form']) {
22
  // hooks for checking if we should subscribe the commenter
23
  add_action('comment_post', array($this, 'subscribe_from_comment'), 20, 2);
24
 
@@ -28,19 +27,19 @@ class MC4WP_Lite_Checkbox
28
  }
29
 
30
  /* Registration Form Actions */
31
- if($opts['checkbox_show_at_registration_form']) {
32
  add_action('register_form',array($this, 'output_checkbox'),20);
33
  add_action('user_register',array($this, 'subscribe_from_registration'), 80, 1);
34
  }
35
 
36
  /* BuddyPress Form Actions */
37
- if($opts['checkbox_show_at_bp_form']) {
38
  add_action('bp_before_registration_submit_buttons', array($this, 'output_checkbox'), 20);
39
  add_action('bp_complete_signup', array($this, 'subscribe_from_buddypress'), 20);
40
  }
41
 
42
  /* Multisite Form Actions */
43
- if($opts['checkbox_show_at_ms_form']) {
44
  add_action('signup_extra_fields', array($this, 'output_checkbox'), 20);
45
  add_action('signup_blogform', array($this, 'add_multisite_hidden_checkbox'), 20);
46
  add_action('wpmu_activate_blog', array($this, 'on_multisite_blog_signup'), 20, 5);
@@ -50,7 +49,7 @@ class MC4WP_Lite_Checkbox
50
  }
51
 
52
  /* bbPress actions */
53
- if($opts['checkbox_show_at_bbpress_forms']) {
54
  add_action('bbp_theme_after_topic_form_subscriptions', array($this, 'output_checkbox'), 10);
55
  add_action('bbp_theme_after_reply_form_subscription', array($this, 'output_checkbox'), 10);
56
  add_action('bbp_theme_anonymous_form_extras_bottom', array($this, 'output_checkbox'), 10);
@@ -59,12 +58,18 @@ class MC4WP_Lite_Checkbox
59
  }
60
 
61
  /* Other actions... catch-all */
62
- if($opts['checkbox_show_at_other_forms']) {
63
  add_action('init', array($this, 'subscribe_from_whatever'));
64
  }
65
 
66
  }
67
 
 
 
 
 
 
 
68
  public function on_init()
69
  {
70
  if(function_exists("wpcf7_add_shortcode")) {
@@ -75,9 +80,9 @@ class MC4WP_Lite_Checkbox
75
 
76
  public function get_checkbox($args = array())
77
  {
78
- $opts = $this->options;
79
- $label = isset($args['labels'][0]) ? $args['labels'][0] : $opts['checkbox_label'];
80
- $checked = $opts['checkbox_precheck'] ? "checked" : '';
81
  $content = "\n<!-- Checkbox by MailChimp for WP plugin v". MC4WP_LITE_VERSION ." - http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/ -->\n";
82
  $content .= '<p id="mc4wp-checkbox">';
83
  $content .= '<input type="checkbox" name="mc4wp-do-subscribe" id="mc4wp-checkbox-input" value="1" '. $checked . ' />';
@@ -96,7 +101,7 @@ class MC4WP_Lite_Checkbox
96
 
97
  public function load_stylesheet()
98
  {
99
- wp_enqueue_style( 'mc4wp-checkbox-reset', plugins_url('mailchimp-for-wp/css/checkbox.css') );
100
  }
101
 
102
 
@@ -295,10 +300,10 @@ class MC4WP_Lite_Checkbox
295
 
296
  public function subscribe($email, array $merge_vars = array())
297
  {
298
- $api = MC4WP_Lite::instance()->get_mailchimp_api();
299
- $opts = $this->options;
300
 
301
- $lists = $opts['checkbox_lists'];
302
 
303
  if(empty($lists)) {
304
  return 'no_lists_selected';
@@ -318,20 +323,25 @@ class MC4WP_Lite_Checkbox
318
  }
319
 
320
  foreach($lists as $list) {
321
- $result = $api->listSubscribe($list, $email, $merge_vars, 'html', $opts['checkbox_double_optin']);
322
- }
323
-
324
- if($api->errorCode) {
325
-
326
- if($api->errorCode == 214) {
327
- return 'already_subscribed';
328
- }
329
-
330
- return 'error';
331
  }
332
 
333
- // flawed
334
- // this will only return the result of the last list a subscribe attempt has been sent to
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  return $result;
336
  }
337
 
2
 
3
  class MC4WP_Lite_Checkbox
4
  {
 
5
  private $showed_checkbox = false;
6
 
7
  public function __construct()
8
  {
9
+ $opts = $this->get_options();
10
 
11
  add_action('init', array($this, 'on_init'));
12
 
13
  // load checkbox css if necessary
14
+ if($opts['css'] == 1) {
15
  add_action( 'wp_enqueue_scripts', array($this, 'load_stylesheet') );
16
  add_action( 'login_enqueue_scripts', array($this, 'load_stylesheet') );
17
  }
18
 
19
  /* Comment Form Actions */
20
+ if($opts['show_at_comment_form']) {
21
  // hooks for checking if we should subscribe the commenter
22
  add_action('comment_post', array($this, 'subscribe_from_comment'), 20, 2);
23
 
27
  }
28
 
29
  /* Registration Form Actions */
30
+ if($opts['show_at_registration_form']) {
31
  add_action('register_form',array($this, 'output_checkbox'),20);
32
  add_action('user_register',array($this, 'subscribe_from_registration'), 80, 1);
33
  }
34
 
35
  /* BuddyPress Form Actions */
36
+ if($opts['show_at_buddypress_form']) {
37
  add_action('bp_before_registration_submit_buttons', array($this, 'output_checkbox'), 20);
38
  add_action('bp_complete_signup', array($this, 'subscribe_from_buddypress'), 20);
39
  }
40
 
41
  /* Multisite Form Actions */
42
+ if($opts['show_at_multisite_form']) {
43
  add_action('signup_extra_fields', array($this, 'output_checkbox'), 20);
44
  add_action('signup_blogform', array($this, 'add_multisite_hidden_checkbox'), 20);
45
  add_action('wpmu_activate_blog', array($this, 'on_multisite_blog_signup'), 20, 5);
49
  }
50
 
51
  /* bbPress actions */
52
+ if($opts['show_at_bbpress_forms']) {
53
  add_action('bbp_theme_after_topic_form_subscriptions', array($this, 'output_checkbox'), 10);
54
  add_action('bbp_theme_after_reply_form_subscription', array($this, 'output_checkbox'), 10);
55
  add_action('bbp_theme_anonymous_form_extras_bottom', array($this, 'output_checkbox'), 10);
58
  }
59
 
60
  /* Other actions... catch-all */
61
+ if($opts['show_at_other_forms']) {
62
  add_action('init', array($this, 'subscribe_from_whatever'));
63
  }
64
 
65
  }
66
 
67
+ public function get_options()
68
+ {
69
+ $options = MC4WP_Lite::instance()->get_options();
70
+ return $options['checkbox'];
71
+ }
72
+
73
  public function on_init()
74
  {
75
  if(function_exists("wpcf7_add_shortcode")) {
80
 
81
  public function get_checkbox($args = array())
82
  {
83
+ $opts = $this->get_options();
84
+ $label = isset($args['labels'][0]) ? $args['labels'][0] : $opts['label'];
85
+ $checked = $opts['precheck'] ? "checked" : '';
86
  $content = "\n<!-- Checkbox by MailChimp for WP plugin v". MC4WP_LITE_VERSION ." - http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/ -->\n";
87
  $content .= '<p id="mc4wp-checkbox">';
88
  $content .= '<input type="checkbox" name="mc4wp-do-subscribe" id="mc4wp-checkbox-input" value="1" '. $checked . ' />';
101
 
102
  public function load_stylesheet()
103
  {
104
+ wp_enqueue_style( 'mc4wp-checkbox-reset', plugins_url('mailchimp-for-wp/assets/css/checkbox.css') );
105
  }
106
 
107
 
300
 
301
  public function subscribe($email, array $merge_vars = array())
302
  {
303
+ $api = MC4WP_Lite::api();
304
+ $opts = $this->get_options();
305
 
306
+ $lists = $opts['lists'];
307
 
308
  if(empty($lists)) {
309
  return 'no_lists_selected';
323
  }
324
 
325
  foreach($lists as $list) {
326
+ $result = $api->subscribe($list, $email, $merge_vars, 'html', $opts['double_optin']);
 
 
 
 
 
 
 
 
 
327
  }
328
 
329
+ // check if result succeeded, show debug message to administrators
330
+ if($result !== true && $api->has_error() && current_user_can('manage_options'))
331
+ {
332
+ wp_die("
333
+ <h3>MailChimp for WP - Error</h3>
334
+ <p>The MailChimp server returned the following error message as a response to our sign-up request:</p>
335
+ <pre>" . $api->get_error_message() . "</pre>
336
+ <p>This is the data that was sent to MailChimp: </p>
337
+ <strong>Email</strong>
338
+ <pre>{$email}</pre>
339
+ <strong>Merge variables</strong>
340
+ <pre>" . print_r($merge_vars, true) . "</pre>
341
+ <p style=\"font-style:italic; font-size:12px; \">This message is only visible to administrators for debugging purposes.</p>
342
+ ", "Error - MailChimp for WP", array('back_link' => true));
343
+ }
344
+
345
  return $result;
346
  }
347
 
includes/MC4WP_Lite_Form.php CHANGED
@@ -2,7 +2,6 @@
2
 
3
  class MC4WP_Lite_Form
4
  {
5
- private $options;
6
  private $form_instance_number = 1;
7
  private $error = null;
8
  private $success = false;
@@ -10,9 +9,9 @@ class MC4WP_Lite_Form
10
 
11
  public function __construct()
12
  {
13
- $this->options = $opts = MC4WP_Lite::instance()->get_options();
14
 
15
- if($opts['form_css']) {
16
  add_action( 'wp_enqueue_scripts', array($this, 'load_stylesheet') );
17
  }
18
 
@@ -26,18 +25,22 @@ class MC4WP_Lite_Form
26
  $this->ensure_backwards_compatibility();
27
  add_action('init', array($this, 'submit'));
28
  }
 
29
 
30
-
 
 
 
31
  }
32
 
33
  public function load_stylesheet()
34
  {
35
- wp_enqueue_style( 'mc4wp-form-reset', plugins_url('mailchimp-for-wp/css/form.css') );
36
  }
37
 
38
  public function output_form($atts, $content = null)
39
  {
40
- $opts = $this->options;
41
 
42
  // add some useful css classes
43
  $css_classes = ' ';
@@ -47,10 +50,9 @@ class MC4WP_Lite_Form
47
  $content = "\n<!-- Form by MailChimp for WP plugin v". MC4WP_LITE_VERSION ." - http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/ -->\n";
48
  $content .= '<form method="post" action="'. $this->get_current_url() .'#mc4wp-form-'. $this->form_instance_number .'" id="mc4wp-form-'.$this->form_instance_number.'" class="mc4wp-form form'.$css_classes.'">';
49
 
50
-
51
  // maybe hide the form
52
- if(!($this->success && $opts['form_hide_after_success'])) {
53
- $form_markup = __($this->options['form_markup']);
54
  // replace special values
55
  $form_markup = $this->replace_form_variables($form_markup);
56
 
@@ -62,27 +64,26 @@ class MC4WP_Lite_Form
62
  $content .= '<input type="hidden" name="mc4wp_form_instance" value="'. $this->form_instance_number .'" />';
63
  }
64
 
65
-
66
  if($this->form_instance_number == $this->submitted_form_instance) {
67
 
68
  if($this->success) {
69
- $content .= '<div class="mc4wp-alert mc4wp-success">' . __($opts['form_text_success']) . '</div>';
70
  } elseif($this->error) {
71
 
72
- $api = MC4WP_Lite::instance()->get_mailchimp_api();
73
  $e = $this->error;
74
 
75
  if($e == 'already_subscribed') {
76
- $text = (empty($opts['form_text_already_subscribed'])) ? $api->errorMessage : $opts['form_text_already_subscribed'];
77
  $content .= '<div class="mc4wp-alert mc4wp-notice">'. __($text) .'</div>';
78
- } elseif(isset($opts['form_text_' . $e]) && !empty($opts['form_text_'. $e] )) {
79
- $content .= '<div class="mc4wp-alert mc4wp-error">' . __($opts['form_text_' . $e]) . '</div>';
80
  }
81
 
82
  if(current_user_can('manage_options')) {
83
 
84
- if($api->errorCode && !empty($api->errorMessage)) {
85
- $content .= '<div class="mc4wp-alert mc4wp-error"><strong>Admin notice:</strong> '. $api->errorMessage . '</div>';
86
  }
87
  }
88
 
@@ -90,8 +91,8 @@ class MC4WP_Lite_Form
90
  // endif
91
  }
92
 
93
- if(current_user_can('manage_options') && empty($opts['form_lists'])) {
94
- $content .= '<div class="mc4wp-alert mc4wp-error"><strong>Admin notice:</strong> you have not selected a MailChimp list for this sign-up form to subscribe to yet. <a href="'. get_admin_url(null, 'admin.php?page=mailchimp-for-wp&tab=form-settings') .'">Edit your form settings</a> and select at least 1 list.</div>';
95
  }
96
 
97
  $content .= "</form>";
@@ -105,7 +106,7 @@ class MC4WP_Lite_Form
105
 
106
  public function submit()
107
  {
108
- $opts = $this->options;
109
  $this->submitted_form_instance = (int) $_POST['mc4wp_form_instance'];
110
 
111
  if(!isset($_POST['EMAIL']) || !is_email($_POST['EMAIL'])) {
@@ -174,8 +175,8 @@ class MC4WP_Lite_Form
174
  $this->success = true;
175
 
176
  // check if we want to redirect the visitor
177
- if(!empty($opts['form_redirect'])) {
178
- wp_redirect($opts['form_redirect']);
179
  exit;
180
  }
181
 
@@ -272,10 +273,10 @@ class MC4WP_Lite_Form
272
 
273
  public function subscribe($email, array $merge_vars = array())
274
  {
275
- $api = MC4WP_Lite::instance()->get_mailchimp_api();
276
- $opts = $this->options;
277
 
278
- $lists = $opts['form_lists'];
279
 
280
  if(empty($lists)) {
281
  return 'no_lists_selected';
@@ -295,16 +296,14 @@ class MC4WP_Lite_Form
295
  }
296
 
297
  foreach($lists as $list) {
298
- $result = $api->listSubscribe($list, $email, $merge_vars, 'html', $opts['form_double_optin']);
299
  }
300
 
301
- if($api->errorCode) {
302
-
303
- if($api->errorCode == 214) {
304
- return 'already_subscribed';
305
- }
306
-
307
- return 'error';
308
  }
309
 
310
  // flawed
@@ -335,4 +334,4 @@ class MC4WP_Lite_Form
335
  return $markup;
336
  }
337
 
338
- }
2
 
3
  class MC4WP_Lite_Form
4
  {
 
5
  private $form_instance_number = 1;
6
  private $error = null;
7
  private $success = false;
9
 
10
  public function __construct()
11
  {
12
+ $opts = $this->get_options();
13
 
14
+ if($opts['css']) {
15
  add_action( 'wp_enqueue_scripts', array($this, 'load_stylesheet') );
16
  }
17
 
25
  $this->ensure_backwards_compatibility();
26
  add_action('init', array($this, 'submit'));
27
  }
28
+ }
29
 
30
+ public function get_options()
31
+ {
32
+ $options = MC4WP_Lite::instance()->get_options();
33
+ return $options['form'];
34
  }
35
 
36
  public function load_stylesheet()
37
  {
38
+ wp_enqueue_style( 'mc4wp-form-reset', plugins_url('mailchimp-for-wp/assets/css/form.css') );
39
  }
40
 
41
  public function output_form($atts, $content = null)
42
  {
43
+ $opts = $this->get_options();
44
 
45
  // add some useful css classes
46
  $css_classes = ' ';
50
  $content = "\n<!-- Form by MailChimp for WP plugin v". MC4WP_LITE_VERSION ." - http://dannyvankooten.com/wordpress-plugins/mailchimp-for-wordpress/ -->\n";
51
  $content .= '<form method="post" action="'. $this->get_current_url() .'#mc4wp-form-'. $this->form_instance_number .'" id="mc4wp-form-'.$this->form_instance_number.'" class="mc4wp-form form'.$css_classes.'">';
52
 
 
53
  // maybe hide the form
54
+ if(!($this->success && $opts['hide_after_success'])) {
55
+ $form_markup = __($opts['markup']);
56
  // replace special values
57
  $form_markup = $this->replace_form_variables($form_markup);
58
 
64
  $content .= '<input type="hidden" name="mc4wp_form_instance" value="'. $this->form_instance_number .'" />';
65
  }
66
 
 
67
  if($this->form_instance_number == $this->submitted_form_instance) {
68
 
69
  if($this->success) {
70
+ $content .= '<div class="mc4wp-alert mc4wp-success">' . __($opts['text_success']) . '</div>';
71
  } elseif($this->error) {
72
 
73
+ $api = MC4WP_Lite::api();
74
  $e = $this->error;
75
 
76
  if($e == 'already_subscribed') {
77
+ $text = (empty($opts['text_already_subscribed'])) ? $api->get_error_message() : $opts['text_already_subscribed'];
78
  $content .= '<div class="mc4wp-alert mc4wp-notice">'. __($text) .'</div>';
79
+ } elseif(isset($opts['text_' . $e]) && !empty($opts['text_'. $e] )) {
80
+ $content .= '<div class="mc4wp-alert mc4wp-error">' . __($opts['text_' . $e]) . '</div>';
81
  }
82
 
83
  if(current_user_can('manage_options')) {
84
 
85
+ if($api->has_error()) {
86
+ $content .= '<div class="mc4wp-alert mc4wp-error"><strong>Admin notice:</strong> '. $api->get_error_message() . '</div>';
87
  }
88
  }
89
 
91
  // endif
92
  }
93
 
94
+ if(current_user_can('manage_options') && empty($opts['lists'])) {
95
+ $content .= '<div class="mc4wp-alert mc4wp-error"><strong>Admin notice:</strong> you have not selected a MailChimp list for this sign-up form to subscribe to yet. <a href="'. admin_url('admin.php?page=mc4wp-lite-form-settings') .'">Edit your form settings</a> and select at least 1 list.</div>';
96
  }
97
 
98
  $content .= "</form>";
106
 
107
  public function submit()
108
  {
109
+ $opts = $this->get_options();
110
  $this->submitted_form_instance = (int) $_POST['mc4wp_form_instance'];
111
 
112
  if(!isset($_POST['EMAIL']) || !is_email($_POST['EMAIL'])) {
175
  $this->success = true;
176
 
177
  // check if we want to redirect the visitor
178
+ if(!empty($opts['redirect'])) {
179
+ wp_redirect($opts['redirect']);
180
  exit;
181
  }
182
 
273
 
274
  public function subscribe($email, array $merge_vars = array())
275
  {
276
+ $api = MC4WP_Lite::api();
277
+ $opts = $this->get_options();
278
 
279
+ $lists = $opts['lists'];
280
 
281
  if(empty($lists)) {
282
  return 'no_lists_selected';
296
  }
297
 
298
  foreach($lists as $list) {
299
+ $result = $api->subscribe($list, $email, $merge_vars, 'html', $opts['double_optin']);
300
  }
301
 
302
+ if($result === true) {
303
+ $this->success = true;
304
+ } else {
305
+ $this->success = false;
306
+ $this->error = $result;
 
 
307
  }
308
 
309
  // flawed
334
  return $markup;
335
  }
336
 
337
+ }
includes/MCAPI.php DELETED
@@ -1,2485 +0,0 @@
1
- <?php
2
-
3
- class MCAPI {
4
- var $version = "1.3";
5
- var $errorMessage;
6
- var $errorCode;
7
-
8
- /**
9
- * Cache the information on the API location on the server
10
- */
11
- var $apiUrl;
12
-
13
- /**
14
- * Default to a 300 second timeout on server calls
15
- */
16
- var $timeout = 300;
17
-
18
- /**
19
- * Default to a 8K chunk size
20
- */
21
- var $chunkSize = 8192;
22
-
23
- /**
24
- * Cache the user api_key so we only have to log in once per client instantiation
25
- */
26
- var $api_key;
27
-
28
- /**
29
- * Cache the user api_key so we only have to log in once per client instantiation
30
- */
31
- var $secure = false;
32
-
33
- /**
34
- * Connect to the MailChimp API for a given list.
35
- *
36
- * @param string $apikey Your MailChimp apikey
37
- * @param string $secure Whether or not this should use a secure connection
38
- */
39
- function MCAPI($apikey, $secure=false) {
40
- $this->secure = $secure;
41
- $this->apiUrl = parse_url("http://api.mailchimp.com/" . $this->version . "/?output=php");
42
- $this->api_key = $apikey;
43
- }
44
- function setTimeout($seconds){
45
- if (is_int($seconds)){
46
- $this->timeout = $seconds;
47
- return true;
48
- }
49
- }
50
- function getTimeout(){
51
- return $this->timeout;
52
- }
53
- function useSecure($val){
54
- if ($val===true){
55
- $this->secure = true;
56
- } else {
57
- $this->secure = false;
58
- }
59
- }
60
-
61
- /**
62
- * Unschedule a campaign that is scheduled to be sent in the future
63
- *
64
- * @section Campaign Related
65
- * @example mcapi_campaignUnschedule.php
66
- * @example xml-rpc_campaignUnschedule.php
67
- *
68
- * @param string $cid the id of the campaign to unschedule
69
- * @return boolean true on success
70
- */
71
- function campaignUnschedule($cid) {
72
- $params = array();
73
- $params["cid"] = $cid;
74
- return $this->callServer("campaignUnschedule", $params);
75
- }
76
-
77
- /**
78
- * Schedule a campaign to be sent in the future
79
- *
80
- * @section Campaign Related
81
- * @example mcapi_campaignSchedule.php
82
- * @example xml-rpc_campaignSchedule.php
83
- *
84
- * @param string $cid the id of the campaign to schedule
85
- * @param string $schedule_time the time to schedule the campaign. For A/B Split "schedule" campaigns, the time for Group A - in YYYY-MM-DD HH:II:SS format in <strong>GMT</strong>
86
- * @param string $schedule_time_b optional -the time to schedule Group B of an A/B Split "schedule" campaign - in YYYY-MM-DD HH:II:SS format in <strong>GMT</strong>
87
- * @return boolean true on success
88
- */
89
- function campaignSchedule($cid, $schedule_time, $schedule_time_b=NULL) {
90
- $params = array();
91
- $params["cid"] = $cid;
92
- $params["schedule_time"] = $schedule_time;
93
- $params["schedule_time_b"] = $schedule_time_b;
94
- return $this->callServer("campaignSchedule", $params);
95
- }
96
-
97
- /**
98
- * Resume sending an AutoResponder or RSS campaign
99
- *
100
- * @section Campaign Related
101
- *
102
- * @param string $cid the id of the campaign to pause
103
- * @return boolean true on success
104
- */
105
- function campaignResume($cid) {
106
- $params = array();
107
- $params["cid"] = $cid;
108
- return $this->callServer("campaignResume", $params);
109
- }
110
-
111
- /**
112
- * Pause an AutoResponder orRSS campaign from sending
113
- *
114
- * @section Campaign Related
115
- *
116
- * @param string $cid the id of the campaign to pause
117
- * @return boolean true on success
118
- */
119
- function campaignPause($cid) {
120
- $params = array();
121
- $params["cid"] = $cid;
122
- return $this->callServer("campaignPause", $params);
123
- }
124
-
125
- /**
126
- * Send a given campaign immediately. For RSS campaigns, this will "start" them.
127
- *
128
- * @section Campaign Related
129
- *
130
- * @example mcapi_campaignSendNow.php
131
- * @example xml-rpc_campaignSendNow.php
132
- *
133
- * @param string $cid the id of the campaign to send
134
- * @return boolean true on success
135
- */
136
- function campaignSendNow($cid) {
137
- $params = array();
138
- $params["cid"] = $cid;
139
- return $this->callServer("campaignSendNow", $params);
140
- }
141
-
142
- /**
143
- * Send a test of this campaign to the provided email address
144
- *
145
- * @section Campaign Related
146
- *
147
- * @example mcapi_campaignSendTest.php
148
- * @example xml-rpc_campaignSendTest.php
149
- *
150
- * @param string $cid the id of the campaign to test
151
- * @param array $test_emails an array of email address to receive the test message
152
- * @param string $send_type optional by default (null) both formats are sent - "html" or "text" send just that format
153
- * @return boolean true on success
154
- */
155
- function campaignSendTest($cid, $test_emails=array (
156
- ), $send_type=NULL) {
157
- $params = array();
158
- $params["cid"] = $cid;
159
- $params["test_emails"] = $test_emails;
160
- $params["send_type"] = $send_type;
161
- return $this->callServer("campaignSendTest", $params);
162
- }
163
-
164
- /**
165
- * Allows one to test their segmentation rules before creating a campaign using them
166
- *
167
- * @section Campaign Related
168
- * @example mcapi_campaignSegmentTest.php
169
- * @example xml-rpc_campaignSegmentTest.php
170
- *
171
- * @param string $list_id the list to test segmentation on - get lists using lists()
172
- * @param array $options with 2 keys:
173
- string "match" controls whether to use AND or OR when applying your options - expects "<strong>any</strong>" (for OR) or "<strong>all</strong>" (for AND)
174
- array "conditions" - up to 10 different criteria to apply while segmenting. Each criteria row must contain 3 keys - "<strong>field</strong>", "<strong>op</strong>", and "<strong>value</strong>" - and possibly a fourth, "<strong>extra</strong>", based on these definitions:
175
-
176
- Field = "<strong>date</strong>" : Select based on signup date
177
- Valid Op(eration): <strong>eq</strong> (is) / <strong>gt</strong> (after) / <strong>lt</strong> (before)
178
- Valid Values:
179
- string last_campaign_sent uses the date of the last campaign sent
180
- string campaign_id - uses the send date of the campaign that carriers the Id submitted - see campaigns()
181
- string YYYY-MM-DD - any date in the form of YYYY-MM-DD - <em>note:</em> anything that appears to start with YYYY will be treated as a date
182
-
183
- Field = "<strong>interests-X</strong>": where X is the Grouping Id from listInterestGroupings()
184
- Valid Op(erations): <strong>one</strong> / <strong>none</strong> / <strong>all</strong>
185
- Valid Values: a comma delimited of interest groups for the list - see listInterestGroupings()
186
-
187
- Field = "<strong>aim</strong>"
188
- Valid Op(erations): <strong>open</strong> / <strong>noopen</strong> / <strong>click</strong> / <strong>noclick</strong>
189
- Valid Values: "<strong>any</strong>" or a valid AIM-enabled Campaign that has been sent
190
-
191
- Field = "<strong>rating</strong>" : allows matching based on list member ratings
192
- Valid Op(erations): <strong>eq</strong> (=) / <strong>ne</strong> (!=) / <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;)
193
- Valid Values: a number between 0 and 5
194
-
195
- Field = "<strong>ecomm_prod</strong>" or "<strong>ecomm_prod</strong>": allows matching product and category names from purchases
196
- Valid Op(erations):
197
- <strong>eq</strong> (=) / <strong>ne</strong> (!=) / <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;) / <strong>like</strong> (like '%blah%') / <strong>nlike</strong> (not like '%blah%') / <strong>starts</strong> (like 'blah%') / <strong>ends</strong> (like '%blah')
198
- Valid Values: any string
199
-
200
- Field = "<strong>ecomm_spent_one</strong>" or "<strong>ecomm_spent_all</strong>" : allows matching purchase amounts on a single order or all orders
201
- Valid Op(erations): <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;)
202
- Valid Values: a number
203
-
204
- Field = "<strong>ecomm_date</strong>" : allow matching based on order dates
205
- Valid Op(eration): <strong>eq</strong> (is) / <strong>gt</strong> (after) / <strong>lt</strong> (before)
206
- Valid Values:
207
- string YYYY-MM-DD - any date in the form of YYYY-MM-DD
208
-
209
- Field = "<strong>social_gender</strong>" : allows matching against the gender acquired from SocialPro
210
- Valid Op(eration): <strong>eq</strong> (is) / <strong>ne</strong> (is not)
211
- Valid Values: male, female
212
-
213
- Field = "<strong>social_age</strong>" : allows matching against the age acquired from SocialPro
214
- Valid Op(erations): <strong>eq</strong> (=) / <strong>ne</strong> (!=) / <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;)
215
- Valid Values: any number
216
-
217
- Field = "<strong>social_influence</strong>" : allows matching against the influence acquired from SocialPro
218
- Valid Op(erations): <strong>eq</strong> (=) / <strong>ne</strong> (!=) / <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;)
219
- Valid Values: a number between 0 and 5
220
-
221
- Field = "<strong>social_network</strong>" :
222
- Valid Op(erations): <strong>member</strong> (is a member of) / <strong>notmember</strong> (is not a member of)
223
- Valid Values: twitter, facebook, myspace, linkedin, flickr
224
-
225
- Field = "<strong>static_segment</strong>" :
226
- Valid Op(eration): <strong>eq</strong> (is in) / <strong>ne</strong> (is not in)
227
- Valid Values: an int - get from listStaticSegments()
228
-
229
- Field = An <strong>Address</strong> Merge Var. Use <strong>Merge0-Merge30</strong> or the <strong>Custom Tag</strong> you've setup for your merge field - see listMergeVars(). Note, Address fields can still be used with the default operations below - this section is broken out solely to highlight the differences in using the geolocation routines.
230
- Valid Op(erations): <strong>geoin</strong>
231
- Valid Values: The number of miles an address should be within
232
- Extra Value: The Zip Code to be used as the center point
233
-
234
- Default Field = A Merge Var. Use <strong>Merge0-Merge30</strong> or the <strong>Custom Tag</strong> you've setup for your merge field - see listMergeVars()
235
- Valid Op(erations):
236
- <strong>eq</strong> (=) / <strong>ne</strong> (!=) / <strong>gt</strong> (&gt;) / <strong>lt</strong> (&lt;) / <strong>like</strong> (like '%blah%') / <strong>nlike</strong> (not like '%blah%') / <strong>starts</strong> (like 'blah%') / <strong>ends</strong> (like '%blah')
237
- Valid Values: any string
238
- * @return int total The total number of subscribers matching your segmentation options
239
- */
240
- function campaignSegmentTest($list_id, $options) {
241
- $params = array();
242
- $params["list_id"] = $list_id;
243
- $params["options"] = $options;
244
- return $this->callServer("campaignSegmentTest", $params);
245
- }
246
-
247
- /**
248
- * Create a new draft campaign to send. You <strong>can not</strong> have more than 32,000 campaigns in your account.
249
- *
250
- * @section Campaign Related
251
- * @example mcapi_campaignCreate.php
252
- * @example xml-rpc_campaignCreate.php
253
- * @example xml-rpc_campaignCreateABSplit.php
254
- * @example xml-rpc_campaignCreateRss.php
255
- *
256
- * @param string $type the Campaign Type to create - one of "regular", "plaintext", "absplit", "rss", "trans", "auto"
257
- * @param array $options a hash of the standard options for this campaign :
258
- string list_id the list to send this campaign to- get lists using lists()
259
- string subject the subject line for your campaign message
260
- string from_email the From: email address for your campaign message
261
- string from_name the From: name for your campaign message (not an email address)
262
- string to_name the To: name recipients will see (not email address)
263
- int template_id optional - use this user-created template to generate the HTML content of the campaign (takes precendence over other template options)
264
- int gallery_template_id optional - use a template from the public gallery to generate the HTML content of the campaign (takes precendence over base template options)
265
- int base_template_id optional - use this a base/start-from-scratch template to generate the HTML content of the campaign
266
- int folder_id optional - automatically file the new campaign in the folder_id passed. Get using folders() - note that Campaigns and Autoresponders have separate folder setupsn
267
- array tracking optional - set which recipient actions will be tracked, as a struct of boolean values with the following keys: "opens", "html_clicks", and "text_clicks". By default, opens and HTML clicks will be tracked. Click tracking can not be disabled for Free accounts.
268
- string title optional - an internal name to use for this campaign. By default, the campaign subject will be used.
269
- boolean authenticate optional - set to true to enable SenderID, DomainKeys, and DKIM authentication, defaults to false.
270
- array analytics optional - if provided, use a struct with "service type" as a key and the "service tag" as a value. For Google, this should be "google"=>"your_google_analytics_key_here". Note that only "google" is currently supported - a Google Analytics tags will be added to all links in the campaign with this string attached. Others may be added in the future
271
- boolean auto_footer optional Whether or not we should auto-generate the footer for your content. Mostly useful for content from URLs or Imports
272
- boolean inline_css optional Whether or not css should be automatically inlined when this campaign is sent, defaults to false.
273
- boolean generate_text optional Whether of not to auto-generate your Text content from the HTML content. Note that this will be ignored if the Text part of the content passed is not empty, defaults to false.
274
- boolean auto_tweet optional If set, this campaign will be auto-tweeted when it is sent - defaults to false. Note that if a Twitter account isn't linked, this will be silently ignored.
275
- boolean timewarp optional If set, this campaign must be scheduled 24 hours in advance of sending - default to false. Only valid for "regular" campaigns and "absplit" campaigns that split on schedule_time.
276
- boolean ecomm360 optional If set, our <a href="http://www.mailchimp.com/blog/ecommerce-tracking-plugin/" target="_blank">Ecommerce360 tracking</a> will be enabled for links in the campaign
277
-
278
- * @param array $content the content for this campaign - use a struct with the following keys:
279
- string html for pasted HTML content
280
- string text for the plain-text version
281
- string url to have us pull in content from a URL. Note, this will override any other content options - for lists with Email Format options, you'll need to turn on generate_text as well
282
- string archive to send a Base64 encoded archive file for us to import all media from. Note, this will override any other content options - for lists with Email Format options, you'll need to turn on generate_text as well
283
- string archive_type optional - only necessary for the "archive" option. Supported formats are: zip, tar.gz, tar.bz2, tar, tgz, tbz . If not included, we will default to zip
284
-
285
- If you chose a template instead of pasting in your HTML content, then use "html_" followed by the template sections as keys - for example, use a key of "html_MAIN" to fill in the "MAIN" section of a template. Supported template sections include: "html_HEADER", "html_MAIN", "html_SIDECOLUMN", and "html_FOOTER"
286
- * @param array $segment_opts optional - if you wish to do Segmentation with this campaign this array should contain: see campaignSegmentTest(). It's suggested that you test your options against campaignSegmentTest(). Also, "trans" campaigns <strong>do not</strong> support segmentation.
287
- * @param array $type_opts optional -
288
- For RSS Campaigns this, array should contain:
289
- string url the URL to pull RSS content from - it will be verified and must exist
290
- string schedule optional one of "daily", "weekly", "monthly" - defaults to "daily"
291
- string schedule_hour optional an hour between 0 and 24 - default to 4 (4am <em>local time</em>) - applies to all schedule types
292
- string schedule_weekday optional for "weekly" only, a number specifying the day of the week to send: 0 (Sunday) - 6 (Saturday) - defaults to 1 (Monday)
293
- string schedule_monthday optional for "monthly" only, a number specifying the day of the month to send (1 - 28) or "last" for the last day of a given month. Defaults to the 1st day of the month
294
-
295
- For A/B Split campaigns, this array should contain:
296
- string split_test The values to segment based on. Currently, one of: "subject", "from_name", "schedule". NOTE, for "schedule", you will need to call campaignSchedule() separately!
297
- string pick_winner How the winner will be picked, one of: "opens" (by the open_rate), "clicks" (by the click rate), "manual" (you pick manually)
298
- int wait_units optional the default time unit to wait before auto-selecting a winner - use "3600" for hours, "86400" for days. Defaults to 86400.
299
- int wait_time optional the number of units to wait before auto-selecting a winner - defaults to 1, so if not set, a winner will be selected after 1 Day.
300
- int split_size optional this is a percentage of what size the Campaign's List plus any segmentation options results in. "schedule" type forces 50%, all others default to 10%
301
- string from_name_a optional sort of, required when split_test is "from_name"
302
- string from_name_b optional sort of, required when split_test is "from_name"
303
- string from_email_a optional sort of, required when split_test is "from_name"
304
- string from_email_b optional sort of, required when split_test is "from_name"
305
- string subject_a optional sort of, required when split_test is "subject"
306
- string subject_b optional sort of, required when split_test is "subject"
307
-
308
- For AutoResponder campaigns, this array should contain:
309
- string offset-units one of "day", "week", "month", "year" - required
310
- string offset-time optional, sort of - the number of units must be a number greater than 0 for signup based autoresponders
311
- string offset-dir either "before" or "after"
312
- string event optional "signup" (default) to base this on double-optin signup, "date" or "annual" to base this on merge field in the list
313
- string event-datemerge optional sort of, this is required if the event is "date" or "annual"
314
-
315
- *
316
- * @return string the ID for the created campaign
317
- */
318
- function campaignCreate($type, $options, $content, $segment_opts=NULL, $type_opts=NULL) {
319
- $params = array();
320
- $params["type"] = $type;
321
- $params["options"] = $options;
322
- $params["content"] = $content;
323
- $params["segment_opts"] = $segment_opts;
324
- $params["type_opts"] = $type_opts;
325
- return $this->callServer("campaignCreate", $params);
326
- }
327
-
328
- /** Update just about any setting for a campaign that has <em>not</em> been sent. See campaignCreate() for details.
329
- *
330
- *
331
- * Caveats:<br/><ul>
332
- * <li>If you set list_id, all segmentation options will be deleted and must be re-added.</li>
333
- * <li>If you set template_id, you need to follow that up by setting it's 'content'</li>
334
- * <li>If you set segment_opts, you should have tested your options against campaignSegmentTest() as campaignUpdate() will not allow you to set a segment that includes no members.</li></ul>
335
- * @section Campaign Related
336
- *
337
- * @example mcapi_campaignUpdate.php
338
- * @example mcapi_campaignUpdateAB.php
339
- * @example xml-rpc_campaignUpdate.php
340
- * @example xml-rpc_campaignUpdateAB.php
341
- *
342
- * @param string $cid the Campaign Id to update
343
- * @param string $name the parameter name ( see campaignCreate() ). For items in the <strong>options</strong> array, this will be that parameter's name (subject, from_email, etc.). Additional parameters will be that option name (content, segment_opts). "type_opts" will be the name of the type - rss, auto, trans, etc.
344
- * @param mixed $value an appropriate value for the parameter ( see campaignCreate() ). For items in the <strong>options</strong> array, this will be that parameter's value. For additional parameters, this is the same value passed to them.
345
- * @return boolean true if the update succeeds, otherwise an error will be thrown
346
- */
347
- function campaignUpdate($cid, $name, $value) {
348
- $params = array();
349
- $params["cid"] = $cid;
350
- $params["name"] = $name;
351
- $params["value"] = $value;
352
- return $this->callServer("campaignUpdate", $params);
353
- }
354
-
355
- /** Replicate a campaign.
356
- *
357
- * @section Campaign Related
358
- *
359
- * @example mcapi_campaignReplicate.php
360
- *
361
- * @param string $cid the Campaign Id to replicate
362
- * @return string the id of the replicated Campaign created, otherwise an error will be thrown
363
- */
364
- function campaignReplicate($cid) {
365
- $params = array();
366
- $params["cid"] = $cid;
367
- return $this->callServer("campaignReplicate", $params);
368
- }
369
-
370
- /** Delete a campaign. Seriously, "poof, gone!" - be careful!
371
- *
372
- * @section Campaign Related
373
- *
374
- * @example mcapi_campaignDelete.php
375
- *
376
- * @param string $cid the Campaign Id to delete
377
- * @return boolean true if the delete succeeds, otherwise an error will be thrown
378
- */
379
- function campaignDelete($cid) {
380
- $params = array();
381
- $params["cid"] = $cid;
382
- return $this->callServer("campaignDelete", $params);
383
- }
384
-
385
- /**
386
- * Get the list of campaigns and their details matching the specified filters
387
- *
388
- * @section Campaign Related
389
- * @example mcapi_campaigns.php
390
- * @example xml-rpc_campaigns.php
391
- *
392
- * @param array $filters a hash of filters to apply to this query - all are optional:
393
- string campaign_id optional - return a single campaign using a know campaign_id
394
- string list_id optional - the list to send this campaign to- get lists using lists(). Accepts multiples separated by commas when not using exact matching.
395
- int folder_id optional - only show campaigns from this folder id - get folders using campaignFolders(). Accepts multiples separated by commas when not using exact matching.
396
- int template_id optional - only show campaigns using this template id - get templates using templates(). Accepts multiples separated by commas when not using exact matching.
397
- string status optional - return campaigns of a specific status - one of "sent", "save", "paused", "schedule", "sending". Accepts multiples separated by commas when not using exact matching.
398
- string type optional - return campaigns of a specific type - one of "regular", "plaintext", "absplit", "rss", "trans", "auto". Accepts multiples separated by commas when not using exact matching.
399
- string from_name optional - only show campaigns that have this "From Name"
400
- string from_email optional - only show campaigns that have this "Reply-to Email"
401
- string title optional - only show campaigns that have this title
402
- string subject optional - only show campaigns that have this subject
403
- string sendtime_start optional - only show campaigns that have been sent since this date/time (in GMT) - format is YYYY-MM-DD HH:mm:ss (24hr)
404
- string sendtime_end optional - only show campaigns that have been sent before this date/time (in GMT) - format is YYYY-MM-DD HH:mm:ss (24hr)
405
- boolean exact optional - flag for whether to filter on exact values when filtering, or search within content for filter values - defaults to true. Using this disables the use of any filters that accept multiples.
406
- * @param int $start optional - control paging of campaigns, start results at this campaign #, defaults to 1st page of data (page 0)
407
- * @param int $limit optional - control paging of campaigns, number of campaigns to return with each call, defaults to 25 (max=1000)
408
- * @return array an array containing a count of all matching campaigns and the specific ones for the current page (see Returned Fields for description)
409
- * @returnf int total the total number of campaigns matching the filters passed in
410
- * @returnf array data the data for each campaign being returned
411
- string id Campaign Id (used for all other campaign functions)
412
- int web_id The Campaign id used in our web app, allows you to create a link directly to it
413
- string list_id The List used for this campaign
414
- int folder_id The Folder this campaign is in
415
- int template_id The Template this campaign uses
416
- string content_type How the campaign's content is put together - one of 'template', 'html', 'url'
417
- string title Title of the campaign
418
- string type The type of campaign this is (regular,plaintext,absplit,rss,inspection,trans,auto)
419
- string create_time Creation time for the campaign
420
- string send_time Send time for the campaign - also the scheduled time for scheduled campaigns.
421
- int emails_sent Number of emails email was sent to
422
- string status Status of the given campaign (save,paused,schedule,sending,sent)
423
- string from_name From name of the given campaign
424
- string from_email Reply-to email of the given campaign
425
- string subject Subject of the given campaign
426
- string to_name Custom "To:" email string using merge variables
427
- string archive_url Archive link for the given campaign
428
- boolean inline_css Whether or not the campaign content's css was auto-inlined
429
- string analytics Either "google" if enabled or "N" if disabled
430
- string analytics_tag The name/tag the campaign's links were tagged with if analytics were enabled.
431
- boolean authenticate Whether or not the campaign was authenticated
432
- boolean ecomm360 Whether or not ecomm360 tracking was appended to links
433
- boolean auto_tweet Whether or not the campaign was auto tweeted after sending
434
- string auto_fb_post A comma delimited list of Facebook Profile/Page Ids the campaign was posted to after sending. If not used, blank.
435
- boolean auto_footer Whether or not the auto_footer was manually turned on
436
- boolean timewarp Whether or not the campaign used Timewarp
437
- boolean timewarp_schedule The time, in GMT, that the Timewarp campaign is being sent. For A/B Split campaigns, this is blank and is instead in their schedule_a and schedule_b in the type_opts array
438
- array tracking containing "text_clicks", "html_clicks", and "opens" as boolean values representing whether or not they were enabled
439
- string segment_text a string marked-up with HTML explaining the segment used for the campaign in plain English
440
- array segment_opts the segment used for the campaign - can be passed to campaignSegmentTest() or campaignCreate()
441
- array type_opts the type-specific options for the campaign - can be passed to campaignCreate()
442
- */
443
- function campaigns($filters=array (
444
- ), $start=0, $limit=25) {
445
- $params = array();
446
- $params["filters"] = $filters;
447
- $params["start"] = $start;
448
- $params["limit"] = $limit;
449
- return $this->callServer("campaigns", $params);
450
- }
451
-
452
- /**
453
- * Given a list and a campaign, get all the relevant campaign statistics (opens, bounces, clicks, etc.)
454
- *
455
- * @section Campaign Stats
456
- *
457
- * @example mcapi_campaignStats.php
458
- * @example xml-rpc_campaignStats.php
459
- *
460
- * @param string $cid the campaign id to pull stats for (can be gathered using campaigns())
461
- * @return array struct of the statistics for this campaign
462
- * @returnf int syntax_errors Number of email addresses in campaign that had syntactical errors.
463
- * @returnf int hard_bounces Number of email addresses in campaign that hard bounced.
464
- * @returnf int soft_bounces Number of email addresses in campaign that soft bounced.
465
- * @returnf int unsubscribes Number of email addresses in campaign that unsubscribed.
466
- * @returnf int abuse_reports Number of email addresses in campaign that reported campaign for abuse.
467
- * @returnf int forwards Number of times email was forwarded to a friend.
468
- * @returnf int forwards_opens Number of times a forwarded email was opened.
469
- * @returnf int opens Number of times the campaign was opened.
470
- * @returnf date last_open Date of the last time the email was opened.
471
- * @returnf int unique_opens Number of people who opened the campaign.
472
- * @returnf int clicks Number of times a link in the campaign was clicked.
473
- * @returnf int unique_clicks Number of unique recipient/click pairs for the campaign.
474
- * @returnf date last_click Date of the last time a link in the email was clicked.
475
- * @returnf int users_who_clicked Number of unique recipients who clicked on a link in the campaign.
476
- * @returnf int emails_sent Number of email addresses campaign was sent to.
477
- * @returnf array absplit If this was an absplit campaign, stats for the A and B groups will be returned
478
- int bounces_a bounces for the A group
479
- int bounces_b bounces for the B group
480
- int forwards_a forwards for the A group
481
- int forwards_b forwards for the B group
482
- int abuse_reports_a abuse reports for the A group
483
- int abuse_reports_b abuse reports for the B group
484
- int unsubs_a unsubs for the A group
485
- int unsubs_b unsubs for the B group
486
- int recipients_click_a clicks for the A group
487
- int recipients_click_b clicks for the B group
488
- int forwards_opens_a opened forwards for the A group
489
- int forwards_opens_b opened forwards for the A group
490
- * @returnf array timewarp If this campaign was a Timewarp campaign, an array of stats from each timezone for it, with the GMT offset as they key. Each timezone will contain:
491
- int opens opens for this timezone
492
- string last_open the date/time of the last open for this timezone
493
- int unique_opens the unique opens for this timezone
494
- int clicks the total clicks for this timezone
495
- string last_click the date/time of the last click for this timezone
496
- int unique_opens the unique clicks for this timezone
497
- int bounces the total bounces for this timezone
498
- int total the total number of members sent to in this timezone
499
- int sent the total number of members delivered to in this timezone
500
- */
501
- function campaignStats($cid) {
502
- $params = array();
503
- $params["cid"] = $cid;
504
- return $this->callServer("campaignStats", $params);
505
- }
506
-
507