PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 1.8.1
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v1.8.1
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 2.3.3 All 194 releases
convertkit / includes / class-convertkit.php

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

678 lines 18.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class WP_ConvertKit
5 */
6 class WP_ConvertKit {
7
8 const POST_META_KEY = '_wp_convertkit_post_meta';
9
10 const SETTINGS_NAME = '_wp_convertkit_settings';
11
12 const SETTINGS_PAGE_SLUG = '_wp_convertkit_settings';
13
14 /**
15 * @var ConvertKit_API
16 */
17 private static $api;
18
19 /**
20 * @var int Data Caching
21 */
22 private static $cache_period = 0;
23
24 /**
25 * @var null
26 */
27 private static $meta_defaults = null;
28
29 /**
30 * @var array
31 */
32 private static $settings_defaults = array(
33 'api_key' => '',
34 'api_secret' => '',
35 'default_form' => 0,
36 'debug' => false,
37 'no_scripts' => false,
38 );
39
40 /**
41 * @var array
42 */
43 private static $forms_markup = array();
44
45 /** @var array */
46 private static $landing_pages_markup = array();
47
48 /** @var string */
49 private static $forms_version = '6';
50
51 /**
52 * Initialize the class
53 */
54 public static function init() {
55 self::add_actions();
56 self::add_filters();
57 self::register_shortcodes();
58
59 self::$cache_period = MINUTE_IN_SECONDS * 10;
60
61 self::_api_connect();
62 }
63
64 /**
65 * Add WP Actions
66 */
67 private static function add_actions() {
68 add_action( 'plugins_loaded', array( __CLASS__, 'load_textdomain' ) );
69 if ( is_admin() ) {
70 add_action( 'add_meta_boxes_page', array( __CLASS__, 'add_meta_boxes' ) );
71 add_action( 'add_meta_boxes_post', array( __CLASS__, 'add_meta_boxes' ) );
72 } else {
73 add_action( 'template_redirect', array( __CLASS__, 'page_takeover' ) );
74 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
75 }
76
77 add_action( 'widgets_init', array( __CLASS__, 'ck_register_widgets' ) );
78
79 add_action( 'save_post', array( __CLASS__, 'save_post_meta' ), 10, 2 );
80
81 add_action( 'init', array( __CLASS__, 'upgrade' ) , 10 );
82 }
83
84 /**
85 * Load plugin textdomain
86 */
87 public static function load_textdomain() {
88 load_plugin_textdomain( 'convertkit', false, basename( dirname( __FILE__ ) ) . '/languages/' );
89 }
90
91 /**
92 * Add WP Filters
93 */
94 private static function add_filters() {
95 if ( ! is_admin() ) {
96 add_filter( 'the_content', array( __CLASS__, 'append_form' ) );
97 }
98
99 add_filter( 'plugin_action_links_' . CONVERTKIT_PLUGIN_FILE, array( __CLASS__, 'add_settings_page_link' ) );
100 }
101
102 /**
103 * Register ConvertKit shortcodes
104 */
105 private static function register_shortcodes() {
106 add_shortcode( 'convertkit', array( __CLASS__, 'shortcode' ) );
107 }
108
109 /**
110 * Plugin action links callback
111 *
112 * @param $links
113 * @return array
114 */
115 public static function add_settings_page_link( $links ) {
116 $settings_link = sprintf( '<a href="%s">%s</a>', self::_get_settings_page_link(), __( 'Settings', 'convertkit' ) );
117
118 return array_merge( array( 'settings' => $settings_link ), $links );
119 }
120
121 /**
122 * Add Meta Boxes callback
123 *
124 * @param WP_Post $post The current post.
125 */
126 public static function add_meta_boxes( $post ) {
127 add_meta_box( 'wp-convertkit-meta-box', __( 'ConvertKit', 'convertkit' ), array( __CLASS__, 'display_meta_box' ), $post->post_type, 'normal' );
128 }
129
130 /**
131 * Metabox callback
132 *
133 * @param $post
134 */
135 public static function display_meta_box( $post ) {
136
137 $forms = get_option( 'convertkit_forms' );
138 $landing_pages = get_option( 'convertkit_landing_pages' );
139 $tags = get_option( 'convertkit_tags' );
140
141 /**
142 * Alphabetize
143 */
144 usort( $forms, function( $a, $b ) {
145 return strcmp( $a['name'], $b['name'] );
146 });
147
148 usort( $landing_pages, function( $a, $b ) {
149 return strcmp( $a['name'], $b['name'] );
150 });
151
152 usort( $tags, function( $a, $b ) {
153 return strcmp( $a['name'], $b['name'] );
154 });
155
156 $meta = self::_get_meta( $post->ID );
157 $settings_link = self::_get_settings_page_link();
158
159 include( CONVERTKIT_PLUGIN_PATH . '/views/backend/meta-boxes/meta-box.php' );
160 }
161
162 /**
163 * Save post meta callback
164 *
165 * @param int $post_id Post id.
166 * @param WP_Post $post The post.
167 */
168 public static function save_post_meta( $post_id, $post ) {
169 if ( wp_is_post_autosave( $post_id )
170 || wp_is_post_revision( $post_id )
171 || ! isset( $_POST['wp-convertkit-save-meta-nonce'] ) // WPCS input var okay.
172 || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wp-convertkit-save-meta-nonce'] ) ), 'wp-convertkit-save-meta' ) ) { // WPCS input var okay.
173 return;
174 }
175 if ( isset( $_POST['wp-convertkit'] ) ) { // WPCS input var okay.
176 $form = '';
177 if ( isset( $_POST['wp-convertkit']['form'] ) ) { // WPCS input var okay.
178 $form = sanitize_text_field( wp_unslash( $_POST['wp-convertkit']['form'] ) ); // WPCS input var okay.
179 }
180 $landing_page = '';
181 if ( isset( $_POST['wp-convertkit']['landing_page'] ) ) { // WPCS input var okay.
182 $landing_page = sanitize_text_field( wp_unslash( $_POST['wp-convertkit']['landing_page'] ) ); // WPCS input var okay.
183 }
184 $tag = '';
185 if ( isset( $_POST['wp-convertkit']['tag'] ) ) { // WPCS input var okay.
186 $tag = sanitize_text_field( wp_unslash( $_POST['wp-convertkit']['tag'] ) ); // WPCS input var okay.
187 }
188
189 $meta = array(
190 'form' => $form,
191 'landing_page' => $landing_page,
192 'tag' => $tag,
193 );
194 update_post_meta( $post_id, self::POST_META_KEY, $meta );
195 }
196 }
197
198 /**
199 * Page/Post display callback
200 *
201 * @param string $content The post content.
202 * @return string
203 */
204 public static function append_form( $content ) {
205
206 if ( is_singular( array( 'post' ) ) || is_page() ) {
207
208 $attributes = self::_get_meta( get_the_ID() );
209
210 // Get post/page form setting
211 if ( isset( $attributes['form'] ) && ( 0 < $attributes['form'] ) ) {
212 $form_id = $attributes['form'];
213 } else {
214 // Get category form
215 $form_id = self::get_category_form( get_the_ID() );
216
217 if ( 0 === $form_id || 'default' === $form_id ) {
218 // Get global default form
219 if ( '-1' === $attributes['form'] ) {
220 $form_id = self::_get_settings( 'default_form' );
221 }
222 }
223 }
224
225 if ( 0 < $form_id && !is_array( $form_id ) ) {
226
227 $forms = get_option( 'convertkit_forms' );
228
229 if ( isset( $forms[ $form_id ]['uid'] ) ) {
230 // new form
231 $tag = '<script async data-uid="' . $forms[ $form_id ]['uid'] . '" src="' . $forms[ $form_id ]['embed_js'] . '"></script>';
232 $content .= $tag;
233
234 } else {
235 // old form
236 $url = add_query_arg(
237 array(
238 'api_key' => self::_get_settings( 'api_key' ),
239 'v' => self::$forms_version,
240 ),
241 'https://forms.convertkit.com/' . $form_id . '.html'
242 );
243
244 $form_markup = self::$api->get_resource( $url );
245 $content .= $form_markup;
246 }
247 }
248 }
249
250 return $content;
251 }
252
253 /**
254 * Replace page content if a landing_page is set
255 */
256 public static function page_takeover() {
257 $queried_object = get_queried_object();
258 if ( isset( $queried_object->post_type )
259 && 'page' === $queried_object->post_type ) {
260
261 $landing_page_id = self::_get_meta( $queried_object->ID, 'landing_page' );
262
263 if ( '0' === $landing_page_id || empty( $landing_page_id ) ) {
264 // Set to None
265 return;
266 }
267
268 if ( strstr( $landing_page_id, 'http') ) {
269 // Old landing page
270 $landing_page = self::$api->get_resource( $landing_page_id );
271 if ( ! empty( $landing_page ) ) {
272 $script = WP_ConvertKit::get_ck_script();
273 $script .= "</head>";
274 $landing_page = str_replace( '</head>', $script, $landing_page );
275 echo $landing_page; // WPCS: XSS ok.
276 exit;
277 }
278 } else {
279 // New landing page
280 $landing_pages = get_option( 'convertkit_landing_pages' );
281 $landing_page = self::$api->get_resource( $landing_pages[$landing_page_id]['embed_url'] );
282 if ( ! empty( $landing_page ) ) {
283 $script = WP_ConvertKit::get_ck_script( true );
284 $script .= "</head>";
285 $landing_page = str_replace( '</head>', $script, $landing_page );
286 echo $landing_page; // WPCS: XSS ok.
287 exit;
288 }
289 }
290 }
291 }
292
293 /**
294 * Generate HTML for including ConvertKit JS in a landing page.
295 *
296 * During the landing page takeover the normal WordPress enqueue routine is not run so we need to add these
297 * javascript if we want subscribers tagged correctly.
298 *
299 * @since 1.5.2
300 * @param bool $include_jquery
301 * @return string
302 */
303 public static function get_ck_script( $include_jquery = false) {
304 $script = '';
305 if ( $include_jquery ) {
306 $scripts = new WP_Scripts();
307 $script .= "<script type='text/javascript' src='" . trailingslashit( $scripts->base_url ) . "wp-includes/js/jquery/jquery.js?ver=1.4.0'></script>";
308 }
309 $script .= "<script type='text/javascript' src='" . CONVERTKIT_PLUGIN_URL . "resources/frontend/jquery.cookie.min.js?ver=1.4.0'></script>";
310 $script .= "<script type='text/javascript' src='" . CONVERTKIT_PLUGIN_URL . 'resources/frontend/wp-convertkit.js?ver=' . CONVERTKIT_PLUGIN_VERSION . "'></script>";
311 $script .= "<script type='text/javascript'>/* <![CDATA[ */var ck_data = {\"ajaxurl\":\"" . admin_url( 'admin-ajax.php' ) . '"};/* ]]> */</script>';
312 return $script;
313 }
314
315 /**
316 * Enqueue scripts
317 */
318 public static function enqueue_scripts() {
319
320 // Only check for tags if we're on a singular post; otherwise, no tags
321 $has_tag = is_singular() ? self::post_has_tag( get_post() ) : false;
322
323 // Only load scripts if no scripts setting is not checked
324 $no_scripts = self::_get_settings( 'no_scripts' );
325 if ( ! $no_scripts ) {
326 wp_register_script(
327 'jquery-cookie',
328 CONVERTKIT_PLUGIN_URL . 'resources/frontend/jquery.cookie.min.js',
329 array( 'jquery' ),
330 '1.4.0'
331 );
332
333 wp_register_script(
334 'convertkit-js',
335 CONVERTKIT_PLUGIN_URL . 'resources/frontend/wp-convertkit.js',
336 array( 'jquery-cookie' ),
337 CONVERTKIT_PLUGIN_VERSION
338 );
339
340 wp_localize_script(
341 'convertkit-js',
342 'ck_data',
343 array(
344 'ajaxurl' => admin_url( 'admin-ajax.php' ),
345 'post_has_tag' => $has_tag,
346 )
347 );
348
349 wp_enqueue_script( 'convertkit-js' );
350 }
351 }
352
353 /**
354 * Register widget.
355 */
356 public static function ck_register_widgets() {
357 register_widget( 'CK_Widget_Form' );
358 }
359
360 /**
361 * Shortcode callback
362 *
363 * @param array $attributes Shortcode attributes.
364 * @param null $content
365 * @return string
366 */
367 public static function shortcode( $attributes, $content = null ) {
368
369 if ( isset( $attributes['id'] ) ) {
370 $form_id = $attributes['id'];
371 $forms = get_option( 'convertkit_forms' );
372
373 if ( isset( $forms[ $form_id ]['uid'] ) ) {
374 // new form
375 $form_markup = '<script async data-uid="' . $forms[ $form_id ]['uid'] . '" src="' . $forms[ $form_id ]['embed_js'] . '"></script>';
376 return apply_filters( 'wp_convertkit_get_form_embed', $form_markup, $attributes );
377 } else {
378 // old form
379 $url = add_query_arg(
380 array(
381 'api_key' => self::_get_settings( 'api_key' ),
382 'v' => self::$forms_version,
383 ),
384 'https://forms.convertkit.com/' . $form_id . '.html'
385 );
386 }
387 } elseif ( isset( $attributes['form'] ) ) {
388 $form_id = $attributes['form'];
389 $forms = get_option( 'convertkit_forms' );
390
391 if ( isset( $forms[ $form_id ]['uid'] ) ) {
392 // new form
393 $form_markup = '<script async data-uid="' . $forms[ $form_id ]['uid'] . '" src="' . $forms[ $form_id ]['embed_js'] . '"></script>';
394 return apply_filters( 'wp_convertkit_get_form_embed', $form_markup, $attributes );
395 } else {
396 $url = add_query_arg(
397 array(
398 'k' => self::_get_settings( 'api_key' ),
399 'v' => '2',
400 ),
401 'https://api.convertkit.com/forms/' . $form_id . '/embed'
402 );
403 }
404 } else {
405 $form_id = self::_get_settings( 'default_form' );
406 $url = add_query_arg(
407 array(
408 'api_key' => self::_get_settings( 'api_key' ),
409 'v' => self::$forms_version,
410 ),
411 'https://forms.convertkit.com/' . $form_id . '.html'
412 );
413 }
414
415 if ( 0 < $form_id ) {
416 $form_markup = self::$api->get_resource( $url );
417 } else {
418 $form_markup = '';
419 }
420
421 return apply_filters( 'wp_convertkit_get_form_embed', $form_markup, $attributes );
422 }
423
424 /**
425 * Retrieve meta
426 *
427 * @return array|null
428 */
429 private static function _get_meta_defaults() {
430 if ( is_null( self::$meta_defaults ) ) {
431 self::$meta_defaults = array(
432 'form' => '-1',
433 'landing_page' => '',
434 'tag' => '',
435 );
436 }
437
438 return self::$meta_defaults;
439 }
440
441 /**
442 * Get selected post meta
443 *
444 * @param int $post_id Post ID.
445 * @param null $meta_key Key string to get.
446 *
447 * @return array|bool
448 */
449 private static function _get_meta( $post_id, $meta_key = null ) {
450 $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
451
452 $meta = get_post_meta( $post_id, self::POST_META_KEY, true );
453 $meta_defaults = self::_get_meta_defaults();
454
455 if ( empty( $meta ) ) {
456 $meta = $meta_defaults;
457
458 $old_value = intval( get_post_meta( $post_id, '_convertkit_convertkit_form', true ) );
459 if ( 0 !== $old_value ) {
460 $meta['form'] = $old_value;
461 }
462 }
463
464 $meta = shortcode_atts( $meta_defaults, $meta );
465
466 return is_null( $meta_key ) ? $meta : ( isset( $meta[ $meta_key ] ) ? $meta[ $meta_key ] : false );
467 }
468
469 /**
470 * Get plugin settings
471 *
472 * @param null $settings_key
473 * @return mixed|null
474 */
475 public static function _get_settings( $settings_key = null ) {
476 $settings = get_option( self::SETTINGS_NAME, self::$settings_defaults );
477
478 return is_null( $settings_key ) ? $settings : ( isset( $settings[ $settings_key ] ) ? $settings[ $settings_key ] : null);
479 }
480
481 /**
482 * Get instance of ConvertKitAPI
483 */
484 private static function _api_connect() {
485 $api_key = self::_get_settings( 'api_key' );
486 $api_secret = self::_get_settings( 'api_secret' );
487 $debug = self::_get_settings( 'debug' );
488
489 self::$api = new ConvertKit_API( $api_key, $api_secret, $debug );
490 }
491
492 /**
493 * Get instance of the CK API
494 *
495 * @return ConvertKit_API
496 */
497 public static function get_api() {
498 return self::$api;
499 }
500
501 /**
502 * Get ConvertKit API key
503 *
504 * @return mixed|null|void
505 */
506 public static function get_api_key() {
507 return self::_get_settings( 'api_key' );
508 }
509
510 /**
511 * Get ConvertKit API secret
512 *
513 * @return mixed|null|void
514 */
515 public static function get_api_secret() {
516 return self::_get_settings( 'api_secret' );
517 }
518
519 /**
520 * @return string
521 */
522 public static function get_forms_version() {
523 return self::$forms_version;
524 }
525
526 /**
527 * Get link to the plugin settings page
528 *
529 * @param array $query_args Args to add to URL.
530 * @return string
531 */
532 private static function _get_settings_page_link( $query_args = array() ) {
533 $query_args = array(
534 'page' => self::SETTINGS_PAGE_SLUG,
535 ) + $query_args;
536
537 return add_query_arg( $query_args, admin_url( 'options-general.php' ) );
538 }
539
540 /**
541 * Get default form for the post's categories.
542 * If there are multiple set the last one found will be returned.
543 *
544 * @param int $id
545 * @return int $form_id
546 */
547 private static function get_category_form( $id ) {
548 $categories = wp_get_post_categories( $id );
549
550 $form_id = 0;
551 foreach ( $categories as $category ) {
552
553 $id = get_term_meta( $category, 'ck_default_form', true );
554 if ( $id ) {
555 $form_id = $id;
556 }
557 }
558
559 return $form_id;
560 }
561
562 /**
563 * Output data to log file
564 *
565 * @param string $message String to add to log.
566 */
567 static function log( $message ) {
568
569 if ( 'on' === self::_get_settings( 'debug' ) ) {
570 $dir = CONVERTKIT_PLUGIN_PATH;
571 $handle = fopen( trailingslashit( $dir ) . 'log.txt', 'a' );
572 if ( $handle ) {
573 $time = date_i18n( 'm-d-Y @ H:i:s -' );
574 fwrite( $handle, $time . ' ' . $message . "\n" );
575 fclose( $handle );
576 }
577 }
578
579 }
580
581 /**
582 * Run version specific upgrade.
583 */
584 public static function upgrade() {
585
586 $current_version = get_option( 'convertkit_version' );
587 $convertkit_user_history_table = get_option( 'convertkit_user_history_table' );
588
589 if ( ! $current_version ) {
590 // Run 1.4.1 upgrade.
591 $settings = self::_get_settings();
592
593 if ( isset( $settings['api_key'] ) ) {
594 // Get all posts and pages to track what has been updated.
595 $posts = get_option( '_wp_convertkit_upgrade_posts' );
596
597 if ( ! $posts ) {
598
599 $args = array(
600 'post_type' => array( 'post', 'page' ),
601 'fields' => 'ids',
602 );
603
604 $result = new WP_Query( $args );
605 if ( ! is_wp_error( $result ) ) {
606 $posts = $result->posts;
607 update_option( '_wp_convertkit_upgrade_posts', $posts );
608 }
609 }
610
611 // Get form mappings.
612 $mappings = self::$api->get_resources( 'subscription_forms' );
613
614 // 1. Update global form. Set 'api_version' so this is only done once.
615 if ( ! isset( $settings['api_version'] ) ) {
616 $old_form_id = $settings['default_form'];
617 $settings['default_form'] = isset( $mappings[ $old_form_id ] ) ? $mappings[ $old_form_id ] : 0;
618 $settings['api_version'] = 'v3';
619 update_option( self::SETTINGS_NAME, $settings );
620 }
621
622 // 2. Scan posts/pages for _wp_convertkit_post_meta and update IDs
623 // Scan content for shortcode and update
624 // Remove page_id from posts array after page is updated.
625 foreach ( $posts as $key => $post_id ) {
626 $post_settings = get_post_meta( $post_id, '_wp_convertkit_post_meta', true );
627
628 if ( isset( $post_settings['form'] ) && ( 0 < $post_settings['form'] ) ) {
629 $post_settings['form'] = isset( $mappings[ $post_settings['form'] ] ) ? $mappings[ $post_settings['form'] ] : 0;
630 }
631 if ( isset( $post_settings['landing_page'] ) && ( 0 < $post_settings['landing_page'] ) ) {
632 $post_settings['landing_page'] = isset( $mappings[ $post_settings['landing_page'] ] ) ? $mappings[ $post_settings['landing_page'] ] : 0;
633 }
634 update_post_meta( $post_id, '_wp_convertkit_post_meta', $post_settings );
635 unset( $posts[ $key ] );
636 update_option( '_wp_convertkit_upgrade_posts', $posts );
637 }
638
639 // Done scanning posts, upgrade complete.
640 if ( empty( $posts ) ) {
641 update_option( 'convertkit_version', CONVERTKIT_PLUGIN_VERSION );
642 delete_option( '_wp_convertkit_upgrade_posts' );
643 }
644 } else {
645 update_option( 'convertkit_version', CONVERTKIT_PLUGIN_VERSION );
646 } // End if().
647 } elseif ( version_compare( $current_version, '1.5.0', '<' ) || ! $convertkit_user_history_table ) {
648
649 // Create User History table
650 ConvertKit_Custom_Content::create_table();
651 update_option( 'convertkit_version', CONVERTKIT_PLUGIN_VERSION );
652
653 } elseif ( version_compare( $current_version, '1.6.1', '<' ) ) {
654 // Refresh the forms meta to get new forms builder settings
655 $api_key = self::_get_settings( 'api_key' );
656 if ( ! empty( $api_key ) ) {
657 self::$api->update_resources( $api_key );
658 }
659 update_option( 'convertkit_version', CONVERTKIT_PLUGIN_VERSION );
660 }// End if().
661 }
662
663
664 /**
665 * @param $post WP_Post
666 *
667 * @return boolean
668 */
669 public static function post_has_tag( $post ) {
670 $meta = get_post_meta( $post->ID, '_wp_convertkit_post_meta', true );
671
672 if ( isset( $meta['tag'] ) ) {
673 return ( $meta['tag'] == 0 ) ? false : true;
674 }
675 return false;
676 }
677 }
678