PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 1.5.3
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v1.5.3
3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 All 195 releases
convertkit / includes / class-convertkit-api.php

class-convertkit-api.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 1.5.3, at includes/class-convertkit-api.php

476 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit PI class
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * ConvertKit_API Class
11 * Establishes API connection to ConvertKit App
12 */
13 class ConvertKit_API {
14
15 /**
16 * ConvertKit API Key
17 *
18 * @var string
19 */
20 protected $api_key;
21
22 /**
23 * ConvertKit API Secret
24 *
25 * @var string
26 */
27 protected $api_secret;
28
29 /**
30 * Save debug data to log
31 *
32 * @var string
33 */
34 protected $debug;
35
36 /**
37 * Version of ConvertKit API
38 *
39 * @var string
40 */
41 protected $api_version = 'v3';
42
43 /**
44 * ConvertKit API URL
45 *
46 * @var string
47 */
48 protected $api_url_base = 'https://api.convertkit.com/';
49
50 /**
51 * API resources
52 *
53 * @var array
54 */
55 protected $resources = array();
56
57 /**
58 * Additional markup
59 *
60 * @var array
61 */
62 protected $markup = array();
63
64 /**
65 * Constructor for ConvertKitAPI instance
66 *
67 * @param string $api_key ConvertKit API Key.
68 * @param string $api_secret ConvertKit API Secret.
69 * @param string $debug Save data to log.
70 */
71 public function __construct( $api_key, $api_secret, $debug ) {
72 $this->api_key = $api_key;
73 $this->api_secret = $api_secret;
74 $this->debug = $debug;
75 }
76
77 /**
78 * Adds a tag to a subscriber
79 *
80 * @param int $tag Tag ID
81 * @param array $options Array of user data
82 * @return object
83 */
84 public function add_tag( $tag, $options ) {
85 $request = $this->api_version . sprintf( '/tags/%s/subscribe', $tag );
86
87 $args = array(
88 'api_key' => $this->api_key,
89 'email' => $options['email'],
90 );
91
92 return $this->make_request( $request, 'POST', $args );
93 }
94
95 /**
96 * Gets a resource index
97 *
98 * GET /{$resource}/
99 *
100 * @param string $resource Resource type.
101 * @return object API response
102 */
103 public function get_resources( $resource ) {
104
105 if ( ! array_key_exists( $resource, $this->resources ) ) {
106
107 if ( 'landing_pages' === $resource ) {
108 $api_response = $this->_get_api_response( 'forms' );
109 } else {
110 $api_response = $this->_get_api_response( $resource );
111 }
112
113 if ( is_null( $api_response ) || is_wp_error( $api_response ) || isset( $api_response['error'] ) || isset( $api_response['error_message'] ) ) {
114 $this->resources[ $resource ] = array(
115 array(
116 'id' => '-2',
117 'name' => 'Error contacting API',
118 ),
119 );
120 } else {
121 $_resource = array();
122
123 if ( 'forms' === $resource ) {
124 $response = isset( $api_response['forms'] ) ? $api_response['forms'] : array();
125 $forms = array();
126 foreach ( $response as $form ) {
127 if ( isset( $form['archived'] ) && $form['archived'] ) {
128 continue;
129 }
130 $_resource[] = $form;
131 $forms[ $form['id'] ] = $form['name'];
132 }
133 update_option( 'convertkit_forms', $forms );
134 } elseif ( 'landing_pages' === $resource ) {
135
136 $response = isset( $api_response['forms'] ) ? $api_response['forms'] : array();
137 foreach ( $response as $landing_page ) {
138 if ( 'hosted' === $landing_page['type'] ) {
139 if ( isset( $landing_page['archived'] ) && $landing_page['archived'] ) {
140 continue;
141 }
142 $_resource[] = $landing_page;
143 }
144 }
145 } elseif ( 'subscription_forms' === $resource ) {
146 foreach ( $api_response as $mapping ) {
147 if ( isset( $mapping['archived'] ) && $mapping['archived'] ) {
148 continue;
149 }
150 $_resource[ $mapping['id'] ] = $mapping['form_id'];
151 }
152 } elseif ( 'tags' === $resource ) {
153 $response = isset( $api_response['tags'] ) ? $api_response['tags'] : array();
154 foreach ( $response as $tag ) {
155 $_resource[] = $tag;
156 }
157 }
158
159 $this->resources[ $resource ] = $_resource;
160 } // End if().
161 } // End if().
162
163 return $this->resources[ $resource ];
164 }
165
166 /**
167 * Adds a subscriber to a form.
168 *
169 * @param string $form_id Form ID.
170 * @param array $options Array of user data.
171 */
172 public function form_subscribe( $form_id, $options ) {
173 $request = $this->api_version . sprintf( '/forms/%s/subscribe', $form_id );
174
175 $args = array(
176 'api_key' => $this->api_key,
177 'email' => $options['email'],
178 'name' => $options['name'],
179 );
180
181 $this->make_request( $request, 'POST', $args );
182 }
183
184 /**
185 * Remove subscription from a form
186 *
187 * @param array $options Array of user data.
188 */
189 public function form_unsubscribe( $options ) {
190 $request = $this->api_version . '/unsubscribe';
191
192 $args = array(
193 'api_secret' => $this->api_secret,
194 'email' => $options['email'],
195 );
196
197 $this->make_request( $request, 'PUT', $args );
198 }
199
200 /**
201 * Get the ConvertKit subscriber ID associated with email address if it exists.
202 * Return 0 if subscriber not found.
203 *
204 * @param $email_address
205 * @return int $subscriber_id
206 */
207 public function get_subscriber_id( $email_address ) {
208
209 $url = add_query_arg(
210 array(
211 'api_secret' => WP_ConvertKit::get_api_secret(),
212 'email_address' => $email_address,
213 'status' => 'all',
214 ),
215 'https://api.convertkit.com/v3/subscribers'
216 );
217
218 WP_ConvertKit::log( 'get_subscriber_id for: ' . $email_address );
219
220 $result = $this->get_resource( $url );
221 if ( is_wp_error( $result ) ) {
222 WP_ConvertKit::log( 'Error getting resource for: ' . $url . '. Error: ' . $result->get_error_messages() );
223 return 0;
224 }
225
226 $subs = json_decode( $result );
227
228 $subscribers = is_array( $subs->subscribers ) ? $subs->subscribers : array();
229 if ( $subscribers ) {
230 $subscriber = array_pop( $subscribers );
231 WP_ConvertKit::log( 'Found ' . count( $subscribers ) . ' subscribers' );
232 WP_ConvertKit::log( 'ID (' . $subscriber->id . ') ' . $subscriber->email_address );
233 return $subscriber->id;
234 }
235 WP_ConvertKit::log( 'Subscriber not found with email ' . $email_address );
236 // subscriber not found
237 return 0;
238
239 }
240
241 /**
242 * @param $subscriber_id
243 *
244 * @return int
245 */
246 public function get_subscriber( $subscriber_id ) {
247 $url = add_query_arg(
248 array(
249 'api_secret' => WP_ConvertKit::get_api_secret(),
250 ),
251 'https://api.convertkit.com/v3/subscribers/' . $subscriber_id
252 );
253
254 WP_ConvertKit::log( 'get_subscriber info for id: ' . $subscriber_id );
255
256 $result = $this->get_resource( $url );
257 if ( is_wp_error( $result ) ) {
258 WP_ConvertKit::log( 'Error getting resource for: ' . $url . '. Error: ' . $result->get_error_messages() );
259 return 0;
260 }
261
262 $result = json_decode( $result );
263
264 if ( isset( $result->subscriber ) ) {
265 $subscriber = $result->subscriber;
266 WP_ConvertKit::log( 'Found: (' . $subscriber->id . ') ' . $subscriber->email_address );
267 return $subscriber;
268 }
269
270 // subscriber not found
271 return 0;
272 }
273
274 /**
275 * Get a list of the tags for a subscriber.
276 *
277 * @param $subscriber_id
278 * @return array $subscriber_tags Array of tags for customer with key of tag_id
279 */
280 public function get_subscriber_tags( $subscriber_id ) {
281
282 $url = add_query_arg(
283 array(
284 'api_key' => WP_ConvertKit::get_api_key(),
285 ),
286 'https://api.convertkit.com/v3/subscribers/' . $subscriber_id . '/tags'
287 );
288
289 WP_ConvertKit::log( 'get_subscriber_tags for: ' . $subscriber_id );
290
291 $result = $this->get_resource( $url );
292 if ( is_wp_error( $result ) ) {
293 WP_ConvertKit::log( 'Error getting resource for: ' . $url . '. Error: ' . $result->get_error_messages() );
294 return array();
295 }
296 $result = json_decode( $result );
297 $tags = isset( $result->tags ) ? $result->tags : array();
298
299 if ( empty( $tags ) ) {
300 WP_ConvertKit::log( 'No tags found for customer.' );
301 } else {
302 WP_ConvertKit::log( 'Found ' . count( $tags ) . 'tags for subscriber' );
303 $tags = wp_list_pluck( $tags, 'name', 'id' );
304 }
305
306 return $tags;
307
308 }
309
310 /**
311 * Get markup from ConvertKit for the provided $url
312 *
313 * @param string $url URL of API action.
314 * @return string
315 */
316 public function get_resource( $url ) {
317 $resource = '';
318
319 if ( ! empty( $url ) && isset( $this->markup[ $url ] ) ) {
320 $resource = $this->markup[ $url ];
321 } elseif ( ! empty( $url ) ) {
322 WP_ConvertKit::log( 'API Request (get_resource): ' . $url );
323
324 $response = wp_remote_get(
325 $url,
326 array(
327 'timeout' => 10,
328 'Accept-Encoding' => 'gzip',
329 )
330 );
331
332 if ( ! is_wp_error( $response ) ) {
333
334 if ( ! function_exists( 'str_get_html' ) ) {
335 require_once( dirname( __FILE__ ) . '/../vendor/simple-html-dom/simple-html-dom.php' );
336 }
337
338 if ( ! function_exists( 'url_to_absolute' ) ) {
339 require_once( dirname( __FILE__ ) . '/../vendor/url-to-absolute/url-to-absolute.php' );
340 }
341
342 // Maybe inflate response body.
343 // @see https://wordpress.stackexchange.com/questions/10088/how-do-i-troubleshoot-responses-with-wp-http-api
344 $inflate = @gzinflate( $response['body'] );
345 if ( $inflate ) {
346 $response['body'] = $inflate;
347 }
348
349 $body = wp_remote_retrieve_body( $response );
350
351 $html = str_get_html( $body );
352 foreach ( $html->find( 'a, link' ) as $element ) {
353 if ( isset( $element->href ) ) {
354 $element->href = url_to_absolute( $url, $element->href );
355 }
356 }
357
358 foreach ( $html->find( 'img, script' ) as $element ) {
359 if ( isset( $element->src ) ) {
360 $element->src = url_to_absolute( $url, $element->src );
361 }
362 }
363
364 foreach ( $html->find( 'form' ) as $element ) {
365 if ( isset( $element->action ) ) {
366 $element->action = url_to_absolute( $url, $element->action );
367 } else {
368 $element->action = $url;
369 }
370 }
371
372 // Check `status_code` for 200, otherwise log error.
373 if ( 200 === $response['response']['code'] ) {
374 $resource = $html->save();
375 $this->markup[ $url ] = $resource;
376 } else {
377 WP_ConvertKit::log( 'Status Code (' . $response['response']['code'] . ') for URL (' . $url . '): ' . $html->save() );
378 }
379 } else {
380 WP_ConvertKit::log( 'API Response was WP_Error (get_resource): ' .
381 'Code: ' . $response->get_error_code() . ' ' .
382 'Message: ' . $response->get_error_message()
383 );
384 } // End if().
385 } // End if().
386
387 return $resource;
388 }
389
390 /**
391 * Do a remote request.
392 *
393 * @param string $path Part of URL.
394 * @return array
395 */
396 private function _get_api_response( $path = '' ) {
397
398 $args = array(
399 'api_key' => $this->api_key,
400 );
401 $api_path = $this->api_url_base . $this->api_version;
402 $url = add_query_arg( $args, path_join( $api_path, $path ) );
403
404 $response = wp_remote_get(
405 $url,
406 array(
407 'timeout' => 10,
408 'Accept-Encoding' => 'gzip',
409 'sslverify' => false,
410 )
411 );
412
413 if ( is_wp_error( $response ) ) {
414 WP_ConvertKit::log( 'Error: ' . $response->get_error_message() );
415
416 return array(
417 'error' => $response->get_error_message(),
418 );
419 } else {
420
421 // Maybe inflate response body.
422 // @see https://wordpress.stackexchange.com/questions/10088/how-do-i-troubleshoot-responses-with-wp-http-api
423 $inflate = @gzinflate( $response['body'] );
424 if ( $inflate ) {
425 $response['body'] = $inflate;
426 }
427
428 $body = wp_remote_retrieve_body( $response );
429 $data = json_decode( $body, true );
430 }
431
432 return $data;
433 }
434
435 /**
436 * Make a request to the ConvertKit API
437 *
438 * @param string $request Request string.
439 * @param string $method HTTP Method.
440 * @param array $args Request arguments.
441 * @return object Response object
442 */
443 private function make_request( $request, $method, $args = array() ) {
444
445 WP_ConvertKit::log( 'API Request (make_request): ' . $request . ' Args: ' . wp_json_encode( $args ) );
446
447 $url = $this->api_url_base . $request;
448
449 $headers = array(
450 'Content-Type' => 'application/json; charset=utf-8',
451 );
452
453 $settings = array(
454 'headers' => $headers,
455 'method' => $method,
456 'body' => wp_json_encode( $args ),
457 );
458
459 $result = wp_remote_request( $url, $settings );
460
461 if ( is_wp_error( $result ) ) {
462 WP_ConvertKit::log( 'API Response (make_request): WPError: ' . $result->get_error_message() );
463 } elseif ( isset( $result['response']['code'] ) && '200' === $result['response']['code'] ) {
464 if ( isset( $result['body'] ) ) {
465 WP_ConvertKit::log( 'API Response (make_request): ' . $result['body'] );
466 } else {
467 WP_ConvertKit::log( 'API Response (make_request): Response code 200, but body is not set.' );
468 }
469 } else {
470 WP_ConvertKit::log( 'API Response (make_request): Result code: ' . $result['response']['code'] . ' ' . $result['response']['message'] );
471 }
472
473 }
474
475 }
476