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

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

671 lines 19.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin activation, update and deactivation class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Runs any steps required on plugin activation, update and deactivation.
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 * @version 1.9.7.4
15 */
16 class ConvertKit_Setup {
17
18 /**
19 * Runs routines when the Plugin is activated.
20 *
21 * @since 1.9.7.4
22 */
23 public function activate() {
24
25 // Call any functions to e.g. schedule WordPress Cron events now.
26 $this->schedule_cron_events();
27
28 // Install entries database table.
29 $entries = new ConvertKit_Form_Entries();
30 $entries->create_database_table();
31
32 }
33
34 /**
35 * Runs routines on every Plugin request e.g.
36 * ensuring WordPress Cron events are scheduled.
37 *
38 * @since 2.6.6
39 */
40 public function initialize() {
41
42 // Call any functions to e.g. schedule WordPress Cron events now.
43 $this->schedule_cron_events();
44
45 }
46
47 /**
48 * Runs routines if the Plugin version has been updated.
49 *
50 * @since 1.9.7.4
51 */
52 public function update() {
53
54 // Get installed Plugin version.
55 $current_version = get_option( 'convertkit_version' );
56
57 // If the version number matches the plugin version, no update routines
58 // need to run.
59 if ( $current_version === CONVERTKIT_PLUGIN_VERSION ) {
60 return;
61 }
62
63 /**
64 * 3.0.0: Migrate reCAPTCHA settings from Restrict Content to General settings.
65 * Install entries database table.
66 */
67 if ( version_compare( $current_version, '3.0.0', '<' ) ) {
68 $this->migrate_recaptcha_settings();
69
70 // Install entries database table.
71 $entries = new ConvertKit_Form_Entries();
72 $entries->create_database_table();
73 }
74
75 /**
76 * 2.6.6: Migrate 'Default' Form value in _wp_convertkit_term_meta[form] from 0 to -1,
77 * to match Posts.
78 */
79 if ( version_compare( $current_version, '2.6.6', '<' ) ) {
80 $this->migrate_term_default_form_settings();
81 }
82
83 /**
84 * 2.5.4: Migrate WishList Member to ConvertKit Form Mappings
85 */
86 if ( ! $current_version || version_compare( $current_version, '2.5.4', '<' ) ) {
87 $this->migrate_wlm_none_setting();
88 $this->migrate_wlm_form_tag_mapping_settings();
89 }
90
91 /**
92 * 2.5.3: Migrate Third Party Form integrations' 'None' option values from `default` to blank.
93 */
94 if ( ! $current_version || version_compare( $current_version, '2.5.3', '<' ) ) {
95 $this->migrate_contact_form_7_none_setting();
96 $this->migrate_forminator_none_setting();
97 $this->migrate_wlm_none_setting();
98 }
99
100 /**
101 * 2.5.2: Migrate Forminator to ConvertKit Form Mappings
102 */
103 if ( ! $current_version || version_compare( $current_version, '2.5.2', '<' ) ) {
104 $this->migrate_forminator_form_mapping_settings();
105 }
106
107 /**
108 * 2.5.2: Migrate Contact Form 7 to ConvertKit Form Mappings
109 */
110 if ( ! $current_version || version_compare( $current_version, '2.5.2', '<' ) ) {
111 $this->migrate_contact_form_7_form_mapping_settings();
112 }
113
114 /**
115 * 2.5.0: Get Access token for API version 4.0 using a v3 API Key and Secret.
116 */
117 if ( ! $current_version || version_compare( $current_version, '2.5.0', '<' ) ) {
118 $this->maybe_get_access_token_by_api_key_and_secret();
119 }
120
121 /**
122 * 2.4.9.1+: Migrate ck_default_form to _wp_convertkit_term_meta[form], as Term settings
123 * support multiple options (form, position etc).
124 */
125 if ( version_compare( $current_version, '2.4.9.1', '<' ) ) {
126 $this->migrate_term_form_settings();
127 }
128
129 /**
130 * 1.6.1+: Refresh Forms, Landing Pages and Tags data stored in settings,
131 * to get new Forms Builder Settings.
132 */
133 if ( version_compare( $current_version, '1.6.1', '<' ) ) {
134 $this->refresh_resources();
135 }
136
137 /**
138 * 1.9.6+: Migrate _wp_convertkit_settings[default_form] to _wp_convertkit_settings[page_form] and
139 * _wp_convertkit_settings[post_form], now that each Post Type has its own Default Form setting
140 * in Settings > Kit > General.
141 */
142 if ( version_compare( $current_version, '1.9.6', '<' ) ) {
143 $this->migrate_default_form_settings();
144 }
145
146 /**
147 * 1.9.7.4+: Schedule Post Resources' Cron event to refresh Posts cache hourly,
148 * as the activate() routine won't pick this up for existing active installations.
149 */
150 if ( version_compare( $current_version, '1.9.7.4', '<' ) ) {
151 $posts = new ConvertKit_Resource_Posts( 'cron' );
152 $posts->schedule_cron_event();
153 }
154
155 // Update the installed version number in the options table.
156 update_option( 'convertkit_version', CONVERTKIT_PLUGIN_VERSION );
157
158 }
159
160 /**
161 * 3.0.0: Migrate reCAPTCHA settings from Restrict Content settings to General settings.
162 *
163 * @since 3.0.0
164 */
165 private function migrate_recaptcha_settings() {
166
167 // Read Restrict Content settings directly from options table,
168 // as Convertkit_Settings_Restrict_Content won't have helper
169 // methods to return the specific settings.
170 $settings = get_option( '_wp_convertkit_settings_restrict_content' );
171
172 // If no reCAPTCHA settings exist, bail.
173 if ( ! isset( $settings['recaptcha_site_key'] ) || ! isset( $settings['recaptcha_secret_key'] ) || ! isset( $settings['recaptcha_minimum_score'] ) ) {
174 return;
175 }
176
177 // Load settings class, saving the reCAPTCHA settings to the General settings.
178 $convertkit_settings = new ConvertKit_Settings();
179 $convertkit_settings->save(
180 array(
181 'recaptcha_site_key' => $settings['recaptcha_site_key'],
182 'recaptcha_secret_key' => $settings['recaptcha_secret_key'],
183 'recaptcha_minimum_score' => $settings['recaptcha_minimum_score'],
184 )
185 );
186
187 // Remove reCAPTCHA settings from Restrict Content settings.
188 unset( $settings['recaptcha_site_key'] );
189 unset( $settings['recaptcha_secret_key'] );
190 unset( $settings['recaptcha_minimum_score'] );
191 update_option( '_wp_convertkit_settings_restrict_content', $settings );
192
193 }
194
195 /**
196 * Change the Default value of 0 to -1 in wp_convertkit_term_meta[form], to
197 * match how the Default value is stored in Posts.
198 *
199 * @since 2.6.6
200 */
201 private function migrate_term_default_form_settings() {
202
203 // Get all Terms that have ConvertKit settings defined.
204 $query = new WP_Term_Query(
205 array(
206 'taxonomy' => 'category',
207 'hide_empty' => false,
208 'fields' => 'ids',
209 'meta_query' => array(
210 array(
211 'key' => '_wp_convertkit_term_meta',
212 'comparison' => 'EXISTS',
213 ),
214 ),
215 )
216 );
217
218 // Bail if no Terms exist.
219 if ( ! $query->terms ) {
220 return;
221 }
222
223 // Iterate through Terms, mapping settings.
224 foreach ( $query->terms as $term_id ) {
225 $term_settings = new ConvertKit_Term( $term_id );
226
227 // If the Form setting is Default i.e. it does not have a formchange it from 0 to -1.
228 if ( ! $term_settings->has_form() ) {
229 $term_settings->save(
230 array(
231 'form' => -1,
232 )
233 );
234 }
235 }
236
237 }
238
239 /**
240 * 2.5.4: Migrate WLM settings:
241 * - Prefix any WishList Member to ConvertKit Form ID mappings with `form:`,
242 * - Prefix any WishList Member to ConvertKit Tag ID mappings with `tag:`,
243 * - Standardise the settings keys to the format {wlm_level_id}_subscribe
244 * and {wlm_level_id}_unsubscribe.
245 *
246 * @since 2.5.4
247 */
248 private function migrate_wlm_form_tag_mapping_settings() {
249
250 $convertkit_wlm_settings = new ConvertKit_Wishlist_Settings();
251
252 // Bail if no settings exist.
253 if ( ! $convertkit_wlm_settings->has_settings() ) {
254 return;
255 }
256
257 // Define new array for settings.
258 $settings = array();
259
260 // Iterate through settings.
261 foreach ( $convertkit_wlm_settings->get() as $key => $convertkit_form_or_tag_id ) {
262 // Split the settings key.
263 list( $wlm_level_id, $type ) = explode( '_', $key );
264
265 switch ( $type ) {
266 case 'form':
267 // This is the action to perform when the user is added to the WLM Level.
268 // Use a new name for the setting key to reflect this.
269 // < 2.5.4, forms were the only option here, so prefix the resource ID with `form:`.
270 $settings[ $wlm_level_id . '_add' ] = ( empty( $convertkit_form_or_tag_id ) ? '' : 'form:' . $convertkit_form_or_tag_id );
271 break;
272
273 case 'unsubscribe':
274 // This is the action to perform when the user is removed from the WLM Level.
275 // Use a new name for the setting key to reflect this.
276 // < 2.5.4, tags were the only option here, so prefix the resource ID with `tag:`.
277 $settings[ $wlm_level_id . '_remove' ] = ( empty( $convertkit_form_or_tag_id ) ? '' : 'tag:' . $convertkit_form_or_tag_id );
278 break;
279 }
280 }
281
282 // Update settings.
283 update_option( $convertkit_wlm_settings::SETTINGS_NAME, $settings );
284
285 }
286
287 /**
288 * 2.5.3: Migrate Third Party Form integrations' 'None' option values from `default` to blank.
289 *
290 * 2.4.9 changed the 'None' label's value from `default` to a blank string, as the v4 API's
291 * `add_subscriber_to_form()` method introduces type declarations, which would result in
292 * an uncaught TypeError when passing a non integer value.
293 *
294 * The PR for that (https://github.com/ConvertKit/convertkit-wordpress/pull/655) didn't include
295 * any tests or upgrade/migration routines to change any existing saved settings where the 'None'
296 * label's value was stored as `default`.
297 */
298 private function migrate_contact_form_7_none_setting() {
299
300 $convertkit_contact_form_7_settings = new ConvertKit_ContactForm7_Settings();
301
302 // Bail if no settings exist.
303 if ( ! $convertkit_contact_form_7_settings->has_settings() ) {
304 return;
305 }
306
307 // Get settings.
308 $settings = $convertkit_contact_form_7_settings->get();
309
310 // Iterate through settings.
311 foreach ( $settings as $contact_form_7_form_id => $convertkit_form_id ) {
312 // Skip keys that are non-numeric e.g. `creator_network_recommendations_*`.
313 if ( ! is_numeric( $contact_form_7_form_id ) ) {
314 continue;
315 }
316
317 // Change 'default' to a blank string.
318 if ( $convertkit_form_id === 'default' ) {
319 $settings[ $contact_form_7_form_id ] = '';
320 }
321 }
322
323 // Update settings.
324 update_option( $convertkit_contact_form_7_settings::SETTINGS_NAME, $settings );
325
326 }
327
328 /**
329 * 2.5.3: Migrate Third Party Form integrations' 'None' option values from `default` to blank.
330 *
331 * 2.4.9 changed the 'None' label's value from `default` to a blank string, as the v4 API's
332 * `add_subscriber_to_form()` method introduces type declarations, which would result in
333 * an uncaught TypeError when passing a non integer value.
334 *
335 * The PR for that (https://github.com/ConvertKit/convertkit-wordpress/pull/655) didn't include
336 * any tests or upgrade/migration routines to change any existing saved settings where the 'None'
337 * label's value was stored as `default`.
338 */
339 private function migrate_forminator_none_setting() {
340
341 $convertkit_forminator_settings = new ConvertKit_Forminator_Settings();
342
343 // Bail if no settings exist.
344 if ( ! $convertkit_forminator_settings->has_settings() ) {
345 return;
346 }
347
348 // Get settings.
349 $settings = $convertkit_forminator_settings->get();
350
351 // Iterate through settings.
352 foreach ( $settings as $forminator_form_id => $convertkit_form_id ) {
353 // Skip keys that are non-numeric e.g. `creator_network_recommendations_*`.
354 if ( ! is_numeric( $forminator_form_id ) ) {
355 continue;
356 }
357
358 // Change 'default' to a blank string.
359 if ( $convertkit_form_id === 'default' ) {
360 $settings[ $forminator_form_id ] = '';
361 }
362 }
363
364 // Update settings.
365 update_option( $convertkit_forminator_settings::SETTINGS_NAME, $settings );
366
367 }
368
369 /**
370 * 2.5.3: Migrate Third Party Form integrations' 'None' option values from `default` to blank.
371 *
372 * 2.4.9 changed the 'None' label's value from `default` to a blank string, as the v4 API's
373 * `add_subscriber_to_form()` method introduces type declarations, which would result in
374 * an uncaught TypeError when passing a non integer value.
375 *
376 * The PR for that (https://github.com/ConvertKit/convertkit-wordpress/pull/655) didn't include
377 * any tests or upgrade/migration routines to change any existing saved settings where the 'None'
378 * label's value was stored as `default`.
379 */
380 private function migrate_wlm_none_setting() {
381
382 $convertkit_wlm_settings = new ConvertKit_Wishlist_Settings();
383
384 // Bail if no settings exist.
385 if ( ! $convertkit_wlm_settings->has_settings() ) {
386 return;
387 }
388
389 // Get settings.
390 $settings = $convertkit_wlm_settings->get();
391
392 // Iterate through settings.
393 foreach ( $settings as $wlm_level_id => $value ) {
394 // Change 'default' to a blank string.
395 if ( $value === 'default' ) {
396 $settings[ $wlm_level_id ] = '';
397 }
398 }
399
400 // Update settings.
401 update_option( $convertkit_wlm_settings::SETTINGS_NAME, $settings );
402
403 }
404
405 /**
406 * 2.5.2: Prefix any Forminator to ConvertKit Form ID mappings with `form:`, now that
407 * the Plugin supports adding a subscriber to a Form, Tag or Sequence.
408 *
409 * @since 2.5.2
410 */
411 private function migrate_forminator_form_mapping_settings() {
412
413 $convertkit_forminator_settings = new ConvertKit_Forminator_Settings();
414
415 // Bail if no settings exist.
416 if ( ! $convertkit_forminator_settings->has_settings() ) {
417 return;
418 }
419
420 // Get settings.
421 $settings = $convertkit_forminator_settings->get();
422
423 // Iterate through settings.
424 foreach ( $settings as $forminator_form_id => $convertkit_form_id ) {
425 // Skip keys that are non-numeric e.g. `creator_network_recommendations_*`.
426 if ( ! is_numeric( $forminator_form_id ) ) {
427 continue;
428 }
429
430 // Skip values that are blank i.e. no ConvertKit Form ID specified.
431 if ( empty( $convertkit_form_id ) ) {
432 continue;
433 }
434
435 // Skip values that are non-numeric i.e. the `form_` prefix was already added.
436 // This should never happen as this routine runs once, but this is a sanity check.
437 if ( ! is_numeric( $convertkit_form_id ) ) {
438 continue;
439 }
440
441 // Prefix the ConvertKit Form ID with `form_`.
442 $settings[ $forminator_form_id ] = 'form:' . $convertkit_form_id;
443 }
444
445 // Update settings.
446 update_option( $convertkit_forminator_settings::SETTINGS_NAME, $settings );
447
448 }
449
450 /**
451 * 2.5.2: Prefix any Contact Form 7 to ConvertKit Form ID mappings with `form:`, now that
452 * the Plugin supports adding a subscriber to a Form, Tag or Sequence.
453 *
454 * @since 2.5.2
455 */
456 private function migrate_contact_form_7_form_mapping_settings() {
457
458 $convertkit_contact_form_7_settings = new ConvertKit_ContactForm7_Settings();
459
460 // Bail if no settings exist.
461 if ( ! $convertkit_contact_form_7_settings->has_settings() ) {
462 return;
463 }
464
465 // Get settings.
466 $settings = $convertkit_contact_form_7_settings->get();
467
468 // Iterate through settings.
469 foreach ( $settings as $contact_form_7_form_id => $convertkit_form_id ) {
470 // Skip keys that are non-numeric e.g. `creator_network_recommendations_*`.
471 if ( ! is_numeric( $contact_form_7_form_id ) ) {
472 continue;
473 }
474
475 // Skip values that are blank i.e. no ConvertKit Form ID specified.
476 if ( empty( $convertkit_form_id ) ) {
477 continue;
478 }
479
480 // Skip values that are non-numeric i.e. the `form_` prefix was already added.
481 // This should never happen as this routine runs once, but this is a sanity check.
482 if ( ! is_numeric( $convertkit_form_id ) ) {
483 continue;
484 }
485
486 // Prefix the ConvertKit Form ID with `form_`.
487 $settings[ $contact_form_7_form_id ] = 'form:' . $convertkit_form_id;
488 }
489
490 // Update settings.
491 update_option( $convertkit_contact_form_7_settings::SETTINGS_NAME, $settings );
492
493 }
494
495 /**
496 * 2.5.0: Fetch an Access Token, Refresh Token and Expiry for v4 API use
497 * based on the Plugin setting's v3 API Key and Secret.
498 *
499 * @since 2.5.0
500 */
501 private function maybe_get_access_token_by_api_key_and_secret() {
502
503 $convertkit_settings = new ConvertKit_Settings();
504
505 // Bail if an Access Token exists; we don't need to fetch another one.
506 if ( $convertkit_settings->has_access_token() ) {
507 return;
508 }
509
510 // Bail if no API Key or Secret.
511 if ( empty( $convertkit_settings->get_api_key() ) ) {
512 return;
513 }
514 if ( empty( $convertkit_settings->get_api_secret() ) ) {
515 return;
516 }
517
518 // Get Access Token by API Key and Secret.
519 $api = new ConvertKit_API_V4( CONVERTKIT_OAUTH_CLIENT_ID, CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI );
520 $result = $api->get_access_token_by_api_key_and_secret(
521 $convertkit_settings->get_api_key(),
522 $convertkit_settings->get_api_secret(),
523 get_site_url()
524 );
525
526 // Bail if an error occured.
527 if ( is_wp_error( $result ) ) {
528 return;
529 }
530
531 // Store the new credentials.
532 // We don't use update_credentials(), because the response
533 // includes an `expires_at`, not a `created_at` and `expires_in`.
534 $convertkit_settings->save(
535 array(
536 'access_token' => $result['oauth']['access_token'],
537 'refresh_token' => $result['oauth']['refresh_token'],
538 'token_expires' => $result['oauth']['expires_at'],
539 )
540 );
541
542 }
543
544 /**
545 * Migrate ck_default_form to _wp_convertkit_term_meta[form], as Term settings
546 * support multiple options (form, position etc).
547 *
548 * @since 2.4.9.1
549 */
550 private function migrate_term_form_settings() {
551
552 // Get all Terms that have ConvertKit settings defined.
553 $query = new WP_Term_Query(
554 array(
555 'taxonomy' => 'category',
556 'hide_empty' => false,
557 'fields' => 'ids',
558 'meta_query' => array(
559 array(
560 'key' => 'ck_default_form',
561 'comparison' => 'EXISTS',
562 ),
563 ),
564 )
565 );
566
567 // Bail if no Terms exist.
568 if ( ! $query->terms ) {
569 return;
570 }
571
572 // Iterate through Terms, mapping settings.
573 foreach ( $query->terms as $term_id ) {
574 $term_settings = new ConvertKit_Term( $term_id );
575 $term_settings->save(
576 array(
577 'form' => get_term_meta( $term_id, 'ck_default_form', true ), // Fetch form setting from old meta key.
578 'form_position' => '', // Default to no position.
579 )
580 );
581
582 // Delete old Term meta.
583 delete_term_meta( $term_id, 'ck_default_form' );
584 }
585
586 }
587
588 /**
589 * 1.9.6+: Migrate _wp_convertkit_settings[default_form] to _wp_convertkit_settings[page_form] and
590 * _wp_convertkit_settings[post_form], now that each Post Type has its own Default Form setting
591 * in Settings > Kit > General.
592 */
593 private function migrate_default_form_settings() {
594
595 $convertkit_settings = new ConvertKit_Settings();
596
597 // Bail if no default_form setting exists.
598 $settings = get_option( $convertkit_settings::SETTINGS_NAME );
599 if ( ! $settings ) {
600 return;
601 }
602 if ( ! array_key_exists( 'default_form', $settings ) ) {
603 return;
604 }
605
606 // Restructure settings.
607 $settings['page_form'] = $settings['default_form'];
608 $settings['post_form'] = $settings['default_form'];
609
610 // Remove obsolete default_form setting.
611 unset( $settings['default_form'] );
612
613 // Update.
614 update_option( $convertkit_settings::SETTINGS_NAME, $settings );
615
616 }
617
618 /**
619 * 1.6.1: Refresh Forms, Landing Pages and Tags data stored in settings,
620 * to get new Forms Builder Settings.
621 */
622 private function refresh_resources() {
623
624 $forms = new ConvertKit_Resource_Forms( 'setup' );
625 $landing_pages = new ConvertKit_Resource_Landing_Pages( 'setup' );
626 $tags = new ConvertKit_Resource_Tags( 'setup' );
627
628 $forms->refresh();
629 $landing_pages->refresh();
630 $tags->refresh();
631
632 }
633
634 /**
635 * Runs routines when the Plugin is deactivated.
636 *
637 * @since 1.9.7.4
638 */
639 public function deactivate() {
640
641 // Call any functions to e.g. unschedule WordPress Cron events now.
642 $this->unschedule_cron_events();
643
644 }
645
646 /**
647 * Schedules any Plugin specific CRON events, if they do not already exist.
648 *
649 * @since 2.6.6
650 */
651 private function schedule_cron_events() {
652
653 $posts = new ConvertKit_Resource_Posts( 'cron' );
654 $posts->schedule_cron_event();
655
656 }
657
658 /**
659 * Unschedules any Plugin specific CRON events, if they exist.
660 *
661 * @since 2.6.6
662 */
663 private function unschedule_cron_events() {
664
665 $posts = new ConvertKit_Resource_Posts( 'cron' );
666 $posts->unschedule_cron_event();
667
668 }
669
670 }
671