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