WP Subscribe - Version 1.2.6

Version Description

  • Fixed PHP notices
Download this release

Release Info

Developer MyThemeShop
Plugin Icon 128x128 WP Subscribe
Version 1.2.6
Comparing to
See all releases

Code changes from version 1.2.5 to 1.2.6

Files changed (37) hide show
  1. includes/wps-helpers.php +2 -2
  2. languages/wp-subscribe.mo +0 -0
  3. languages/wp-subscribe.po +0 -370
  4. languages/wp-subscribe.pot +396 -0
  5. readme.txt +4 -1
  6. trunk/assets/css/wp-subscribe-form.css +5 -0
  7. trunk/assets/css/wp-subscribe-options.css +69 -0
  8. trunk/assets/js/jquery.cookie.js +117 -0
  9. trunk/assets/js/jquery.exitIntent.js +64 -0
  10. trunk/assets/js/magnificpopup.js +4 -0
  11. trunk/assets/js/wp-subscribe-admin.js +198 -0
  12. trunk/assets/js/wp-subscribe-form.js +105 -0
  13. trunk/assets/js/wp-subscribe-options.js +512 -0
  14. trunk/includes/class-wps-base.php +87 -0
  15. trunk/includes/subscription/class-wps-aweber.php +236 -0
  16. trunk/includes/subscription/class-wps-base.php +140 -0
  17. trunk/includes/subscription/class-wps-feedburner.php +45 -0
  18. trunk/includes/subscription/class-wps-mailchimp.php +87 -0
  19. trunk/includes/subscription/libs/aweber_api/aweber.php +307 -0
  20. trunk/includes/subscription/libs/aweber_api/aweber_api.php +8 -0
  21. trunk/includes/subscription/libs/aweber_api/aweber_collection.php +273 -0
  22. trunk/includes/subscription/libs/aweber_api/aweber_entry.php +350 -0
  23. trunk/includes/subscription/libs/aweber_api/aweber_entry_data_array.php +65 -0
  24. trunk/includes/subscription/libs/aweber_api/aweber_response.php +75 -0
  25. trunk/includes/subscription/libs/aweber_api/curl_object.php +103 -0
  26. trunk/includes/subscription/libs/aweber_api/curl_response.php +51 -0
  27. trunk/includes/subscription/libs/aweber_api/exceptions.php +152 -0
  28. trunk/includes/subscription/libs/aweber_api/oauth_adapter.php +10 -0
  29. trunk/includes/subscription/libs/aweber_api/oauth_application.php +689 -0
  30. trunk/includes/subscription/libs/mailchimp.php +306 -0
  31. trunk/includes/wps-functions-options.php +42 -0
  32. trunk/includes/wps-helpers.php +343 -0
  33. trunk/includes/wps-widget.php +385 -0
  34. trunk/languages/wp-subscribe.pot +396 -0
  35. trunk/readme.txt +161 -0
  36. trunk/wp-subscribe.php +333 -0
  37. wp-subscribe.php +2 -2
includes/wps-helpers.php CHANGED
@@ -35,7 +35,7 @@ function wps_the_form( $options = null ) {
35
  <div class="wp-subscribe-popup-form-wrapper">
36
  <?php endif; ?>
37
 
38
- <div id="wp-subscribe" class="wp-subscribe-wrap wp-subscribe wp-subscribe-<?php echo $wp_subscribe_forms ?>" data-thanks_page="<?php echo absint( $options['thanks_page'] ) ?>" data-thanks_page_url="<?php echo esc_url( $options['thanks_page_url'] ) ?>" data-thanks_page_new_window="0">
39
 
40
  <h4 class="title"><?php echo wp_kses_post( $options['title'] )?></h4>
41
 
@@ -67,7 +67,7 @@ function wps_the_form( $options = null ) {
67
 
68
  <div class="wp-subscribe-loader">
69
  <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
70
- <path fill="<?php echo $options['title_color'] ?>" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z">
71
  <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/>
72
  </path>
73
  </svg>
35
  <div class="wp-subscribe-popup-form-wrapper">
36
  <?php endif; ?>
37
 
38
+ <div id="wp-subscribe" class="wp-subscribe-wrap wp-subscribe wp-subscribe-<?php echo $wp_subscribe_forms ?>" data-thanks_page="<?php echo absint( isset( $options['thanks_page'] ) ? $options['thanks_page'] : 0 ) ?>" data-thanks_page_url="<?php echo isset( $options['thanks_page_url'] ) ? esc_url( $options['thanks_page_url'] ) : '' ?>" data-thanks_page_new_window="0">
39
 
40
  <h4 class="title"><?php echo wp_kses_post( $options['title'] )?></h4>
41
 
67
 
68
  <div class="wp-subscribe-loader">
69
  <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
70
+ <path fill="#ffffff" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z">
71
  <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/>
72
  </path>
73
  </svg>
languages/wp-subscribe.mo DELETED
Binary file
languages/wp-subscribe.po DELETED
@@ -1,370 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: WP Subscribe by MyThemeShop\n"
4
- "Report-Msgid-Bugs-To: \n"
5
- "POT-Creation-Date: 2017-04-12 16:50+0530\n"
6
- "PO-Revision-Date: 2017-04-12 16:50+0530\n"
7
- "Last-Translator: MyThemeShop <support-team@mythemeshop.com>\n"
8
- "Language-Team: MyThemeShop <support-team@mythemeshop.com>\n"
9
- "Language: en_US\n"
10
- "MIME-Version: 1.0\n"
11
- "Content-Type: text/plain; charset=UTF-8\n"
12
- "Content-Transfer-Encoding: 8bit\n"
13
- "X-Poedit-KeywordsList: __;_e;esc_html__\n"
14
- "X-Poedit-Basepath: .\n"
15
- "X-Generator: Poedit 1.6.2\n"
16
- "X-Poedit-SearchPath-0: ..\n"
17
-
18
- #: ../wp-subscribe.php:61 ../wp-subscribe.php:68
19
- msgid "Cheatin&#8217; huh?"
20
- msgstr ""
21
-
22
- #: ../wp-subscribe.php:163
23
- msgid "No data found."
24
- msgstr ""
25
-
26
- #: ../wp-subscribe.php:171
27
- msgid "No email address found."
28
- msgstr ""
29
-
30
- #: ../wp-subscribe.php:178
31
- msgid "Not a valid email address."
32
- msgstr ""
33
-
34
- #: ../wp-subscribe.php:187
35
- msgid "Unknown mailing service called."
36
- msgstr ""
37
-
38
- #: ../wp-subscribe.php:222
39
- msgid "Not permitted."
40
- msgstr ""
41
-
42
- #: ../wp-subscribe.php:231
43
- msgid "Service not defined."
44
- msgstr ""
45
-
46
- #: ../wp-subscribe.php:248
47
- msgid "No lists found."
48
- msgstr ""
49
-
50
- #: ../includes/wps-functions-options.php:17
51
- msgid "Aweber"
52
- msgstr ""
53
-
54
- #: ../includes/wps-functions-options.php:18
55
- msgid "Adds subscribers to your Aweber account."
56
- msgstr ""
57
-
58
- #: ../includes/wps-functions-options.php:23
59
- msgid "FeedBurner"
60
- msgstr ""
61
-
62
- #: ../includes/wps-functions-options.php:24
63
- msgid "Adds subscribers to your FeedBurner account."
64
- msgstr ""
65
-
66
- #: ../includes/wps-functions-options.php:29
67
- msgid "MailChimp"
68
- msgstr ""
69
-
70
- #: ../includes/wps-functions-options.php:30
71
- msgid "Adds subscribers to your MailChimp account."
72
- msgstr ""
73
-
74
- #: ../includes/wps-helpers.php:239
75
- msgid "No Animation"
76
- msgstr ""
77
-
78
- #: ../includes/wps-helpers.php:240
79
- msgid "Attention Seekers"
80
- msgstr ""
81
-
82
- #: ../includes/wps-helpers.php:241
83
- msgid "bounce"
84
- msgstr ""
85
-
86
- #: ../includes/wps-helpers.php:242
87
- msgid "flash"
88
- msgstr ""
89
-
90
- #: ../includes/wps-helpers.php:243
91
- msgid "pulse"
92
- msgstr ""
93
-
94
- #: ../includes/wps-helpers.php:244
95
- msgid "rubberBand"
96
- msgstr ""
97
-
98
- #: ../includes/wps-helpers.php:245
99
- msgid "shake"
100
- msgstr ""
101
-
102
- #: ../includes/wps-helpers.php:246
103
- msgid "swing"
104
- msgstr ""
105
-
106
- #: ../includes/wps-helpers.php:247
107
- msgid "tada"
108
- msgstr ""
109
-
110
- #: ../includes/wps-helpers.php:248
111
- msgid "wobble"
112
- msgstr ""
113
-
114
- #: ../includes/wps-helpers.php:250
115
- msgid "Bouncing Entrances"
116
- msgstr ""
117
-
118
- #: ../includes/wps-helpers.php:251
119
- msgid "bounceIn"
120
- msgstr ""
121
-
122
- #: ../includes/wps-helpers.php:252
123
- msgid "bounceInDown"
124
- msgstr ""
125
-
126
- #: ../includes/wps-helpers.php:253
127
- msgid "bounceInLeft"
128
- msgstr ""
129
-
130
- #: ../includes/wps-helpers.php:254
131
- msgid "bounceInRight"
132
- msgstr ""
133
-
134
- #: ../includes/wps-helpers.php:255
135
- msgid "bounceInUp"
136
- msgstr ""
137
-
138
- #: ../includes/wps-helpers.php:257
139
- msgid "Fading Entrances"
140
- msgstr ""
141
-
142
- #: ../includes/wps-helpers.php:258
143
- msgid "fadeIn"
144
- msgstr ""
145
-
146
- #: ../includes/wps-helpers.php:259
147
- msgid "fadeInDown"
148
- msgstr ""
149
-
150
- #: ../includes/wps-helpers.php:260
151
- msgid "fadeInDownBig"
152
- msgstr ""
153
-
154
- #: ../includes/wps-helpers.php:261
155
- msgid "fadeInLeft"
156
- msgstr ""
157
-
158
- #: ../includes/wps-helpers.php:262
159
- msgid "fadeInLeftBig"
160
- msgstr ""
161
-
162
- #: ../includes/wps-helpers.php:263
163
- msgid "fadeInRight"
164
- msgstr ""
165
-
166
- #: ../includes/wps-helpers.php:264
167
- msgid "fadeInRightBig"
168
- msgstr ""
169
-
170
- #: ../includes/wps-helpers.php:265
171
- msgid "fadeInUp"
172
- msgstr ""
173
-
174
- #: ../includes/wps-helpers.php:266
175
- msgid "fadeInUpBig"
176
- msgstr ""
177
-
178
- #: ../includes/wps-helpers.php:268
179
- msgid "Flippers"
180
- msgstr ""
181
-
182
- #: ../includes/wps-helpers.php:269
183
- msgid "flipInX"
184
- msgstr ""
185
-
186
- #: ../includes/wps-helpers.php:270
187
- msgid "flipInY"
188
- msgstr ""
189
-
190
- #: ../includes/wps-helpers.php:272
191
- msgid "Lightspeed"
192
- msgstr ""
193
-
194
- #: ../includes/wps-helpers.php:273
195
- msgid "lightSpeedIn"
196
- msgstr ""
197
-
198
- #: ../includes/wps-helpers.php:275
199
- msgid "Rotating Entrances"
200
- msgstr ""
201
-
202
- #: ../includes/wps-helpers.php:276
203
- msgid "rotateIn"
204
- msgstr ""
205
-
206
- #: ../includes/wps-helpers.php:277
207
- msgid "rotateInDownLeft"
208
- msgstr ""
209
-
210
- #: ../includes/wps-helpers.php:278
211
- msgid "rotateInDownRight"
212
- msgstr ""
213
-
214
- #: ../includes/wps-helpers.php:279
215
- msgid "rotateInUpLeft"
216
- msgstr ""
217
-
218
- #: ../includes/wps-helpers.php:280
219
- msgid "rotateInUpRight"
220
- msgstr ""
221
-
222
- #: ../includes/wps-helpers.php:282
223
- msgid "Specials"
224
- msgstr ""
225
-
226
- #: ../includes/wps-helpers.php:283
227
- msgid "rollIn"
228
- msgstr ""
229
-
230
- #: ../includes/wps-helpers.php:285
231
- msgid "Zoom Entrances"
232
- msgstr ""
233
-
234
- #: ../includes/wps-helpers.php:286
235
- msgid "zoomIn"
236
- msgstr ""
237
-
238
- #: ../includes/wps-helpers.php:287
239
- msgid "zoomInDown"
240
- msgstr ""
241
-
242
- #: ../includes/wps-helpers.php:288
243
- msgid "zoomInLeft"
244
- msgstr ""
245
-
246
- #: ../includes/wps-helpers.php:289
247
- msgid "zoomInRight"
248
- msgstr ""
249
-
250
- #: ../includes/wps-helpers.php:290
251
- msgid "zoomInUp"
252
- msgstr ""
253
-
254
- #: ../includes/wps-widget.php:23
255
- msgid "Displays subscription form, supports FeedBurner, MailChimp & AWeber."
256
- msgstr ""
257
-
258
- #: ../includes/wps-widget.php:34
259
- msgid "WP Subscribe Widget"
260
- msgstr ""
261
-
262
- #: ../includes/wps-widget.php:50
263
- msgid "Get more stuff"
264
- msgstr ""
265
-
266
- #: ../includes/wps-widget.php:51
267
- msgid ""
268
- "Subscribe to our mailing list and get interesting stuff and updates to your "
269
- "email inbox."
270
- msgstr ""
271
-
272
- #: ../includes/wps-widget.php:52
273
- msgid "Enter your email here"
274
- msgstr ""
275
-
276
- #: ../includes/wps-widget.php:53
277
- msgid "Enter your name here"
278
- msgstr ""
279
-
280
- #: ../includes/wps-widget.php:54
281
- msgid "Sign Up Now"
282
- msgstr ""
283
-
284
- #: ../includes/wps-widget.php:55
285
- msgid "Thank you for subscribing."
286
- msgstr ""
287
-
288
- #: ../includes/wps-widget.php:56
289
- msgid "Something went wrong."
290
- msgstr ""
291
-
292
- #: ../includes/wps-widget.php:57
293
- msgid "we respect your privacy and take protecting it seriously"
294
- msgstr ""
295
-
296
- #: ../includes/wps-widget.php:174
297
- msgid "Include <strong>Name</strong> field"
298
- msgstr ""
299
-
300
- #: ../includes/wps-widget.php:180
301
- msgid "Labels"
302
- msgstr ""
303
-
304
- #: ../includes/wps-widget.php:286 ../includes/wps-widget.php:356
305
- msgid "Click here"
306
- msgstr ""
307
-
308
- #: ../includes/wps-widget.php:352
309
- msgid "Get list"
310
- msgstr ""
311
-
312
- #: ../includes/subscription/class-wps-aweber.php:57
313
- msgid "Unable to connect to Aweber. The Authorization Code is empty."
314
- msgstr ""
315
-
316
- #: ../includes/subscription/class-wps-aweber.php:67
317
- msgid ""
318
- "Unable to connect your Aweber Account. The Authorization Code is incorrect."
319
- msgstr ""
320
-
321
- #: ../includes/subscription/class-wps-aweber.php:155
322
- #, php-format
323
- msgid ""
324
- "<span>1.</span> <a href=\"%s\" target=\"_blank\">Click here</a> <span>to "
325
- "open the authorization page and log in.</span>"
326
- msgstr ""
327
-
328
- #: ../includes/subscription/class-wps-aweber.php:156
329
- msgid ""
330
- "<span>2.</span> Copy and paste the authorization code in the field below."
331
- msgstr ""
332
-
333
- #: ../includes/subscription/class-wps-aweber.php:165
334
- msgid "Your Aweber Account is connected."
335
- msgstr ""
336
-
337
- #: ../includes/subscription/class-wps-aweber.php:166
338
- msgid ""
339
- "<a href=\"#\" class=\"aweber_disconnect\">Click here</a> <span>to disconnect."
340
- "</span>"
341
- msgstr ""
342
-
343
- #: ../includes/subscription/class-wps-aweber.php:202
344
- msgid "AWeber List"
345
- msgstr ""
346
-
347
- #: ../includes/subscription/class-wps-aweber.php:203
348
- #: ../includes/subscription/class-wps-mailchimp.php:70
349
- msgid "Select List"
350
- msgstr ""
351
-
352
- #: ../includes/subscription/class-wps-feedburner.php:39
353
- msgid "Feedburner ID"
354
- msgstr ""
355
-
356
- #: ../includes/subscription/class-wps-mailchimp.php:60
357
- msgid "MailChimp API URL"
358
- msgstr ""
359
-
360
- #: ../includes/subscription/class-wps-mailchimp.php:61
361
- msgid "The API key of your MailChimp account."
362
- msgstr ""
363
-
364
- #: ../includes/subscription/class-wps-mailchimp.php:69
365
- msgid "MailChimp List"
366
- msgstr ""
367
-
368
- #: ../includes/subscription/class-wps-mailchimp.php:78
369
- msgid "Send double opt-in notification"
370
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/wp-subscribe.pot ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2018 WP Subscribe
2
+ # This file is distributed under the same license as the WP Subscribe package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: WP Subscribe 1.2.6\n"
6
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-subscribe\n"
7
+ "POT-Creation-Date: 2018-02-17 01:23:40+00:00\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
12
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
+ "Language-Team: LANGUAGE <LL@li.org>\n"
14
+
15
+ #: includes/subscription/class-wps-aweber.php:67
16
+ msgid "Unable to connect to Aweber. The Authorization Code is empty."
17
+ msgstr ""
18
+
19
+ #: includes/subscription/class-wps-aweber.php:77
20
+ msgid ""
21
+ "Unable to connect your Aweber Account. The Authorization Code is incorrect."
22
+ msgstr ""
23
+
24
+ #: includes/subscription/class-wps-aweber.php:203
25
+ msgid "AWeber List"
26
+ msgstr ""
27
+
28
+ #: includes/subscription/class-wps-aweber.php:204
29
+ #: includes/subscription/class-wps-mailchimp.php:73
30
+ msgid "Select List"
31
+ msgstr ""
32
+
33
+ #: includes/subscription/class-wps-aweber.php:217
34
+ msgid "To connect your Aweber account:"
35
+ msgstr ""
36
+
37
+ #: includes/subscription/class-wps-aweber.php:220
38
+ msgid ""
39
+ "<span>1.</span> <a href=\"%s\" target=\"_blank\">Click here</a> <span>to "
40
+ "open the authorization page and log in.</span>"
41
+ msgstr ""
42
+
43
+ #: includes/subscription/class-wps-aweber.php:221
44
+ msgid ""
45
+ "<span>2.</span> Copy and paste the authorization code in the field below."
46
+ msgstr ""
47
+
48
+ #: includes/subscription/class-wps-aweber.php:230
49
+ msgid "Your Aweber Account is connected."
50
+ msgstr ""
51
+
52
+ #: includes/subscription/class-wps-aweber.php:231
53
+ msgid ""
54
+ "<a href=\"#\" class=\"aweber_disconnect\">Click here</a> <span>to disconnect."
55
+ "</span>"
56
+ msgstr ""
57
+
58
+ #: includes/subscription/class-wps-feedburner.php:39
59
+ msgid "Feedburner ID"
60
+ msgstr ""
61
+
62
+ #: includes/subscription/class-wps-mailchimp.php:63
63
+ msgid "MailChimp API URL"
64
+ msgstr ""
65
+
66
+ #: includes/subscription/class-wps-mailchimp.php:64
67
+ msgid "The API key of your MailChimp account."
68
+ msgstr ""
69
+
70
+ #: includes/subscription/class-wps-mailchimp.php:72
71
+ msgid "MailChimp List"
72
+ msgstr ""
73
+
74
+ #: includes/subscription/class-wps-mailchimp.php:81
75
+ msgid "Send double opt-in notification"
76
+ msgstr ""
77
+
78
+ #: includes/wps-functions-options.php:17
79
+ msgid "Aweber"
80
+ msgstr ""
81
+
82
+ #: includes/wps-functions-options.php:18
83
+ msgid "Adds subscribers to your Aweber account."
84
+ msgstr ""
85
+
86
+ #: includes/wps-functions-options.php:23
87
+ msgid "FeedBurner"
88
+ msgstr ""
89
+
90
+ #: includes/wps-functions-options.php:24
91
+ msgid "Adds subscribers to your FeedBurner account."
92
+ msgstr ""
93
+
94
+ #: includes/wps-functions-options.php:29
95
+ msgid "MailChimp"
96
+ msgstr ""
97
+
98
+ #: includes/wps-functions-options.php:30
99
+ msgid "Adds subscribers to your MailChimp account."
100
+ msgstr ""
101
+
102
+ #: includes/wps-helpers.php:217
103
+ msgid "No Animation"
104
+ msgstr ""
105
+
106
+ #: includes/wps-helpers.php:218
107
+ msgid "Attention Seekers"
108
+ msgstr ""
109
+
110
+ #: includes/wps-helpers.php:219
111
+ msgid "bounce"
112
+ msgstr ""
113
+
114
+ #: includes/wps-helpers.php:220
115
+ msgid "flash"
116
+ msgstr ""
117
+
118
+ #: includes/wps-helpers.php:221
119
+ msgid "pulse"
120
+ msgstr ""
121
+
122
+ #: includes/wps-helpers.php:222
123
+ msgid "rubberBand"
124
+ msgstr ""
125
+
126
+ #: includes/wps-helpers.php:223
127
+ msgid "shake"
128
+ msgstr ""
129
+
130
+ #: includes/wps-helpers.php:224
131
+ msgid "swing"
132
+ msgstr ""
133
+
134
+ #: includes/wps-helpers.php:225
135
+ msgid "tada"
136
+ msgstr ""
137
+
138
+ #: includes/wps-helpers.php:226
139
+ msgid "wobble"
140
+ msgstr ""
141
+
142
+ #: includes/wps-helpers.php:228
143
+ msgid "Bouncing Entrances"
144
+ msgstr ""
145
+
146
+ #: includes/wps-helpers.php:229
147
+ msgid "bounceIn"
148
+ msgstr ""
149
+
150
+ #: includes/wps-helpers.php:230
151
+ msgid "bounceInDown"
152
+ msgstr ""
153
+
154
+ #: includes/wps-helpers.php:231
155
+ msgid "bounceInLeft"
156
+ msgstr ""
157
+
158
+ #: includes/wps-helpers.php:232
159
+ msgid "bounceInRight"
160
+ msgstr ""
161
+
162
+ #: includes/wps-helpers.php:233
163
+ msgid "bounceInUp"
164
+ msgstr ""
165
+
166
+ #: includes/wps-helpers.php:235
167
+ msgid "Fading Entrances"
168
+ msgstr ""
169
+
170
+ #: includes/wps-helpers.php:236
171
+ msgid "fadeIn"
172
+ msgstr ""
173
+
174
+ #: includes/wps-helpers.php:237
175
+ msgid "fadeInDown"
176
+ msgstr ""
177
+
178
+ #: includes/wps-helpers.php:238
179
+ msgid "fadeInDownBig"
180
+ msgstr ""
181
+
182
+ #: includes/wps-helpers.php:239
183
+ msgid "fadeInLeft"
184
+ msgstr ""
185
+
186
+ #: includes/wps-helpers.php:240
187
+ msgid "fadeInLeftBig"
188
+ msgstr ""
189
+
190
+ #: includes/wps-helpers.php:241
191
+ msgid "fadeInRight"
192
+ msgstr ""
193
+
194
+ #: includes/wps-helpers.php:242
195
+ msgid "fadeInRightBig"
196
+ msgstr ""
197
+
198
+ #: includes/wps-helpers.php:243
199
+ msgid "fadeInUp"
200
+ msgstr ""
201
+
202
+ #: includes/wps-helpers.php:244
203
+ msgid "fadeInUpBig"
204
+ msgstr ""
205
+
206
+ #: includes/wps-helpers.php:246
207
+ msgid "Flippers"
208
+ msgstr ""
209
+
210
+ #: includes/wps-helpers.php:247
211
+ msgid "flipInX"
212
+ msgstr ""
213
+
214
+ #: includes/wps-helpers.php:248
215
+ msgid "flipInY"
216
+ msgstr ""
217
+
218
+ #: includes/wps-helpers.php:250
219
+ msgid "Lightspeed"
220
+ msgstr ""
221
+
222
+ #: includes/wps-helpers.php:251
223
+ msgid "lightSpeedIn"
224
+ msgstr ""
225
+
226
+ #: includes/wps-helpers.php:253
227
+ msgid "Rotating Entrances"
228
+ msgstr ""
229
+
230
+ #: includes/wps-helpers.php:254
231
+ msgid "rotateIn"
232
+ msgstr ""
233
+
234
+ #: includes/wps-helpers.php:255
235
+ msgid "rotateInDownLeft"
236
+ msgstr ""
237
+
238
+ #: includes/wps-helpers.php:256
239
+ msgid "rotateInDownRight"
240
+ msgstr ""
241
+
242
+ #: includes/wps-helpers.php:257
243
+ msgid "rotateInUpLeft"
244
+ msgstr ""
245
+
246
+ #: includes/wps-helpers.php:258
247
+ msgid "rotateInUpRight"
248
+ msgstr ""
249
+
250
+ #: includes/wps-helpers.php:260
251
+ msgid "Specials"
252
+ msgstr ""
253
+
254
+ #: includes/wps-helpers.php:261
255
+ msgid "rollIn"
256
+ msgstr ""
257
+
258
+ #: includes/wps-helpers.php:263
259
+ msgid "Zoom Entrances"
260
+ msgstr ""
261
+
262
+ #: includes/wps-helpers.php:264
263
+ msgid "zoomIn"
264
+ msgstr ""
265
+
266
+ #: includes/wps-helpers.php:265
267
+ msgid "zoomInDown"
268
+ msgstr ""
269
+
270
+ #: includes/wps-helpers.php:266
271
+ msgid "zoomInLeft"
272
+ msgstr ""
273
+
274
+ #: includes/wps-helpers.php:267
275
+ msgid "zoomInRight"
276
+ msgstr ""
277
+
278
+ #: includes/wps-helpers.php:268
279
+ msgid "zoomInUp"
280
+ msgstr ""
281
+
282
+ #: includes/wps-widget.php:23
283
+ msgid "Displays subscription form, supports FeedBurner, MailChimp & AWeber."
284
+ msgstr ""
285
+
286
+ #: includes/wps-widget.php:34
287
+ msgid "WP Subscribe Widget"
288
+ msgstr ""
289
+
290
+ #: includes/wps-widget.php:50
291
+ msgid "Get more stuff"
292
+ msgstr ""
293
+
294
+ #: includes/wps-widget.php:51
295
+ msgid ""
296
+ "Subscribe to our mailing list and get interesting stuff and updates to your "
297
+ "email inbox."
298
+ msgstr ""
299
+
300
+ #: includes/wps-widget.php:52
301
+ msgid "Enter your email here"
302
+ msgstr ""
303
+
304
+ #: includes/wps-widget.php:53
305
+ msgid "Enter your name here"
306
+ msgstr ""
307
+
308
+ #: includes/wps-widget.php:54
309
+ msgid "Sign Up Now"
310
+ msgstr ""
311
+
312
+ #: includes/wps-widget.php:55
313
+ msgid "Thank you for subscribing."
314
+ msgstr ""
315
+
316
+ #: includes/wps-widget.php:56
317
+ msgid "Something went wrong."
318
+ msgstr ""
319
+
320
+ #: includes/wps-widget.php:57
321
+ msgid "we respect your privacy and take protecting it seriously"
322
+ msgstr ""
323
+
324
+ #: includes/wps-widget.php:174
325
+ msgid "Include <strong>Name</strong> field"
326
+ msgstr ""
327
+
328
+ #: includes/wps-widget.php:180
329
+ msgid "Labels"
330
+ msgstr ""
331
+
332
+ #: includes/wps-widget.php:286 includes/wps-widget.php:361
333
+ msgid "Click here"
334
+ msgstr ""
335
+
336
+ #: includes/wps-widget.php:357
337
+ msgid "Get list"
338
+ msgstr ""
339
+
340
+ #: wp-subscribe.php:61 wp-subscribe.php:68
341
+ msgid "Cheatin&#8217; huh?"
342
+ msgstr ""
343
+
344
+ #: wp-subscribe.php:160
345
+ msgid "No aweber authorization code found."
346
+ msgstr ""
347
+
348
+ #: wp-subscribe.php:192
349
+ msgid "No data found."
350
+ msgstr ""
351
+
352
+ #: wp-subscribe.php:200
353
+ msgid "No email address found."
354
+ msgstr ""
355
+
356
+ #: wp-subscribe.php:207
357
+ msgid "Not a valid email address."
358
+ msgstr ""
359
+
360
+ #: wp-subscribe.php:216
361
+ msgid "Unknown mailing service called."
362
+ msgstr ""
363
+
364
+ #: wp-subscribe.php:251
365
+ msgid "Not permitted."
366
+ msgstr ""
367
+
368
+ #: wp-subscribe.php:260
369
+ msgid "Service not defined."
370
+ msgstr ""
371
+
372
+ #: wp-subscribe.php:278
373
+ msgid "No lists found."
374
+ msgstr ""
375
+
376
+ #. Plugin Name of the plugin/theme
377
+ msgid "WP Subscribe"
378
+ msgstr ""
379
+
380
+ #. Plugin URI of the plugin/theme
381
+ msgid "http://mythemeshop.com/plugins/wp-subscribe/"
382
+ msgstr ""
383
+
384
+ #. Description of the plugin/theme
385
+ msgid ""
386
+ "WP Subscribe is a simple but powerful subscription plugin which supports "
387
+ "MailChimp, Aweber and Feedburner."
388
+ msgstr ""
389
+
390
+ #. Author of the plugin/theme
391
+ msgid "MyThemeShop"
392
+ msgstr ""
393
+
394
+ #. Author URI of the plugin/theme
395
+ msgid "http://mythemeshop.com/"
396
+ msgstr ""
readme.txt CHANGED
@@ -4,7 +4,7 @@ Creator's website link: http://mythemeshop.com/plugins/wp-subscribe/
4
  Tags: subscribe, subscription, subscription box, newsletter, subscribe widget, mailchimp, aweber, feedburner,
5
  Requires at least: 4.0
6
  Tested up to: 4.9.1
7
- Stable tag: 1.2.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -82,6 +82,9 @@ Please disable all plugins and check if plugin is working properly. Then you can
82
 
83
  == Changelog ==
84
 
 
 
 
85
  = 1.2.5 =
86
  * Fixed aweber list issue
87
 
4
  Tags: subscribe, subscription, subscription box, newsletter, subscribe widget, mailchimp, aweber, feedburner,
5
  Requires at least: 4.0
6
  Tested up to: 4.9.1
7
+ Stable tag: 1.2.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
82
 
83
  == Changelog ==
84
 
85
+ = 1.2.6 =
86
+ * Fixed PHP notices
87
+
88
  = 1.2.5 =
89
  * Fixed aweber list issue
90
 
trunk/assets/css/wp-subscribe-form.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*!
2
+ * Plugin: WP Subscribe Pro
3
+ * Name: wp-subscribe-form.css
4
+ * Written by: MyThemeShop
5
+ */.wp-subscribe-wrap{padding:20px;text-align:center;background:#f47555}.wp-subscribe-wrap h4.title{font-size:22px;line-height:1;margin-bottom:0;text-transform:uppercase;color:#fff}.wp-subscribe-wrap h4.title span{font-size:38px;font-weight:bold;display:inline-block;margin-top:15px}#wp_subscribe_popup .wp-subscribe-wrap h4.title{margin-top:0}.wp-subscribe-wrap p{margin:0;color:#fff}.wp-subscribe-wrap p.text{margin:15px 0;opacity:.8}.wp-subscribe-wrap p.footer-text{font-size:12px;margin-top:10px}.wp-subscribe-wrap input{box-sizing:border-box;width:100%;height:45px;margin:0;padding:10px 0;text-align:center;text-indent:10px;border:none;border-radius:0;box-shadow:none}.wp-subscribe-wrap input::-webkit-input-placeholder{opacity:.8;color:inherit}.wp-subscribe-wrap input:-moz-placeholder{opacity:.8;color:inherit}.wp-subscribe-wrap input::-moz-placeholder{opacity:.8;color:inherit}.wp-subscribe-wrap input:-ms-input-placeholder{opacity:.8;color:inherit}.wp-subscribe-wrap input:focus::-webkit-input-placeholder{color:transparent !important}.wp-subscribe-wrap input:focus:-moz-placeholder{color:transparent !important}.wp-subscribe-wrap input:focus::-moz-placeholder{color:transparent !important}.wp-subscribe-wrap input:focus:-ms-input-placeholder{color:transparent !important}.wp-subscribe-wrap .email-field{margin-top:10px}.wp-subscribe-wrap input.email-field,.wp-subscribe-wrap input.name-field{color:#fff;background:#d56144}.wp-subscribe-wrap input.submit{font-size:18px;font-weight:500;margin-top:20px;cursor:pointer;text-transform:uppercase;color:#f47555;background:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,0.05)}.wp-subscribe-single .wp-subscribe-wrap{clear:both;margin:10px 0;text-align:left}.wp-subscribe-single .wp-subscribe-wrap input{text-align:left}.wp-subscribe-wrap .error,.wp-subscribe-wrap .thanks{margin-top:10px}.wp-subscribe-wrap .wp-subscribe-loader{display:none;padding:1em;text-align:center;vertical-align:top}.wp-subscribe-wrap.loading .wp-subscribe-form,.thanks,.error{display:none}.wp-subscribe-wrap.loading .wp-subscribe-loader{display:block}
trunk/assets/css/wp-subscribe-options.css ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plugin Name: WP Subscribe Pro
3
+ Plugin URI: http://mythemeshop.com/plugins/wp-subscribe-pro/
4
+ Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
5
+ Author: MyThemeShop
6
+ Author URI: http://mythemeshop.com/
7
+ */
8
+ .wp_subscribe_options_form label { vertical-align: top }
9
+ .wp_subscribe_colors, .wp_subscribe_labels { }
10
+ .wp_subscribe_options_form .wp-picker-container { position: absolute; right: 0; }
11
+ .wp_subscribe_colors > div { position: relative; margin: 20px 0; }
12
+ .wp_subscribe_colors label { display: inline-block; margin-top: 2px; }
13
+ .wp_subscribe_options_form .wp-picker-container > a { margin-right: 0 }
14
+ .wp-subscribe h2 { margin-bottom: 1em }
15
+ .wp-subscribe-preview-popup:before { content: "\f177"; display: inline-block; width: 20px; height: 20px; font-size: 20px; margin-right: 5px; margin-top: 2px; line-height: 1; font-family: dashicons; text-decoration: inherit; font-weight: 400; font-style: normal; vertical-align: top; text-align: center; transition: color .1s ease-in 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
16
+ .wp-subscribe-preview-popup.disabled { pointer-events: none }
17
+ #cookies-cleared { display: none; line-height: 27px; margin-left: 4px; color: #777; float: left; margin-top: 8px; }
18
+ #cookies-cleared .dashicons { vertical-align: middle }
19
+ .wp-subscribe-field h4 { margin-top: 0; float: left; width: 100%; margin-bottom: .5em; }
20
+ .wp-subscribe-field p { margin: 0; float: left; width: 100%; }
21
+ .wp-subscribe-field select { margin-left: 0 }
22
+ h3.wp-subscribe-field { margin-top: 1em; margin-bottom: 1.8em; }
23
+ .wp-subscribe-field { clear: both; margin: 0 0 1em 0; overflow: hidden; float: left; width: 100%; }
24
+ .wp-subscribe-color-field { width: 181px; float: left; margin-top: 7px; margin-right: 7px; }
25
+ .wp-picker-holder { position: absolute; z-index: 10; }
26
+ .wp-picker-input-wrap { position: absolute; z-index: 1; }
27
+ .wp-subscribe-color-field label { display: block; margin-bottom: .8em; font-weight: bold; }
28
+ .wp-subscribe-label-field { float: left; margin-right: 14px; margin-bottom: 10px; }
29
+ .wp-subscribe-label-field label { width: 168px; display: inline-block; font-weight: bold; vertical-align: top; padding-top: 7px; }
30
+ .wp-subscribe-label-field .wps-input-wrapper { display: inline-block; }
31
+ .wp-subscribe-label-field .wps-desc {display: block;font-size: 12px;color: #787878;font-style: italic;margin-top: 3px;}
32
+ .wp-subscribe-label-field .list-selectbox { display: inline-block; width: auto; }
33
+ .wps-tabs-wrapper > div { margin-top: 12px }
34
+ p.submit { clear: both; float: left; margin-top: 0; }
35
+ .postmeta-label { clear: both; float: left; }
36
+ .wps-popup-content-options .wp-subscribe-label-field, .wps-post-options .wp-subscribe-label-field { width: 100% }
37
+ .wps-popup-content-options .wp-subscribe-label-field input, .wps-post-options .wp-subscribe-label-field input { width: 400px }
38
+ .wps-popup-content-options h4 { width: 100%; float: left; clear: both; }
39
+ #wp-subscribe-opacity-slider, #wp-subscribe-popup-width-slider { width: 300px; margin: 10px 20px 10px 0; float: left; }
40
+ #wp_subscribe_overlay_opacity, #wp_subscribe_popup_width { float: left }
41
+ .wp-subscribe-content-colors { float: left; width: 100%; margin-top: 30px; margin-bottom: 20px; }
42
+ .wp-subscribe-content-colors .wp-subscribe-color-field:nth-child(5) { clear: left }
43
+ label[for="wp_subscribe_overlay_opacity"], label[for="wp_subscribe_popup_width"] { width: 100%; display: block; font-weight: bold; margin-bottom: .1em; }
44
+ .wp_subscribe_account_details { clear: both; float: left; width: 100%; margin-bottom: 10px; }
45
+ #wp_subscribe_regenerate_cookie { margin-top: 7px; margin-bottom: 15px; float: left; }
46
+ .wps-colors-loader { margin-bottom: 12px }
47
+ .wps-palettes { display: none }
48
+ .wps-colors-loader .color-palette { max-width: 300px; height: 40px; margin-top: 12px; border: 1px solid #ccc; }
49
+ .wps-colors-loader a { background: #D56144; color: #FFF; padding: 5px 10px; border-radius: 3px; text-decoration: none; }
50
+ .wps-colors-loader a:hover,.wps-colors-loader a:hover {color: #fff;}
51
+ .single-palette { position: relative; clear: both; }
52
+ .single-palette .wps-load-palette { display: none }
53
+ .single-palette:hover .wps-load-palette { display: block; position: absolute; top: 6px; left: 6px; }
54
+ span.width-px-label { line-height: 27px }
55
+ .description { color: #666; font-size: 13px; font-style: italic; }
56
+ .clear { clear: both }
57
+
58
+ .widget .wp-subscribe-label-field { float: none }
59
+ .widget .wp-subscribe-label-field label { display: block; width: auto; padding: 0 0 7px; }
60
+ .widget .wp-subscribe-label-field .wps-input-wrapper { display: block; }
61
+ .widget .wps-account-details input.widefat { width: 75% }
62
+ .widget .wp-subscribe-service-field .list-selectbox { display: block; width: 100%; }
63
+ .widget .wp-subscribe-service-field { padding-top: 10px; }
64
+
65
+ .widget .wp-subscribe-color-field { width: 100%; float: none }
66
+ .widget .wp-picker-container { position: absolute; right: 0; }
67
+ .widget .wp_subscribe_colors > div { position: relative; margin: 20px 0 }
68
+ .widget .wp_subscribe_colors label { display: inline-block; margin-top: 2px }
69
+ .widget .wp_subscribe_options_form .wp-picker-container > a { margin-right: 0 }
trunk/assets/js/jquery.cookie.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery Cookie Plugin v1.4.1
3
+ * https://github.com/carhartl/jquery-cookie
4
+ *
5
+ * Copyright 2006, 2014 Klaus Hartl
6
+ * Released under the MIT license
7
+ */
8
+ (function (factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD
11
+ define(['jquery'], factory);
12
+ } else if (typeof exports === 'object') {
13
+ // CommonJS
14
+ factory(require('jquery'));
15
+ } else {
16
+ // Browser globals
17
+ factory(jQuery);
18
+ }
19
+ }(function ($) {
20
+
21
+ var pluses = /\+/g;
22
+
23
+ function encode(s) {
24
+ return config.raw ? s : encodeURIComponent(s);
25
+ }
26
+
27
+ function decode(s) {
28
+ return config.raw ? s : decodeURIComponent(s);
29
+ }
30
+
31
+ function stringifyCookieValue(value) {
32
+ return encode(config.json ? JSON.stringify(value) : String(value));
33
+ }
34
+
35
+ function parseCookieValue(s) {
36
+ if (s.indexOf('"') === 0) {
37
+ // This is a quoted cookie as according to RFC2068, unescape...
38
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39
+ }
40
+
41
+ try {
42
+ // Replace server-side written pluses with spaces.
43
+ // If we can't decode the cookie, ignore it, it's unusable.
44
+ // If we can't parse the cookie, ignore it, it's unusable.
45
+ s = decodeURIComponent(s.replace(pluses, ' '));
46
+ return config.json ? JSON.parse(s) : s;
47
+ } catch(e) {}
48
+ }
49
+
50
+ function read(s, converter) {
51
+ var value = config.raw ? s : parseCookieValue(s);
52
+ return $.isFunction(converter) ? converter(value) : value;
53
+ }
54
+
55
+ var config = $.cookie = function (key, value, options) {
56
+
57
+ // Write
58
+
59
+ if (arguments.length > 1 && !$.isFunction(value)) {
60
+ options = $.extend({}, config.defaults, options);
61
+
62
+ if (typeof options.expires === 'number') {
63
+ var days = options.expires, t = options.expires = new Date();
64
+ t.setTime(+t + days * 864e+5);
65
+ }
66
+
67
+ return (document.cookie = [
68
+ encode(key), '=', stringifyCookieValue(value),
69
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70
+ options.path ? '; path=' + options.path : '',
71
+ options.domain ? '; domain=' + options.domain : '',
72
+ options.secure ? '; secure' : ''
73
+ ].join(''));
74
+ }
75
+
76
+ // Read
77
+
78
+ var result = key ? undefined : {};
79
+
80
+ // To prevent the for loop in the first place assign an empty array
81
+ // in case there are no cookies at all. Also prevents odd result when
82
+ // calling $.cookie().
83
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
84
+
85
+ for (var i = 0, l = cookies.length; i < l; i++) {
86
+ var parts = cookies[i].split('=');
87
+ var name = decode(parts.shift());
88
+ var cookie = parts.join('=');
89
+
90
+ if (key && key === name) {
91
+ // If second argument (value) is a function it's a converter...
92
+ result = read(cookie, value);
93
+ break;
94
+ }
95
+
96
+ // Prevent storing a cookie that we couldn't decode.
97
+ if (!key && (cookie = read(cookie)) !== undefined) {
98
+ result[name] = cookie;
99
+ }
100
+ }
101
+
102
+ return result;
103
+ };
104
+
105
+ config.defaults = {};
106
+
107
+ $.removeCookie = function (key, options) {
108
+ if ($.cookie(key) === undefined) {
109
+ return false;
110
+ }
111
+
112
+ // Must not alter options, thus extending a fresh object...
113
+ $.cookie(key, '', $.extend({}, options, { expires: -1 }));
114
+ return !$.cookie(key);
115
+ };
116
+
117
+ }));
trunk/assets/js/jquery.exitIntent.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plugin Name: WP Subscribe Pro
3
+ Plugin URI: http://mythemeshop.com/plugins/wp-subscribe-pro/
4
+ Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
5
+ Author: MyThemeShop
6
+ Author URI: http://mythemeshop.com/
7
+ */
8
+
9
+ (function($){
10
+ $.exitIntent = function(el, callback, options){
11
+ var base = this;
12
+ base.delayTimer = null;
13
+ base.$el = $(el);
14
+ base.el = el;
15
+ base.disabled = false;
16
+
17
+ base.$el.data("exitIntent", base);
18
+
19
+ base.init = function(){
20
+ base.options = $.extend({},$.exitIntent.defaultOptions, options);
21
+
22
+ base.$el.mouseleave(function(e) {
23
+ if (e.clientY > 0 || Math.abs(e.clientY) < base.options.minexitspeed || (base.disabled && !base.options.repeat)) return;
24
+
25
+ base.delayTimer = setTimeout(base.runCallback, base.options.delay);
26
+ }).mouseenter(function(event) {
27
+ if (base.delayTimer) {
28
+ clearTimeout(base.delayTimer);
29
+ base.delayTimer = null;
30
+ }
31
+ });
32
+ if (base.options.keyboard) {
33
+ base.$el.keydown(function(e) {
34
+ if (base.disabled && !base.options.repeat) return;
35
+ else if (e.keyCode !== 8 && (!e.metaKey || e.keyCode !== 76)) return;
36
+
37
+ base.runCallback();
38
+ });
39
+ }
40
+ };
41
+ base.runCallback = function() {
42
+ if (typeof callback == 'function') {
43
+ callback.call(this);
44
+ }
45
+ base.disabled = true;
46
+ };
47
+
48
+ base.init();
49
+ };
50
+
51
+ $.exitIntent.defaultOptions = {
52
+ minexitspeed: 0,
53
+ delay: 0,
54
+ repeat: false,
55
+ keyboard: true // capture ctrl + L
56
+ };
57
+
58
+ $.fn.exitIntent = function(callback, options){
59
+ return this.each(function(){
60
+ (new $.exitIntent(this, callback, options));
61
+ });
62
+ };
63
+
64
+ })(jQuery);
trunk/assets/js/magnificpopup.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*! Magnific Popup - v0.9.9 - 2014-09-06
2
+ * http://dimsemenov.com/plugins/magnific-popup/
3
+ * Copyright (c) 2014 Dmitry Semenov; */
4
+ (function(e){var t,n,i,o,r,a,s,l="Close",c="BeforeClose",d="AfterClose",u="BeforeAppend",p="MarkupParse",f="Open",m="Change",g="mfp",h="."+g,v="mfp-ready",C="mfp-removing",y="mfp-prevent-close",w=function(){},b=!!window.jQuery,I=e(window),x=function(e,n){t.ev.on(g+e+h,n)},k=function(t,n,i,o){var r=document.createElement("div");return r.className="mfp-"+t,i&&(r.innerHTML=i),o?n&&n.appendChild(r):(r=e(r),n&&r.appendTo(n)),r},T=function(n,i){t.ev.triggerHandler(g+n,i),t.st.callbacks&&(n=n.charAt(0).toLowerCase()+n.slice(1),t.st.callbacks[n]&&t.st.callbacks[n].apply(t,e.isArray(i)?i:[i]))},E=function(n){return n===s&&t.currTemplate.closeBtn||(t.currTemplate.closeBtn=e(t.st.closeMarkup.replace("%title%",t.st.tClose)),s=n),t.currTemplate.closeBtn},_=function(){e.magnificPopup.instance||(t=new w,t.init(),e.magnificPopup.instance=t)},S=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1};w.prototype={constructor:w,init:function(){var n=navigator.appVersion;t.isIE7=-1!==n.indexOf("MSIE 7."),t.isIE8=-1!==n.indexOf("MSIE 8."),t.isLowIE=t.isIE7||t.isIE8,t.isAndroid=/android/gi.test(n),t.isIOS=/iphone|ipad|ipod/gi.test(n),t.supportsTransition=S(),t.probablyMobile=t.isAndroid||t.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),o=e(document),t.popupsCache={}},open:function(n){i||(i=e(document.body));var r;if(n.isObj===!1){t.items=n.items.toArray(),t.index=0;var s,l=n.items;for(r=0;l.length>r;r++)if(s=l[r],s.parsed&&(s=s.el[0]),s===n.el[0]){t.index=r;break}}else t.items=e.isArray(n.items)?n.items:[n.items],t.index=n.index||0;if(t.isOpen)return t.updateItemHTML(),void 0;t.types=[],a="",t.ev=n.mainEl&&n.mainEl.length?n.mainEl.eq(0):o,n.key?(t.popupsCache[n.key]||(t.popupsCache[n.key]={}),t.currTemplate=t.popupsCache[n.key]):t.currTemplate={},t.st=e.extend(!0,{},e.magnificPopup.defaults,n),t.fixedContentPos="auto"===t.st.fixedContentPos?!t.probablyMobile:t.st.fixedContentPos,t.st.modal&&(t.st.closeOnContentClick=!1,t.st.closeOnBgClick=!1,t.st.showCloseBtn=!1,t.st.enableEscapeKey=!1),t.bgOverlay||(t.bgOverlay=k("bg").on("click"+h,function(){t.close()}),t.wrap=k("wrap").attr("tabindex",-1).on("click"+h,function(e){t._checkIfClose(e.target)&&t.close()}),t.container=k("container",t.wrap)),t.contentContainer=k("content"),t.st.preloader&&(t.preloader=k("preloader",t.container,t.st.tLoading));var c=e.magnificPopup.modules;for(r=0;c.length>r;r++){var d=c[r];d=d.charAt(0).toUpperCase()+d.slice(1),t["init"+d].call(t)}T("BeforeOpen"),t.st.showCloseBtn&&(t.st.closeBtnInside?(x(p,function(e,t,n,i){n.close_replaceWith=E(i.type)}),a+=" mfp-close-btn-in"):t.wrap.append(E())),t.st.alignTop&&(a+=" mfp-align-top"),t.fixedContentPos?t.wrap.css({overflow:t.st.overflowY,overflowX:"hidden",overflowY:t.st.overflowY}):t.wrap.css({top:I.scrollTop(),position:"absolute"}),(t.st.fixedBgPos===!1||"auto"===t.st.fixedBgPos&&!t.fixedContentPos)&&t.bgOverlay.css({height:o.height(),position:"absolute"}),t.st.enableEscapeKey&&o.on("keyup"+h,function(e){27===e.keyCode&&t.close()}),I.on("resize"+h,function(){t.updateSize()}),t.st.closeOnContentClick||(a+=" mfp-auto-cursor"),a&&t.wrap.addClass(a);var u=t.wH=I.height(),m={};if(t.fixedContentPos&&t._hasScrollBar(u)){var g=t._getScrollbarSize();g&&(m.marginRight=g)}t.fixedContentPos&&(t.isIE7?e("body, html").css("overflow","hidden"):m.overflow="hidden");var C=t.st.mainClass;return t.isIE7&&(C+=" mfp-ie7"),C&&t._addClassToMFP(C),t.updateItemHTML(),T("BuildControls"),e("html").css(m),t.bgOverlay.add(t.wrap).prependTo(t.st.prependTo||i),t._lastFocusedEl=document.activeElement,setTimeout(function(){t.content?(t._addClassToMFP(v),t._setFocus()):t.bgOverlay.addClass(v),o.on("focusin"+h,t._onFocusIn)},16),t.isOpen=!0,t.updateSize(u),T(f),n},close:function(){t.isOpen&&(T(c),t.isOpen=!1,t.st.removalDelay&&!t.isLowIE&&t.supportsTransition?(t._addClassToMFP(C),setTimeout(function(){t._close()},t.st.removalDelay)):t._close())},_close:function(){T(l);var n=C+" "+v+" ";if(t.bgOverlay.detach(),t.wrap.detach(),t.container.empty(),t.st.mainClass&&(n+=t.st.mainClass+" "),t._removeClassFromMFP(n),t.fixedContentPos){var i={marginRight:""};t.isIE7?e("body, html").css("overflow",""):i.overflow="",e("html").css(i)}o.off("keyup"+h+" focusin"+h),t.ev.off(h),t.wrap.attr("class","mfp-wrap").removeAttr("style"),t.bgOverlay.attr("class","mfp-bg"),t.container.attr("class","mfp-container"),!t.st.showCloseBtn||t.st.closeBtnInside&&t.currTemplate[t.currItem.type]!==!0||t.currTemplate.closeBtn&&t.currTemplate.closeBtn.detach(),t._lastFocusedEl&&e(t._lastFocusedEl).focus(),t.currItem=null,t.content=null,t.currTemplate=null,t.prevHeight=0,T(d)},updateSize:function(e){if(t.isIOS){var n=document.documentElement.clientWidth/window.innerWidth,i=window.innerHeight*n;t.wrap.css("height",i),t.wH=i}else t.wH=e||I.height();t.fixedContentPos||t.wrap.css("height",t.wH),T("Resize")},updateItemHTML:function(){var n=t.items[t.index];t.contentContainer.detach(),t.content&&t.content.detach(),n.parsed||(n=t.parseEl(t.index));var i=n.type;if(T("BeforeChange",[t.currItem?t.currItem.type:"",i]),t.currItem=n,!t.currTemplate[i]){var o=t.st[i]?t.st[i].markup:!1;T("FirstMarkupParse",o),t.currTemplate[i]=o?e(o):!0}r&&r!==n.type&&t.container.removeClass("mfp-"+r+"-holder");var a=t["get"+i.charAt(0).toUpperCase()+i.slice(1)](n,t.currTemplate[i]);t.appendContent(a,i),n.preloaded=!0,T(m,n),r=n.type,t.container.prepend(t.contentContainer),T("AfterChange")},appendContent:function(e,n){t.content=e,e?t.st.showCloseBtn&&t.st.closeBtnInside&&t.currTemplate[n]===!0?t.content.find(".mfp-close").length||t.content.append(E()):t.content=e:t.content="",T(u),t.container.addClass("mfp-"+n+"-holder"),t.contentContainer.append(t.content)},parseEl:function(n){var i,o=t.items[n];if(o.tagName?o={el:e(o)}:(i=o.type,o={data:o,src:o.src}),o.el){for(var r=t.types,a=0;r.length>a;a++)if(o.el.hasClass("mfp-"+r[a])){i=r[a];break}o.src=o.el.attr("data-mfp-src"),o.src||(o.src=o.el.attr("href"))}return o.type=i||t.st.type||"inline",o.index=n,o.parsed=!0,t.items[n]=o,T("ElementParse",o),t.items[n]},addGroup:function(e,n){var i=function(i){i.mfpEl=this,t._openClick(i,e,n)};n||(n={});var o="click.magnificPopup";n.mainEl=e,n.items?(n.isObj=!0,e.off(o).on(o,i)):(n.isObj=!1,n.delegate?e.off(o).on(o,n.delegate,i):(n.items=e,e.off(o).on(o,i)))},_openClick:function(n,i,o){var r=void 0!==o.midClick?o.midClick:e.magnificPopup.defaults.midClick;if(r||2!==n.which&&!n.ctrlKey&&!n.metaKey){var a=void 0!==o.disableOn?o.disableOn:e.magnificPopup.defaults.disableOn;if(a)if(e.isFunction(a)){if(!a.call(t))return!0}else if(a>I.width())return!0;n.type&&(n.preventDefault(),t.isOpen&&n.stopPropagation()),o.el=e(n.mfpEl),o.delegate&&(o.items=i.find(o.delegate)),t.open(o)}},updateStatus:function(e,i){if(t.preloader){n!==e&&t.container.removeClass("mfp-s-"+n),i||"loading"!==e||(i=t.st.tLoading);var o={status:e,text:i};T("UpdateStatus",o),e=o.status,i=o.text,t.preloader.html(i),t.preloader.find("a").on("click",function(e){e.stopImmediatePropagation()}),t.container.addClass("mfp-s-"+e),n=e}},_checkIfClose:function(n){if(!e(n).hasClass(y)){var i=t.st.closeOnContentClick,o=t.st.closeOnBgClick;if(i&&o)return!0;if(!t.content||e(n).hasClass("mfp-close")||t.preloader&&n===t.preloader[0])return!0;if(n===t.content[0]||e.contains(t.content[0],n)){if(i)return!0}else if(o&&e.contains(document,n))return!0;return!1}},_addClassToMFP:function(e){t.bgOverlay.addClass(e),t.wrap.addClass(e)},_removeClassFromMFP:function(e){this.bgOverlay.removeClass(e),t.wrap.removeClass(e)},_hasScrollBar:function(e){return(t.isIE7?o.height():document.body.scrollHeight)>(e||I.height())},_setFocus:function(){(t.st.focus?t.content.find(t.st.focus).eq(0):t.wrap).focus()},_onFocusIn:function(n){return n.target===t.wrap[0]||e.contains(t.wrap[0],n.target)?void 0:(t._setFocus(),!1)},_parseMarkup:function(t,n,i){var o;i.data&&(n=e.extend(i.data,n)),T(p,[t,n,i]),e.each(n,function(e,n){if(void 0===n||n===!1)return!0;if(o=e.split("_"),o.length>1){var i=t.find(h+"-"+o[0]);if(i.length>0){var r=o[1];"replaceWith"===r?i[0]!==n[0]&&i.replaceWith(n):"img"===r?i.is("img")?i.attr("src",n):i.replaceWith('<img src="'+n+'" class="'+i.attr("class")+'" />'):i.attr(o[1],n)}}else t.find(h+"-"+e).html(n)})},_getScrollbarSize:function(){if(void 0===t.scrollbarSize){var e=document.createElement("div");e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),t.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return t.scrollbarSize}},e.magnificPopup={instance:null,proto:w.prototype,modules:[],open:function(t,n){return _(),t=t?e.extend(!0,{},t):{},t.isObj=!0,t.index=n||0,this.instance.open(t)},close:function(){return e.magnificPopup.instance&&e.magnificPopup.instance.close()},registerModule:function(t,n){n.options&&(e.magnificPopup.defaults[t]=n.options),e.extend(this.proto,n.proto),this.modules.push(t)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">&times;</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},e.fn.magnificPopup=function(n){_();var i=e(this);if("string"==typeof n)if("open"===n){var o,r=b?i.data("magnificPopup"):i[0].magnificPopup,a=parseInt(arguments[1],10)||0;r.items?o=r.items[a]:(o=i,r.delegate&&(o=o.find(r.delegate)),o=o.eq(a)),t._openClick({mfpEl:o},i,r)}else t.isOpen&&t[n].apply(t,Array.prototype.slice.call(arguments,1));else n=e.extend(!0,{},n),b?i.data("magnificPopup",n):i[0].magnificPopup=n,t.addGroup(i,n);return i};var P,O,z,M="inline",B=function(){z&&(O.after(z.addClass(P)).detach(),z=null)};e.magnificPopup.registerModule(M,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){t.types.push(M),x(l+"."+M,function(){B()})},getInline:function(n,i){if(B(),n.src){var o=t.st.inline,r=e(n.src);if(r.length){var a=r[0].parentNode;a&&a.tagName&&(O||(P=o.hiddenClass,O=k(P),P="mfp-"+P),z=r.after(O).detach().removeClass(P)),t.updateStatus("ready")}else t.updateStatus("error",o.tNotFound),r=e("<div>");return n.inlineElement=r,r}return t.updateStatus("ready"),t._parseMarkup(i,{},n),i}}});var F,H="ajax",L=function(){F&&i.removeClass(F)},A=function(){L(),t.req&&t.req.abort()};e.magnificPopup.registerModule(H,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){t.types.push(H),F=t.st.ajax.cursor,x(l+"."+H,A),x("BeforeChange."+H,A)},getAjax:function(n){F&&i.addClass(F),t.updateStatus("loading");var o=e.extend({url:n.src,success:function(i,o,r){var a={data:i,xhr:r};T("ParseAjax",a),t.appendContent(e(a.data),H),n.finished=!0,L(),t._setFocus(),setTimeout(function(){t.wrap.addClass(v)},16),t.updateStatus("ready"),T("AjaxContentAdded")},error:function(){L(),n.finished=n.loadError=!0,t.updateStatus("error",t.st.ajax.tError.replace("%url%",n.src))}},t.st.ajax.settings);return t.req=e.ajax(o),""}}});var j,N=function(n){if(n.data&&void 0!==n.data.title)return n.data.title;var i=t.st.image.titleSrc;if(i){if(e.isFunction(i))return i.call(t,n);if(n.el)return n.el.attr(i)||""}return""};e.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var e=t.st.image,n=".image";t.types.push("image"),x(f+n,function(){"image"===t.currItem.type&&e.cursor&&i.addClass(e.cursor)}),x(l+n,function(){e.cursor&&i.removeClass(e.cursor),I.off("resize"+h)}),x("Resize"+n,t.resizeImage),t.isLowIE&&x("AfterChange",t.resizeImage)},resizeImage:function(){var e=t.currItem;if(e&&e.img&&t.st.image.verticalFit){var n=0;t.isLowIE&&(n=parseInt(e.img.css("padding-top"),10)+parseInt(e.img.css("padding-bottom"),10)),e.img.css("max-height",t.wH-n)}},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,j&&clearInterval(j),e.isCheckingImgSize=!1,T("ImageHasSize",e),e.imgHidden&&(t.content&&t.content.removeClass("mfp-loading"),e.imgHidden=!1))},findImageSize:function(e){var n=0,i=e.img[0],o=function(r){j&&clearInterval(j),j=setInterval(function(){return i.naturalWidth>0?(t._onImageHasSize(e),void 0):(n>200&&clearInterval(j),n++,3===n?o(10):40===n?o(50):100===n&&o(500),void 0)},r)};o(1)},getImage:function(n,i){var o=0,r=function(){n&&(n.img[0].complete?(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("ready")),n.hasSize=!0,n.loaded=!0,T("ImageLoadComplete")):(o++,200>o?setTimeout(r,100):a()))},a=function(){n&&(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("error",s.tError.replace("%url%",n.src))),n.hasSize=!0,n.loaded=!0,n.loadError=!0)},s=t.st.image,l=i.find(".mfp-img");if(l.length){var c=document.createElement("img");c.className="mfp-img",n.img=e(c).on("load.mfploader",r).on("error.mfploader",a),c.src=n.src,l.is("img")&&(n.img=n.img.clone()),c=n.img[0],c.naturalWidth>0?n.hasSize=!0:c.width||(n.hasSize=!1)}return t._parseMarkup(i,{title:N(n),img_replaceWith:n.img},n),t.resizeImage(),n.hasSize?(j&&clearInterval(j),n.loadError?(i.addClass("mfp-loading"),t.updateStatus("error",s.tError.replace("%url%",n.src))):(i.removeClass("mfp-loading"),t.updateStatus("ready")),i):(t.updateStatus("loading"),n.loading=!0,n.hasSize||(n.imgHidden=!0,i.addClass("mfp-loading"),t.findImageSize(n)),i)}}});var W,R=function(){return void 0===W&&(W=void 0!==document.createElement("p").style.MozTransform),W};e.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(e){return e.is("img")?e:e.find("img")}},proto:{initZoom:function(){var e,n=t.st.zoom,i=".zoom";if(n.enabled&&t.supportsTransition){var o,r,a=n.duration,s=function(e){var t=e.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),i="all "+n.duration/1e3+"s "+n.easing,o={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},r="transition";return o["-webkit-"+r]=o["-moz-"+r]=o["-o-"+r]=o[r]=i,t.css(o),t},d=function(){t.content.css("visibility","visible")};x("BuildControls"+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.content.css("visibility","hidden"),e=t._getItemToZoom(),!e)return d(),void 0;r=s(e),r.css(t._getOffset()),t.wrap.append(r),o=setTimeout(function(){r.css(t._getOffset(!0)),o=setTimeout(function(){d(),setTimeout(function(){r.remove(),e=r=null,T("ZoomAnimationEnded")},16)},a)},16)}}),x(c+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.st.removalDelay=a,!e){if(e=t._getItemToZoom(),!e)return;r=s(e)}r.css(t._getOffset(!0)),t.wrap.append(r),t.content.css("visibility","hidden"),setTimeout(function(){r.css(t._getOffset())},16)}}),x(l+i,function(){t._allowZoom()&&(d(),r&&r.remove(),e=null)})}},_allowZoom:function(){return"image"===t.currItem.type},_getItemToZoom:function(){return t.currItem.hasSize?t.currItem.img:!1},_getOffset:function(n){var i;i=n?t.currItem.img:t.st.zoom.opener(t.currItem.el||t.currItem);var o=i.offset(),r=parseInt(i.css("padding-top"),10),a=parseInt(i.css("padding-bottom"),10);o.top-=e(window).scrollTop()-r;var s={width:i.width(),height:(b?i.innerHeight():i[0].offsetHeight)-a-r};return R()?s["-moz-transform"]=s.transform="translate("+o.left+"px,"+o.top+"px)":(s.left=o.left,s.top=o.top),s}}});var Z="iframe",q="//about:blank",D=function(e){if(t.currTemplate[Z]){var n=t.currTemplate[Z].find("iframe");n.length&&(e||(n[0].src=q),t.isIE8&&n.css("display",e?"block":"none"))}};e.magnificPopup.registerModule(Z,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){t.types.push(Z),x("BeforeChange",function(e,t,n){t!==n&&(t===Z?D():n===Z&&D(!0))}),x(l+"."+Z,function(){D()})},getIframe:function(n,i){var o=n.src,r=t.st.iframe;e.each(r.patterns,function(){return o.indexOf(this.index)>-1?(this.id&&(o="string"==typeof this.id?o.substr(o.lastIndexOf(this.id)+this.id.length,o.length):this.id.call(this,o)),o=this.src.replace("%id%",o),!1):void 0});var a={};return r.srcAction&&(a[r.srcAction]=o),t._parseMarkup(i,a,n),t.updateStatus("ready"),i}}});var K=function(e){var n=t.items.length;return e>n-1?e-n:0>e?n+e:e},Y=function(e,t,n){return e.replace(/%curr%/gi,t+1).replace(/%total%/gi,n)};e.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var n=t.st.gallery,i=".mfp-gallery",r=Boolean(e.fn.mfpFastClick);return t.direction=!0,n&&n.enabled?(a+=" mfp-gallery",x(f+i,function(){n.navigateByImgClick&&t.wrap.on("click"+i,".mfp-img",function(){return t.items.length>1?(t.next(),!1):void 0}),o.on("keydown"+i,function(e){37===e.keyCode?t.prev():39===e.keyCode&&t.next()})}),x("UpdateStatus"+i,function(e,n){n.text&&(n.text=Y(n.text,t.currItem.index,t.items.length))}),x(p+i,function(e,i,o,r){var a=t.items.length;o.counter=a>1?Y(n.tCounter,r.index,a):""}),x("BuildControls"+i,function(){if(t.items.length>1&&n.arrows&&!t.arrowLeft){var i=n.arrowMarkup,o=t.arrowLeft=e(i.replace(/%title%/gi,n.tPrev).replace(/%dir%/gi,"left")).addClass(y),a=t.arrowRight=e(i.replace(/%title%/gi,n.tNext).replace(/%dir%/gi,"right")).addClass(y),s=r?"mfpFastClick":"click";o[s](function(){t.prev()}),a[s](function(){t.next()}),t.isIE7&&(k("b",o[0],!1,!0),k("a",o[0],!1,!0),k("b",a[0],!1,!0),k("a",a[0],!1,!0)),t.container.append(o.add(a))}}),x(m+i,function(){t._preloadTimeout&&clearTimeout(t._preloadTimeout),t._preloadTimeout=setTimeout(function(){t.preloadNearbyImages(),t._preloadTimeout=null},16)}),x(l+i,function(){o.off(i),t.wrap.off("click"+i),t.arrowLeft&&r&&t.arrowLeft.add(t.arrowRight).destroyMfpFastClick(),t.arrowRight=t.arrowLeft=null}),void 0):!1},next:function(){t.direction=!0,t.index=K(t.index+1),t.updateItemHTML()},prev:function(){t.direction=!1,t.index=K(t.index-1),t.updateItemHTML()},goTo:function(e){t.direction=e>=t.index,t.index=e,t.updateItemHTML()},preloadNearbyImages:function(){var e,n=t.st.gallery.preload,i=Math.min(n[0],t.items.length),o=Math.min(n[1],t.items.length);for(e=1;(t.direction?o:i)>=e;e++)t._preloadItem(t.index+e);for(e=1;(t.direction?i:o)>=e;e++)t._preloadItem(t.index-e)},_preloadItem:function(n){if(n=K(n),!t.items[n].preloaded){var i=t.items[n];i.parsed||(i=t.parseEl(n)),T("LazyLoad",i),"image"===i.type&&(i.img=e('<img class="mfp-img" />').on("load.mfploader",function(){i.hasSize=!0}).on("error.mfploader",function(){i.hasSize=!0,i.loadError=!0,T("LazyLoadError",i)}).attr("src",i.src)),i.preloaded=!0}}}});var U="retina";e.magnificPopup.registerModule(U,{options:{replaceSrc:function(e){return e.src.replace(/\.\w+$/,function(e){return"@2x"+e})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var e=t.st.retina,n=e.ratio;n=isNaN(n)?n():n,n>1&&(x("ImageHasSize."+U,function(e,t){t.img.css({"max-width":t.img[0].naturalWidth/n,width:"100%"})}),x("ElementParse."+U,function(t,i){i.src=e.replaceSrc(i,n)}))}}}}),function(){var t=1e3,n="ontouchstart"in window,i=function(){I.off("touchmove"+r+" touchend"+r)},o="mfpFastClick",r="."+o;e.fn.mfpFastClick=function(o){return e(this).each(function(){var a,s=e(this);if(n){var l,c,d,u,p,f;s.on("touchstart"+r,function(e){u=!1,f=1,p=e.originalEvent?e.originalEvent.touches[0]:e.touches[0],c=p.clientX,d=p.clientY,I.on("touchmove"+r,function(e){p=e.originalEvent?e.originalEvent.touches:e.touches,f=p.length,p=p[0],(Math.abs(p.clientX-c)>10||Math.abs(p.clientY-d)>10)&&(u=!0,i())}).on("touchend"+r,function(e){i(),u||f>1||(a=!0,e.preventDefault(),clearTimeout(l),l=setTimeout(function(){a=!1},t),o())})})}s.on("click"+r,function(){a||o()})})},e.fn.destroyMfpFastClick=function(){e(this).off("touchstart"+r+" click"+r),n&&I.off("touchmove"+r+" touchend"+r)}}(),_()})(window.jQuery||window.Zepto);
trunk/assets/js/wp-subscribe-admin.js ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plugin Name: WP Subscribe Pro
3
+ Plugin URI: http://mythemeshop.com/plugins/wp-subscribe-pro/
4
+ Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
5
+ Author: MyThemeShop
6
+ Author URI: http://mythemeshop.com/
7
+ */
8
+
9
+ ( function( $ ){
10
+
11
+ // color picker
12
+ function initColorPicker( widget ) {
13
+
14
+ var colorPickers = widget.find( '.wp-subscribe-color-select' );
15
+
16
+ if ( colorPickers.length > 0 ) {
17
+ colorPickers.wpColorPicker();
18
+ }
19
+
20
+ // and services dropdown
21
+ widget.find('.wp-subscribe-service-field select').change(function() {
22
+
23
+ var $this = $(this);
24
+
25
+ widget.find('.wp_subscribe_account_details_'+$this.val()).show().siblings('div').hide();
26
+ widget.find('.wp_subscribe_account_details').slideDown();
27
+
28
+ // Include "name" field
29
+ if ($this.val() === 'feedburner') {
30
+ widget.find('.wp_subscribe_include_name, .wp-subscribe-name_placeholder-field').hide();
31
+ } else {
32
+ widget.find('.wp_subscribe_include_name').show().find('input').trigger('change');
33
+ }
34
+
35
+ // Thanks Page option
36
+ if ($this.val() === 'mailchimp' || $this.val() === 'getresponse' || $this.val() === 'mailerlite' || $this.val() === 'benchmark' || $this.val() === 'constantcontact' || $this.val() === 'mailrelay' || $this.val() === 'activecampaign' ) {
37
+ widget.find('.wp_subscribe_thanks_page').show();
38
+ } else {
39
+ widget.find('.wp_subscribe_thanks_page').hide();
40
+ }
41
+ }).trigger('change');
42
+
43
+ widget.find('.wp_subscribe_include_name input').change(function() {
44
+ if ($(this).is(':checked')) {
45
+ $('.wp-subscribe-name_placeholder-field').show();
46
+ } else {
47
+ $('.wp-subscribe-name_placeholder-field').hide();
48
+ }
49
+ }).trigger('change');
50
+
51
+ widget.find('.thanks-page-field').change(function() {
52
+ if ($(this).is(':checked')) {
53
+ $('.wp_subscribe_thanks_page_details').show();
54
+ } else {
55
+ $('.wp_subscribe_thanks_page_details').hide();
56
+ }
57
+ }).trigger('change');
58
+ }
59
+
60
+ function onFormUpdate( event, widget ) {
61
+ initColorPicker( widget );
62
+ }
63
+
64
+ $( document ).on( 'widget-added widget-updated', onFormUpdate );
65
+
66
+ $( document ).ready( function() {
67
+ $( '#widgets-right .widget:has(.wp-subscribe-service-field select)' ).each( function () {
68
+ initColorPicker( $( this ) );
69
+ });
70
+ } );
71
+
72
+ // Get List Code
73
+ $( document ).on( 'click', '.wps-get-list', function( event ) {
74
+ event.preventDefault();
75
+
76
+ var button = $(this),
77
+ select = button.prev('select'),
78
+ parent = button.closest('.wps-account-details'),
79
+ fields = parent.find('input, textarea'),
80
+ service = parent.data('service');
81
+
82
+ var args = {};
83
+ fields.each(function(){
84
+ var f = $(this);
85
+
86
+ if ( f.data( 'id' ) && f.data( 'id' ).length > 0 ) {
87
+ var key = f.data( 'id' ).replace(service+'_', '').replace(service, '');
88
+ args[key] = f.val();
89
+ }
90
+ });
91
+
92
+ $.ajax({
93
+ url: ajaxurl,
94
+ method: 'post',
95
+ data: {
96
+ action: 'wps_get_service_list',
97
+ service: service,
98
+ args: args
99
+ },
100
+
101
+ success: function( response ) {
102
+
103
+ if( response.success && response.lists ) {
104
+ var sel = select.val();
105
+ select.html( '<option value="none">Select List</option>' );
106
+ $.each( response.lists, function( key, val ){
107
+ select.append('<option value="'+ key +'">'+ val +'</option>');
108
+ });
109
+ select.val(sel);
110
+ }
111
+ else {
112
+ console.log( response.error );
113
+ }
114
+ }
115
+ });
116
+
117
+ } );
118
+
119
+ // Aweber Autorize Code
120
+ $( document ).on( 'click', 'button.aweber_authorization', function() {
121
+
122
+ var $this= $( this ),
123
+ parent = $this.parent(),
124
+ code = parent.find( 'textarea' ).val().trim();
125
+
126
+ if( '' === code ) {
127
+ alert( 'No authorization code found.' );
128
+ return;
129
+ }
130
+
131
+ $.ajax({
132
+ url: ajaxurl,
133
+ type: 'POST',
134
+ data: {
135
+ action: 'connect_aweber',
136
+ aweber_code: code
137
+ }
138
+
139
+ }).done(function(response) {
140
+
141
+ if ( response && ! response.success && response.error ) {
142
+ alert( response.error );
143
+ return;
144
+ }
145
+
146
+ var details = parent.parent();
147
+ for( key in response.data ) {
148
+ details.find( '[id$="_' + key + '"]' ).val( response.data[ key ] );
149
+ }
150
+
151
+ parent.hide();
152
+ parent.next().show();
153
+ });
154
+ });
155
+
156
+ // Disconnect Aweber
157
+ $( document ).on( 'click', 'a.aweber_disconnect', function() {
158
+ var $this= $( this ),
159
+ parent = $this.closest( '.alert-hint' );
160
+
161
+ parent.hide();
162
+ parent.prev().show();
163
+
164
+ parent.parent().find( 'input[type="hidden"]' ).val( '' );
165
+ });
166
+
167
+ // slideToggle
168
+ $(document).on('click', function(e) {
169
+ var $this = jQuery(e.target);
170
+ var $widget = $this.closest('.wp_subscribe_options_form');
171
+ if ($widget.length) {
172
+ if ($this.is('.wp-subscribe-toggle')) {
173
+ e.preventDefault();
174
+ var $related = $widget.find('.'+$this.attr('rel'));
175
+ $related.slideToggle();
176
+ }
177
+ }
178
+ });
179
+
180
+ /*
181
+ Load Palettes
182
+ */
183
+ $(document).on('click', '.wps-load-palette', function(e) {
184
+ var $this = $(this),
185
+ $palette = $this.closest('.single-palette');
186
+
187
+ $palette.find('input.wps-palette-color').each(function(i, el) {
188
+ $('#'+$(el).attr('name')).iris('color', $(el).val());
189
+ });
190
+
191
+ e.preventDefault();
192
+ });
193
+ $(document).on('click', '.wps-toggle-palettes', function(e) {
194
+ $(this).closest('.wps-colors-loader').find('.wps-palettes').slideToggle();
195
+ e.preventDefault();
196
+ });
197
+
198
+ }( jQuery ) );
trunk/assets/js/wp-subscribe-form.js ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plugin Name: WP Subscribe Pro
3
+ Plugin URI: http://mythemeshop.com/plugins/wp-subscribe-pro/
4
+ Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
5
+ Author: MyThemeShop
6
+ Author URI: http://mythemeshop.com/
7
+ */
8
+
9
+ /* global wp_subscribe*/
10
+ jQuery(document).ready(function($) {
11
+
12
+ // AJAX subscribe form
13
+ // not working on Feedburner
14
+ $( '.wp-subscribe-form' ).submit( function( event ) {
15
+
16
+ event.preventDefault();
17
+
18
+ var form = $(this),
19
+ $widget = form.closest('.wp-subscribe').addClass('loading'),
20
+ fields = {};
21
+
22
+ $widget.find('.error').hide();
23
+ $widget.find('.thanks').hide();
24
+
25
+ if ( form.hasClass('wp-subscribe-feedburner') ) {
26
+
27
+ var original = window.open;
28
+ window.open = function( url, name, specs, replace ) {
29
+ var popup = original( url, name, specs, replace );
30
+
31
+ if( ! popup ) {
32
+ return popup;
33
+ }
34
+
35
+ if( ! url.includes( 'feedburner.google.com' ) ) {
36
+ return popup;
37
+ }
38
+
39
+ var interval = setInterval( function() {
40
+
41
+ if( popup && popup.closed ) {
42
+ clearInterval( interval );
43
+
44
+ form.hide();
45
+ $widget.removeClass('loading');
46
+ $widget.find('.error').hide();
47
+ $widget.find('.thanks').show();
48
+
49
+ var thanks_page_url = $widget.data('thanks_page_url');
50
+ if ( parseInt($widget.data('thanks_page'), 10) === 1 && thanks_page_url !== '') {
51
+ window.location.href = thanks_page_url;
52
+ }
53
+ }
54
+ }, 300 );
55
+
56
+ return popup;
57
+ };
58
+
59
+ window.open( form.attr('action') + '&' + form.serialize() , 'popupwindow', 'scrollbars=yes,width=550,height=520' );
60
+
61
+ window.open = original;
62
+
63
+ return false;
64
+ }
65
+
66
+ $.map( form.serializeArray(), function( item ){
67
+ fields[ item['name'] ] = item['value'];
68
+ });
69
+
70
+ $.ajax({
71
+
72
+ url: wp_subscribe.ajaxurl,
73
+ type: 'POST',
74
+ data: {
75
+ action: 'validate_subscribe',
76
+ wps_data: fields
77
+ }
78
+
79
+ }).done( function( data ) {
80
+
81
+ $widget.removeClass('loading');
82
+
83
+ if( data.success ) {
84
+
85
+ form.hide();
86
+ $widget.find('.error').hide();
87
+ $widget.find('.thanks').show();
88
+
89
+ var thanks_page_url = $widget.data('thanks_page_url');
90
+ if ( parseInt($widget.data('thanks_page'), 10) === 1 && thanks_page_url !== '') {
91
+ window.location.href = thanks_page_url;
92
+ }
93
+ }
94
+ else {
95
+ if ( data.error ) {
96
+ $widget.find('.error').html(data.error).show();
97
+ }
98
+ else {
99
+ $widget.find('.error').show();
100
+ }
101
+ }
102
+ });
103
+
104
+ });
105
+ });
trunk/assets/js/wp-subscribe-options.js ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plugin Name: WP Subscribe Pro
3
+ Plugin URI: http://mythemeshop.com/plugins/wp-subscribe-pro/
4
+ Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
5
+ Author: MyThemeShop
6
+ Author URI: http://mythemeshop.com/
7
+ */
8
+
9
+ /* global wps_opts */
10
+ ;( function( $ ) {
11
+
12
+ var WpSubscriber = {
13
+
14
+ init: function() {
15
+
16
+ // Cache
17
+ this.previewButtons = $('.wp-subscribe-preview-popup');
18
+ this.popupOptions = $('#wp-subscribe-popup-options');
19
+
20
+ // Init others
21
+ this.colorPicker();
22
+ this.popup();
23
+ this.subscription();
24
+ this.singlePost();
25
+ this.misc();
26
+ },
27
+
28
+ singlePost: function() {
29
+
30
+ $('#wp_subscribe_enable_single_post_form').change(function() {
31
+
32
+ if ( $(this).is(':checked') ) {
33
+ $('#wp-subscribe-single-options').slideDown();
34
+ } else {
35
+ $('#wp-subscribe-single-options').slideUp();
36
+ }
37
+
38
+ });
39
+
40
+ $('#copy_options_popup_to_single').click(function( event ) {
41
+
42
+ event.preventDefault();
43
+
44
+ $('#wp-subscribe-single-options').find('input').each(function() {
45
+ var $input = $(this);
46
+ var $mapped = $('#'+this.id.replace('single_post', 'popup'));
47
+ if ( $mapped.length && $mapped.prop('id') !== this.id ) {
48
+ $input.val($mapped.val()).trigger('change');
49
+ }
50
+ });
51
+
52
+ var service = $('#popup_form_service').val();
53
+ $('#single_post_form_service option').each(function() {
54
+ var $this = $(this);
55
+ if ( service === $this.attr('value') ) {
56
+ $this.prop('selected', true);
57
+ }
58
+ else {
59
+ $this.prop('selected', false);
60
+ }
61
+ }).trigger('change');
62
+ });
63
+ },
64
+
65
+ subscription: function() {
66
+
67
+ var formLabels = $('._popup_form_labels_name_placeholder-wrapper'),
68
+ postLabels = $('._single_post_form_labels_name_placeholder-wrapper');
69
+
70
+ $('.services_dropdown').change(function() {
71
+
72
+ var $this = $(this),
73
+ value = $this.val(),
74
+ parent = $this.parent(),
75
+ nameFields = parent.siblings( '.wp_subscribe_include_name_wrapper' ),
76
+ thankyouFields = parent.siblings( '.wp_subscribe_thanks_page' );
77
+
78
+ parent.next().find('.wp_subscribe_account_details_'+$this.val()).show().siblings().hide();
79
+
80
+ if ( 'feedburner' === value ) {
81
+ nameFields.hide();
82
+
83
+ if ( $this.closest('#wp-subscribe-single-options').length ) {
84
+ postLabels.hide();
85
+ }
86
+ else {
87
+ formLabels.hide();
88
+ }
89
+
90
+ } else {
91
+ nameFields.show().find('input').trigger('change');
92
+ }
93
+
94
+ // Thanks Page option
95
+ if ( -1 < $.inArray( value, [ 'mailchimp', 'getresponse', 'mailerlite', 'benchmark', 'constantcontact', 'mailrelay', 'activecampaign' ] ) ) {
96
+ thankyouFields.show();
97
+ } else {
98
+ thankyouFields.hide();
99
+ }
100
+
101
+ }).trigger('change');
102
+
103
+ $('.thanks-page-field').change(function() {
104
+
105
+ $(this).parent().siblings('.wp_subscribe_thanks_page_details').toggle( this.checked );
106
+
107
+ }).trigger( 'change' );
108
+
109
+ $('.wp_subscribe_include_name_wrapper input').change(function() {
110
+
111
+ var $this = $(this);
112
+
113
+ if ( $this.is(':checked') ) {
114
+ if ($this.closest('#wp-subscribe-single-options').length) {
115
+ postLabels.show();
116
+ }
117
+ else {
118
+ formLabels.show();
119
+ }
120
+ } else {
121
+ if ($this.closest('#wp-subscribe-single-options').length) {
122
+ postLabels.hide();
123
+ }
124
+ else {
125
+ formLabels.hide();
126
+ }
127
+ }
128
+
129
+ }).trigger('change');
130
+
131
+ // Get List Code
132
+ $('.wps-get-list').on( 'click', function( event ) {
133
+ event.preventDefault();
134
+
135
+ var button = $(this),
136
+ select = button.prev('select'),
137
+ parent = button.closest('.wps-account-details'),
138
+ fields = parent.find('input, textarea'),
139
+ service = parent.data('service');
140
+
141
+ var args = {};
142
+ fields.each(function(){
143
+ var f = $(this);
144
+
145
+ if ( f.data( 'id' ) && f.data( 'id' ).length > 0 ) {
146
+ var key = f.data( 'id' ).replace(service+'_', '').replace(service, '');
147
+ args[key] = f.val();
148
+ }
149
+ });
150
+
151
+ $.ajax({
152
+ url: ajaxurl,
153
+ method: 'post',
154
+ data: {
155
+ action: 'wps_get_service_list',
156
+ service: service,
157
+ args: args
158
+ },
159
+
160
+ success: function( response ) {
161
+
162
+ if( response.success && response.lists ) {
163
+ var sel = select.val();
164
+ select.html( '<option value="none">Select List</option>' );
165
+ $.each( response.lists, function( key, val ){
166
+ select.append('<option value="'+ key +'">'+ val +'</option>');
167
+ });
168
+ select.val(sel);
169
+ }
170
+ else {
171
+ console.log( response.error );
172
+ }
173
+ }
174
+ });
175
+
176
+ } );
177
+ },
178
+
179
+ colorPicker: function() {
180
+
181
+ $('.wp-subscribe-color-select').wpColorPicker({
182
+ change: _.throttle(function(event, ui) {
183
+ $(this).trigger( 'colorchange', [ui.color.toString()] );
184
+ }, 2000 )
185
+ });
186
+
187
+ $(document).on('click', '.wps-load-palette', function( event ) {
188
+
189
+ event.preventDefault();
190
+
191
+ var $this = $(this),
192
+ palette = $this.closest('.single-palette');
193
+
194
+ palette.find('input.wps-palette-color').each(function( i, el ) {
195
+
196
+ var elem = $(el);
197
+
198
+ $('#' + elem.attr('name') ).iris('color', elem.val() );
199
+ });
200
+ });
201
+
202
+ $(document).on('click', '.wps-toggle-palettes', function( event ) {
203
+
204
+ event.preventDefault();
205
+
206
+ $(this).closest('.wps-colors-loader').find('.wps-palettes').slideToggle();
207
+ });
208
+ },
209
+
210
+ popup: function() {
211
+
212
+ var wps = this;
213
+
214
+ wps.popupColor();
215
+ wps.popupOpacity();
216
+ wps.popupWidth();
217
+ wps.popupPreview();
218
+
219
+ $('#wp_subscribe_enable_popup').change(function() {
220
+
221
+ if ( $(this).is(':checked') ) {
222
+
223
+ wps.popupOptions.slideDown();
224
+ $('.ifpopup').show();
225
+
226
+ } else {
227
+
228
+ wps.popupOptions.slideUp();
229
+ $('.ifpopup').hide();
230
+
231
+ }
232
+ });
233
+
234
+ $('.popup_content_field').change(function() {
235
+
236
+ var value = $(this).val(),
237
+ form = $('#wp-subscribe-form-options'),
238
+ posts = $('#wp-subscribe-popup-posts-options'),
239
+ custom = $('#wp-subscribe-custom-html-field');
240
+
241
+ // Hide All
242
+ form.hide();
243
+ posts.hide();
244
+ custom.hide();
245
+
246
+ switch( value ) {
247
+
248
+ case 'subscribe_form':
249
+ form.show();
250
+ break;
251
+
252
+ case 'posts':
253
+ posts.show();
254
+ break;
255
+
256
+ case 'custom_html':
257
+ custom.show();
258
+ break;
259
+ }
260
+
261
+ var $tab = $('#popup-content-tab');
262
+ $tab.addClass('nav-tab-active');
263
+ setTimeout(function() {
264
+ $tab.removeClass('nav-tab-active');
265
+ }, 200);
266
+ });
267
+
268
+ wps.firePopup( wps_opts.popup_removal_delay );
269
+
270
+ $('#popup_animation_in').on('change', function() {
271
+ wps.previewButtons.attr( 'data-animatein', $(this).val() );
272
+ });
273
+
274
+ $('#popup_animation_out').on('change', function() {
275
+
276
+ var value = $(this).val();
277
+ wps.previewButtons.attr( 'data-animateout', value );
278
+
279
+ if (value === 'hinge') {
280
+ wps.firePopup(2000);
281
+ } else if (value === '0') {
282
+ wps.firePopup(0);
283
+ } else {
284
+ wps.firePopup(800);
285
+ }
286
+ });
287
+ },
288
+
289
+ firePopup: function(removal_delay) {
290
+
291
+ var wps = this;
292
+
293
+ wps.previewButtons.magnificPopup({
294
+ type:'inline',
295
+ midClick: true,
296
+ removalDelay: removal_delay, //delay removal by X to allow out-animation
297
+ callbacks: {
298
+ beforeOpen: function() {
299
+ this.st.mainClass = 'animated ' + this.st.el.attr( 'data-animatein' );
300
+ },
301
+ beforeClose: function() {
302
+ var $wrap = this.wrap,
303
+ $bg = $wrap.prev(),
304
+ $mfp = $wrap.add($bg);
305
+
306
+ $mfp.removeClass( this.st.el.attr( 'data-animatein' ) ).addClass( this.st.el.attr( 'data-animateout' ) );
307
+ }
308
+ }
309
+ });
310
+ },
311
+
312
+ popupPreview: function() {
313
+
314
+ var wps = this;
315
+
316
+ $('.popup_content_field, .wps-popup-content-options input, .wp-editor-area').on('change colorchange', function() {
317
+
318
+ wps.previewButtons.addClass('disabled');
319
+
320
+ var fields = $('#wp_subscribe_options_form').serialize() + '&action=preview_popup';
321
+ $.ajax({
322
+ url: ajaxurl,
323
+ type: 'POST',
324
+ dataType: 'html',
325
+ data: fields,
326
+
327
+ }).done(function(response) {
328
+
329
+ $('#wp_subscribe_popup').html(response);
330
+
331
+ }).always(function() {
332
+
333
+ wps.previewButtons.removeClass('disabled');
334
+
335
+ });
336
+ });
337
+ },
338
+
339
+ popupOpacity: function() {
340
+
341
+ var changeOpacity = function( opacity ) {
342
+ $( '#overlay-style-opacity' ).html( '.mfp-bg.mfp-ready {opacity: ' + opacity + ';}' );
343
+ };
344
+
345
+ var input = $( '#wp_subscribe_overlay_opacity' ),
346
+ slider = $( '#wp-subscribe-opacity-slider' );
347
+
348
+ input.on('change', function() {
349
+ var value = parseFloat( input.val() );
350
+ if ( value < 0 ) {
351
+ value = 0;
352
+ input.val('0');
353
+ } else if ( value > 1 ) {
354
+ value = 1;
355
+ input.val('1');
356
+ }
357
+ slider.slider( 'value', value );
358
+ changeOpacity( value );
359
+ });
360
+
361
+ slider.slider({
362
+ range: 'min',
363
+ value: input.val(),
364
+ step: 0.01,
365
+ min: 0,
366
+ max: 1,
367
+ slide: function(event, ui) {
368
+ input.val( ui.value );
369
+ changeOpacity( ui.value );
370
+ }
371
+ });
372
+ },
373
+
374
+ popupColor: function() {
375
+
376
+ $('#wp_subscribe_options_colors_popup_overlay_color').on( 'colorchange', function( event, color ) {
377
+ $('#overlay-style-color').html('.mfp-bg {background: ' + color + ';}');
378
+ });
379
+ },
380
+
381
+ popupWidth: function() {
382
+
383
+ var changeWidth = function( width ) {
384
+ $('#popup-style-width').html('#wp_subscribe_popup {width: ' + width + 'px;}');
385
+
386
+ var breakpoints = [300, 600, 900],
387
+ popup = $('#wp_subscribe_popup');
388
+
389
+ $.each(breakpoints, function(index, breakpoint) {
390
+ if (width < breakpoint) {
391
+ popup.addClass( 'lt_' + breakpoint );
392
+ } else {
393
+ popup.removeClass( 'lt_' + breakpoint );
394
+ }
395
+ });
396
+ };
397
+
398
+ var input = $( '#wp_subscribe_popup_width' ),
399
+ slider = $( '#wp-subscribe-popup-width-slider' );
400
+
401
+ input.on('change', function() {
402
+ var value = parseFloat( input.val() );
403
+
404
+ if (value < 0) {
405
+ value = 0;
406
+ input.val('0');
407
+ } else if (value > 1200) {
408
+ value = 1200;
409
+ input.val('1200');
410
+ }
411
+
412
+ slider.slider( 'value', value );
413
+ changeWidth( value );
414
+ });
415
+
416
+ slider.slider({
417
+ range: 'min',
418
+ value: input.val(),
419
+ step: 10,
420
+ min: 200,
421
+ max: 1200,
422
+ slide: function(event, ui) {
423
+ input.val( ui.value );
424
+ changeWidth( ui.value );
425
+ }
426
+ });
427
+ },
428
+
429
+ misc: function() {
430
+
431
+ $('#wp_subscribe_regenerate_cookie').click(function( event ) {
432
+
433
+ event.preventDefault();
434
+
435
+ $('#cookies-cleared').fadeIn();
436
+ $('#cookiehash').val(new Date().getTime());
437
+
438
+ });
439
+
440
+ // Tabs
441
+ var tabNav = $( '.wps-nav-tab-wrapper a' ),
442
+ tabContent = $( ' > div ', '.wps-tabs-wrapper');
443
+
444
+ tabNav.click(function( event ) {
445
+
446
+ event.preventDefault();
447
+
448
+ var $this = $(this);
449
+
450
+ tabNav.removeClass( 'nav-tab-active' );
451
+ $this.addClass( 'nav-tab-active' );
452
+
453
+ tabContent.hide();
454
+ tabContent.closest( $this.data('rel') ).show();
455
+
456
+ });
457
+
458
+ // Aweber Autorize Code
459
+ $( 'button.aweber_authorization' ).on( 'click', function() {
460
+
461
+ var $this= $( this ),
462
+ parent = $this.parent(),
463
+ code = parent.find( 'textarea' ).val().trim();
464
+
465
+ if( '' === code ) {
466
+ alert( 'No authorization code found.' );
467
+ return;
468
+ }
469
+
470
+ $.ajax({
471
+ url: ajaxurl,
472
+ type: 'POST',
473
+ data: {
474
+ action: 'connect_aweber',
475
+ aweber_code: code
476
+ }
477
+
478
+ }).done(function(response) {
479
+
480
+ if ( response && ! response.success && response.error ) {
481
+ alert( response.error );
482
+ return;
483
+ }
484
+
485
+ var details = parent.parent();
486
+ for( key in response.data ) {
487
+ details.find( '[id$="_' + key + '"]' ).val( response.data[ key ] );
488
+ }
489
+
490
+ parent.hide();
491
+ parent.next().show();
492
+ });
493
+ });
494
+
495
+ // Disconnect Aweber
496
+ $( 'a.aweber_disconnect' ).on( 'click', function() {
497
+ var $this= $( this ),
498
+ parent = $this.closest( '.alert-hint' );
499
+
500
+ parent.hide();
501
+ parent.prev().show();
502
+
503
+ parent.parent().find( 'input[type="hidden"]' ).val( '' );
504
+ });
505
+ }
506
+ };
507
+
508
+ $( document ).ready( function() {
509
+ WpSubscriber.init();
510
+ } );
511
+
512
+ }( jQuery ) );
trunk/includes/class-wps-base.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Base
4
+ * The base class for all the classes
5
+ */
6
+
7
+ if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
+
9
+ if( ! class_exists( 'WPS_Base' ) ):
10
+
11
+ /**
12
+ * Base Class
13
+ */
14
+ class WPS_Base {
15
+
16
+ /**
17
+ * Admin page ID
18
+ * @var string
19
+ */
20
+ public $id;
21
+
22
+ /**
23
+ * Add action
24
+ *
25
+ * @see add_action
26
+ */
27
+ protected function add_action( $hook, $func, $priority = 10, $args = 1 ) {
28
+ add_action( $hook, array( &$this, $func ), $priority, $args );
29
+ }
30
+
31
+ /**
32
+ * Add filter
33
+ *
34
+ * @see add_filter
35
+ */
36
+ protected function add_filter( $hook, $func, $priority = 10, $args = 1 ) {
37
+ add_filter( $hook, array( &$this, $func ), $priority, $args );
38
+ }
39
+
40
+ /**
41
+ * Remove Action
42
+ *
43
+ * @see remove_action
44
+ */
45
+ protected function remove_action( $hook, $func, $priority = 10, $args = 1 ) {
46
+ remove_action( $hook, array( &$this, $func ), $priority, $args );
47
+ }
48
+
49
+ /**
50
+ * Remove filter
51
+ *
52
+ * @see remove_filter
53
+ */
54
+ protected function remove_filter( $hook, $func, $priority = 10, $args = 1 ) {
55
+ remove_filter( $hook, array( &$this, $func ), $priority, $args );
56
+ }
57
+
58
+ /**
59
+ * Inject config into class
60
+ *
61
+ * @param array $config
62
+ * @return void
63
+ */
64
+ protected function config( $config = array() ) {
65
+
66
+ // check
67
+ if( empty( $config ) ) {
68
+ return;
69
+ }
70
+
71
+ foreach( $config as $key => $value ) {
72
+ $this->$key = $value;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Is current page equals this
78
+ *
79
+ * @return boolean
80
+ */
81
+ protected function is_current_page() {
82
+ $page = isset( $_GET['page'] ) && !empty( $_GET['page'] ) ? $_GET['page'] : false;
83
+ return $page === $this->id;
84
+ }
85
+ }
86
+
87
+ endif;
trunk/includes/subscription/class-wps-aweber.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Aweber Subscription
4
+ */
5
+ class WPS_Subscription_Aweber extends WPS_Subscription_Base {
6
+
7
+ /**
8
+ * Aweber Credentials
9
+ * @var mixed
10
+ */
11
+ public $credentials;
12
+
13
+ /**
14
+ * API Key
15
+ * @var string
16
+ */
17
+ public $api_key;
18
+
19
+ /**
20
+ * Credential option key
21
+ * @return string
22
+ */
23
+ private $key = 'mts_wps_awerber_credentials';
24
+
25
+ public function init() {
26
+
27
+ if( !class_exists( 'AWeberAPI' ) ) {
28
+ require_once 'libs/aweber_api/aweber.php';
29
+ }
30
+
31
+ $credentials = $this->get_credentials();
32
+
33
+ if( empty( $credentials['consumer_key'] ) || empty( $credentials['consumer_secret'] ) ) {
34
+ throw new Exception ('Aweber is not connected.');
35
+ }
36
+
37
+ if( empty( $credentials['account_id'] ) ) {
38
+ throw new Exception ('The Aweber Account ID is not set.');
39
+ }
40
+
41
+ $api = new AWeberAPI( $credentials['consumer_key'], $credentials['consumer_secret'] );
42
+
43
+ return $api;
44
+ }
45
+
46
+ public function get_credentials() {
47
+
48
+ if( !empty( $this->credentials ) ) {
49
+ return $this->credentials;
50
+ }
51
+
52
+ $credentials = array_filter( $credentials );
53
+
54
+ if ( empty( $credentials ) ) {
55
+ $credentials = get_option( $this->key );
56
+ }
57
+
58
+ $this->credentials = empty( $credentials ) ? null : $credentials;
59
+
60
+ return $this->credentials;
61
+ }
62
+
63
+ public function connect( $api_key = '' ) {
64
+
65
+ // if the auth code is empty, show the error
66
+ if ( empty( $api_key ) ) {
67
+ throw new Exception( esc_html__( 'Unable to connect to Aweber. The Authorization Code is empty.', 'wp-subscribe' ) );
68
+ }
69
+
70
+ if ( ! class_exists( 'AWeberAPI' ) ) {
71
+ require_once dirname( __FILE__ ) . '/libs/aweber_api/aweber.php';
72
+ }
73
+
74
+ list( $consumer_key, $consumer_secret, $access_key, $access_secret ) = AWeberAPI::getDataFromAweberID( $api_key );
75
+
76
+ if ( empty( $consumer_key ) || empty( $consumer_secret ) || empty( $access_key ) || empty( $access_secret ) ) {
77
+ throw new Exception( esc_html__('Unable to connect your Aweber Account. The Authorization Code is incorrect.', 'wp-subscribe' ) );
78
+ }
79
+
80
+ $aweber = new AWeberAPI( $consumer_key, $consumer_secret );
81
+ $account = $aweber->getAccount( $access_key, $access_secret );
82
+
83
+ $credentials = array(
84
+ 'consumer_key' => $consumer_key,
85
+ 'consumer_secret' => $consumer_secret,
86
+ 'access_key' => $access_key,
87
+ 'access_secret' => $access_secret,
88
+ 'account_id' => $account->id
89
+ );
90
+
91
+ update_option( $this->key, $credentials );
92
+
93
+ return $credentials;
94
+ }
95
+
96
+ public function get_account() {
97
+
98
+ $aweber = $this->init();
99
+ $credentials = $this->get_credentials();
100
+
101
+ if( empty( $credentials['access_key'] ) || empty( $credentials['access_secret'] ) ) {
102
+ throw new Exception ('[init]: Aweber is not connected.');
103
+ }
104
+
105
+ return $aweber->getAccount( $credentials['access_key'], $credentials['access_secret'] );
106
+ }
107
+
108
+ public function get_lists() {
109
+
110
+ $this->credentials = end( func_get_args() );
111
+ $account = $this->get_account();
112
+
113
+ $lists = array();
114
+ foreach( $account->lists->data['entries'] as $list ) {
115
+ $lists[ $list['id'] ] = $list['name'];
116
+ }
117
+
118
+ return $lists;
119
+ }
120
+
121
+ public function subscribe( $identity, $options ) {
122
+
123
+ try {
124
+ $this->credentials = $options;
125
+ $account = $this->get_account();
126
+
127
+ $list_url = "/accounts/{$account->id}/lists/{$options['list_id']}/subscribers";
128
+ $list = $account->loadFromUrl($list_url);
129
+
130
+ $name = $this->get_fullname( $identity );
131
+ $params = array(
132
+ 'name' => $name,
133
+ 'email' => $identity['email'],
134
+ 'ip_address' => $_SERVER['REMOTE_ADDR'],
135
+ 'ad_tracking' => 'mythemeshop'
136
+ );
137
+
138
+ $list->create( $params );
139
+
140
+ return array(
141
+ 'status' => 'subscribed'
142
+ );
143
+ }
144
+ catch( Exception $e ) {
145
+
146
+ // already waiting confirmation:
147
+ // "Subscriber already subscribed and has not confirmed."
148
+ if ( strpos( $e->getMessage(), 'has not confirmed' ) ) {
149
+ return array( 'status' => 'pending' );
150
+ }
151
+
152
+ // already waiting confirmation:
153
+ // "Subscriber already subscribed."
154
+ if ( strpos( $e->getMessage(), 'already subscribed' ) ) {
155
+ return array( 'status' => 'pending' );
156
+ }
157
+
158
+ throw new Exception ( '[subscribe]: ' . $e->getMessage() );
159
+ }
160
+ }
161
+
162
+ public function get_fields() {
163
+
164
+ $fields = array(
165
+
166
+ 'aweber_raw' => array(
167
+ 'id' => 'aweber_raw',
168
+ 'name' => 'aweber_raw',
169
+ 'type' => 'raw',
170
+ 'content' => array( $this, 'raw_content' )
171
+ ),
172
+
173
+ 'aweber_consumer_key' => array(
174
+ 'id' => 'aweber_consumer_key',
175
+ 'name' => 'aweber_consumer_key',
176
+ 'type' => 'hidden',
177
+ ),
178
+ 'aweber_consumer_secret' => array(
179
+ 'id' => 'aweber_consumer_secret',
180
+ 'name' => 'aweber_consumer_secret',
181
+ 'type' => 'hidden',
182
+ ),
183
+ 'aweber_access_key' => array(
184
+ 'id' => 'aweber_access_key',
185
+ 'name' => 'aweber_access_key',
186
+ 'type' => 'hidden',
187
+ ),
188
+ 'aweber_access_secret' => array(
189
+ 'id' => 'aweber_access_secret',
190
+ 'name' => 'aweber_access_secret',
191
+ 'type' => 'hidden',
192
+ ),
193
+ 'aweber_account_id' => array(
194
+ 'id' => 'aweber_account_id',
195
+ 'name' => 'aweber_account_id',
196
+ 'type' => 'hidden',
197
+ ),
198
+
199
+ 'aweber_list_id' => array(
200
+ 'id' => 'aweber_list_id',
201
+ 'name' => 'aweber_list_id',
202
+ 'type' => 'select',
203
+ 'title' => esc_html__( 'AWeber List', 'wp-subscribe' ),
204
+ 'options' => array( 'none' => esc_html__( 'Select List', 'wp-subscribe' ) ) + wps_get_service_list( 'aweber' ),
205
+ 'is_list' => true
206
+ ),
207
+ );
208
+
209
+ return $fields;
210
+ }
211
+
212
+ public function raw_content() {
213
+ $instance = $this->instance;
214
+
215
+ ?>
216
+ <div class="aweber_authorization_area mb30<?php echo ! empty( $instance['aweber_access_key'] ) ? ' hidden' : '' ?>">
217
+ <strong><?php esc_html_e( 'To connect your Aweber account:', 'content-locker' ) ?></strong>
218
+ <br />
219
+ <ul>
220
+ <li><?php printf( wp_kses_post( __( '<span>1.</span> <a href="%s" target="_blank">Click here</a> <span>to open the authorization page and log in.</span>', 'content-locker' ) ), 'https://auth.aweber.com/1.0/oauth/authorize_app/1afc783e' ) ?></li>
221
+ <li><?php echo wp_kses_post( __( '<span>2.</span> Copy and paste the authorization code in the field below.', 'content-locker' ) ) ?></li>
222
+ </ul>
223
+
224
+ <textarea rows="4" cols="80"></textarea>
225
+ <br />
226
+ <button type="button" class="button-primary aweber_authorization">Authorize</button>
227
+ </div>
228
+ <div class="alert alert-hint mb30 <?php echo empty( $instance['aweber_access_key'] ) ? ' hidden' : '' ?>">
229
+ <p>
230
+ <strong><?php _e( 'Your Aweber Account is connected.', 'content-locker' ) ?></strong>
231
+ <?php echo wp_kses_post( __( '<a href="#" class="aweber_disconnect">Click here</a> <span>to disconnect.</span>', 'content-locker' ) ) ?>
232
+ </p>
233
+ </div>
234
+ <?php
235
+ }
236
+ }
trunk/includes/subscription/class-wps-base.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A class for subscription services
4
+ */
5
+ abstract class WPS_Subscription_Base {
6
+
7
+ /**
8
+ * To hold the configuration
9
+ * @var array
10
+ */
11
+ public $config;
12
+
13
+ /**
14
+ * Hold Service Options
15
+ * @var array
16
+ */
17
+ public $options;
18
+
19
+ /**
20
+ * The Constructor
21
+ * @param array $config [description]
22
+ */
23
+ public function __construct( $config = array() ) {
24
+
25
+ $this->config = $config;
26
+ }
27
+
28
+ /**
29
+ * Is a valid email address
30
+ * @param string $email
31
+ * @return boolean
32
+ */
33
+ public function is_email( $email ) {
34
+ return filter_var( $email, FILTER_VALIDATE_EMAIL );
35
+ }
36
+
37
+ /**
38
+ * Check for single optin method
39
+ * @return boolean
40
+ */
41
+ public function has_single_optin() {
42
+ return in_array( 'quick', $this->config['modes'] );
43
+ }
44
+
45
+ /**
46
+ * Get identity fullname
47
+ * @param array $identity
48
+ * @return string
49
+ */
50
+ public function get_fullname( $identity ) {
51
+
52
+ if ( !empty( $identity['name'] ) && !empty( $identity['family'] ) ) {
53
+ return $identity['name'] . ' ' . $identity['family'];
54
+ }
55
+
56
+ if ( !empty( $identity['name'] ) ) {
57
+ return $identity['name'];
58
+ }
59
+
60
+ if ( !empty( $identity['family'] ) ) {
61
+ return $identity['family'];
62
+ }
63
+
64
+ if( !empty( $identity['display_name'] ) ) {
65
+ return $identity['display_name'];
66
+ }
67
+
68
+ return '';
69
+ }
70
+
71
+ public function get_fields() {
72
+ return array();
73
+ }
74
+
75
+ public function get_options( $data ) {
76
+
77
+ $options = array();
78
+ $new_options = array();
79
+
80
+ if( 'widget' === $data['form_type'] && $data['widget'] ) {
81
+ $options = wps_get_widget_settings( $data['widget'] );
82
+ }
83
+ else {
84
+ $options = wps_get_options();
85
+ $options = $options["{$data['form_type']}_form_options"];
86
+ }
87
+
88
+ foreach( $this->get_fields() as $key => $item ) {
89
+
90
+ if( isset( $options[ $key ] ) ) {
91
+ $new_key = str_replace( "{$data['service']}_", '', $key );
92
+ $new_key = str_replace( "{$data['service']}", '', $new_key );
93
+ $new_options[$new_key] = $options[ $key ];
94
+ }
95
+ }
96
+
97
+ return $new_options;
98
+ }
99
+
100
+ public function display_form() {
101
+
102
+ $args = func_get_args();
103
+ $instance = array_shift($args);
104
+ $widget = array_shift($args);
105
+ $fields = $this->get_fields( $instance );
106
+ $this->instance = $instance;
107
+
108
+ foreach( $fields as $id => $field ) {
109
+ $func = is_null( $widget ) ? 'wps_field_' . $field['type'] : 'field_' . $field['type'];
110
+ $field['value'] = isset( $instance[$id] ) ? $instance[$id] : '';
111
+
112
+ if( is_null( $widget ) && function_exists( $func ) ) {
113
+ $arguments = array_merge( array( $field ), $args );
114
+ call_user_func_array( $func, $arguments );
115
+ }
116
+
117
+ if( !is_null( $widget ) && method_exists( $widget, $func ) ) {
118
+ $arguments = array_merge( array( $field ), $args );
119
+ call_user_func_array( array( $widget, $func ), $arguments );
120
+ }
121
+ }
122
+ }
123
+
124
+ public function the_name_field( $name ) {
125
+
126
+ if( !empty( $this->options['include_name_field'] ) ) {
127
+ printf( '<input class="regular-text name-field" type="text" name="%s" placeholder="%s">', esc_attr( $name ), esc_attr( $this->options['name_placeholder'] ) );
128
+ }
129
+ }
130
+
131
+ public function the_email_field( $name ) {
132
+
133
+ printf( '<input class="regular-text email-field" type="text" name="%s" placeholder="%s">', esc_attr( $name ), esc_attr( $this->options['email_placeholder'] ) );
134
+ }
135
+
136
+ public function the_submit_button() {
137
+
138
+ printf( '<input class="submit" type="submit" name="submit" value="%s">', esc_attr( $this->options['button_text'] ) );
139
+ }
140
+ }
trunk/includes/subscription/class-wps-feedburner.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FeedBurner Subscription
4
+ */
5
+
6
+ class WPS_Subscription_FeedBurner extends WPS_Subscription_Base {
7
+
8
+ public function the_form( $id, $options ) {
9
+ ?>
10
+
11
+ <form action="https://feedburner.google.com/fb/a/mailverify?uri=<?php echo $options['feedburner_id'] ?>" method="post" class="wp-subscribe-form wp-subscribe-feedburner" id="wp-subscribe-form-<?php echo $id ?>" target="popupwindow">
12
+
13
+ <input class="regular-text email-field" type="text" name="email" placeholder="<?php echo esc_attr( $options['email_placeholder'] ) ?>">
14
+
15
+ <input type="hidden" name="uri" value="<?php echo $options['feedburner_id'] ?>">
16
+
17
+ <input type="hidden" name="loc" value="en_US">
18
+
19
+ <input type="hidden" name="form_type" value="<?php echo $options['form_type'] ?>">
20
+
21
+ <input type="hidden" name="service" value="<?php echo $options['service'] ?>">
22
+
23
+ <input type="hidden" name="widget" value="<?php echo isset( $options['widget_id'] ) ? $options['widget_id'] : '0'; ?>">
24
+
25
+ <input class="submit" type="submit" name="submit" value="<?php echo esc_attr( $options['button_text'] ) ?>">
26
+
27
+ </form>
28
+
29
+ <?php
30
+ }
31
+
32
+ public function get_fields() {
33
+
34
+ $fields = array(
35
+ 'feedburner_id' => array(
36
+ 'id' => 'feedburner_id',
37
+ 'name' => 'feedburner_id',
38
+ 'type' => 'text',
39
+ 'title' => esc_html__( 'Feedburner ID', 'wp-subscribe' ),
40
+ )
41
+ );
42
+
43
+ return $fields;
44
+ }
45
+ }
trunk/includes/subscription/class-wps-mailchimp.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MailChimp Subscription
4
+ */
5
+
6
+ class WPS_Subscription_MailChimp extends WPS_Subscription_Base {
7
+
8
+ public function init( $api_key ) {
9
+
10
+ require_once 'libs/mailchimp.php';
11
+ return new MailChimp( $api_key );
12
+ }
13
+
14
+ public function get_lists( $api_key ) {
15
+
16
+ $mailchimp = $this->init( $api_key );
17
+ $result = $mailchimp->get('lists');
18
+
19
+ if( $mailchimp->getLastError() ) {
20
+ throw new Exception( $mailchimp->getLastError() );
21
+ }
22
+
23
+ $lists = array();
24
+ foreach( $result['lists'] as $list ) {
25
+ $lists[ $list['id'] ] = $list['name'];
26
+ }
27
+
28
+ return $lists;
29
+ }
30
+
31
+ public function subscribe( $identity, $options ) {
32
+
33
+ $vars = array();
34
+ if ( !empty( $identity['name'] ) ) {
35
+ $vars['FNAME'] = $identity['name'];
36
+ $vars['MERGE1'] = $identity['name'];
37
+ }
38
+
39
+ $mailchimp = $this->init( $options['api_key'] );
40
+ $subscriber_hash = $mailchimp->subscriberHash($identity['email']);
41
+ $mailchimp->put( 'lists/'. $options['list_id'] .'/members/' . $subscriber_hash, [
42
+ 'email_address' => $identity['email'],
43
+ 'merge_fields' => empty( $vars ) ? new stdClass : $vars,
44
+ 'status' => $options['double_optin'] ? 'pending' : 'subscribed'
45
+ ]);
46
+
47
+ if( $mailchimp->getLastError() ) {
48
+ throw new Exception( $mailchimp->getLastError() );
49
+ }
50
+
51
+ return array(
52
+ 'status' => 'subscribed'
53
+ );
54
+ }
55
+
56
+ public function get_fields() {
57
+
58
+ $fields = array(
59
+ 'mailchimp_api_key' => array(
60
+ 'id' => 'mailchimp_api_key',
61
+ 'name' => 'mailchimp_api_key',
62
+ 'type' => 'text',
63
+ 'title' => esc_html__( 'MailChimp API URL', 'wp-subscribe' ),
64
+ 'desc' => esc_html__( 'The API key of your MailChimp account.', 'wp-subscribe' ),
65
+ 'link' => 'http://kb.mailchimp.com/integrations/api-integrations/about-api-keys#Finding-or-generating-your-API-key',
66
+ ),
67
+
68
+ 'mailchimp_list_id' => array(
69
+ 'id' => 'mailchimp_list_id',
70
+ 'name' => 'mailchimp_list_id',
71
+ 'type' => 'select',
72
+ 'title' => esc_html__( 'MailChimp List', 'wp-subscribe' ),
73
+ 'options' => array( 'none' => esc_html__( 'Select List', 'wp-subscribe' ) ) + wps_get_service_list('mailchimp'),
74
+ 'is_list' => true
75
+ ),
76
+
77
+ 'mailchimp_double_optin' => array(
78
+ 'id' => 'mailchimp_double_optin',
79
+ 'name' => 'mailchimp_double_optin',
80
+ 'type' => 'checkbox',
81
+ 'title' => esc_html__( 'Send double opt-in notification', 'wp-subscribe' )
82
+ )
83
+ );
84
+
85
+ return $fields;
86
+ }
87
+ }
trunk/includes/subscription/libs/aweber_api/aweber.php ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( 'exceptions.php' );
4
+ require_once( 'oauth_adapter.php' );
5
+ require_once( 'oauth_application.php' );
6
+
7
+ /**
8
+ * AWeberServiceProvider
9
+ *
10
+ * Provides specific AWeber information or implementing OAuth.
11
+ * @uses OAuthServiceProvider
12
+ * @package
13
+ * @version $id$
14
+ */
15
+
16
+ if( ! class_exists('AWeberServiceProvider') ) :
17
+
18
+ class AWeberServiceProvider implements OAuthServiceProvider {
19
+
20
+ /**
21
+ * @var String Location for API calls
22
+ */
23
+ public $baseUri = 'https://api.aweber.com/1.0';
24
+
25
+ /**
26
+ * @var String Location to request an access token
27
+ */
28
+ public $accessTokenUrl = 'https://auth.aweber.com/1.0/oauth/access_token';
29
+
30
+ /**
31
+ * @var String Location to authorize an Application
32
+ */
33
+ public $authorizeUrl = 'https://auth.aweber.com/1.0/oauth/authorize';
34
+
35
+ /**
36
+ * @var String Location to request a request token
37
+ */
38
+ public $requestTokenUrl = 'https://auth.aweber.com/1.0/oauth/request_token';
39
+
40
+
41
+ public function getBaseUri() {
42
+ return $this->baseUri;
43
+ }
44
+
45
+ public function removeBaseUri($url) {
46
+ return str_replace($this->getBaseUri(), '', $url);
47
+ }
48
+
49
+ public function getAccessTokenUrl() {
50
+ return $this->accessTokenUrl;
51
+ }
52
+
53
+ public function getAuthorizeUrl() {
54
+ return $this->authorizeUrl;
55
+ }
56
+
57
+ public function getRequestTokenUrl() {
58
+ return $this->requestTokenUrl;
59
+ }
60
+
61
+ public function getAuthTokenFromUrl() { return ''; }
62
+ public function getUserData() { return ''; }
63
+
64
+ }
65
+
66
+ endif; // AWeberServiceProvider
67
+
68
+ /**
69
+ * AWeberAPIBase
70
+ *
71
+ * Base object that all AWeberAPI objects inherit from. Allows specific pieces
72
+ * of functionality to be shared across any object in the API, such as the
73
+ * ability to introspect the collections map.
74
+ *
75
+ * @package
76
+ * @version $id$
77
+ */
78
+
79
+ if ( ! class_exists('AWeberAPIBase') ) :
80
+
81
+ class AWeberAPIBase {
82
+
83
+ /**
84
+ * Maintains data about what children collections a given object type
85
+ * contains.
86
+ */
87
+ static protected $_collectionMap = array(
88
+ 'account' => array('lists', 'integrations'),
89
+ 'broadcast_campaign' => array('links', 'messages', 'stats'),
90
+ 'followup_campaign' => array('links', 'messages', 'stats'),
91
+ 'link' => array('clicks'),
92
+ 'list' => array('campaigns', 'custom_fields', 'subscribers',
93
+ 'web_forms', 'web_form_split_tests'),
94
+ 'web_form' => array(),
95
+ 'web_form_split_test' => array('components'),
96
+ );
97
+
98
+ /**
99
+ * loadFromUrl
100
+ *
101
+ * Creates an object, either collection or entry, based on the given
102
+ * URL.
103
+ *
104
+ * @param mixed $url URL for this request
105
+ * @access public
106
+ * @return AWeberEntry or AWeberCollection
107
+ */
108
+ public function loadFromUrl($url) {
109
+ $data = $this->adapter->request('GET', $url);
110
+ return $this->readResponse($data, $url);
111
+ }
112
+
113
+ protected function _cleanUrl($url) {
114
+ return str_replace($this->adapter->app->getBaseUri(), '', $url);
115
+ }
116
+
117
+ /**
118
+ * readResponse
119
+ *
120
+ * Interprets a response, and creates the appropriate object from it.
121
+ * @param mixed $response Data returned from a request to the AWeberAPI
122
+ * @param mixed $url URL that this data was requested from
123
+ * @access protected
124
+ * @return mixed
125
+ */
126
+ protected function readResponse($response, $url) {
127
+ $this->adapter->parseAsError($response);
128
+ if (!empty($response['id']) || !empty($response['broadcast_id'])) {
129
+ return new AWeberEntry($response, $url, $this->adapter);
130
+ } else if (array_key_exists('entries', $response)) {
131
+ return new AWeberCollection($response, $url, $this->adapter);
132
+ }
133
+ return false;
134
+ }
135
+ }
136
+
137
+ endif; // AWeberAPIBase
138
+
139
+ require_once( 'aweber_response.php' );
140
+ require_once( 'aweber_collection.php' );
141
+ require_once( 'aweber_entry_data_array.php' );
142
+ require_once( 'aweber_entry.php' );
143
+
144
+ /**
145
+ * AWeberAPI
146
+ *
147
+ * Creates a connection to the AWeberAPI for a given consumer application.
148
+ * This is generally the starting point for this library. Instances can be
149
+ * created directly with consumerKey and consumerSecret.
150
+ * @uses AWeberAPIBase
151
+ * @package
152
+ * @version $id$
153
+ */
154
+
155
+ if( ! class_exists('AWeberAPI') ) :
156
+
157
+ class AWeberAPI extends AWeberAPIBase {
158
+
159
+ /**
160
+ * @var String Consumer Key
161
+ */
162
+ public $consumerKey = false;
163
+
164
+ /**
165
+ * @var String Consumer Secret
166
+ */
167
+ public $consumerSecret = false;
168
+
169
+ /**
170
+ * @var Object - Populated in setAdapter()
171
+ */
172
+ public $adapter = false;
173
+
174
+ /**
175
+ * Uses the app's authorization code to fetch an access token
176
+ *
177
+ * @param String Authorization code from authorize app page
178
+ */
179
+ public static function getDataFromAweberID($string) {
180
+ list($consumerKey, $consumerSecret, $requestToken, $tokenSecret, $verifier) = AWeberAPI::_parseAweberID($string);
181
+
182
+ if (!$verifier) {
183
+ return null;
184
+ }
185
+ $aweber = new AweberAPI($consumerKey, $consumerSecret);
186
+ $aweber->adapter->user->requestToken = $requestToken;
187
+ $aweber->adapter->user->tokenSecret = $tokenSecret;
188
+ $aweber->adapter->user->verifier = $verifier;
189
+ list($accessToken, $accessSecret) = $aweber->getAccessToken();
190
+ return array($consumerKey, $consumerSecret, $accessToken, $accessSecret);
191
+ }
192
+
193
+ protected static function _parseAWeberID($string) {
194
+ $values = explode('|', $string);
195
+ if (count($values) < 5) {
196
+ return null;
197
+ }
198
+ return array_slice($values, 0, 5);
199
+ }
200
+
201
+ /**
202
+ * Sets the consumer key and secret for the API object. The
203
+ * key and secret are listed in the My Apps page in the labs.aweber.com
204
+ * Control Panel OR, in the case of distributed apps, will be returned
205
+ * from the getDataFromAweberID() function
206
+ *
207
+ * @param String Consumer Key
208
+ * @param String Consumer Secret
209
+ * @return null
210
+ */
211
+ public function __construct($key, $secret) {
212
+ // Load key / secret
213
+ $this->consumerKey = $key;
214
+ $this->consumerSecret = $secret;
215
+
216
+ $this->setAdapter();
217
+ }
218
+
219
+ /**
220
+ * Returns the authorize URL by appending the request
221
+ * token to the end of the Authorize URI, if it exists
222
+ *
223
+ * @return string The Authorization URL
224
+ */
225
+ public function getAuthorizeUrl() {
226
+ $requestToken = $this->user->requestToken;
227
+ return (empty($requestToken)) ?
228
+ $this->adapter->app->getAuthorizeUrl()
229
+ :
230
+ $this->adapter->app->getAuthorizeUrl() . "?oauth_token={$this->user->requestToken}";
231
+ }
232
+
233
+ /**
234
+ * Sets the adapter for use with the API
235
+ */
236
+ public function setAdapter($adapter=null) {
237
+ if (empty($adapter)) {
238
+ $serviceProvider = new AWeberServiceProvider();
239
+ $adapter = new OAuthApplication($serviceProvider);
240
+ $adapter->consumerKey = $this->consumerKey;
241
+ $adapter->consumerSecret = $this->consumerSecret;
242
+ }
243
+ $this->adapter = $adapter;
244
+ }
245
+
246
+ /**
247
+ * Fetches account data for the associated account
248
+ *
249
+ * @param String Access Token (Only optional/cached if you called getAccessToken() earlier
250
+ * on the same page)
251
+ * @param String Access Token Secret (Only optional/cached if you called getAccessToken() earlier
252
+ * on the same page)
253
+ * @return Object AWeberCollection Object with the requested
254
+ * account data
255
+ */
256
+ public function getAccount($token=false, $secret=false) {
257
+ if ($token && $secret) {
258
+ $user = new OAuthUser();
259
+ $user->accessToken = $token;
260
+ $user->tokenSecret = $secret;
261
+ $this->adapter->user = $user;
262
+ }
263
+
264
+ $body = $this->adapter->request('GET', '/accounts');
265
+ $accounts = $this->readResponse($body, '/accounts');
266
+ return $accounts[0];
267
+ }
268
+
269
+ /**
270
+ * PHP Automagic
271
+ */
272
+ public function __get($item) {
273
+ if ($item == 'user') return $this->adapter->user;
274
+ trigger_error("Could not find \"{$item}\"");
275
+ }
276
+
277
+ /**
278
+ * Request a request token from AWeber and associate the
279
+ * provided $callbackUrl with the new token
280
+ * @param String The URL where users should be redirected
281
+ * once they authorize your app
282
+ * @return Array Contains the request token as the first item
283
+ * and the request token secret as the second item of the array
284
+ */
285
+ public function getRequestToken($callbackUrl) {
286
+ $requestToken = $this->adapter->getRequestToken($callbackUrl);
287
+ return array($requestToken, $this->user->tokenSecret);
288
+ }
289
+
290
+ /**
291
+ * Request an access token using the request tokens stored in the
292
+ * current user object. You would want to first set the request tokens
293
+ * on the user before calling this function via:
294
+ *
295
+ * $aweber->user->tokenSecret = $_COOKIE['requestTokenSecret'];
296
+ * $aweber->user->requestToken = $_GET['oauth_token'];
297
+ * $aweber->user->verifier = $_GET['oauth_verifier'];
298
+ *
299
+ * @return Array Contains the access token as the first item
300
+ * and the access token secret as the second item of the array
301
+ */
302
+ public function getAccessToken() {
303
+ return $this->adapter->getAccessToken();
304
+ }
305
+ }
306
+
307
+ endif; // AWeberAPI
trunk/includes/subscription/libs/aweber_api/aweber_api.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (class_exists('AWeberAPI')) {
4
+ trigger_error("Duplicate: Another AWeberAPI client library is already in scope.", E_USER_WARNING);
5
+ }
6
+ else {
7
+ require_once('aweber.php');
8
+ }
trunk/includes/subscription/libs/aweber_api/aweber_collection.php ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists('AWeberCollection') ) :
4
+
5
+ class AWeberCollection extends AWeberResponse implements ArrayAccess, Iterator, Countable {
6
+
7
+ protected $pageSize = 100;
8
+ protected $pageStart = 0;
9
+
10
+ protected function _updatePageSize() {
11
+
12
+ # grab the url, or prev and next url and pull ws.size from it
13
+ $url = $this->url;
14
+ if (array_key_exists('next_collection_link', $this->data)) {
15
+ $url = $this->data['next_collection_link'];
16
+
17
+ } elseif (array_key_exists('prev_collection_link', $this->data)) {
18
+ $url = $this->data['prev_collection_link'];
19
+ }
20
+
21
+ # scan querystring for ws_size
22
+ $url_parts = parse_url($url);
23
+
24
+ # we have a query string
25
+ if (array_key_exists('query', $url_parts)) {
26
+ parse_str($url_parts['query'], $params);
27
+
28
+ # we have a ws_size
29
+ if (array_key_exists('ws_size', $params)) {
30
+
31
+ # set pageSize
32
+ $this->pageSize = $params['ws_size'];
33
+ return;
34
+ }
35
+ }
36
+
37
+ # we dont have one, just count the # of entries
38
+ $this->pageSize = count($this->data['entries']);
39
+ }
40
+
41
+ public function __construct($response, $url, $adapter) {
42
+ parent::__construct($response, $url, $adapter);
43
+ $this->_updatePageSize();
44
+ }
45
+
46
+ /**
47
+ * @var array Holds list of keys that are not publicly accessible
48
+ */
49
+ protected $_privateData = array(
50
+ 'entries',
51
+ 'start',
52
+ 'next_collection_link',
53
+ );
54
+
55
+ /**
56
+ * getById
57
+ *
58
+ * Gets an entry object of this collection type with the given id
59
+ * @param mixed $id ID of the entry you are requesting
60
+ * @access public
61
+ * @return AWeberEntry
62
+ */
63
+ public function getById($id) {
64
+ $data = $this->adapter->request('GET', "{$this->url}/{$id}");
65
+ $url = "{$this->url}/{$id}";
66
+ return new AWeberEntry($data, $url, $this->adapter);
67
+ }
68
+
69
+ /** getParentEntry
70
+ *
71
+ * Gets an entry's parent entry
72
+ * Returns NULL if no parent entry
73
+ */
74
+ public function getParentEntry(){
75
+ $url_parts = explode('/', $this->url);
76
+ $size = count($url_parts);
77
+
78
+ # Remove collection id and slash from end of url
79
+ $url = substr($this->url, 0, -strlen($url_parts[$size-1])-1);
80
+
81
+ try {
82
+ $data = $this->adapter->request('GET', $url);
83
+ return new AWeberEntry($data, $url, $this->adapter);
84
+ } catch (Exception $e) {
85
+ return NULL;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * _type
91
+ *
92
+ * Interpret what type of resources are held in this collection by
93
+ * analyzing the URL
94
+ *
95
+ * @access protected
96
+ * @return void
97
+ */
98
+ protected function _type() {
99
+ $urlParts = explode('/', $this->url);
100
+ $type = array_pop($urlParts);
101
+ return $type;
102
+ }
103
+
104
+ /**
105
+ * create
106
+ *
107
+ * Invoke the API method to CREATE a new entry resource.
108
+ *
109
+ * Note: Not all entry resources are eligible to be created, please
110
+ * refer to the AWeber API Reference Documentation at
111
+ * https://labs.aweber.com/docs/reference/1.0 for more
112
+ * details on which entry resources may be created and what
113
+ * attributes are required for creating resources.
114
+ *
115
+ * @access public
116
+ * @param params mixed associtative array of key/value pairs.
117
+ * @return AWeberEntry(Resource) The new resource created
118
+ */
119
+ public function create($kv_pairs) {
120
+ # Create Resource
121
+ $params = array_merge(array('ws.op' => 'create'), $kv_pairs);
122
+ $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'));
123
+
124
+ # Return new Resource
125
+ $url = $data['Location'];
126
+ $resource_data = $this->adapter->request('GET', $url);
127
+ return new AWeberEntry($resource_data, $url, $this->adapter);
128
+ }
129
+
130
+ /**
131
+ * find
132
+ *
133
+ * Invoke the API 'find' operation on a collection to return a subset
134
+ * of that collection. Not all collections support the 'find' operation.
135
+ * refer to https://labs.aweber.com/docs/reference/1.0 for more information.
136
+ *
137
+ * @param mixed $search_data Associative array of key/value pairs used as search filters
138
+ * * refer to https://labs.aweber.com/docs/reference/1.0 for a
139
+ * complete list of valid search filters.
140
+ * * filtering on attributes that require additional permissions to
141
+ * display requires an app authorized with those additional permissions.
142
+ * @access public
143
+ * @return AWeberCollection
144
+ */
145
+ public function find($search_data) {
146
+ # invoke find operation
147
+ $params = array_merge($search_data, array('ws.op' => 'find'));
148
+ $data = $this->adapter->request('GET', $this->url, $params);
149
+
150
+ # get total size
151
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
152
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
153
+ $data['total_size'] = $total_size;
154
+
155
+ # return collection
156
+ return $this->readResponse($data, $this->url);
157
+ }
158
+
159
+ /*
160
+ * ArrayAccess Functions
161
+ *
162
+ * Allows this object to be accessed via bracket notation (ie $obj[$x])
163
+ * http://php.net/manual/en/class.arrayaccess.php
164
+ */
165
+
166
+ public function offsetSet($offset, $value) {}
167
+ public function offsetUnset($offset) {}
168
+ public function offsetExists($offset) {
169
+
170
+ if ($offset >=0 && $offset < $this->total_size) {
171
+ return true;
172
+ }
173
+ return false;
174
+ }
175
+ protected function _fetchCollectionData($offset) {
176
+
177
+ # we dont have a next page, we're done
178
+ if (!array_key_exists('next_collection_link', $this->data)) {
179
+ return null;
180
+ }
181
+
182
+ # snag query string args from collection
183
+ $parsed = parse_url($this->data['next_collection_link']);
184
+
185
+ # parse the query string to get params
186
+ $pairs = explode('&', $parsed['query']);
187
+ foreach ($pairs as $pair) {
188
+ list($key, $val) = explode('=', $pair);
189
+ $params[$key] = $val;
190
+ }
191
+
192
+ # calculate new args
193
+ $limit = $params['ws.size'];
194
+ $pagination_offset = intval($offset / $limit) * $limit;
195
+ $params['ws.start'] = $pagination_offset;
196
+
197
+ # fetch data, exclude query string
198
+ $url_parts = explode('?', $this->url);
199
+ $data = $this->adapter->request('GET', $url_parts[0], $params);
200
+ $this->pageStart = $params['ws.start'];
201
+ $this->pageSize = $params['ws.size'];
202
+
203
+ $collection_data = array('entries', 'next_collection_link', 'prev_collection_link', 'ws.start');
204
+
205
+ foreach ($collection_data as $item) {
206
+ if (!array_key_exists($item, $this->data)) {
207
+ continue;
208
+ }
209
+ if (!array_key_exists($item, $data)) {
210
+ continue;
211
+ }
212
+ $this->data[$item] = $data[$item];
213
+ }
214
+ }
215
+
216
+ public function offsetGet($offset) {
217
+
218
+ if (!$this->offsetExists($offset)) {
219
+ return null;
220
+ }
221
+
222
+ $limit = $this->pageSize;
223
+ $pagination_offset = intval($offset / $limit) * $limit;
224
+
225
+ # load collection page if needed
226
+ if ($pagination_offset !== $this->pageStart) {
227
+ $this->_fetchCollectionData($offset);
228
+ }
229
+
230
+ $entry = $this->data['entries'][$offset - $pagination_offset];
231
+
232
+ # we have an entry, cast it to an AWeberEntry and return it
233
+ $entry_url = $this->adapter->app->removeBaseUri($entry['self_link']);
234
+ return new AWeberEntry($entry, $entry_url, $this->adapter);
235
+ }
236
+
237
+ /*
238
+ * Iterator
239
+ */
240
+ protected $_iterationKey = 0;
241
+
242
+ public function current() {
243
+ return $this->offsetGet($this->_iterationKey);
244
+ }
245
+
246
+ public function key() {
247
+ return $this->_iterationKey;
248
+ }
249
+
250
+ public function next() {
251
+ $this->_iterationKey++;
252
+ }
253
+
254
+ public function rewind() {
255
+ $this->_iterationKey = 0;
256
+ }
257
+
258
+ public function valid() {
259
+ return $this->offsetExists($this->key());
260
+ }
261
+
262
+ /*
263
+ * Countable interface methods
264
+ * Allows PHP's count() and sizeOf() functions to act on this object
265
+ * http://www.php.net/manual/en/class.countable.php
266
+ */
267
+
268
+ public function count() {
269
+ return $this->total_size;
270
+ }
271
+ }
272
+
273
+ endif;
trunk/includes/subscription/libs/aweber_api/aweber_entry.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists('AWeberEntry') ) :
4
+
5
+ class AWeberEntry extends AWeberResponse {
6
+
7
+ /**
8
+ * @var array Holds list of data keys that are not publicly accessible
9
+ */
10
+ protected $_privateData = array(
11
+ 'resource_type_link',
12
+ 'http_etag',
13
+ );
14
+
15
+ /**
16
+ * @var array Stores local modifications that have not been saved
17
+ */
18
+ protected $_localDiff = array();
19
+
20
+ /**
21
+ * @var array Holds AWeberCollection objects already instantiated, keyed by
22
+ * their resource name (plural)
23
+ */
24
+ protected $_collections = array();
25
+
26
+ /**
27
+ * attrs
28
+ *
29
+ * Provides a simple array of all the available data (and collections) available
30
+ * in this entry.
31
+ *
32
+ * @access public
33
+ * @return array
34
+ */
35
+ public function attrs() {
36
+ $attrs = array();
37
+ foreach ($this->data as $key => $value) {
38
+ if (!in_array($key, $this->_privateData) && !strpos($key, 'collection_link')) {
39
+ $attrs[$key] = $value;
40
+ }
41
+ }
42
+ if (!empty(AWeberAPI::$_collectionMap[$this->type])) {
43
+ foreach (AWeberAPI::$_collectionMap[$this->type] as $child) {
44
+ $attrs[$child] = 'collection';
45
+ }
46
+ }
47
+ return $attrs;
48
+ }
49
+
50
+ /**
51
+ * _type
52
+ *
53
+ * Used to pull the name of this resource from its resource_type_link
54
+ * @access protected
55
+ * @return String
56
+ */
57
+ protected function _type() {
58
+ if (empty($this->type)) {
59
+ if (!empty($this->data['resource_type_link'])) {
60
+ list($url, $type) = explode('#', $this->data['resource_type_link']);
61
+ $this->type = $type;
62
+ } elseif (!empty($this->data['broadcast_id'])) {
63
+ $this->type = 'broadcast';
64
+ } else {
65
+ return null;
66
+ }
67
+ }
68
+ return $this->type;
69
+ }
70
+
71
+ /**
72
+ * delete
73
+ *
74
+ * Delete this object from the AWeber system. May not be supported
75
+ * by all entry types.
76
+ * @access public
77
+ * @return boolean Returns true if it is successfully deleted, false
78
+ * if the delete request failed.
79
+ */
80
+ public function delete() {
81
+ $this->adapter->request('DELETE', $this->url, array(), array('return' => 'status'));
82
+ return true;
83
+ }
84
+
85
+ /**
86
+ * move
87
+ *
88
+ * Invoke the API method to MOVE an entry resource to a different List.
89
+ *
90
+ * Note: Not all entry resources are eligible to be moved, please
91
+ * refer to the AWeber API Reference Documentation at
92
+ * https://labs.aweber.com/docs/reference/1.0 for more
93
+ * details on which entry resources may be moved and if there
94
+ * are any requirements for moving that resource.
95
+ *
96
+ * @access public
97
+ * @param AWeberEntry(List) List to move Resource (this) too.
98
+ * @return mixed AWeberEntry(Resource) Resource created on List ($list)
99
+ * or False if resource was not created.
100
+ */
101
+ public function move($list, $last_followup_message_number_sent=NULL) {
102
+ # Move Resource
103
+ $params = array(
104
+ 'ws.op' => 'move',
105
+ 'list_link' => $list->self_link
106
+ );
107
+ if (isset($last_followup_message_number_sent)) {
108
+ $params['last_followup_message_number_sent'] = $last_followup_message_number_sent;
109
+ }
110
+
111
+ $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'));
112
+
113
+ # Return new Resource
114
+ $url = $data['Location'];
115
+ $resource_data = $this->adapter->request('GET', $url);
116
+ return new AWeberEntry($resource_data, $url, $this->adapter);
117
+ }
118
+
119
+ /**
120
+ * save
121
+ *
122
+ * Saves the current state of this object if it has been changed.
123
+ * @access public
124
+ * @return void
125
+ */
126
+ public function save() {
127
+ if (!empty($this->_localDiff)) {
128
+ $data = $this->adapter->request('PATCH', $this->url, $this->_localDiff, array('return' => 'status'));
129
+ }
130
+ $this->_localDiff = array();
131
+ return true;
132
+
133
+ }
134
+
135
+ /**
136
+ * __get
137
+ *
138
+ * Used to look up items in data, and special properties like type and
139
+ * child collections dynamically.
140
+ *
141
+ * @param String $value Attribute being accessed
142
+ * @access public
143
+ * @throws AWeberResourceNotImplemented
144
+ * @return mixed
145
+ */
146
+ public function __get($value) {
147
+ if (in_array($value, $this->_privateData)) {
148
+ return null;
149
+ }
150
+ if (!empty($this->data) && array_key_exists($value, $this->data)) {
151
+ if (is_array($this->data[$value])) {
152
+ $array = new AWeberEntryDataArray($this->data[$value], $value, $this);
153
+ $this->data[$value] = $array;
154
+ }
155
+ return $this->data[$value];
156
+ }
157
+ if ($value == 'type') return $this->_type();
158
+ if ($this->_isChildCollection($value)) {
159
+ return $this->_getCollection($value);
160
+ }
161
+ throw new AWeberResourceNotImplemented($this, $value);
162
+ }
163
+
164
+ /**
165
+ * __set
166
+ *
167
+ * If the key provided is part of the data array, then update it in the
168
+ * data array. Otherwise, use the default __set() behavior.
169
+ *
170
+ * @param mixed $key Key of the attr being set
171
+ * @param mixed $value Value being set to the $key attr
172
+ * @access public
173
+ */
174
+ public function __set($key, $value) {
175
+ if (array_key_exists($key, $this->data)) {
176
+ $this->_localDiff[$key] = $value;
177
+ return $this->data[$key] = $value;
178
+ } else {
179
+ return parent::__set($key, $value);
180
+ }
181
+ }
182
+
183
+ /**
184
+ * findSubscribers
185
+ *
186
+ * Looks through all lists for subscribers
187
+ * that match the given filter
188
+ * @access public
189
+ * @return AWeberCollection
190
+ */
191
+ public function findSubscribers($search_data) {
192
+ $this->_methodFor(array('account'));
193
+ $params = array_merge($search_data, array('ws.op' => 'findSubscribers'));
194
+ $data = $this->adapter->request('GET', $this->url, $params);
195
+
196
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
197
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
198
+
199
+ # return collection
200
+ $data['total_size'] = $total_size;
201
+ $url = $this->url . '?'. http_build_query($params);
202
+ return new AWeberCollection($data, $url, $this->adapter);
203
+ }
204
+
205
+ /**
206
+ * getActivity
207
+ *
208
+ * Returns analytics activity for a given subscriber
209
+ * @access public
210
+ * @return AWeberCollection
211
+ */
212
+ public function getActivity() {
213
+ $this->_methodFor(array('subscriber'));
214
+ $params = array('ws.op' => 'getActivity');
215
+ $data = $this->adapter->request('GET', $this->url, $params);
216
+
217
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
218
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
219
+
220
+ # return collection
221
+ $data['total_size'] = $total_size;
222
+ $url = $this->url . '?'. http_build_query($params);
223
+ return new AWeberCollection($data, $url, $this->adapter);
224
+ }
225
+
226
+ /** getParentEntry
227
+ *
228
+ * Gets an entry's parent entry
229
+ * Returns NULL if no parent entry
230
+ */
231
+ public function getParentEntry(){
232
+ $url_parts = explode('/', $this->url);
233
+ $size = count($url_parts);
234
+
235
+ #Remove entry id and slash from end of url
236
+ $url = substr($this->url, 0, -strlen($url_parts[$size-1])-1);
237
+
238
+ #Remove collection name and slash from end of url
239
+ $url = substr($url, 0, -strlen($url_parts[$size-2])-1);
240
+
241
+ try {
242
+ $data = $this->adapter->request('GET', $url);
243
+ return new AWeberEntry($data, $url, $this->adapter);
244
+ } catch (Exception $e) {
245
+ return NULL;
246
+ }
247
+ }
248
+
249
+ /**
250
+ * getWebForms
251
+ *
252
+ * Gets all web_forms for this account
253
+ * @access public
254
+ * @return array
255
+ */
256
+ public function getWebForms() {
257
+ $this->_methodFor(array('account'));
258
+ $data = $this->adapter->request('GET', $this->url.'?ws.op=getWebForms', array(),
259
+ array('allow_empty' => true));
260
+ return $this->_parseNamedOperation($data);
261
+ }
262
+
263
+
264
+ /**
265
+ * getWebFormSplitTests
266
+ *
267
+ * Gets all web_form split tests for this account
268
+ * @access public
269
+ * @return array
270
+ */
271
+ public function getWebFormSplitTests() {
272
+ $this->_methodFor(array('account'));
273
+ $data = $this->adapter->request('GET', $this->url.'?ws.op=getWebFormSplitTests', array(),
274
+ array('allow_empty' => true));
275
+ return $this->_parseNamedOperation($data);
276
+ }
277
+
278
+ /**
279
+ * _parseNamedOperation
280
+ *
281
+ * Turns a dumb array of json into an array of Entries. This is NOT
282
+ * a collection, but simply an array of entries, as returned from a
283
+ * named operation.
284
+ *
285
+ * @param array $data
286
+ * @access protected
287
+ * @return array
288
+ */
289
+ protected function _parseNamedOperation($data) {
290
+ $results = array();
291
+ foreach($data as $entryData) {
292
+ $results[] = new AWeberEntry($entryData, str_replace($this->adapter->app->getBaseUri(), '',
293
+ $entryData['self_link']), $this->adapter);
294
+ }
295
+ return $results;
296
+ }
297
+
298
+ /**
299
+ * _methodFor
300
+ *
301
+ * Raises exception if $this->type is not in array entryTypes.
302
+ * Used to restrict methods to specific entry type(s).
303
+ * @param mixed $entryTypes Array of entry types as strings, ie array('account')
304
+ * @access protected
305
+ * @return void
306
+ */
307
+ protected function _methodFor($entryTypes) {
308
+ if (in_array($this->type, $entryTypes)) return true;
309
+ throw new AWeberMethodNotImplemented($this);
310
+ }
311
+
312
+ /**
313
+ * _getCollection
314
+ *
315
+ * Returns the AWeberCollection object representing the given
316
+ * collection name, relative to this entry.
317
+ *
318
+ * @param String $value The name of the sub-collection
319
+ * @access protected
320
+ * @return AWeberCollection
321
+ */
322
+ protected function _getCollection($value) {
323
+ if (empty($this->_collections[$value])) {
324
+ $url = "{$this->url}/{$value}";
325
+ $data = $this->adapter->request('GET', $url);
326
+ $this->_collections[$value] = new AWeberCollection($data, $url, $this->adapter);
327
+ }
328
+ return $this->_collections[$value];
329
+ }
330
+
331
+
332
+ /**
333
+ * _isChildCollection
334
+ *
335
+ * Is the given name of a collection a child collection of this entry?
336
+ *
337
+ * @param String $value The name of the collection we are looking for
338
+ * @access protected
339
+ * @return boolean
340
+ * @throws AWeberResourceNotImplemented
341
+ */
342
+ protected function _isChildCollection($value) {
343
+ $this->_type();
344
+ if (!empty(AWeberAPI::$_collectionMap[$this->type]) &&
345
+ in_array($value, AWeberAPI::$_collectionMap[$this->type])) return true;
346
+ return false;
347
+ }
348
+
349
+ }
350
+ endif;
trunk/includes/subscription/libs/aweber_api/aweber_entry_data_array.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists('AWeberEntryDataArray') ) :
4
+
5
+ class AWeberEntryDataArray implements ArrayAccess, Countable, Iterator {
6
+ private $counter = 0;
7
+
8
+ protected $data;
9
+ protected $keys;
10
+ protected $name;
11
+ protected $parent;
12
+
13
+ public function __construct($data, $name, $parent) {
14
+ $this->data = $data;
15
+ $this->keys = array_keys($data);
16
+ $this->name = $name;
17
+ $this->parent = $parent;
18
+ }
19
+
20
+ public function count() {
21
+ return sizeOf($this->data);
22
+ }
23
+
24
+ public function offsetExists($offset) {
25
+ return (isset($this->data[$offset]));
26
+ }
27
+
28
+ public function offsetGet($offset) {
29
+ return $this->data[$offset];
30
+ }
31
+
32
+ public function offsetSet($offset, $value) {
33
+ $this->data[$offset] = $value;
34
+ $this->parent->{$this->name} = $this->data;
35
+ return $value;
36
+ }
37
+
38
+ public function offsetUnset($offset) {
39
+ unset($this->data[$offset]);
40
+ }
41
+
42
+ public function rewind() {
43
+ $this->counter = 0;
44
+ }
45
+
46
+ public function current() {
47
+ return $this->data[$this->key()];
48
+ }
49
+
50
+ public function key() {
51
+ return $this->keys[$this->counter];
52
+ }
53
+
54
+ public function next() {
55
+ $this->counter++;
56
+ }
57
+
58
+ public function valid() {
59
+ if ($this->counter >= sizeOf($this->data)) {
60
+ return false;
61
+ }
62
+ return true;
63
+ }
64
+ }
65
+ endif;
trunk/includes/subscription/libs/aweber_api/aweber_response.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * AWeberResponse
5
+ *
6
+ * Base class for objects that represent a response from the AWeberAPI.
7
+ * Responses will exist as one of the two AWeberResponse subclasses:
8
+ * - AWeberEntry - a single instance of an AWeber resource
9
+ * - AWeberCollection - a collection of AWeber resources
10
+ * @uses AWeberAPIBase
11
+ * @package
12
+ * @version $id$
13
+ */
14
+
15
+ if( ! class_exists('AWeberResponse') ) :
16
+
17
+ class AWeberResponse extends AWeberAPIBase {
18
+
19
+ public $adapter = false;
20
+ public $data = array();
21
+ public $_dynamicData = array();
22
+
23
+ /**
24
+ * __construct
25
+ *
26
+ * Creates a new AWeberRespones
27
+ *
28
+ * @param mixed $response Data returned by the API servers
29
+ * @param mixed $url URL we hit to get the data
30
+ * @param mixed $adapter OAuth adapter used for future interactions
31
+ * @access public
32
+ * @return void
33
+ */
34
+ public function __construct($response, $url, $adapter) {
35
+ $this->adapter = $adapter;
36
+ $this->url = $url;
37
+ $this->data = $response;
38
+ }
39
+
40
+ /**
41
+ * __set
42
+ *
43
+ * Manual re-implementation of __set, allows sub classes to access
44
+ * the default behavior by using the parent:: format.
45
+ *
46
+ * @param mixed $key Key of the attr being set
47
+ * @param mixed $value Value being set to the attr
48
+ * @access public
49
+ */
50
+ public function __set($key, $value) {
51
+ $this->{$key} = $value;
52
+ }
53
+
54
+ /**
55
+ * __get
56
+ *
57
+ * PHP "MagicMethod" to allow for dynamic objects. Defers first to the
58
+ * data in $this->data.
59
+ *
60
+ * @param String $value Name of the attribute requested
61
+ * @access public
62
+ * @return mixed
63
+ */
64
+ public function __get($value) {
65
+ if (in_array($value, $this->_privateData)) {
66
+ return null;
67
+ }
68
+ if (array_key_exists($value, $this->data)) {
69
+ return $this->data[$value];
70
+ }
71
+ if ($value == 'type') return $this->_type();
72
+ }
73
+
74
+ }
75
+ endif;
trunk/includes/subscription/libs/aweber_api/curl_object.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CurlInterface
5
+ *
6
+ * An object-oriented shim that wraps the standard PHP cURL library.
7
+ *
8
+ * This interface has been created so that cURL functionality can be stubbed
9
+ * out for unit testing, or swapped for an alternative library.
10
+ *
11
+ * @see curl
12
+ * @package
13
+ * @version $id$
14
+ */
15
+ interface CurlInterface {
16
+
17
+ /**
18
+ * errNo
19
+ *
20
+ * Encapsulates curl_errno - Returns the last error number
21
+ * @param resource $ch - A cURL handle returned by init.
22
+ * @access public
23
+ * @return the error number or 0 if no error occured.
24
+ */
25
+ public function errno($ch);
26
+
27
+ /**
28
+ * error
29
+ *
30
+ * Encapsulates curl_error - Return last error string
31
+ * @param resource $ch - A cURL handle returned by init.
32
+ * @access public
33
+ * @return the error messge or '' if no error occured.
34
+ */
35
+ public function error($ch);
36
+
37
+ /**
38
+ * execute
39
+ *
40
+ * Encapsulates curl_exec - Perform a cURL session.
41
+ * @param resource $ch - A cURL handle returned by init.
42
+ * @access public
43
+ * @return TRUE on success, FALSE on failure.
44
+ */
45
+ public function execute($ch);
46
+
47
+ /**
48
+ * init
49
+ *
50
+ * Encapsulates curl_init - Initialize a cURL session.
51
+ * @param string $url - url to use.
52
+ * @access public
53
+ * @return cURL handle on success, FALSE on failure.
54
+ */
55
+ public function init($url);
56
+
57
+ /**
58
+ * setopt
59
+ *
60
+ * Encapsulates curl_setopt - Set an option for cURL transfer.
61
+ * @param resource $ch - A cURL handle returned by init.
62
+ * @param int $opt - The CURLOPT to set.
63
+ * @param mixed $value - The value to set.
64
+ * @access public
65
+ * @return True on success, FALSE on failure.
66
+ */
67
+ public function setopt ($ch , $option , $value);
68
+ }
69
+
70
+
71
+ /**
72
+ * CurlObject
73
+ *
74
+ * A concrete implementation of CurlInterface using the PHP cURL library.
75
+ *
76
+ * @package
77
+ * @version $id$
78
+ */
79
+ class CurlObject implements CurlInterface {
80
+
81
+ public function errno($ch) {
82
+ return curl_errno($ch);
83
+ }
84
+
85
+ public function error($ch) {
86
+ return curl_error($ch);
87
+ }
88
+
89
+ public function execute($ch) {
90
+ return curl_exec($ch);
91
+ }
92
+
93
+ public function init($url) {
94
+ return curl_init($url);
95
+ }
96
+
97
+ public function setopt ($ch , $option , $value) {
98
+ return curl_setopt($ch, $option, $value);
99
+ }
100
+
101
+ }
102
+
103
+ ?>
trunk/includes/subscription/libs/aweber_api/curl_response.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ # CurlResponse
4
+ #
5
+ # Author Sean Huber - shuber@huberry.com
6
+ # Date May 2008
7
+ #
8
+ # A basic CURL wrapper for PHP
9
+ #
10
+ # See the README for documentation/examples or http://php.net/curl for more information
11
+ # about the libcurl extension for PHP -- http://github.com/shuber/curl/tree/master
12
+ #
13
+
14
+ class CurlResponse
15
+ {
16
+ public $body = '';
17
+ public $headers = array();
18
+
19
+ public function __construct($response)
20
+ {
21
+ # Extract headers from response
22
+ $pattern = '#HTTP/\d\.\d.*?$.*?\r\n\r\n#ims';
23
+ preg_match_all($pattern, $response, $matches);
24
+ $headers = explode("\r\n", str_replace("\r\n\r\n", '', array_pop($matches[0])));
25
+
26
+ # Extract the version and status from the first header
27
+ $version_and_status = array_shift($headers);
28
+ preg_match('#HTTP/(\d\.\d)\s(\d\d\d)\s(.*)#', $version_and_status, $matches);
29
+ $this->headers['Http-Version'] = $matches[1];
30
+ $this->headers['Status-Code'] = $matches[2];
31
+ $this->headers['Status'] = $matches[2].' '.$matches[3];
32
+
33
+ # Convert headers into an associative array
34
+ foreach ($headers as $header) {
35
+ preg_match('#(.*?)\:\s(.*)#', $header, $matches);
36
+ $this->headers[$matches[1]] = $matches[2];
37
+ }
38
+
39
+ # Remove the headers from the response body
40
+ $this->body = preg_replace($pattern, '', $response);
41
+ }
42
+
43
+ public function __toString()
44
+ {
45
+ return $this->body;
46
+ }
47
+
48
+ public function headers(){
49
+ return $this->headers;
50
+ }
51
+ }
trunk/includes/subscription/libs/aweber_api/exceptions.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists('AWeberException') ) :
4
+ class AWeberException extends Exception {
5
+
6
+ }
7
+ endif;
8
+
9
+ /**
10
+ * Thrown when the API returns an error. (HTTP status >= 400)
11
+ *
12
+ *
13
+ * @uses AWeberException
14
+ * @package
15
+ * @version $id$
16
+ */
17
+
18
+ if( ! class_exists('AWeberAPIException') ) :
19
+ class AWeberAPIException extends AWeberException {
20
+
21
+ public $type;
22
+ public $status;
23
+ public $message;
24
+ public $documentation_url;
25
+ public $url;
26
+
27
+ public function __construct($error, $url) {
28
+ // record specific details of the API exception for processing
29
+ $this->url = $url;
30
+ $this->type = $error['type'];
31
+ $this->status = array_key_exists('status', $error) ? $error['status'] : '';
32
+ $this->message = $error['message'];
33
+ $this->documentation_url = $error['documentation_url'];
34
+
35
+ parent::__construct($this->message);
36
+ }
37
+ }
38
+ endif;
39
+
40
+ /**
41
+ * Thrown when attempting to use a resource that is not implemented.
42
+ *
43
+ * @uses AWeberException
44
+ * @package
45
+ * @version $id$
46
+ */
47
+
48
+ if( ! class_exists('AWeberResourceNotImplemented') ) :
49
+ class AWeberResourceNotImplemented extends AWeberException {
50
+
51
+ public function __construct($object, $value) {
52
+ $this->object = $object;
53
+ $this->value = $value;
54
+ parent::__construct("Resource \"{$value}\" is not implemented on this resource.");
55
+ }
56
+ }
57
+ endif;
58
+
59
+ /**
60
+ * AWeberMethodNotImplemented
61
+ *
62
+ * Thrown when attempting to call a method that is not implemented for a resource
63
+ * / collection. Differs from standard method not defined errors, as this will
64
+ * be thrown when the method is infact implemented on the base class, but the
65
+ * current resource type does not provide access to that method (ie calling
66
+ * getByMessageNumber on a web_forms collection).
67
+ *
68
+ * @uses AWeberException
69
+ * @package
70
+ * @version $id$
71
+ */
72
+
73
+ if( ! class_exists('AWeberMethodNotImplemented') ) :
74
+ class AWeberMethodNotImplemented extends AWeberException {
75
+
76
+ public function __construct($object) {
77
+ $this->object = $object;
78
+ parent::__construct("This method is not implemented by the current resource.");
79
+
80
+ }
81
+ }
82
+ endif;
83
+
84
+ /**
85
+ * AWeberOAuthException
86
+ *
87
+ * OAuth exception, as generated by an API JSON error response
88
+ * @uses AWeberException
89
+ * @package
90
+ * @version $id$
91
+ */
92
+
93
+ if( ! class_exists('AWeberOAuthException') ) :
94
+ class AWeberOAuthException extends AWeberException {
95
+
96
+ public function __construct($type, $message) {
97
+ $this->type = $type;
98
+ $this->message = $message;
99
+ parent::__construct("{$type}: {$message}");
100
+ }
101
+ }
102
+ endif;
103
+
104
+ /**
105
+ * AWeberOAuthDataMissing
106
+ *
107
+ * Used when a specific piece or pieces of data was not found in the
108
+ * response. This differs from the exception that might be thrown as
109
+ * an AWeberOAuthException when parameters are not provided because
110
+ * it is not the servers' expectations that were not met, but rather
111
+ * the expecations of the client were not met by the server.
112
+ *
113
+ * @uses AWeberException
114
+ * @package
115
+ * @version $id$
116
+ */
117
+
118
+ if( ! class_exists('AWeberOAuthDataMissing') ) :
119
+ class AWeberOAuthDataMissing extends AWeberException {
120
+
121
+ public function __construct($missing) {
122
+ if (!is_array($missing)) $missing = array($missing);
123
+ $this->missing = $missing;
124
+ $required = join(', ', $this->missing);
125
+ parent::__construct("OAuthDataMissing: Response was expected to contain: {$required}");
126
+
127
+ }
128
+ }
129
+ endif;
130
+
131
+ /**
132
+ * AWeberResponseError
133
+ *
134
+ * This is raised when the server returns a non-JSON response. This
135
+ * should only occur when there is a server or some type of connectivity
136
+ * issue.
137
+ *
138
+ * @uses AWeberException
139
+ * @package
140
+ * @version $id$
141
+ */
142
+
143
+ if( ! class_exists('AWeberResponseError') ) :
144
+ class AWeberResponseError extends AWeberException {
145
+
146
+ public function __construct($uri) {
147
+ $this->uri = $uri;
148
+ parent::__construct("Request for {$uri} did not respond properly.");
149
+ }
150
+
151
+ }
152
+ endif;
trunk/includes/subscription/libs/aweber_api/oauth_adapter.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! interface_exists('AWeberOAuthAdapter') ) :
4
+ interface AWeberOAuthAdapter {
5
+
6
+ public function request($method, $uri, $data = array());
7
+ public function getRequestToken($callbackUrl=false);
8
+
9
+ }
10
+ endif;
trunk/includes/subscription/libs/aweber_api/oauth_application.php ADDED
@@ -0,0 +1,689 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! class_exists('CurlObject') ) require_once( 'curl_object.php' );
3
+ if ( ! class_exists('CurlResponse') ) require_once( 'curl_response.php' );
4
+
5
+ /**
6
+ * OAuthServiceProvider
7
+ *
8
+ * Represents the service provider in the OAuth authentication model.
9
+ * The class that implements the service provider will contain the
10
+ * specific knowledge about the API we are interfacing with, and
11
+ * provide useful methods for interfacing with its API.
12
+ *
13
+ * For example, an OAuthServiceProvider would know the URLs necessary
14
+ * to perform specific actions, the type of data that the API calls
15
+ * would return, and would be responsible for manipulating the results
16
+ * into a useful manner.
17
+ *
18
+ * It should be noted that the methods enforced by the OAuthServiceProvider
19
+ * interface are made so that it can interact with our OAuthApplication
20
+ * cleanly, rather than from a general use perspective, though some
21
+ * methods for those purposes do exists (such as getUserData).
22
+ *
23
+ * @package
24
+ * @version $id$
25
+ */
26
+
27
+ if( ! interface_exists('OAuthServiceProvider') ) :
28
+ interface OAuthServiceProvider {
29
+
30
+ public function getAccessTokenUrl();
31
+ public function getAuthorizeUrl();
32
+ public function getRequestTokenUrl();
33
+ public function getAuthTokenFromUrl();
34
+ public function getBaseUri();
35
+ public function getUserData();
36
+
37
+ }
38
+ endif;
39
+
40
+ /**
41
+ * OAuthApplication
42
+ *
43
+ * Base class to represent an OAuthConsumer application. This class is
44
+ * intended to be extended and modified for each ServiceProvider. Each
45
+ * OAuthServiceProvider should have a complementary OAuthApplication
46
+ *
47
+ * The OAuthApplication class should contain any details on preparing
48
+ * requires that is unique or specific to that specific service provider's
49
+ * implementation of the OAuth model.
50
+ *
51
+ * This base class is based on OAuth 1.0, designed with AWeber's implementation
52
+ * as a model. An OAuthApplication built to work with a different service
53
+ * provider (especially an OAuth2.0 Application) may alter or bypass portions
54
+ * of the logic in this class to meet the needs of the service provider it
55
+ * is designed to interface with.
56
+ *
57
+ * @package
58
+ * @version $id$
59
+ */
60
+
61
+ if( ! class_exists('OAuthApplication') ) :
62
+ class OAuthApplication implements AWeberOAuthAdapter {
63
+ public $debug = false;
64
+
65
+ public $userAgent = 'AWeber OAuth Consumer Application 1.0 - https://labs.aweber.com/';
66
+
67
+ public $format = false;
68
+
69
+ public $requiresTokenSecret = true;
70
+
71
+ public $signatureMethod = 'HMAC-SHA1';
72
+ public $version = '1.0';
73
+
74
+ public $curl = false;
75
+
76
+ /**
77
+ * @var OAuthUser User currently interacting with the service provider
78
+ */
79
+ public $user = false;
80
+
81
+ // Data binding this OAuthApplication to the consumer application it is acting
82
+ // as a proxy for
83
+ public $consumerKey = false;
84
+ public $consumerSecret = false;
85
+
86
+ /**
87
+ * __construct
88
+ *
89
+ * Create a new OAuthApplication, based on an OAuthServiceProvider
90
+ * @access public
91
+ * @return void
92
+ */
93
+ public function __construct($parentApp = false) {
94
+ if ($parentApp) {
95
+ if (!is_a($parentApp, 'OAuthServiceProvider')) {
96
+ throw new Exception('Parent App must be a valid OAuthServiceProvider!');
97
+ }
98
+ $this->app = $parentApp;
99
+ }
100
+ $this->user = new OAuthUser();
101
+ $this->curl = new CurlObject();
102
+ }
103
+
104
+ /**
105
+ * request
106
+ *
107
+ * Implemented for a standard OAuth adapter interface
108
+ * @param mixed $method
109
+ * @param mixed $uri
110
+ * @param array $data
111
+ * @param array $options
112
+ * @access public
113
+ * @return void
114
+ */
115
+ public function request($method, $uri, $data = array(), $options = array()) {
116
+ $uri = $this->app->removeBaseUri($uri);
117
+ $url = $this->app->getBaseUri() . $uri;
118
+
119
+ # WARNING: non-primative items in data must be json serialized in GET and POST.
120
+ if ($method == 'POST' or $method == 'GET') {
121
+ foreach ($data as $key => $value) {
122
+ if (is_array($value)) {
123
+ $data[$key] = json_encode($value);
124
+ }
125
+ }
126
+ }
127
+
128
+ $response = $this->makeRequest($method, $url, $data);
129
+ if (!empty($options['return'])) {
130
+ if ($options['return'] == 'status') {
131
+ return $response->headers['Status-Code'];
132
+ }
133
+ if ($options['return'] == 'headers') {
134
+ return $response->headers;
135
+ }
136
+ if ($options['return'] == 'integer') {
137
+ return intval($response->body);
138
+ }
139
+ }
140
+
141
+ $data = json_decode($response->body, true);
142
+
143
+ if (empty($options['allow_empty']) && !isset($data)) {
144
+ throw new AWeberResponseError($uri);
145
+ }
146
+ return $data;
147
+ }
148
+
149
+ /**
150
+ * getRequestToken
151
+ *
152
+ * Gets a new request token / secret for this user.
153
+ * @access public
154
+ * @return void
155
+ */
156
+ public function getRequestToken($callbackUrl=false) {
157
+ $data = ($callbackUrl)? array('oauth_callback' => $callbackUrl) : array();
158
+ $resp = $this->makeRequest('POST', $this->app->getRequestTokenUrl(), $data);
159
+ $data = $this->parseResponse($resp);
160
+ $this->requiredFromResponse($data, array('oauth_token', 'oauth_token_secret'));
161
+ $this->user->requestToken = $data['oauth_token'];
162
+ $this->user->tokenSecret = $data['oauth_token_secret'];
163
+ return $data['oauth_token'];
164
+ }
165
+
166
+ /**
167
+ * getAccessToken
168
+ *
169
+ * Makes a request for access tokens. Requires that the current user has an authorized
170
+ * token and token secret.
171
+ *
172
+ * @access public
173
+ * @return void
174
+ */
175
+ public function getAccessToken() {
176
+ $resp = $this->makeRequest('POST', $this->app->getAccessTokenUrl(),
177
+ array('oauth_verifier' => $this->user->verifier)
178
+ );
179
+ $data = $this->parseResponse($resp);
180
+ $this->requiredFromResponse($data, array('oauth_token', 'oauth_token_secret'));
181
+
182
+ if (empty($data['oauth_token'])) {
183
+ throw new AWeberOAuthDataMissing('oauth_token');
184
+ }
185
+
186
+ $this->user->accessToken = $data['oauth_token'];
187
+ $this->user->tokenSecret = $data['oauth_token_secret'];
188
+ return array($data['oauth_token'], $data['oauth_token_secret']);
189
+ }
190
+
191
+ /**
192
+ * parseAsError
193
+ *
194
+ * Checks if response is an error. If it is, raise an appropriately
195
+ * configured exception.
196
+ *
197
+ * @param mixed $response Data returned from the server, in array form
198
+ * @access public
199
+ * @throws AWeberOAuthException
200
+ * @return void
201
+ */
202
+ public function parseAsError($response) {
203
+ if (!empty($response['error'])) {
204
+ throw new AWeberOAuthException($response['error']['type'],
205
+ $response['error']['message']);
206
+ }
207
+ }
208
+
209
+ /**
210
+ * requiredFromResponse
211
+ *
212
+ * Enforce that all the fields in requiredFields are present and not
213
+ * empty in data. If a required field is empty, throw an exception.
214
+ *
215
+ * @param mixed $data Array of data
216
+ * @param mixed $requiredFields Array of required field names.
217
+ * @access protected
218
+ * @return void
219
+ */
220
+ protected function requiredFromResponse($data, $requiredFields) {
221
+ foreach ($requiredFields as $field) {
222
+ if (empty($data[$field])) {
223
+ throw new AWeberOAuthDataMissing($field);
224
+ }
225
+ }
226
+ }
227
+
228
+ /**
229
+ * get
230
+ *
231
+ * Make a get request. Used to exchange user tokens with serice provider.
232
+ * @param mixed $url URL to make a get request from.
233
+ * @param array $data Data for the request.
234
+ * @access protected
235
+ * @return void
236
+ */
237
+ protected function get($url, $data) {
238
+ $url = $this->_addParametersToUrl($url, $data);
239
+ $handle = $this->curl->init($url);
240
+ $resp = $this->_sendRequest($handle);
241
+ return $resp;
242
+ }
243
+
244
+ /**
245
+ * _addParametersToUrl
246
+ *
247
+ * Adds the parameters in associative array $data to the
248
+ * given URL
249
+ * @param String $url URL
250
+ * @param array $data Parameters to be added as a query string to
251
+ * the URL provided
252
+ * @access protected
253
+ * @return void
254
+ */
255
+ protected function _addParametersToUrl($url, $data) {
256
+ if (!empty($data)) {
257
+ if (strpos($url, '?') === false) {
258
+ $url .= '?'.$this->buildData($data);
259
+ } else {
260
+ $url .= '&'.$this->buildData($data);
261
+ }
262
+ }
263
+ return $url;
264
+ }
265
+
266
+ /**
267
+ * generateNonce
268
+ *
269
+ * Generates a 'nonce', which is a unique request id based on the
270
+ * timestamp. If no timestamp is provided, generate one.
271
+ * @param mixed $timestamp Either a timestamp (epoch seconds) or false,
272
+ * in which case it will generate a timestamp.
273
+ * @access public
274
+ * @return string Returns a unique nonce
275
+ */
276
+ public function generateNonce($timestamp = false) {
277
+ if (!$timestamp) $timestamp = $this->generateTimestamp();
278
+ return md5($timestamp.'-'.rand(10000,99999).'-'.uniqid());
279
+ }
280
+
281
+ /**
282
+ * generateTimestamp
283
+ *
284
+ * Generates a timestamp, in seconds
285
+ * @access public
286
+ * @return int Timestamp, in epoch seconds
287
+ */
288
+ public function generateTimestamp() {
289
+ return time();
290
+ }
291
+
292
+ /**
293
+ * createSignature
294
+ *
295
+ * Creates a signature on the signature base and the signature key
296
+ * @param mixed $sigBase Base string of data to sign
297
+ * @param mixed $sigKey Key to sign the data with
298
+ * @access public
299
+ * @return string The signature
300
+ */
301
+ public function createSignature($sigBase, $sigKey) {
302
+ switch ($this->signatureMethod) {
303
+ case 'HMAC-SHA1':
304
+ default:
305
+ return base64_encode(hash_hmac('sha1', $sigBase, $sigKey, true));
306
+ }
307
+ }
308
+
309
+ /**
310
+ * encode
311
+ *
312
+ * Short-cut for utf8_encode / rawurlencode
313
+ * @param mixed $data Data to encode
314
+ * @access protected
315
+ * @return void Encoded data
316
+ */
317
+ protected function encode($data) {
318
+ return rawurlencode($data);
319
+ }
320
+
321
+ /**
322
+ * createSignatureKey
323
+ *
324
+ * Creates a key that will be used to sign our signature. Signatures
325
+ * are signed with the consumerSecret for this consumer application and
326
+ * the token secret of the user that the application is acting on behalf
327
+ * of.
328
+ * @access public
329
+ * @return void
330
+ */
331
+ public function createSignatureKey() {
332
+ return $this->consumerSecret.'&'.$this->user->tokenSecret;
333
+ }
334
+
335
+ /**
336
+ * getOAuthRequestData
337
+ *
338
+ * Get all the pre-signature, OAuth specific parameters for a request.
339
+ * @access public
340
+ * @return void
341
+ */
342
+ public function getOAuthRequestData() {
343
+ $token = $this->user->getHighestPriorityToken();
344
+ $ts = $this->generateTimestamp();
345
+ $nonce = $this->generateNonce($ts);
346
+ return array(
347
+ 'oauth_token' => $token,
348
+ 'oauth_consumer_key' => $this->consumerKey,
349
+ 'oauth_version' => $this->version,
350
+ 'oauth_timestamp' => $ts,
351
+ 'oauth_signature_method' => $this->signatureMethod,
352
+ 'oauth_nonce' => $nonce);
353
+ }
354
+
355
+
356
+ /**
357
+ * mergeOAuthData
358
+ *
359
+ * @param mixed $requestData
360
+ * @access public
361
+ * @return void
362
+ */
363
+ public function mergeOAuthData($requestData) {
364
+ $oauthData = $this->getOAuthRequestData();
365
+ return array_merge($requestData, $oauthData);
366
+ }
367
+
368
+ /**
369
+ * createSignatureBase
370
+ *
371
+ * @param mixed $method String name of HTTP method, such as "GET"
372
+ * @param mixed $url URL where this request will go
373
+ * @param mixed $data Array of params for this request. This should
374
+ * include ALL oauth properties except for the signature.
375
+ * @access public
376
+ * @return void
377
+ */
378
+ public function createSignatureBase($method, $url, $data) {
379
+ $method = $this->encode(strtoupper($method));
380
+ $query = parse_url($url, PHP_URL_QUERY);
381
+ if ($query) {
382
+ $parts = explode('?', $url, 2);
383
+ $url = array_shift($parts);
384
+ $items = explode('&', $query);
385
+ foreach ($items as $item) {
386
+ list($key, $value) = explode('=', $item);
387
+ $data[rawurldecode($key)] = rawurldecode($value);
388
+ }
389
+ }
390
+ $url = $this->encode($url);
391
+ $data = $this->encode($this->collapseDataForSignature($data));
392
+
393
+ return $method.'&'.$url.'&'.$data;
394
+ }
395
+
396
+ /**
397
+ * collapseDataForSignature
398
+ *
399
+ * Turns an array of request data into a string, as used by the oauth
400
+ * signature
401
+ * @param mixed $data
402
+ * @access public
403
+ * @return void
404
+ */
405
+ public function collapseDataForSignature($data) {
406
+ ksort($data);
407
+ $collapse = '';
408
+ foreach ($data as $key => $val) {
409
+ if (!empty($collapse)) $collapse .= '&';
410
+ $collapse .= $key.'='.$this->encode($val);
411
+ }
412
+ return $collapse;
413
+ }
414
+
415
+ /**
416
+ * signRequest
417
+ *
418
+ * Signs the request.
419
+ *
420
+ * @param mixed $method HTTP method
421
+ * @param mixed $url URL for the request
422
+ * @param mixed $data The data to be signed
423
+ * @access public
424
+ * @return array The data, with the signature.
425
+ */
426
+ public function signRequest($method, $url, $data) {
427
+ $base = $this->createSignatureBase($method, $url, $data);
428
+ $key = $this->createSignatureKey();
429
+ $data['oauth_signature'] = $this->createSignature($base, $key);
430
+ ksort($data);
431
+ return $data;
432
+ }
433
+
434
+
435
+ /**
436
+ * makeRequest
437
+ *
438
+ * Public facing function to make a request
439
+ *
440
+ * @param mixed $method
441
+ * @param mixed $url - Reserved characters in query params MUST be escaped
442
+ * @param mixed $data - Reserved characters in values MUST NOT be escaped
443
+ * @access public
444
+ * @return void
445
+ */
446
+ public function makeRequest($method, $url, $data=array()) {
447
+
448
+ if ($this->debug) echo "\n** {$method}: $url\n";
449
+
450
+ switch (strtoupper($method)) {
451
+ case 'POST':
452
+ $oauth = $this->prepareRequest($method, $url, $data);
453
+ $resp = $this->post($url, $oauth);
454
+ break;
455
+
456
+ case 'GET':
457
+ $oauth = $this->prepareRequest($method, $url, $data);
458
+ $resp = $this->get($url, $oauth, $data);
459
+ break;
460
+
461
+ case 'DELETE':
462
+ $oauth = $this->prepareRequest($method, $url, $data);
463
+ $resp = $this->delete($url, $oauth);
464
+ break;
465
+
466
+ case 'PATCH':
467
+ $oauth = $this->prepareRequest($method, $url, array());
468
+ $resp = $this->patch($url, $oauth, $data);
469
+ break;
470
+ }
471
+
472
+ // enable debug output
473
+ if ($this->debug) {
474
+ echo "<pre>";
475
+ print_r($oauth);
476
+ echo " --> Status: {$resp->headers['Status-Code']}\n";
477
+ echo " --> Body: {$resp->body}";
478
+ echo "</pre>";
479
+ }
480
+
481
+ if (!$resp) {
482
+ $msg = 'Unable to connect to the AWeber API. (' . $this->error . ')';
483
+ $error = array('message' => $msg, 'type' => 'APIUnreachableError',
484
+ 'documentation_url' => 'https://labs.aweber.com/docs/troubleshooting');
485
+ throw new AWeberAPIException($error, $url);
486
+ }
487
+
488
+ if($resp->headers['Status-Code'] >= 400) {
489
+ $data = json_decode($resp->body, true);
490
+ throw new AWeberAPIException($data['error'], $url);
491
+ }
492
+
493
+ return $resp;
494
+ }
495
+
496
+ /**
497
+ * put
498
+ *
499
+ * Prepare an OAuth put method.
500
+ *
501
+ * @param mixed $url URL where we are making the request to
502
+ * @param mixed $data Data that is used to make the request
503
+ * @access protected
504
+ * @return void
505
+ */
506
+ protected function patch($url, $oauth, $data) {
507
+ $url = $this->_addParametersToUrl($url, $oauth);
508
+ $handle = $this->curl->init($url);
509
+ $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'PATCH');
510
+ $this->curl->setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
511
+ $resp = $this->_sendRequest($handle, array('Expect:', 'Content-Type: application/json'));
512
+ return $resp;
513
+ }
514
+
515
+ /**
516
+ * post
517
+ *
518
+ * Prepare an OAuth post method.
519
+ *
520
+ * @param mixed $url URL where we are making the request to
521
+ * @param mixed $data Data that is used to make the request
522
+ * @access protected
523
+ * @return void
524
+ */
525
+ protected function post($url, $oauth) {
526
+ $handle = $this->curl->init($url);
527
+ $postData = $this->buildData($oauth);
528
+ $this->curl->setopt($handle, CURLOPT_POST, true);
529
+ $this->curl->setopt($handle, CURLOPT_POSTFIELDS, $postData);
530
+ $resp = $this->_sendRequest($handle);
531
+ return $resp;
532
+ }
533
+
534
+ /**
535
+ * delete
536
+ *
537
+ * Makes a DELETE request
538
+ * @param mixed $url URL where we are making the request to
539
+ * @param mixed $data Data that is used in the request
540
+ * @access protected
541
+ * @return void
542
+ */
543
+ protected function delete($url, $data) {
544
+ $url = $this->_addParametersToUrl($url, $data);
545
+ $handle = $this->curl->init($url);
546
+ $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'DELETE');
547
+ $resp = $this->_sendRequest($handle);
548
+ return $resp;
549
+ }
550
+
551
+ /**
552
+ * buildData
553
+ *
554
+ * Creates a string of data for either post or get requests.
555
+ * @param mixed $data Array of key value pairs
556
+ * @access public
557
+ * @return void
558
+ */
559
+ public function buildData($data) {
560
+ ksort($data);
561
+ $params = array();
562
+ foreach ($data as $key => $value) {
563
+ $params[] = $key.'='.$this->encode($value);
564
+ }
565
+ return implode('&', $params);
566
+ }
567
+
568
+ /**
569
+ * _sendRequest
570
+ *
571
+ * Actually makes a request.
572
+ * @param mixed $handle Curl handle
573
+ * @param array $headers Additional headers needed for request
574
+ * @access private
575
+ * @return void
576
+ */
577
+ private function _sendRequest($handle, $headers = array('Expect:')) {
578
+ $this->curl->setopt($handle, CURLOPT_RETURNTRANSFER, true);
579
+ $this->curl->setopt($handle, CURLOPT_HEADER, true);
580
+ $this->curl->setopt($handle, CURLOPT_HTTPHEADER, $headers);
581
+ $this->curl->setopt($handle, CURLOPT_USERAGENT, $this->userAgent);
582
+ $this->curl->setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);
583
+ $this->curl->setopt($handle, CURLOPT_VERBOSE, FALSE);
584
+ $this->curl->setopt($handle, CURLOPT_CONNECTTIMEOUT, 10);
585
+ $this->curl->setopt($handle, CURLOPT_TIMEOUT, 90);
586
+ $resp = $this->curl->execute($handle);
587
+ if ($resp) {
588
+ return new CurlResponse($resp);
589
+ }
590
+ $this->error = $this->curl->errno($handle) . ' - ' .
591
+ $this->curl->error($handle);
592
+ return false;
593
+ }
594
+
595
+ /**
596
+ * prepareRequest
597
+ *
598
+ * @param mixed $method HTTP method
599
+ * @param mixed $url URL for the request
600
+ * @param mixed $data The data to generate oauth data and be signed
601
+ * @access public
602
+ * @return void The data, with all its OAuth variables and signature
603
+ */
604
+ public function prepareRequest($method, $url, $data) {
605
+ $data = $this->mergeOAuthData($data);
606
+ $data = $this->signRequest($method, $url, $data);
607
+ return $data;
608
+ }
609
+
610
+ /**
611
+ * parseResponse
612
+ *
613
+ * Parses the body of the response into an array
614
+ * @param mixed $string The body of a response
615
+ * @access public
616
+ * @return void
617
+ */
618
+ public function parseResponse($resp) {
619
+ $data = array();
620
+
621
+ if (!$resp) { return $data; }
622
+ if (empty($resp)) { return $data; }
623
+ if (empty($resp->body)) { return $data; }
624
+
625
+ switch ($this->format) {
626
+ case 'json':
627
+ $data = json_decode($resp->body);
628
+ break;
629
+ default:
630
+ parse_str($resp->body, $data);
631
+ }
632
+ $this->parseAsError($data);
633
+ return $data;
634
+ }
635
+
636
+ }
637
+ endif;
638
+
639
+ /**
640
+ * OAuthUser
641
+ *
642
+ * Simple data class representing the user in an OAuth application.
643
+ * @package
644
+ * @version $id$
645
+ */
646
+
647
+ if( ! class_exists('OAuthUser') ) :
648
+ class OAuthUser {
649
+
650
+ public $authorizedToken = false;
651
+ public $requestToken = false;
652
+ public $verifier = false;
653
+ public $tokenSecret = false;
654
+ public $accessToken = false;
655
+
656
+ /**
657
+ * isAuthorized
658
+ *
659
+ * Checks if this user is authorized.
660
+ * @access public
661
+ * @return void
662
+ */
663
+ public function isAuthorized() {
664
+ if (empty($this->authorizedToken) && empty($this->accessToken)) {
665
+ return false;
666
+ }
667
+ return true;
668
+ }
669
+
670
+
671
+ /**
672
+ * getHighestPriorityToken
673
+ *
674
+ * Returns highest priority token - used to define authorization
675
+ * state for a given OAuthUser
676
+ * @access public
677
+ * @return void
678
+ */
679
+ public function getHighestPriorityToken() {
680
+ if (!empty($this->accessToken)) return $this->accessToken;
681
+ if (!empty($this->authorizedToken)) return $this->authorizedToken;
682
+ if (!empty($this->requestToken)) return $this->requestToken;
683
+
684
+ // Return no token, new user
685
+ return '';
686
+ }
687
+
688
+ }
689
+ endif;
trunk/includes/subscription/libs/mailchimp.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Super-simple, minimum abstraction MailChimp API v3 wrapper
4
+ * MailChimp API v3: http://developer.mailchimp.com
5
+ * This wrapper: https://github.com/drewm/mailchimp-api
6
+ *
7
+ * @author Drew McLellan <drew.mclellan@gmail.com>
8
+ * @version 2.2
9
+ */
10
+
11
+ if( ! class_exists('MailChimp') ):
12
+
13
+ class MailChimp {
14
+
15
+ private $api_key;
16
+ private $api_endpoint = 'https://<dc>.api.mailchimp.com/3.0';
17
+
18
+ /* SSL Verification
19
+ Read before disabling:
20
+ http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/
21
+ */
22
+ public $verify_ssl = false;
23
+
24
+ private $request_successful = false;
25
+ private $last_error = '';
26
+ private $last_response = array();
27
+ private $last_request = array();
28
+
29
+ /**
30
+ * Create a new instance
31
+ * @param string $api_key Your MailChimp API key
32
+ * @throws \Exception
33
+ */
34
+ public function __construct( $api_key ) {
35
+
36
+ $this->api_key = $api_key;
37
+
38
+ list(, $data_center) = explode( '-', $this->api_key );
39
+ $this->api_endpoint = str_replace('<dc>', $data_center, $this->api_endpoint);
40
+
41
+ $this->last_response = array('headers' => null, 'body' => null);
42
+ }
43
+
44
+ /**
45
+ * Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL
46
+ * @param string $email The subscriber's email address
47
+ * @return string Hashed version of the input
48
+ */
49
+ public function subscriberHash($email) {
50
+ return md5(strtolower($email));
51
+ }
52
+
53
+ /**
54
+ * Was the last request successful?
55
+ * @return bool True for success, false for failure
56
+ */
57
+ public function success() {
58
+ return $this->request_successful;
59
+ }
60
+
61
+ /**
62
+ * Get the last error returned by either the network transport, or by the API.
63
+ * If something didn't work, this should contain the string describing the problem.
64
+ * @return array|false describing the error
65
+ */
66
+ public function getLastError() {
67
+ return $this->last_error ?: false;
68
+ }
69
+
70
+ /**
71
+ * Get an array containing the HTTP headers and the body of the API response.
72
+ * @return array Assoc array with keys 'headers' and 'body'
73
+ */
74
+ public function getLastResponse() {
75
+ return $this->last_response;
76
+ }
77
+
78
+ /**
79
+ * Get an array containing the HTTP headers and the body of the API request.
80
+ * @return array Assoc array
81
+ */
82
+ public function getLastRequest() {
83
+ return $this->last_request;
84
+ }
85
+
86
+ /**
87
+ * Make an HTTP DELETE request - for deleting data
88
+ * @param string $method URL of the API request method
89
+ * @param array $args Assoc array of arguments (if any)
90
+ * @param int $timeout Timeout limit for request in seconds
91
+ * @return array|false Assoc array of API response, decoded from JSON
92
+ */
93
+ public function delete( $method, $args = array(), $timeout = 10 ) {
94
+ return $this->makeRequest('delete', $method, $args, $timeout);
95
+ }
96
+
97
+ /**
98
+ * Make an HTTP GET request - for retrieving data
99
+ * @param string $method URL of the API request method
100
+ * @param array $args Assoc array of arguments (usually your data)
101
+ * @param int $timeout Timeout limit for request in seconds
102
+ * @return array|false Assoc array of API response, decoded from JSON
103
+ */
104
+ public function get( $method, $args = array(), $timeout = 10 ) {
105
+ return $this->makeRequest('get', $method, $args, $timeout);
106
+ }
107
+
108
+ /**
109
+ * Make an HTTP PATCH request - for performing partial updates
110
+ * @param string $method URL of the API request method
111
+ * @param array $args Assoc array of arguments (usually your data)
112
+ * @param int $timeout Timeout limit for request in seconds
113
+ * @return array|false Assoc array of API response, decoded from JSON
114
+ */
115
+ public function patch( $method, $args = array(), $timeout = 10 ) {
116
+ return $this->makeRequest('patch', $method, $args, $timeout);
117
+ }
118
+
119
+ /**
120
+ * Make an HTTP POST request - for creating and updating items
121
+ * @param string $method URL of the API request method
122
+ * @param array $args Assoc array of arguments (usually your data)
123
+ * @param int $timeout Timeout limit for request in seconds
124
+ * @return array|false Assoc array of API response, decoded from JSON
125
+ */
126
+ public function post( $method, $args = array(), $timeout = 10 ) {
127
+ return $this->makeRequest('post', $method, $args, $timeout);
128
+ }
129
+
130
+ /**
131
+ * Make an HTTP PUT request - for creating new items
132
+ * @param string $method URL of the API request method
133
+ * @param array $args Assoc array of arguments (usually your data)
134
+ * @param int $timeout Timeout limit for request in seconds
135
+ * @return array|false Assoc array of API response, decoded from JSON
136
+ */
137
+ public function put( $method, $args = array(), $timeout = 10 ) {
138
+ return $this->makeRequest('put', $method, $args, $timeout);
139
+ }
140
+
141
+ /**
142
+ * Performs the underlying HTTP request. Not very exciting.
143
+ * @param string $http_verb The HTTP verb to use: get, post, put, patch, delete
144
+ * @param string $method The API method to be called
145
+ * @param array $args Assoc array of parameters to be passed
146
+ * @param int $timeout
147
+ * @return array|false Assoc array of decoded result
148
+ * @throws \Exception
149
+ */
150
+ private function makeRequest( $http_verb, $method, $args = array(), $timeout = 10 ) {
151
+
152
+ if (!function_exists('curl_init') || !function_exists('curl_setopt')) {
153
+ throw new \Exception("cURL support is required, but can't be found.");
154
+ }
155
+
156
+ $url = $this->api_endpoint . '/' . $method;
157
+
158
+ $this->last_error = '';
159
+ $this->request_successful = false;
160
+ $response = array('headers' => null, 'body' => null);
161
+ $this->last_response = $response;
162
+
163
+ $this->last_request = array(
164
+ 'method' => $http_verb,
165
+ 'path' => $method,
166
+ 'url' => $url,
167
+ 'body' => '',
168
+ 'timeout' => $timeout,
169
+ );
170
+
171
+ $ch = curl_init();
172
+ curl_setopt($ch, CURLOPT_URL, $url);
173
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array(
174
+ 'Accept: application/vnd.api+json',
175
+ 'Content-Type: application/vnd.api+json',
176
+ 'Authorization: apikey ' . $this->api_key
177
+ ));
178
+ curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)');
179
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
180
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
181
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
182
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
183
+ curl_setopt($ch, CURLOPT_ENCODING, '');
184
+ curl_setopt($ch, CURLINFO_HEADER_OUT, true);
185
+
186
+ switch ($http_verb) {
187
+ case 'post':
188
+ curl_setopt($ch, CURLOPT_POST, true);
189
+ $this->attachRequestPayload($ch, $args);
190
+ break;
191
+
192
+ case 'get':
193
+ $query = http_build_query($args, '', '&');
194
+ curl_setopt($ch, CURLOPT_URL, $url . '?' . $query);
195
+ break;
196
+
197
+ case 'delete':
198
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
199
+ break;
200
+
201
+ case 'patch':
202
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
203
+ $this->attachRequestPayload($ch, $args);
204
+ break;
205
+
206
+ case 'put':
207
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
208
+ $this->attachRequestPayload($ch, $args);
209
+ break;
210
+ }
211
+
212
+ $response['body'] = curl_exec($ch);
213
+ $response['headers'] = curl_getinfo($ch);
214
+
215
+ if (isset($response['headers']['request_header'])) {
216
+ $this->last_request['headers'] = $response['headers']['request_header'];
217
+ }
218
+
219
+ if ($response['body'] === false) {
220
+ $this->last_error = curl_error($ch);
221
+ }
222
+
223
+ curl_close($ch);
224
+
225
+ $formattedResponse = $this->formatResponse($response);
226
+
227
+ $this->determineSuccess($response, $formattedResponse);
228
+
229
+ return $formattedResponse;
230
+ }
231
+
232
+ /**
233
+ * @return string The url to the API endpoint
234
+ */
235
+ public function getApiEndpoint() {
236
+ return $this->api_endpoint;
237
+ }
238
+
239
+ /**
240
+ * Encode the data and attach it to the request
241
+ * @param resource $ch cURL session handle, used by reference
242
+ * @param array $data Assoc array of data to attach
243
+ */
244
+ private function attachRequestPayload(&$ch, $data) {
245
+ $encoded = json_encode($data);
246
+ $this->last_request['body'] = $encoded;
247
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
248
+ }
249
+
250
+ /**
251
+ * Decode the response and format any error messages for debugging
252
+ * @param array $response The response from the curl request
253
+ * @return array|false The JSON decoded into an array
254
+ */
255
+ private function formatResponse($response) {
256
+ $this->last_response = $response;
257
+
258
+ if (!empty($response['body'])) {
259
+ return json_decode($response['body'], true);
260
+ }
261
+
262
+ return false;
263
+ }
264
+
265
+ /**
266
+ * Check if the response was successful or a failure. If it failed, store the error.
267
+ * @param array $response The response from the curl request
268
+ * @param array|false $formattedResponse The response body payload from the curl request
269
+ * @return bool If the request was successful
270
+ */
271
+ private function determineSuccess($response, $formattedResponse) {
272
+ $status = $this->findHTTPStatus($response, $formattedResponse);
273
+
274
+ if ($status >= 200 && $status <= 299) {
275
+ $this->request_successful = true;
276
+ return true;
277
+ }
278
+
279
+ if (isset($formattedResponse['detail'])) {
280
+ $this->last_error = sprintf('%d: %s', $formattedResponse['status'], $formattedResponse['detail']);
281
+ return false;
282
+ }
283
+
284
+ $this->last_error = 'Unknown error, call getLastResponse() to find out what happened.';
285
+ return false;
286
+ }
287
+
288
+ /**
289
+ * Find the HTTP status code from the headers or API response body
290
+ * @param array $response The response from the curl request
291
+ * @param array|false $formattedResponse The response body payload from the curl request
292
+ * @return int HTTP status code
293
+ */
294
+ private function findHTTPStatus($response, $formattedResponse) {
295
+ if (!empty($response['headers']) && isset($response['headers']['http_code'])) {
296
+ return (int) $response['headers']['http_code'];
297
+ }
298
+
299
+ if (!empty($response['body']) && isset($formattedResponse['status'])) {
300
+ return (int) $formattedResponse['status'];
301
+ }
302
+
303
+ return 418;
304
+ }
305
+ }
306
+ endif;
trunk/includes/wps-functions-options.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin options functions.
4
+ */
5
+
6
+ /**
7
+ * Get mailing services
8
+ *
9
+ * @use filter wp_subscribe_mailing_services
10
+ * @return array
11
+ */
12
+ function wps_get_mailing_services( $type = 'raw' ) {
13
+
14
+ $services = array(
15
+
16
+ 'aweber' => array(
17
+ 'title' => esc_html__( 'Aweber', 'wp-subscribe' ),
18
+ 'description' => esc_html__( 'Adds subscribers to your Aweber account.', 'wp-subscribe' ),
19
+ 'class' => 'WPS_Subscription_Aweber'
20
+ ),
21
+
22
+ 'feedburner' => array(
23
+ 'title' => esc_html__( 'FeedBurner', 'wp-subscribe' ),
24
+ 'description' => esc_html__( 'Adds subscribers to your FeedBurner account.', 'wp-subscribe' ),
25
+ 'class' => 'WPS_Subscription_FeedBurner'
26
+ ),
27
+
28
+ 'mailchimp' => array(
29
+ 'title' => esc_html__( 'MailChimp', 'wp-subscribe' ),
30
+ 'description' => esc_html__( 'Adds subscribers to your MailChimp account.', 'wp-subscribe' ),
31
+ 'class' => 'WPS_Subscription_MailChimp'
32
+ )
33
+ );
34
+
35
+ $services = apply_filters( 'wp_subscribe_mailing_services', $services );
36
+
37
+ if( 'options' === $type ) {
38
+ return wp_list_pluck( $services, 'title' );
39
+ }
40
+
41
+ return $services;
42
+ }
trunk/includes/wps-helpers.php ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Helper Functions
4
+ */
5
+
6
+ // Exit if accessed directly
7
+ if ( ! defined( 'ABSPATH' ) ) exit;
8
+
9
+ // ---------------- PLUGIN HELPERS -----------------------------------
10
+
11
+ /**
12
+ * Generate the subscription form
13
+ * @return void
14
+ */
15
+ function wps_the_form( $options = null ) {
16
+
17
+ global $wp, $wp_subscribe_forms;
18
+
19
+ // Options
20
+ if ( null == $options ) {
21
+ return;
22
+ }
23
+
24
+ // Enqueue script and styles
25
+ wp_enqueue_style( 'wp-subscribe' );
26
+ wp_enqueue_script( 'wp-subscribe' );
27
+
28
+ $wp_subscribe_forms++;
29
+ $service = wps_get_subscription_service( $options['service'] );
30
+ $current_url = add_query_arg( $wp->query_string, '', home_url( $wp->request ) );
31
+ ?>
32
+ <?php if( isset( $options['before_widget'] ) ) : ?>
33
+ <?php echo $options['before_widget'] ?>
34
+ <?php else: ?>
35
+ <div class="wp-subscribe-popup-form-wrapper">
36
+ <?php endif; ?>
37
+
38
+ <div id="wp-subscribe" class="wp-subscribe-wrap wp-subscribe wp-subscribe-<?php echo $wp_subscribe_forms ?>" data-thanks_page="<?php echo absint( isset( $options['thanks_page'] ) ? $options['thanks_page'] : 0 ) ?>" data-thanks_page_url="<?php echo isset( $options['thanks_page_url'] ) ? esc_url( $options['thanks_page_url'] ) : '' ?>" data-thanks_page_new_window="0">
39
+
40
+ <h4 class="title"><?php echo wp_kses_post( $options['title'] )?></h4>
41
+
42
+ <p class="text"><?php echo wp_kses_post( $options['text'] ) ?></p>
43
+
44
+ <?php if( method_exists( $service, 'the_form' ) ) :
45
+ $service->the_form( $wp_subscribe_forms, $options );
46
+ else: ?>
47
+
48
+ <form action="<?php echo $current_url ?>" method="post" class="wp-subscribe-form wp-subscribe-<?php echo $options['service'] ?>" id="wp-subscribe-form-<?php echo $wp_subscribe_forms ?>">
49
+
50
+ <?php if( !empty( $options['include_name_field'] ) ) : ?>
51
+ <input class="regular-text name-field" type="text" name="name" placeholder="<?php echo esc_attr( $options['name_placeholder'] ) ?>">
52
+ <?php endif; ?>
53
+
54
+ <input class="regular-text email-field" type="text" name="email" placeholder="<?php echo esc_attr( $options['email_placeholder'] ) ?>">
55
+
56
+ <input type="hidden" name="form_type" value="<?php echo $options['form_type'] ?>">
57
+
58
+ <input type="hidden" name="service" value="<?php echo $options['service'] ?>">
59
+
60
+ <input type="hidden" name="widget" value="<?php echo isset( $options['widget_id'] ) ? $options['widget_id'] : '0'; ?>">
61
+
62
+ <input class="submit" type="submit" name="submit" value="<?php echo esc_attr( $options['button_text'] ) ?>">
63
+
64
+ </form>
65
+
66
+ <?php endif; ?>
67
+
68
+ <div class="wp-subscribe-loader">
69
+ <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
70
+ <path fill="#ffffff" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z">
71
+ <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/>
72
+ </path>
73
+ </svg>
74
+ </div>
75
+
76
+ <?php if( !empty( $options['success_message'] ) ) {
77
+ printf( '<p class="thanks">%s</p>', wp_kses_post( $options['success_message'] ) );
78
+ } ?>
79
+
80
+ <?php if( !empty( $options['error_message'] ) ) {
81
+ printf( '<p class="error">%s</p>', wp_kses_post( $options['error_message'] ) );
82
+ } ?>
83
+
84
+ <div class="clear"></div>
85
+
86
+ <p class="footer-text"><?php echo $options['footer_text'];?></p>
87
+
88
+ </div>
89
+
90
+ <?php if( isset( $options['after_widget'] ) ) : ?>
91
+ <?php echo $options['after_widget'] ?>
92
+ <?php else: ?>
93
+ </div><!-- /form-wrapper -->
94
+ <?php endif; ?>
95
+
96
+ <?php
97
+ }
98
+
99
+ /**
100
+ * Get widget setting by id
101
+ * @param int $widget_id
102
+ * @return mixed
103
+ */
104
+ function wps_get_widget_settings( $widget_id ) {
105
+
106
+ $options = array();
107
+ global $wp_registered_widgets;
108
+
109
+ if ( isset( $wp_registered_widgets ) && isset( $wp_registered_widgets[$widget_id] ) ) {
110
+
111
+ $widget = $wp_registered_widgets[$widget_id];
112
+ $settings = $widget['callback'][0]->get_settings();
113
+
114
+ if ( isset( $settings[$widget['params'][0]['number']] ) ) {
115
+ $options = $settings[$widget['params'][0]['number']];
116
+ }
117
+ }
118
+
119
+ return $options;
120
+ }
121
+
122
+
123
+ // ---------------- STRING HELPERS ---------------------------------
124
+
125
+ /**
126
+ * Check if the string begins with the given value
127
+ *
128
+ * @param string $needle The sub-string to search for
129
+ * @param string $haystack The string to search
130
+ *
131
+ * @return bool
132
+ */
133
+ function wps_str_start_with( $needle, $haystack ) {
134
+ return substr_compare( $haystack, $needle, 0, strlen( $needle ) ) === 0;
135
+ }
136
+
137
+ /**
138
+ * Check if the string contains the given value
139
+ *
140
+ * @param string $needle The sub-string to search for
141
+ * @param string $haystack The string to search
142
+ *
143
+ * @return bool
144
+ */
145
+ function wps_str_contains( $needle, $haystack ) {
146
+ return strpos( $haystack, $needle ) !== false;
147
+ }
148
+
149
+
150
+ // ---------------- HTML HELPERS ---------------------------------
151
+
152
+ /**
153
+ * Output select field html
154
+ *
155
+ * @param array $args
156
+ *
157
+ * @return void
158
+ */
159
+ function wps_field_select( $args = array() ) {
160
+
161
+ extract( wp_parse_args( $args, array(
162
+ 'class' => 'widefat'
163
+ ) ) );
164
+ ?>
165
+ <select class="<?php echo esc_attr( $class ) ?>" id="<?php echo esc_attr( $id ) ?>" name="<?php echo esc_attr( $name ) ?>">
166
+
167
+ <?php foreach ( $options as $key => $text ) : ?>
168
+ <option value="<?php echo esc_attr( $key ) ?>"<?php selected( $key, $value ) ?>>
169
+ <?php echo esc_html( $text ) ?>
170
+ </option>
171
+ <?php endforeach ?>
172
+ </select>
173
+ <?php
174
+ }
175
+
176
+ /**
177
+ * Output text field html
178
+ *
179
+ * @param array $args
180
+ *
181
+ * @return void
182
+ */
183
+ function wps_field_text( $args = array() ) {
184
+
185
+ extract( wp_parse_args( $args, array(
186
+ 'class' => 'widefat'
187
+ ) ) );
188
+ ?>
189
+ <input class="<?php echo esc_attr( $class ) ?>" id="<?php echo esc_attr( $id ) ?>" name="<?php echo esc_attr( $name ) ?>" type="text" value="<?php echo esc_attr( $value ) ?>"<?php if( isset( $data_id ) ) { printf( 'data-id="%s"', $data_id ); } ?>>
190
+ <?php
191
+ }
192
+
193
+ /**
194
+ * Output hidden field html
195
+ *
196
+ * @param array $args
197
+ *
198
+ * @return void
199
+ */
200
+ function wps_field_hidden( $args = array() ) {
201
+
202
+ extract( $args );
203
+ ?>
204
+ <input id="<?php echo esc_attr( $id ) ?>" name="<?php echo esc_attr( $name ) ?>" type="hidden" value="<?php echo esc_attr( $value ) ?>"<?php if( isset( $data_id ) ) { printf( 'data-id="%s"', $data_id ); } ?>>
205
+ <?php
206
+ }
207
+
208
+ /**
209
+ * Get animation select
210
+ * @param string $id
211
+ * @param string $name
212
+ * @return void
213
+ */
214
+ function wps_get_animations( $id = '', $name = '', $value = '' ) {
215
+
216
+ $animations = array(
217
+ '0' => esc_html__( 'No Animation', 'wp-subscribe' ),
218
+ esc_html__( 'Attention Seekers', 'wp-subscribe' ) => array(
219
+ 'bounce' => esc_html__( 'bounce', 'wp-subscribe' ),
220
+ 'flash' => esc_html__( 'flash', 'wp-subscribe' ),
221
+ 'pulse' => esc_html__( 'pulse', 'wp-subscribe' ),
222
+ 'rubberBand' => esc_html__( 'rubberBand', 'wp-subscribe' ),
223
+ 'shake' => esc_html__( 'shake', 'wp-subscribe' ),
224
+ 'swing' => esc_html__( 'swing', 'wp-subscribe' ),
225
+ 'tada' => esc_html__( 'tada', 'wp-subscribe' ),
226
+ 'wobble' => esc_html__( 'wobble', 'wp-subscribe' ),
227
+ ),
228
+ esc_html__( 'Bouncing Entrances', 'wp-subscribe' ) => array(
229
+ 'bounceIn' => esc_html__( 'bounceIn', 'wp-subscribe' ),
230
+ 'bounceInDown' => esc_html__( 'bounceInDown', 'wp-subscribe' ),
231
+ 'bounceInLeft' => esc_html__( 'bounceInLeft', 'wp-subscribe' ),
232
+ 'bounceInRight' => esc_html__( 'bounceInRight', 'wp-subscribe' ),
233
+ 'bounceInUp' => esc_html__( 'bounceInUp', 'wp-subscribe' ),
234
+ ),
235
+ esc_html__( 'Fading Entrances', 'wp-subscribe' ) => array(
236
+ 'fadeIn' => esc_html__( 'fadeIn', 'wp-subscribe' ),
237
+ 'fadeInDown' => esc_html__( 'fadeInDown', 'wp-subscribe' ),
238
+ 'fadeInDownBig' => esc_html__( 'fadeInDownBig', 'wp-subscribe' ),
239
+ 'fadeInLeft' => esc_html__( 'fadeInLeft', 'wp-subscribe' ),
240
+ 'fadeInLeftBig' => esc_html__( 'fadeInLeftBig', 'wp-subscribe' ),
241
+ 'fadeInRight' => esc_html__( 'fadeInRight', 'wp-subscribe' ),
242
+ 'fadeInRightBig' => esc_html__( 'fadeInRightBig', 'wp-subscribe' ),
243
+ 'fadeInUp' => esc_html__( 'fadeInUp', 'wp-subscribe' ),
244
+ 'fadeInUpBig' => esc_html__( 'fadeInUpBig', 'wp-subscribe' ),
245
+ ),
246
+ esc_html__( 'Flippers', 'wp-subscribe' ) => array(
247
+ 'flipInX' => esc_html__( 'flipInX', 'wp-subscribe' ),
248
+ 'flipInY' => esc_html__( 'flipInY', 'wp-subscribe' ),
249
+ ),
250
+ esc_html__( 'Lightspeed', 'wp-subscribe' ) => array(
251
+ 'lightSpeedIn' => esc_html__( 'lightSpeedIn', 'wp-subscribe' ),
252
+ ),
253
+ esc_html__( 'Rotating Entrances', 'wp-subscribe' ) => array(
254
+ 'rotateIn' => esc_html__( 'rotateIn', 'wp-subscribe' ),
255
+ 'rotateInDownLeft' => esc_html__( 'rotateInDownLeft', 'wp-subscribe' ),
256
+ 'rotateInDownRight' => esc_html__( 'rotateInDownRight', 'wp-subscribe' ),
257
+ 'rotateInUpLeft' => esc_html__( 'rotateInUpLeft', 'wp-subscribe' ),
258
+ 'rotateInUpRight' => esc_html__( 'rotateInUpRight', 'wp-subscribe' ),
259
+ ),
260
+ esc_html__( 'Specials', 'wp-subscribe' ) => array(
261
+ 'rollIn' => esc_html__( 'rollIn', 'wp-subscribe' ),
262
+ ),
263
+ esc_html__( 'Zoom Entrances', 'wp-subscribe' ) => array(
264
+ 'zoomIn' => esc_html__( 'zoomIn', 'wp-subscribe' ),
265
+ 'zoomInDown' => esc_html__( 'zoomInDown', 'wp-subscribe' ),
266
+ 'zoomInLeft' => esc_html__( 'zoomInLeft', 'wp-subscribe' ),
267
+ 'zoomInRight' => esc_html__( 'zoomInRight', 'wp-subscribe' ),
268
+ 'zoomInUp' => esc_html__( 'zoomInUp', 'wp-subscribe' ),
269
+ )
270
+ );
271
+
272
+ printf( '<select id="%1$s" name="%2$s">', $id, $name );
273
+ wps_print_select_options( $animations, $value );
274
+ echo '</select>';
275
+ }
276
+
277
+ function wps_print_select_options( $options, $value ) {
278
+
279
+ foreach( $options as $key => $text ) {
280
+
281
+ if( is_array( $text ) ) {
282
+ printf( '<optgroup label="%s">', $key );
283
+ wps_print_select_options( $text, $value );
284
+ echo '</optgroup>';
285
+ }
286
+ else {
287
+ printf(
288
+ '<option value="%1$s"%3$s>%2$s</option>',
289
+ $key, $text,
290
+ selected( $value, $key, false )
291
+ );
292
+ }
293
+ }
294
+ }
295
+
296
+ // ---------------- SERVICE HELPERS ---------------------------------
297
+
298
+ /**
299
+ * Get subscription service info
300
+ *
301
+ * @param string $id
302
+ * @return string
303
+ */
304
+ function wps_get_subscription_info( $id ) {
305
+
306
+ $services = wps_get_mailing_services();
307
+
308
+ return isset( $services[$id] ) ? $services[$id] : null;
309
+ }
310
+
311
+ /**
312
+ * Get subscription service class instance
313
+ *
314
+ * @param string $id
315
+ * @return object
316
+ */
317
+ function wps_get_subscription_service( $id ) {
318
+
319
+ $info = wps_get_subscription_info( $id );
320
+
321
+ if( is_null( $info ) ) {
322
+ return;
323
+ }
324
+
325
+ return new $info['class']( $info );
326
+ }
327
+
328
+ /**
329
+ * Get service list stored in db as trasient
330
+ *
331
+ * @param string $name
332
+ * @return array
333
+ */
334
+ function wps_get_service_list( $name = '' ) {
335
+
336
+ if( !$name ) {
337
+ return;
338
+ }
339
+
340
+ $list = get_option( 'mts_wps_'. $name . '_lists' );
341
+
342
+ return empty( $list ) ? array() : $list;
343
+ }
trunk/includes/wps-widget.php ADDED
@@ -0,0 +1,385 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The WP Subscribe widget class
5
+ */
6
+
7
+ if( ! class_exists('wp_subscribe') ) :
8
+
9
+ class wp_subscribe extends WP_Widget {
10
+
11
+ /**
12
+ * The Constructor
13
+ */
14
+ public function __construct() {
15
+
16
+ add_action( 'wp_enqueue_scripts', array( &$this, 'register_scripts' ) );
17
+ add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
18
+ add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
19
+
20
+ // Widget settings
21
+ $widget_ops = array(
22
+ 'classname' => 'wp_subscribe',
23
+ 'description' => esc_html__( 'Displays subscription form, supports FeedBurner, MailChimp & AWeber.', 'wp-subscribe' )
24
+ );
25
+
26
+ // Widget control settings
27
+ $control_ops = array(
28
+ 'id_base' => 'wp_subscribe'
29
+ );
30
+
31
+ // Create the widget.
32
+ parent::__construct(
33
+ 'wp_subscribe',
34
+ esc_html__( 'WP Subscribe Widget', 'wp-subscribe' ),
35
+ $widget_ops,
36
+ $control_ops
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Get default values for widget
42
+ * @return array
43
+ */
44
+ public function get_defaults() {
45
+
46
+ return apply_filters( 'wp_subscribe_form_defaults', array(
47
+ 'service' => 'feedburner',
48
+ 'include_name_field' => false,
49
+
50
+ 'title' => esc_html__( 'Get more stuff', 'wp-subscribe' ),
51
+ 'text' => esc_html__( 'Subscribe to our mailing list and get interesting stuff and updates to your email inbox.', 'wp-subscribe' ),
52
+ 'email_placeholder' => esc_html__( 'Enter your email here', 'wp-subscribe' ),
53
+ 'name_placeholder' => esc_html__( 'Enter your name here', 'wp-subscribe' ),
54
+ 'button_text' => esc_html__( 'Sign Up Now', 'wp-subscribe' ),
55
+ 'success_message' => esc_html__( 'Thank you for subscribing.', 'wp-subscribe' ),
56
+ 'error_message' => esc_html__( 'Something went wrong.', 'wp-subscribe' ),
57
+ 'footer_text' => esc_html__( 'we respect your privacy and take protecting it seriously', 'wp-subscribe' )
58
+ ));
59
+ }
60
+
61
+ /**
62
+ * Register scripts and json to be used in plugin
63
+ * @return void
64
+ */
65
+ function register_scripts() {
66
+
67
+ wp_register_style( 'wp-subscribe', wps()->plugin_url() . '/assets/css/wp-subscribe-form.css' );
68
+ wp_register_script( 'wp-subscribe', wps()->plugin_url() . '/assets/js/wp-subscribe-form.js', array( 'jquery' ) );
69
+
70
+ wp_localize_script( 'wp-subscribe', 'wp_subscribe', array(
71
+ 'ajaxurl' => admin_url( 'admin-ajax.php' )
72
+ ) );
73
+ }
74
+
75
+ /**
76
+ * Enqueue script for specific screens only
77
+ * @return void
78
+ */
79
+ function enqueue_scripts() {
80
+
81
+ $screen = get_current_screen();
82
+ $current_filter = current_filter();
83
+
84
+ if ( 'widgets' === $screen->id || 'customize_controls_enqueue_scripts' === $current_filter ) {
85
+
86
+ wp_enqueue_style( 'wp-subscribe-options', wps()->plugin_url() . '/assets/css/wp-subscribe-options.css' );
87
+ wp_enqueue_script( 'wp-subscribe-admin', wps()->plugin_url() . '/assets/js/wp-subscribe-admin.js', array( 'jquery' ) );
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Display widget
93
+ * @param array $args
94
+ * @param array $instance
95
+ * @return void
96
+ */
97
+ function widget( $args, $instance ) {
98
+
99
+ extract( $args );
100
+ $instance = wp_parse_args( (array) $instance, $this->get_defaults() );
101
+
102
+ $instance['before_widget'] = $before_widget;
103
+ $instance['after_widget'] = $after_widget;
104
+ $instance['widget_id'] = $this->id;
105
+ $instance['form_type'] = 'widget';
106
+
107
+ wps_the_form( $instance );
108
+ }
109
+
110
+ /**
111
+ * Update widget
112
+ *
113
+ * @param array $new_instance
114
+ * @param array $old_instance
115
+ *
116
+ * @return array
117
+ */
118
+ function update( $new_instance, $old_instance ) {
119
+
120
+ $instance = $old_instance;
121
+ $instance = array_merge( $instance, $new_instance );
122
+
123
+ // Feedburner ID -- make sure the user didn't insert full url
124
+ if( isset( $instance['feedburner_id'] ) && 0 === strpos( $instance['feedburner_id'], 'http' ) ) {
125
+ $instance['feedburner_id'] = substr( $instance['feedburner_id'], strrpos( $instance['feedburner_id'], '/' ) + 1 );
126
+ }
127
+
128
+ return $instance;
129
+ }
130
+
131
+ /**
132
+ * Display widget form
133
+ *
134
+ * @param array $instance
135
+ * @return void
136
+ */
137
+ function form( $instance ) {
138
+
139
+ $instance = wp_parse_args( (array) $instance, $this->get_defaults() );
140
+ $services = wps_get_mailing_services('options');
141
+ ?>
142
+ <div class="wp_subscribe_options_form">
143
+
144
+ <!-- Hidden title field to prevent WP picking up Title Color field as widget title -->
145
+ <input type="hidden" value="" id="<?php echo $this->get_field_id('title') ?>" name="<?php echo $this->get_field_name('title') ?>">
146
+
147
+ <?php $this->field_select(array(
148
+ 'id' => 'service',
149
+ 'name' => 'service',
150
+ 'title' => esc_html( 'Service:', 'wp-subscribe' ),
151
+ 'value' => $instance['service'],
152
+ 'options' => $services,
153
+ 'class' => 'services_dropdown'
154
+ )); ?>
155
+
156
+ <div class="wp_subscribe_account_details">
157
+
158
+ <?php foreach( $services as $service_id => $service_name ): ?>
159
+ <div class="wps-account-details wp_subscribe_account_details_<?php echo esc_attr( $service_id ) ?>" data-service="<?php echo esc_attr( $service_id ) ?>" style="display: none;">
160
+ <?php
161
+ $service = wps_get_subscription_service( $service_id );
162
+ $service->display_form( $instance, $this );
163
+ ?>
164
+ </div><!-- /wp_subscribe_account_details_<?php echo esc_attr( $service_id ) ?> -->
165
+ <?php endforeach; ?>
166
+
167
+ </div><!-- .wp_subscribe_account_details -->
168
+
169
+ <p class="wp_subscribe_include_name">
170
+
171
+ <label for="<?php echo $this->get_field_id('include_name_field') ?>">
172
+ <input type="hidden" name="<?php echo $this->get_field_name('include_name_field'); ?>" value="0">
173
+ <input id="<?php echo $this->get_field_id('include_name_field'); ?>" type="checkbox" class="include-name-field" name="<?php echo $this->get_field_name('include_name_field'); ?>" value="1" <?php checked($instance['include_name_field']); ?>>
174
+ <?php echo wp_kses_post( __( 'Include <strong>Name</strong> field', 'wp-subscribe' ) ) ?>
175
+ </label>
176
+
177
+ </p>
178
+
179
+ <h4 class="wp_subscribe_labels_header">
180
+ <a class="wp-subscribe-toggle" href="#" rel="wp_subscribe_labels"><?php _e('Labels', 'wp-subscribe'); ?></a>
181
+ </h4>
182
+
183
+ <div class="wp_subscribe_labels" style="display: none;">
184
+
185
+ <?php
186
+
187
+ $this->field_textarea(array(
188
+ 'id' => 'title',
189
+ 'name' => 'title',
190
+ 'title' => esc_html( 'Title', 'wp-subscribe' ),
191
+ 'value' => $instance['title']
192
+ ));
193
+
194
+ $this->field_text(array(
195
+ 'id' => 'text',
196
+ 'name' => 'text',
197
+ 'title' => esc_html( 'Text', 'wp-subscribe' ),
198
+ 'value' => $instance['text']
199
+ ));
200
+
201
+ $this->field_text(array(
202
+ 'id' => 'name_placeholder',
203
+ 'name' => 'name_placeholder',
204
+ 'title' => esc_html( 'Name Placeholder', 'wp-subscribe' ),
205
+ 'value' => $instance['name_placeholder']
206
+ ));
207
+
208
+ $this->field_text(array(
209
+ 'id' => 'email_placeholder',
210
+ 'name' => 'email_placeholder',
211
+ 'title' => esc_html( 'Email Placeholder', 'wp-subscribe' ),
212
+ 'value' => $instance['email_placeholder']
213
+ ));
214
+
215
+ $this->field_text(array(
216
+ 'id' => 'button_text',
217
+ 'name' => 'button_text',
218
+ 'title' => esc_html( 'Button Text', 'wp-subscribe' ),
219
+ 'value' => $instance['button_text']
220
+ ));
221
+
222
+ $this->field_text(array(
223
+ 'id' => 'success_message',
224
+ 'name' => 'success_message',
225
+ 'title' => esc_html( 'Success Message', 'wp-subscribe' ),
226
+ 'value' => $instance['success_message']
227
+ ));
228
+
229
+ $this->field_text(array(
230
+ 'id' => 'error_message',
231
+ 'name' => 'error_message',
232
+ 'title' => esc_html( 'Error Message', 'wp-subscribe' ),
233
+ 'value' => $instance['error_message']
234
+ ));
235
+
236
+ $this->field_text(array(
237
+ 'id' => 'footer_text',
238
+ 'name' => 'footer_text',
239
+ 'title' => esc_html( 'Footer Text', 'wp-subscribe' ),
240
+ 'value' => $instance['footer_text']
241
+ ));
242
+ ?>
243
+
244
+ </div><!-- .wp_subscribe_labels -->
245
+
246
+ </div><!-- .wp_subscribe_options_form -->
247
+ <?php
248
+ }
249
+
250
+ // -------------------------- FIELD HELPRES ----------------------
251
+
252
+ public function field_textarea( $args = array() ) {
253
+
254
+ extract( $args );
255
+ ?>
256
+ <p class="wp-subscribe-label-field wp-subscribe-<?php echo $id; ?>-field">
257
+ <label for="<?php echo $this->get_field_id($id) ?>">
258
+ <?php echo $title ?>
259
+ </label>
260
+
261
+ <textarea class="widefat" id="<?php echo $this->get_field_id($id) ?>" name="<?php echo $this->get_field_name($id) ?>"><?php echo esc_textarea( $value ) ?></textarea>
262
+ </p>
263
+
264
+ <?php
265
+ }
266
+
267
+ public function field_text( $args = array() ) {
268
+
269
+ extract( $args );
270
+ ?>
271
+ <div class="wp-subscribe-label-field wp-subscribe-<?php echo $id; ?>-field">
272
+ <label for="<?php echo $this->get_field_id( $id ) ?>">
273
+ <?php echo esc_html( $title ) ?>
274
+ </label>
275
+
276
+ <div class="wps-input-wrapper">
277
+
278
+ <?php wps_field_text(array(
279
+ 'id' => $this->get_field_id( $id ),
280
+ 'name' => $this->get_field_name( $id ),
281
+ 'value' => $value,
282
+ 'data_id' => $id
283
+ )) ?>
284
+
285
+ <?php if( isset( $link ) ) {
286
+ printf( ' <a target="_blank" href="%s" class="button">%s</a>', esc_url( $link ), esc_html__( 'Click here', 'wp-subscribe' ) );
287
+ } ?>
288
+
289
+ <?php if( isset( $desc ) ) {
290
+ printf( '<span class="wps-desc">%s</span>', wp_kses_post( $desc ) );
291
+ } ?>
292
+
293
+ </div>
294
+
295
+ </div>
296
+ <?php
297
+ }
298
+
299
+ public function field_hidden( $args = array() ) {
300
+
301
+ extract( $args );
302
+
303
+ wps_field_hidden(array(
304
+ 'id' => $this->get_field_id( $id ),
305
+ 'name' => $this->get_field_name( $id ),
306
+ 'value' => $value,
307
+ 'data_id' => $id
308
+ ));
309
+ }
310
+
311
+ public function field_raw( $args = array() ) {
312
+
313
+ call_user_func_array( $args['content'], array( $args['value'] ) );
314
+ }
315
+
316
+ public function field_checkbox( $args = array() ) {
317
+
318
+ extract( $args );
319
+ ?>
320
+ <div class="wp-subscribe-<?php echo $id; ?>-field">
321
+
322
+ <label for="<?php echo $this->get_field_id( $id ) ?>">
323
+
324
+ <input type="hidden" name="<?php echo $this->get_field_name( $id ) ?>" value="0" data-id="<?php echo $this->get_field_id( $id ) ?>">
325
+
326
+ <input type="checkbox" id="<?php echo $this->get_field_id( $id ) ?>" name="<?php echo $this->get_field_name( $id ) ?>" value="1"<?php checked( $value ) ?> data-id="<?php echo $id ?>">
327
+
328
+ <?php echo esc_html($title) ?>
329
+
330
+ </label>
331
+
332
+ </div>
333
+ <?php
334
+ }
335
+
336
+ public function field_select( $args = array() ) {
337
+
338
+ $options = array();
339
+ extract( $args );
340
+ ?>
341
+
342
+ <div class="wp-subscribe-label-field wp-subscribe-<?php echo $id ?>-field">
343
+ <label for="<?php echo $this->get_field_id( $id ) ?>">
344
+ <?php echo esc_html( $title ) ?>
345
+ </label>
346
+
347
+ <div class="wps-input-wrapper">
348
+ <?php wps_field_select(array(
349
+ 'id' => $this->get_field_id( $id ),
350
+ 'name' => $this->get_field_name( $id ),
351
+ 'value' => $value,
352
+ 'options' => $options,
353
+ 'class' => 'widefat list-selectbox'
354
+ )) ?>
355
+
356
+ <?php if( isset( $is_list ) && $is_list ) {
357
+ printf( ' <button class="button wps-get-list">%s</button>', esc_html__( 'Get list', 'wp-subscribe' ) );
358
+ } ?>
359
+
360
+ <?php if( isset( $link ) ) {
361
+ printf( ' <a target="_blank" href="%s" class="button">%s</a>', esc_url( $link ), esc_html__( 'Click here', 'wp-subscribe' ) );
362
+ } ?>
363
+
364
+ <?php if( isset( $desc ) ) {
365
+ printf( '<span class="wps-desc">%s</span>', wp_kses_post( $desc ) );
366
+ } ?>
367
+
368
+ </div>
369
+
370
+ </div>
371
+
372
+ <?php
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Register widget
378
+ * @return void
379
+ */
380
+ add_action( 'widgets_init', 'wps_register_widget' );
381
+ function wps_register_widget() {
382
+ register_widget( 'wp_subscribe' );
383
+ }
384
+
385
+ endif;
trunk/languages/wp-subscribe.pot ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2018 WP Subscribe
2
+ # This file is distributed under the same license as the WP Subscribe package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: WP Subscribe 1.2.6\n"
6
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-subscribe\n"
7
+ "POT-Creation-Date: 2018-02-17 01:23:40+00:00\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
12
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
+ "Language-Team: LANGUAGE <LL@li.org>\n"
14
+
15
+ #: includes/subscription/class-wps-aweber.php:67
16
+ msgid "Unable to connect to Aweber. The Authorization Code is empty."
17
+ msgstr ""
18
+
19
+ #: includes/subscription/class-wps-aweber.php:77
20
+ msgid ""
21
+ "Unable to connect your Aweber Account. The Authorization Code is incorrect."
22
+ msgstr ""
23
+
24
+ #: includes/subscription/class-wps-aweber.php:203
25
+ msgid "AWeber List"
26
+ msgstr ""
27
+
28
+ #: includes/subscription/class-wps-aweber.php:204
29
+ #: includes/subscription/class-wps-mailchimp.php:73
30
+ msgid "Select List"
31
+ msgstr ""
32
+
33
+ #: includes/subscription/class-wps-aweber.php:217
34
+ msgid "To connect your Aweber account:"
35
+ msgstr ""
36
+
37
+ #: includes/subscription/class-wps-aweber.php:220
38
+ msgid ""
39
+ "<span>1.</span> <a href=\"%s\" target=\"_blank\">Click here</a> <span>to "
40
+ "open the authorization page and log in.</span>"
41
+ msgstr ""
42
+
43
+ #: includes/subscription/class-wps-aweber.php:221
44
+ msgid ""
45
+ "<span>2.</span> Copy and paste the authorization code in the field below."
46
+ msgstr ""
47
+
48
+ #: includes/subscription/class-wps-aweber.php:230
49
+ msgid "Your Aweber Account is connected."
50
+ msgstr ""
51
+
52
+ #: includes/subscription/class-wps-aweber.php:231
53
+ msgid ""
54
+ "<a href=\"#\" class=\"aweber_disconnect\">Click here</a> <span>to disconnect."
55
+ "</span>"
56
+ msgstr ""
57
+
58
+ #: includes/subscription/class-wps-feedburner.php:39
59
+ msgid "Feedburner ID"
60
+ msgstr ""
61
+
62
+ #: includes/subscription/class-wps-mailchimp.php:63
63
+ msgid "MailChimp API URL"
64
+ msgstr ""
65
+
66
+ #: includes/subscription/class-wps-mailchimp.php:64
67
+ msgid "The API key of your MailChimp account."
68
+ msgstr ""
69
+
70
+ #: includes/subscription/class-wps-mailchimp.php:72
71
+ msgid "MailChimp List"
72
+ msgstr ""
73
+
74
+ #: includes/subscription/class-wps-mailchimp.php:81
75
+ msgid "Send double opt-in notification"
76
+ msgstr ""
77
+
78
+ #: includes/wps-functions-options.php:17
79
+ msgid "Aweber"
80
+ msgstr ""
81
+
82
+ #: includes/wps-functions-options.php:18
83
+ msgid "Adds subscribers to your Aweber account."
84
+ msgstr ""
85
+
86
+ #: includes/wps-functions-options.php:23
87
+ msgid "FeedBurner"
88
+ msgstr ""
89
+
90
+ #: includes/wps-functions-options.php:24
91
+ msgid "Adds subscribers to your FeedBurner account."
92
+ msgstr ""
93
+
94
+ #: includes/wps-functions-options.php:29
95
+ msgid "MailChimp"
96
+ msgstr ""
97
+
98
+ #: includes/wps-functions-options.php:30
99
+ msgid "Adds subscribers to your MailChimp account."
100
+ msgstr ""
101
+
102
+ #: includes/wps-helpers.php:217
103
+ msgid "No Animation"
104
+ msgstr ""
105
+
106
+ #: includes/wps-helpers.php:218
107
+ msgid "Attention Seekers"
108
+ msgstr ""
109
+
110
+ #: includes/wps-helpers.php:219
111
+ msgid "bounce"
112
+ msgstr ""
113
+
114
+ #: includes/wps-helpers.php:220
115
+ msgid "flash"
116
+ msgstr ""
117
+
118
+ #: includes/wps-helpers.php:221
119
+ msgid "pulse"
120
+ msgstr ""
121
+
122
+ #: includes/wps-helpers.php:222
123
+ msgid "rubberBand"
124
+ msgstr ""
125
+
126
+ #: includes/wps-helpers.php:223
127
+ msgid "shake"
128
+ msgstr ""
129
+
130
+ #: includes/wps-helpers.php:224
131
+ msgid "swing"
132
+ msgstr ""
133
+
134
+ #: includes/wps-helpers.php:225
135
+ msgid "tada"
136
+ msgstr ""
137
+
138
+ #: includes/wps-helpers.php:226
139
+ msgid "wobble"
140
+ msgstr ""
141
+
142
+ #: includes/wps-helpers.php:228
143
+ msgid "Bouncing Entrances"
144
+ msgstr ""
145
+
146
+ #: includes/wps-helpers.php:229
147
+ msgid "bounceIn"
148
+ msgstr ""
149
+
150
+ #: includes/wps-helpers.php:230
151
+ msgid "bounceInDown"
152
+ msgstr ""
153
+
154
+ #: includes/wps-helpers.php:231
155
+ msgid "bounceInLeft"
156
+ msgstr ""
157
+
158
+ #: includes/wps-helpers.php:232
159
+ msgid "bounceInRight"
160
+ msgstr ""
161
+
162
+ #: includes/wps-helpers.php:233
163
+ msgid "bounceInUp"
164
+ msgstr ""
165
+
166
+ #: includes/wps-helpers.php:235
167
+ msgid "Fading Entrances"
168
+ msgstr ""
169
+
170
+ #: includes/wps-helpers.php:236
171
+ msgid "fadeIn"
172
+ msgstr ""
173
+
174
+ #: includes/wps-helpers.php:237
175
+ msgid "fadeInDown"
176
+ msgstr ""
177
+
178
+ #: includes/wps-helpers.php:238
179
+ msgid "fadeInDownBig"
180
+ msgstr ""
181
+
182
+ #: includes/wps-helpers.php:239
183
+ msgid "fadeInLeft"
184
+ msgstr ""
185
+
186
+ #: includes/wps-helpers.php:240
187
+ msgid "fadeInLeftBig"
188
+ msgstr ""
189
+
190
+ #: includes/wps-helpers.php:241
191
+ msgid "fadeInRight"
192
+ msgstr ""
193
+
194
+ #: includes/wps-helpers.php:242
195
+ msgid "fadeInRightBig"
196
+ msgstr ""
197
+
198
+ #: includes/wps-helpers.php:243
199
+ msgid "fadeInUp"
200
+ msgstr ""
201
+
202
+ #: includes/wps-helpers.php:244
203
+ msgid "fadeInUpBig"
204
+ msgstr ""
205
+
206
+ #: includes/wps-helpers.php:246
207
+ msgid "Flippers"
208
+ msgstr ""
209
+
210
+ #: includes/wps-helpers.php:247
211
+ msgid "flipInX"
212
+ msgstr ""
213
+
214
+ #: includes/wps-helpers.php:248
215
+ msgid "flipInY"
216
+ msgstr ""
217
+
218
+ #: includes/wps-helpers.php:250
219
+ msgid "Lightspeed"
220
+ msgstr ""
221
+
222
+ #: includes/wps-helpers.php:251
223
+ msgid "lightSpeedIn"
224
+ msgstr ""
225
+
226
+ #: includes/wps-helpers.php:253
227
+ msgid "Rotating Entrances"
228
+ msgstr ""
229
+
230
+ #: includes/wps-helpers.php:254
231
+ msgid "rotateIn"
232
+ msgstr ""
233
+
234
+ #: includes/wps-helpers.php:255
235
+ msgid "rotateInDownLeft"
236
+ msgstr ""
237
+
238
+ #: includes/wps-helpers.php:256
239
+ msgid "rotateInDownRight"
240
+ msgstr ""
241
+
242
+ #: includes/wps-helpers.php:257
243
+ msgid "rotateInUpLeft"
244
+ msgstr ""
245
+
246
+ #: includes/wps-helpers.php:258
247
+ msgid "rotateInUpRight"
248
+ msgstr ""
249
+
250
+ #: includes/wps-helpers.php:260
251
+ msgid "Specials"
252
+ msgstr ""
253
+
254
+ #: includes/wps-helpers.php:261
255
+ msgid "rollIn"
256
+ msgstr ""
257
+
258
+ #: includes/wps-helpers.php:263
259
+ msgid "Zoom Entrances"
260
+ msgstr ""
261
+
262
+ #: includes/wps-helpers.php:264
263
+ msgid "zoomIn"
264
+ msgstr ""
265
+
266
+ #: includes/wps-helpers.php:265
267
+ msgid "zoomInDown"
268
+ msgstr ""
269
+
270
+ #: includes/wps-helpers.php:266
271
+ msgid "zoomInLeft"
272
+ msgstr ""
273
+
274
+ #: includes/wps-helpers.php:267
275
+ msgid "zoomInRight"
276
+ msgstr ""
277
+
278
+ #: includes/wps-helpers.php:268
279
+ msgid "zoomInUp"
280
+ msgstr ""
281
+
282
+ #: includes/wps-widget.php:23
283
+ msgid "Displays subscription form, supports FeedBurner, MailChimp & AWeber."
284
+ msgstr ""
285
+
286
+ #: includes/wps-widget.php:34
287
+ msgid "WP Subscribe Widget"
288
+ msgstr ""
289
+
290
+ #: includes/wps-widget.php:50
291
+ msgid "Get more stuff"
292
+ msgstr ""
293
+
294
+ #: includes/wps-widget.php:51
295
+ msgid ""
296
+ "Subscribe to our mailing list and get interesting stuff and updates to your "
297
+ "email inbox."
298
+ msgstr ""
299
+
300
+ #: includes/wps-widget.php:52
301
+ msgid "Enter your email here"
302
+ msgstr ""
303
+
304
+ #: includes/wps-widget.php:53
305
+ msgid "Enter your name here"
306
+ msgstr ""
307
+
308
+ #: includes/wps-widget.php:54
309
+ msgid "Sign Up Now"
310
+ msgstr ""
311
+
312
+ #: includes/wps-widget.php:55
313
+ msgid "Thank you for subscribing."
314
+ msgstr ""
315
+
316
+ #: includes/wps-widget.php:56
317
+ msgid "Something went wrong."
318
+ msgstr ""
319
+
320
+ #: includes/wps-widget.php:57
321
+ msgid "we respect your privacy and take protecting it seriously"
322
+ msgstr ""
323
+
324
+ #: includes/wps-widget.php:174
325
+ msgid "Include <strong>Name</strong> field"
326
+ msgstr ""
327
+
328
+ #: includes/wps-widget.php:180
329
+ msgid "Labels"
330
+ msgstr ""
331
+
332
+ #: includes/wps-widget.php:286 includes/wps-widget.php:361
333
+ msgid "Click here"
334
+ msgstr ""
335
+
336
+ #: includes/wps-widget.php:357
337
+ msgid "Get list"
338
+ msgstr ""
339
+
340
+ #: wp-subscribe.php:61 wp-subscribe.php:68
341
+ msgid "Cheatin&#8217; huh?"
342
+ msgstr ""
343
+
344
+ #: wp-subscribe.php:160
345
+ msgid "No aweber authorization code found."
346
+ msgstr ""
347
+
348
+ #: wp-subscribe.php:192
349
+ msgid "No data found."
350
+ msgstr ""
351
+
352
+ #: wp-subscribe.php:200
353
+ msgid "No email address found."
354
+ msgstr ""
355
+
356
+ #: wp-subscribe.php:207
357
+ msgid "Not a valid email address."
358
+ msgstr ""
359
+
360
+ #: wp-subscribe.php:216
361
+ msgid "Unknown mailing service called."
362
+ msgstr ""
363
+
364
+ #: wp-subscribe.php:251
365
+ msgid "Not permitted."
366
+ msgstr ""
367
+
368
+ #: wp-subscribe.php:260
369
+ msgid "Service not defined."
370
+ msgstr ""
371
+
372
+ #: wp-subscribe.php:278
373
+ msgid "No lists found."
374
+ msgstr ""
375
+
376
+ #. Plugin Name of the plugin/theme
377
+ msgid "WP Subscribe"
378
+ msgstr ""
379
+
380
+ #. Plugin URI of the plugin/theme
381
+ msgid "http://mythemeshop.com/plugins/wp-subscribe/"
382
+ msgstr ""
383
+
384
+ #. Description of the plugin/theme
385
+ msgid ""
386
+ "WP Subscribe is a simple but powerful subscription plugin which supports "
387
+ "MailChimp, Aweber and Feedburner."
388
+ msgstr ""
389
+
390
+ #. Author of the plugin/theme
391
+ msgid "MyThemeShop"
392
+ msgstr ""
393
+
394
+ #. Author URI of the plugin/theme
395
+ msgid "http://mythemeshop.com/"
396
+ msgstr ""
trunk/readme.txt ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === WP Subscribe ===
2
+ Contributors: mythemeshop
3
+ Creator's website link: http://mythemeshop.com/plugins/wp-subscribe/
4
+ Tags: subscribe, subscription, subscription box, newsletter, subscribe widget, mailchimp, aweber, feedburner,
5
+ Requires at least: 4.0
6
+ Tested up to: 4.9.1
7
+ Stable tag: 1.2.6
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
12
+
13
+ == Description ==
14
+
15
+ If you aren’t building an email list, you’re missing out on the most powerful and consistent way to drive repeat visitors and customers to your website or blog. With an email list, you become less and less dependent on external sources of traffic, and gain more ability to interact with your blog’s audience.
16
+
17
+ We at <a href="http://mythemeshop.com/">MyThemeShop</a> understand your need, and have developed a unique, cleanly coded, premium subscription plugin. We are now distributing it for FREE to give back to the WordPress community. We have been given so much by the WordPress community, it's time to give back.
18
+
19
+ **WP Subscribe** is the only plugin you need to get the perfect subscription forms on your website. With optimized code, it loads before you can even blink your eye. If you're a website owner, you can make a lot more money than regular blogs, which is why so many marketers focus on creating email lists. With the WP Subscribe plugin, you can do it in a simple yet effective way. Install the plugin, configure the widget and convert visitors into loyal email subscribers.
20
+
21
+ = Live demos: =
22
+ See the WP Subscribe Plugin in action on our demo page: <a href="http://demo.mythemeshop.com/sociallyviral/">http://demo.mythemeshop.com/sociallyviral/</a>
23
+
24
+ = Why choose WP Subscribe from <a href="http://mythemeshop.com/">MyThemeShop</a>: =
25
+ * It's the only free all-in-one plugin which offers Aweber, Mailchimp and FeedBurner.
26
+ * Choose between Mailchimp, Aweber or FeedBurner.
27
+ * Options to change text showing in subscription box.
28
+ * Fully responsive.
29
+ * Can be easily customized using custom CSS.
30
+ * Can be used more than once in different sidebars.
31
+ * Super lightweight.
32
+ * Compatible with caching and SEO plugins.
33
+ * Eye-catching design.
34
+ * Position it anywhere where a widget is configured in your theme.
35
+
36
+ = Support =
37
+
38
+ All support for this plugin is provided through our forums. If you have not registered yet, you can do so here for **FREE** <br>
39
+ <a href=“https://mythemeshop.com/#signup”>https://mythemeshop.com/#signup</a>
40
+
41
+ If after checking our Free WordPress video tutorials here:<br>
42
+ <a href=“https://mythemeshop.com/wordpress-101/”>https://mythemeshop.com/wordpress-101/</a><br>
43
+ &<br>
44
+ <a href=“https://community.mythemeshop.com/tutorials/category/2-free-video-tutorials/“>https://community.mythemeshop.com/tutorials/category/2-free-video-tutorials/</a><br>
45
+ <br>
46
+ you are still stuck, please feel free to open a new thread, and a member of our support team will be happy to help.<br>
47
+
48
+ Support link:<br>
49
+ <a href=“https://community.mythemeshop.com/forum/11-free-plugin-support/”>https://community.mythemeshop.com/forum/11-free-plugin-support/</a><br>
50
+ <br>
51
+
52
+ = Help to make it better =
53
+
54
+ MyThemeShop is a premium WordPress theme provider, and we develop premium plugins in our free time and distribute them for free to give back to the community. Though we take a lot of care while developing anything, we might have missed something useful or important. Please help us make it better by submitting your bug/suggestions/feedback on GitHub.
55
+
56
+ GitHub link: <a href="https://github.com/MyThemeShop/WP-Subscribe/">https://github.com/MyThemeShop/WP-Subscribe/</a>
57
+
58
+ = Feedback =
59
+ If you like this plugin, then please leave us a good rating and review.<br/>
60
+ Consider following us on <a rel="author" href="https://plus.google.com/+Mythemeshop/">Google+</a>, <a href="https://twitter.com/MyThemeShopTeam">Twitter</a>, and <a href="https://www.facebook.com/MyThemeShop">Facebook</a>
61
+
62
+ == Installation ==
63
+
64
+ This section describes how to install the plugin and get it working.
65
+
66
+ 1. Upload the `wp-subscribe` folder to the to the `/wp-content/plugins/` directory
67
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
68
+ 3. You can see **WP Subscribe** widget in widgets section.
69
+ 4. Add it in sidebar and footer and configure as you want.
70
+ 5. Enjoy!
71
+
72
+ == Frequently Asked Questions ==
73
+
74
+ = Plugin is not working =
75
+
76
+ Please disable all plugins and check if plugin is working properly. Then you can enable all plugins one by one to find out which plugin is conflicting with WP Subscribe.
77
+
78
+ == Screenshots ==
79
+
80
+ 1. WP Subscribe Widget
81
+ 2. WP Subscribe Settings
82
+
83
+ == Changelog ==
84
+
85
+ = 1.2.6 =
86
+ * Fixed PHP notices
87
+
88
+ = 1.2.5 =
89
+ * Fixed aweber list issue
90
+
91
+ = 1.2.4 =
92
+ * Fixed aweber issues
93
+
94
+ = 1.2.3 =
95
+ * Fixed some CSS issues
96
+
97
+ = 1.2.2 =
98
+ * Fixed some javascript issues
99
+ * Fixed some credentials in Aweber
100
+ * Improve Mailchimp class
101
+ * Remove notices and warnings on some places
102
+ * Change the behavior of saving mailing service lists
103
+
104
+ = 1.2.1 =
105
+ * Provided backward compatibility for CSS
106
+ * Provided backward compatibility for Scoped CSS
107
+ * Remove magnific popup classes from inline form
108
+ * Add loader when submitting form
109
+ * Fixed inline form responsiveness
110
+ * Minify the CSS File
111
+
112
+ = 1.2.0 =
113
+ * Whole plugin is re-written in OOP
114
+ * Huge performance Improvements
115
+ * Moved JS and CSS folders inside assets folder
116
+ * Enhanced: Functions are more organized in wps-helpers and wps-functions-options file.
117
+ * Fixed: Missing and in-correct textdomain
118
+
119
+ = 1.1.4 =
120
+ * Changed AWeber form URL to HTTPS
121
+
122
+ = 1.1.3 =
123
+ * Added option to enable name field
124
+ * Added MyThemeShop tab in "Add Plugins" page
125
+
126
+ = 1.1.2 =
127
+ * Removed nonce from frontend
128
+
129
+ = 1.1.0 =
130
+ * Replaced Feedburner HTTP link with HTTPS
131
+
132
+ = 1.0.9 =
133
+ * Fixed spelling mistake in Pro Notification
134
+
135
+ = 1.0.8 =
136
+ * Fixed translation and text domain issue
137
+
138
+ = 1.0.7 =
139
+ * Fixed notification closing issue
140
+
141
+ = 1.0.6 =
142
+ * Switched to PHP 5 style constructor method for the widget class
143
+
144
+ = 1.0.5 =
145
+ * Improvement - input placeholder text hides on click.
146
+
147
+ = 1.0.4 =
148
+ * Fixed AWeber signup issue
149
+
150
+ = 1.0.3 =
151
+ * Fixed add_query_arg vulnerability
152
+
153
+ = 1.0.2 =
154
+ * Added double opt-in possibility for Mailchimp
155
+
156
+ = 1.0.1 =
157
+ * Fixed Title field saving issue in newly added widget
158
+ * Fixed compatibility with other plugins using Mailchimp API
159
+
160
+ = 1.0 =
161
+ * Official plugin release.
trunk/wp-subscribe.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: WP Subscribe
4
+ * Plugin URI: http://mythemeshop.com/plugins/wp-subscribe/
5
+ * Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
6
+ * Version: 1.2.6
7
+ * Author: MyThemeShop
8
+ * Author URI: http://mythemeshop.com/
9
+ * Text Domain: wp-subscribe
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ } // Exit if accessed directly.
15
+
16
+ /**
17
+ * Include Base Class
18
+ * From which all other classes are derived
19
+ */
20
+ include_once 'includes/class-wps-base.php';
21
+
22
+ if( ! class_exists('MTS_WP_Subscribe') ) :
23
+
24
+ final class MTS_WP_Subscribe extends WPS_Base {
25
+
26
+ /**
27
+ * Plugin Version
28
+ * @var string
29
+ */
30
+ private $version = '1.2.6';
31
+
32
+ /**
33
+ * Hold an instance of MTS_WP_Subscribe class
34
+ * @var MTS_WP_Subscribe
35
+ */
36
+ protected static $instance = null;
37
+
38
+ /**
39
+ * Hold WPS_Settings instance.
40
+ * @var WPS_Settings
41
+ */
42
+ public $settings;
43
+
44
+ /**
45
+ * Hold an instance of MTS_ContentLocker class.
46
+ * @return MTS_WP_Subscribe
47
+ */
48
+ public static function get_instance() {
49
+
50
+ if( is_null( self::$instance ) ) {
51
+ self::$instance = new MTS_WP_Subscribe;
52
+ }
53
+
54
+ return self::$instance;
55
+ }
56
+
57
+ /**
58
+ * You cannot clone this class
59
+ */
60
+ public function __clone() {
61
+ _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'wp-subscribe' ), $this->version );
62
+ }
63
+
64
+ /**
65
+ * You cannot unserialize instances of this class
66
+ */
67
+ public function __wakeup() {
68
+ _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'wp-subscribe' ), $this->version );
69
+ }
70
+
71
+ /**
72
+ * The Constructor
73
+ */
74
+ private function __construct() {
75
+
76
+ // Include files
77
+ include_once 'includes/wps-helpers.php';
78
+ include_once 'includes/wps-functions-options.php';
79
+ include_once 'includes/wps-widget.php';
80
+
81
+ $this->autoloader();
82
+ $this->hooks();
83
+ }
84
+
85
+ /**
86
+ * Register file autoloading mechanism
87
+ * @return void
88
+ */
89
+ private function autoloader() {
90
+
91
+ if ( function_exists( '__autoload' ) ) {
92
+ spl_autoload_register( '__autoload' );
93
+ }
94
+
95
+ spl_autoload_register( array( $this, 'autoload' ) );
96
+ }
97
+
98
+ /**
99
+ * Add hooks
100
+ * @return void
101
+ */
102
+ private function hooks() {
103
+
104
+ $this->add_action( 'init', 'load_textdomain' );
105
+
106
+ // AJAX
107
+ $this->add_action( 'wp_ajax_wps_get_service_list', 'get_service_list' );
108
+ $this->add_action( 'wp_ajax_validate_subscribe', 'validate_subscribe' );
109
+ $this->add_action( 'wp_ajax_nopriv_validate_subscribe', 'validate_subscribe' );
110
+ $this->add_action( 'wp_ajax_connect_aweber', 'connect_aweber' );
111
+ }
112
+
113
+ /**
114
+ * Autoload strategy
115
+ *
116
+ * @param string $class
117
+ * @return void
118
+ */
119
+ public function autoload( $class ) {
120
+
121
+ if( ! wps_str_start_with( 'WPS_', $class ) ) {
122
+ return;
123
+ }
124
+
125
+ $path = '';
126
+ $class = strtolower( $class );
127
+ $file = 'class-' . str_replace( '_', '-', strtolower( $class ) ) . '.php';
128
+ $path = $this->plugin_dir() . '/includes/';
129
+
130
+ if( wps_str_start_with('wps_subscription', $class ) ) {
131
+ $path .= 'subscription/';
132
+ $file = str_replace( 'subscription-', '', $file );
133
+ }
134
+
135
+ // Load File
136
+ $load = $path . $file;
137
+ if ( $load && is_readable( $load ) ) {
138
+ include_once $load;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Load localization files
144
+ * @return void
145
+ */
146
+ public function load_textdomain() {
147
+ $locale = apply_filters( 'plugin_locale', get_locale(), 'wp-subscribe' );
148
+
149
+ load_textdomain( 'wp-subscribe', WP_LANG_DIR . '/wp-subscribe/wp-subscribe-' . $locale . '.mo' );
150
+ load_plugin_textdomain( 'wp-subscribe', false, $this->plugin_dir() . '/languages' );
151
+ }
152
+
153
+ public function connect_aweber() {
154
+
155
+ // check for data
156
+ $aweber_code = isset( $_REQUEST['aweber_code'] ) ? $_REQUEST['aweber_code'] : array();
157
+ if( empty( $aweber_code ) ) {
158
+ wp_send_json( array(
159
+ 'success' => false,
160
+ 'error' => esc_html__( 'No aweber authorization code found.', 'wp-subscribe' )
161
+ ) );
162
+ }
163
+
164
+ try {
165
+ $service = new WPS_Subscription_Aweber();
166
+ $data = $service->connect( $aweber_code );
167
+
168
+ wp_send_json(array(
169
+ 'success' => true,
170
+ 'data' => $data
171
+ ));
172
+ }
173
+ catch( Exception $e ) {
174
+ wp_send_json(array(
175
+ 'success' => false,
176
+ 'error' => $e->getMessage()
177
+ ));
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Validate subscription
183
+ * @return void
184
+ */
185
+ public function validate_subscribe() {
186
+
187
+ // check for data
188
+ $data = isset( $_POST['wps_data'] ) ? $_POST['wps_data'] : array();
189
+ if( empty( $data ) ) {
190
+ wp_send_json( array(
191
+ 'success' => false,
192
+ 'error' => esc_html__( 'No data found.', 'wp-subscribe' )
193
+ ) );
194
+ }
195
+
196
+ // check for valid data
197
+ if( empty( $data['email'] ) ) {
198
+ wp_send_json( array(
199
+ 'success' => false,
200
+ 'error' => esc_html__( 'No email address found.', 'wp-subscribe' )
201
+ ) );
202
+ }
203
+
204
+ if( !filter_var( $data['email'], FILTER_VALIDATE_EMAIL ) ) {
205
+ wp_send_json( array(
206
+ 'success' => false,
207
+ 'error' => esc_html__( 'Not a valid email address.', 'wp-subscribe' )
208
+ ) );
209
+ }
210
+
211
+ // check for valid service
212
+ $services = wps_get_mailing_services('options');
213
+ if( !array_key_exists( $data['service'], $services ) ) {
214
+ wp_send_json( array(
215
+ 'success' => false,
216
+ 'error' => esc_html__( 'Unknown mailing service called.', 'wp-subscribe' )
217
+ ) );
218
+ }
219
+
220
+ // Call service subscription method
221
+ try {
222
+ $service = wps_get_subscription_service( $data['service'] );
223
+ $status = $service->subscribe( $data, $service->get_options( $data ) );
224
+
225
+ wp_send_json(array(
226
+ 'success' => true,
227
+ 'status' => $status['status']
228
+ ));
229
+ }
230
+ catch( Exception $e ) {
231
+ wp_send_json(array(
232
+ 'success' => false,
233
+ 'error' => $e->getMessage()
234
+ ));
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Get mailing lists according to service
240
+ *
241
+ * @return array
242
+ */
243
+ public function get_service_list() {
244
+
245
+ $name = $_REQUEST['service'];
246
+ $args = $_REQUEST['args'];
247
+
248
+ if( empty( $name ) || empty( $args ) ) {
249
+ wp_send_json(array(
250
+ 'success' => false,
251
+ 'error' => esc_html__( 'Not permitted.', 'wp-subscribe' )
252
+ ));
253
+ }
254
+
255
+ $service = wps_get_subscription_service( $name );
256
+
257
+ if( is_null( $service ) ) {
258
+ wp_send_json(array(
259
+ 'success' => false,
260
+ 'error' => esc_html__( 'Service not defined.', 'wp-subscribe' )
261
+ ));
262
+ }
263
+
264
+ try {
265
+ $args['raw'] = $args;
266
+ $lists = call_user_func_array( array( $service, 'get_lists' ), $args );
267
+ }
268
+ catch( Exception $e ) {
269
+ wp_send_json(array(
270
+ 'success' => false,
271
+ 'error' => $e->getMessage()
272
+ ));
273
+ }
274
+
275
+ if( empty( $lists ) ) {
276
+ wp_send_json(array(
277
+ 'success' => false,
278
+ 'error' => esc_html__( 'No lists found.', 'wp-subscribe' )
279
+ ));
280
+ }
281
+
282
+ // Save for letter use
283
+ update_option( 'mts_wps_'. $name . '_lists', $lists );
284
+
285
+ wp_send_json(array(
286
+ 'success' => true,
287
+ 'lists' => $lists
288
+ ));
289
+ }
290
+
291
+ // Helper ------------------------------------------------------
292
+
293
+ /**
294
+ * Get plugin directory
295
+ *
296
+ * @return string
297
+ */
298
+ public function plugin_dir() {
299
+ return untrailingslashit( plugin_dir_path( __FILE__ ) );
300
+ }
301
+
302
+ /**
303
+ * Get plugin uri
304
+ *
305
+ * @return string
306
+ */
307
+ public function plugin_url() {
308
+ return untrailingslashit( plugin_dir_url( __FILE__ ) );
309
+ }
310
+
311
+ /**
312
+ * Get plugin version
313
+ *
314
+ * @return string
315
+ */
316
+ public function get_version() {
317
+ return $this->version;
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Main instance of MTS_WP_Subscribe
323
+ *
324
+ * Return the main instance of MTS_WP_Subscribe to prevent the need to use globals.
325
+ *
326
+ * @return MTS_WP_Subscribe
327
+ */
328
+ function wps() {
329
+ return MTS_WP_Subscribe::get_instance();
330
+ }
331
+ wps(); // Init it
332
+
333
+ endif;
wp-subscribe.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WP Subscribe
4
  * Plugin URI: http://mythemeshop.com/plugins/wp-subscribe/
5
  * Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
6
- * Version: 1.2.5
7
  * Author: MyThemeShop
8
  * Author URI: http://mythemeshop.com/
9
  * Text Domain: wp-subscribe
@@ -27,7 +27,7 @@ if( ! class_exists('MTS_WP_Subscribe') ) :
27
  * Plugin Version
28
  * @var string
29
  */
30
- private $version = '1.2.5';
31
 
32
  /**
33
  * Hold an instance of MTS_WP_Subscribe class
3
  * Plugin Name: WP Subscribe
4
  * Plugin URI: http://mythemeshop.com/plugins/wp-subscribe/
5
  * Description: WP Subscribe is a simple but powerful subscription plugin which supports MailChimp, Aweber and Feedburner.
6
+ * Version: 1.2.6
7
  * Author: MyThemeShop
8
  * Author URI: http://mythemeshop.com/
9
  * Text Domain: wp-subscribe
27
  * Plugin Version
28
  * @var string
29
  */
30
+ private $version = '1.2.6';
31
 
32
  /**
33
  * Hold an instance of MTS_WP_Subscribe class