|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* BetterOptin Provider Aweber |
|
4
|
|
|
* |
|
5
|
|
|
* @package BetterOptin/Provider/Aweber/Settingd |
|
6
|
|
|
* @author ThemeAvenue <[email protected]> |
|
7
|
|
|
* @license GPL-2.0+ |
|
8
|
|
|
* @link http://themeavenue.net |
|
9
|
|
|
* @copyright 2015 ThemeAvenue |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
// If this file is called directly, abort. |
|
13
|
|
|
if ( ! defined( 'WPINC' ) ) { |
|
14
|
|
|
die; |
|
15
|
|
|
} |
|
16
|
|
|
|
|
17
|
|
|
class WPBO_Aweber { |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* Aweber authorization code |
|
21
|
|
|
* |
|
22
|
|
|
* @since 2.0 |
|
23
|
|
|
* @var string |
|
24
|
|
|
*/ |
|
25
|
|
|
private $auth_code; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* Aweber API key |
|
29
|
|
|
* |
|
30
|
|
|
* @since 2.0 |
|
31
|
|
|
* @var string |
|
32
|
|
|
*/ |
|
33
|
|
|
private $api_key; |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* Aweber API secret key |
|
37
|
|
|
* |
|
38
|
|
|
* @since 2.0 |
|
39
|
|
|
* @var string |
|
40
|
|
|
*/ |
|
41
|
|
|
private $api_secret; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* Aweber app access token |
|
45
|
|
|
* |
|
46
|
|
|
* @since 2.0 |
|
47
|
|
|
* @var string |
|
48
|
|
|
*/ |
|
49
|
|
|
private $access_token = ''; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* Aweber app access secret |
|
53
|
|
|
* |
|
54
|
|
|
* @since 2.0 |
|
55
|
|
|
* @var string |
|
56
|
|
|
*/ |
|
57
|
|
|
private $access_secret = ''; |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* Aweber registered app ID |
|
61
|
|
|
* |
|
62
|
|
|
* @since 2.0 |
|
63
|
|
|
* @var string |
|
64
|
|
|
*/ |
|
65
|
|
|
public static $app_id = '0cdbc51e'; |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* Aweber list ID |
|
69
|
|
|
* |
|
70
|
|
|
* @since 2.0 |
|
71
|
|
|
* @var string |
|
72
|
|
|
*/ |
|
73
|
|
|
private $list_id; |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* Aweber app authorize URL |
|
77
|
|
|
* |
|
78
|
|
|
* @since 2.0 |
|
79
|
|
|
* @var string |
|
80
|
|
|
*/ |
|
81
|
|
|
public static $authorize_url = 'https://auth.aweber.com/1.0/oauth/authorize_app/'; |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* Instance of the Aweber class |
|
85
|
|
|
* |
|
86
|
|
|
* @since 2.0 |
|
87
|
|
|
* @var AWeberAPI |
|
88
|
|
|
*/ |
|
89
|
|
|
private $aweber; |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Aweber user account |
|
93
|
|
|
* |
|
94
|
|
|
* @since 2.0 |
|
95
|
|
|
* @var |
|
96
|
|
|
*/ |
|
97
|
|
|
private $account; |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* Holds possible errors if the Aweber class can't be instantiated |
|
101
|
|
|
* |
|
102
|
|
|
* @since 2.0 |
|
103
|
|
|
* @var null|WP_Error |
|
104
|
|
|
*/ |
|
105
|
|
|
public $error; |
|
106
|
|
|
|
|
107
|
|
|
public function __construct() { |
|
108
|
|
|
|
|
109
|
|
|
if ( ! class_exists( 'AWeberAPI' ) ) { |
|
110
|
|
|
require( WPBO_PATH . 'vendor/aweber/aweber/aweber_api/aweber.php' ); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
$this->auth_code = trim( wpbo_get_option( 'aw_auth_code', '' ) ); |
|
114
|
|
|
$this->api_key = false !== $this->get_credentials() ? $this->get_credentials()['consumerKey'] : ''; |
|
115
|
|
|
$this->api_secret = false !== $this->get_credentials() ? $this->get_credentials()['consumerSecret'] : ''; |
|
116
|
|
|
$this->list_id = wpbo_get_option( 'aw_list_id', '' ); |
|
117
|
|
|
$this->get_tokens(); |
|
118
|
|
|
|
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
|
|
public static function get_authorization_url() { |
|
122
|
|
|
return self::$authorize_url . self::$app_id; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Get Aweber authorization tokens |
|
127
|
|
|
* |
|
128
|
|
|
* Try and get the tokens from the database. If no token is found, we query Aweber and request |
|
129
|
|
|
* authorization. |
|
130
|
|
|
* |
|
131
|
|
|
* @since 1.0 |
|
132
|
|
|
* @return bool|WP_Error True if the auth tokens are set, WP_Error otherwise |
|
133
|
|
|
*/ |
|
134
|
|
|
private function get_tokens() { |
|
135
|
|
|
|
|
136
|
|
|
$tokens = maybe_unserialize( get_option( 'wpbo_aweber_tokens' ) ); |
|
137
|
|
|
|
|
138
|
|
|
if ( empty( $tokens ) || ! is_array( $tokens ) ) { |
|
139
|
|
|
$tokens = $this->get_access_tokens(); |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
if ( is_wp_error( $tokens ) ) { |
|
143
|
|
|
return $tokens; |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
$this->access_token = isset( $tokens[0] ) ? trim( $tokens[0] ) : ''; |
|
147
|
|
|
$this->access_secret = isset( $tokens[1] ) ? trim( $tokens[1] ) : ''; |
|
148
|
|
|
|
|
149
|
|
|
return true; |
|
150
|
|
|
|
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
/** |
|
154
|
|
|
* Get access tokens from Aweber. |
|
155
|
|
|
* |
|
156
|
|
|
* @return array Aweber tokens |
|
157
|
|
|
* @since 1.0.0 |
|
158
|
|
|
*/ |
|
159
|
|
|
protected function get_access_tokens() { |
|
160
|
|
|
|
|
161
|
|
|
if ( is_wp_error( $this->aweber() ) ) { |
|
162
|
|
|
return $this->aweber(); |
|
|
|
|
|
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
/* Get credentials from Aweber key */ |
|
166
|
|
|
$credentials = $this->get_credentials(); |
|
167
|
|
|
|
|
168
|
|
|
if ( false === $credentials ) { |
|
169
|
|
|
return $this->error = new WP_Error( 'aweber_missing_auth_code', esc_html__( 'Aweber authorization code is missing', 'betteroptin' ) ); |
|
|
|
|
|
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
/* Set tokens */ |
|
173
|
|
|
$this->aweber()->adapter->user->requestToken = $credentials['requestToken']; |
|
174
|
|
|
$this->aweber()->adapter->user->tokenSecret = $credentials['tokenSecret']; |
|
175
|
|
|
$this->aweber()->adapter->user->verifier = $credentials['verifier']; |
|
176
|
|
|
|
|
177
|
|
|
/* Request access tokens */ |
|
178
|
|
|
try { |
|
179
|
|
|
|
|
180
|
|
|
$access_tokens = $this->aweber()->getAccessToken(); |
|
181
|
|
|
$this->access_token = $access_tokens[0]; |
|
182
|
|
|
$this->access_secret = $access_tokens[1]; |
|
183
|
|
|
|
|
184
|
|
|
/* Save access tokens */ |
|
185
|
|
|
update_option( 'wpbo_aweber_tokens', $access_tokens ); |
|
186
|
|
|
|
|
187
|
|
|
return $access_tokens; |
|
188
|
|
|
|
|
189
|
|
|
} catch ( Exception $e ) { |
|
190
|
|
|
return $this->error = new WP_Error( '', esc_html__( 'The Aweber authorization code you provided is incorrect or expired. Please authorize the plugin again.', 'betteroptin' ) ); |
|
|
|
|
|
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
/** |
|
196
|
|
|
* Get the instance of the Aweber class |
|
197
|
|
|
* |
|
198
|
|
|
* @since 2.0 |
|
199
|
|
|
* @return AWeberAPI|WP_Error |
|
200
|
|
|
*/ |
|
201
|
|
|
public function aweber() { |
|
202
|
|
|
|
|
203
|
|
|
if ( is_object( $this->aweber ) && is_a( $this->aweber, 'AWeberAPI' ) ) { |
|
204
|
|
|
return $this->aweber; |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
/* Make sure we have the tokens */ |
|
208
|
|
|
if ( empty( $this->api_key ) || empty( $this->api_secret ) ) { |
|
209
|
|
|
return $this->error = new WP_Error( 'missing_tokens', __( 'Aweber API keys are missing.', 'betteroptin' ) ); |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
return $this->aweber = new AWeberAPI( $this->api_key, $this->api_secret ); |
|
213
|
|
|
|
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* Get an account instance. |
|
218
|
|
|
* |
|
219
|
|
|
* @return object User account instance |
|
220
|
|
|
*/ |
|
221
|
|
|
public function account() { |
|
222
|
|
|
|
|
223
|
|
|
if ( ! is_null( $this->account ) ) { |
|
224
|
|
|
return $this->account; |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
/* Get user account */ |
|
228
|
|
|
try { |
|
229
|
|
|
$this->account = $this->aweber()->getAccount( $this->access_token, $this->access_secret ); |
|
|
|
|
|
|
230
|
|
|
} catch ( Exception $e ) { |
|
231
|
|
|
return $this->error = new WP_Error( 'aweber_connection_error', __( 'Unable to connect to Aweber', 'betteroptin' ) ); |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
return $this->account; |
|
235
|
|
|
|
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
/** |
|
239
|
|
|
* Get account credentials. |
|
240
|
|
|
* |
|
241
|
|
|
* Takes the authorization code and extract account credentials. |
|
242
|
|
|
* |
|
243
|
|
|
* @since 1.0.0 |
|
244
|
|
|
* @return array Credentials |
|
245
|
|
|
*/ |
|
246
|
|
|
protected function get_credentials() { |
|
247
|
|
|
|
|
248
|
|
|
if ( empty( $this->auth_code ) ) { |
|
249
|
|
|
return false; |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
$code = explode( '|', $this->auth_code ); |
|
253
|
|
|
|
|
254
|
|
|
$credentials = array( |
|
255
|
|
|
'consumerKey' => trim( $code[0] ), |
|
256
|
|
|
'consumerSecret' => trim( $code[1] ), |
|
257
|
|
|
'requestToken' => trim( $code[2] ), |
|
258
|
|
|
'tokenSecret' => trim( $code[3] ), |
|
259
|
|
|
'verifier' => trim( $code[4] ), |
|
260
|
|
|
); |
|
261
|
|
|
|
|
262
|
|
|
return $credentials; |
|
263
|
|
|
|
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* Subscribe the visitor to a list. |
|
268
|
|
|
* |
|
269
|
|
|
* @since 1.0.0 |
|
270
|
|
|
* |
|
271
|
|
|
* @param array $data Form post data |
|
272
|
|
|
* |
|
273
|
|
|
* @return array Result |
|
274
|
|
|
*/ |
|
275
|
|
|
public function subscribe( $data ) { |
|
276
|
|
|
|
|
277
|
|
|
if ( is_wp_error( $this->account() ) ) { |
|
278
|
|
|
return $this->account(); |
|
279
|
|
|
} |
|
280
|
|
|
|
|
281
|
|
|
$account_id = $this->account()->data['id']; |
|
282
|
|
|
$list_custom = get_post_meta( (int) $data['wpbo_id'], 'wpbo_aw_list', true ); |
|
283
|
|
|
$list_id = ( '' != $list_custom ) ? $list_custom : $this->list_id; |
|
284
|
|
|
$list_url = "/accounts/$account_id/lists/$list_id"; |
|
285
|
|
|
$subscriber = array( 'email' => sanitize_email( $data['email'] ), 'name' => $data['name'] ); |
|
286
|
|
|
|
|
287
|
|
|
/* Subscribe the new user */ |
|
288
|
|
|
try { |
|
289
|
|
|
|
|
290
|
|
|
$list = $this->account()->loadFromUrl( $list_url ); |
|
291
|
|
|
$newSubscriber = $list->subscribers->create( $subscriber ); |
|
|
|
|
|
|
292
|
|
|
|
|
293
|
|
|
return true; |
|
294
|
|
|
|
|
295
|
|
|
} catch ( Exception $exc ) { |
|
296
|
|
|
return false; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
} |
|
300
|
|
|
|
|
301
|
|
|
/** |
|
302
|
|
|
* Get user lists. |
|
303
|
|
|
* |
|
304
|
|
|
* @since 1.0.0 |
|
305
|
|
|
* @return array Array of available lists for this account |
|
306
|
|
|
*/ |
|
307
|
|
|
public function get_lists() { |
|
308
|
|
|
|
|
309
|
|
|
$lists = maybe_unserialize( get_transient( 'wpbo_aw_lists' ) ); |
|
310
|
|
|
|
|
311
|
|
|
if ( is_array( $lists ) ) { |
|
312
|
|
|
return $lists; |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
if ( is_wp_error( $this->account() ) ) { |
|
316
|
|
|
return array(); |
|
317
|
|
|
} |
|
318
|
|
|
|
|
319
|
|
|
foreach ( $this->account()->lists as $list ) { |
|
320
|
|
|
$lists[] = array( 'id' => $list->id, 'name' => $list->name ); |
|
321
|
|
|
} |
|
322
|
|
|
|
|
323
|
|
|
/* Cache the lists to avoid slow loading */ |
|
324
|
|
|
set_transient( 'wpbo_aw_lists', $lists, 24 * 60 * 60 ); |
|
325
|
|
|
|
|
326
|
|
|
return $lists; |
|
327
|
|
|
|
|
328
|
|
|
} |
|
329
|
|
|
|
|
330
|
|
|
public function is_error() { |
|
331
|
|
|
return $this->error; |
|
332
|
|
|
} |
|
333
|
|
|
|
|
334
|
|
|
} |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.