PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 2.4.7
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v2.4.7
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 2.3.1 All 196 releases
← All changes | includes/class-convertkit-output.php +66 -544 3.3.32.4.7 View file →
@@ -66,16 +66,13 @@
66 66 * @since 1.9.6
67 67 */
68 68 public function __construct() {
69 69
70 - add_action( 'rest_api_init', array( $this, 'register_routes' ) );
71 - add_action( 'wp', array( $this, 'maybe_tag_subscriber' ) );
70 + add_action( 'init', array( $this, 'get_subscriber_id_from_request' ), 1 );
72 71 add_action( 'template_redirect', array( $this, 'output_form' ) );
73 72 add_action( 'template_redirect', array( $this, 'page_takeover' ) );
74 73 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
75 74 add_filter( 'the_content', array( $this, 'append_form_to_content' ) );
76 - add_filter( 'hooked_block_types', array( $this, 'maybe_register_form_block_on_category_archive' ), 10, 4 );
77 - add_filter( 'hooked_block_convertkit/form', array( $this, 'append_form_block_to_category_archive' ), 10, 1 );
78 75 add_action( 'wp_footer', array( $this, 'output_global_non_inline_form' ), 1 );
79 76 add_action( 'wp_footer', array( $this, 'output_scripts_footer' ) );
80 77
81 78 }
@@ -80,144 +77,8 @@
80 77
81 78 }
82 79
83 80 /**
84 - * Register REST API routes.
85 - *
86 - * @since 3.1.7
87 - */
88 - public function register_routes() {
89 -
90 - // Register route to store the Kit subscriber's email's ID in a cookie.
91 - register_rest_route(
92 - 'kit/v1',
93 - '/subscriber/store-email-as-id-in-cookie',
94 - array(
95 - 'methods' => WP_REST_Server::CREATABLE,
96 - 'args' => array(
97 - // Email: Validate email is included in the request, a valid email address
98 - // and sanitize the email address.
99 - 'email' => array(
100 - 'required' => true,
101 - 'validate_callback' => function ( $param ) {
102 -
103 - return is_string( $param ) && is_email( $param );
104 -
105 - },
106 - 'sanitize_callback' => 'sanitize_email',
107 - ),
108 - ),
109 - 'callback' => function ( $request ) {
110 -
111 - // Get email address.
112 - $email = $request->get_param( 'email' );
113 -
114 - // Get subscriber ID.
115 - $subscriber = new ConvertKit_Subscriber();
116 - $subscriber_id = $subscriber->validate_and_store_subscriber_email( $email );
117 -
118 - // Bail if an error occurred i.e. API hasn't been configured.
119 - if ( is_wp_error( $subscriber_id ) ) {
120 - return rest_ensure_response( $subscriber_id );
121 - }
122 -
123 - // Return the subscriber ID.
124 - return rest_ensure_response(
125 - array(
126 - 'id' => $subscriber_id,
127 - )
128 - );
129 -
130 - },
131 -
132 - // No authentication required, as this is on the frontend site.
133 - 'permission_callback' => '__return_true',
134 - )
135 - );
136 -
137 - }
138 -
139 - /**
140 - * Tags the subscriber, if:
141 - * - a subscriber ID exists in the cookie or URL,
142 - * - the WordPress Page has the "Add a Tag" setting specified
143 - *
144 - * @since 2.4.9.1
145 - */
146 - public function maybe_tag_subscriber() {
147 -
148 - // Bail if not a singular Post Type supported by ConvertKit.
149 - if ( ! is_singular( convertkit_get_supported_post_types() ) ) {
150 - return;
151 - }
152 -
153 - // Get Post ID.
154 - $post_id = get_the_ID();
155 -
156 - // Bail if a Post ID couldn't be identified.
157 - if ( ! $post_id ) {
158 - return;
159 - }
160 -
161 - // Get Settings, if they have not yet been loaded.
162 - if ( ! $this->settings ) {
163 - $this->settings = new ConvertKit_Settings();
164 - }
165 -
166 - // Bail if the API hasn't been configured.
167 - if ( ! $this->settings->has_access_and_refresh_token() ) {
168 - return;
169 - }
170 -
171 - // Get ConvertKit Post's Settings, if they have not yet been loaded.
172 - if ( ! $this->post_settings ) {
173 - $this->post_settings = new ConvertKit_Post( $post_id );
174 - }
175 -
176 - // Bail if no "Add a Tag" setting specified for this Page.
177 - if ( ! $this->post_settings->has_tag() ) {
178 - return;
179 - }
180 -
181 - // Get subscriber ID from URL or cookie.
182 - $this->get_subscriber_id_from_request();
183 -
184 - // Bail if no subscriber ID detected.
185 - if ( ! $this->subscriber_id ) {
186 - return;
187 - }
188 -
189 - // Initialize the API.
190 - $api = new ConvertKit_API_V4(
191 - CONVERTKIT_OAUTH_CLIENT_ID,
192 - CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI,
193 - $this->settings->get_access_token(),
194 - $this->settings->get_refresh_token(),
195 - $this->settings->debug_enabled(),
196 - 'output'
197 - );
198 -
199 - // If the subscriber ID is not numeric, it's a cryptographically-signed subscriber ID, set
200 - // when using the Member Content functionality by Kit's API.
201 - // Fetch the underlying subscriber ID for the tag_subscriber() method.
202 - if ( ! is_numeric( $this->subscriber_id ) ) {
203 - $result = $api->profile( $this->subscriber_id );
204 -
205 - // If an error occurred, the subscriber ID is invalid.
206 - if ( is_wp_error( $result ) ) {
207 - return;
208 - }
209 -
210 - // Set the subscriber ID.
211 - $this->subscriber_id = $result['id'];
212 - }
213 -
214 - // Tag subscriber.
215 - $api->tag_subscriber( $this->post_settings->get_tag(), $this->subscriber_id );
216 -
217 - }
218 -
219 - /**
220 81 * Runs the `convertkit_output_output_form` action for singular Post Types that don't use the_content()
221 82 * or apply_filters( 'the_content' ) to output a ConvertKit Form.
222 83 *
223 84 * @since 1.9.6
@@ -291,9 +152,9 @@
291 152
292 153 // Get Landing Page.
293 154 $landing_page = $this->landing_pages->get_html( $this->post_settings->get_landing_page() );
294 155
295 - // Bail if an error occurred.
156 + // Bail if an error occured.
296 157 if ( is_wp_error( $landing_page ) ) {
297 158 return;
298 159 }
299 160
@@ -322,9 +183,9 @@
322 183
323 184 }
324 185
325 186 /**
326 - * Inserts a form to the singular Page, Post or Custom Post Type's Content.
187 + * Appends a form to the singular Page, Post or Custom Post Type's Content.
327 188 *
328 189 * @param string $content Post Content.
329 190 * @return string Post Content with Form Appended, if applicable
330 191 */
@@ -334,17 +195,10 @@
334 195 if ( ! is_singular( convertkit_get_supported_post_types() ) ) {
335 196 return $content;
336 197 }
337 198
338 - // Get Post ID.
199 + // Get Post ID and ConvertKit Form ID for the Post.
339 200 $post_id = get_the_ID();
340 -
341 - // Bail if Post Type is not supported by Kit.
342 - if ( ! in_array( get_post_type( $post_id ), convertkit_get_supported_post_types(), true ) ) {
343 - return $content;
344 - }
345 -
346 - // Get Form ID for the Post.
347 201 $form_id = $this->get_post_form_id( $post_id );
348 202
349 203 /**
350 204 * Define the ConvertKit Form ID to display for the given Post ID,
@@ -369,17 +223,17 @@
369 223 $this->forms = new ConvertKit_Resource_Forms( 'output_form' );
370 224 }
371 225
372 226 // Get Form HTML.
373 - $form = $this->forms->get_html( $form_id, $post_id );
227 + $form = $this->forms->get_html( $form_id );
374 228
375 - // If an error occurred, it could be because the specified Form ID for the Post either:
229 + // If an error occured, it could be because the specified Form ID for the Post either:
376 230 // - belongs to another ConvertKit account (i.e. API credentials were changed in the Plugin, but this Post's specified Form was not changed), or
377 231 // - the form was deleted from the ConvertKit account.
378 232 // Attempt to fallback to the default form for this Post Type.
379 233 if ( is_wp_error( $form ) ) {
380 234 if ( $this->settings->debug_enabled() ) {
381 - $content .= '<!-- Kit append_form_to_content(): ' . $form->get_error_message() . ' Attempting fallback to Default Form. -->';
235 + $content .= '<!-- ConvertKit append_form_to_content(): ' . $form->get_error_message() . ' Attempting fallback to Default Form. -->';
382 236 }
383 237
384 238 // Get Default Form ID for this Post's Type.
385 239 $form_id = $this->settings->get_default_form( get_post_type( $post_id ) );
@@ -386,9 +240,9 @@
386 240
387 241 // If no Default Form is specified, just return the Post Content, unedited.
388 242 if ( ! $form_id ) {
389 243 if ( $this->settings->debug_enabled() ) {
390 - $content .= '<!-- Kit append_form_to_content(): No Default Form exists as a fallback. -->';
244 + $content .= '<!-- ConvertKit append_form_to_content(): No Default Form exists as a fallback. -->';
391 245 }
392 246
393 247 return $content;
394 248 }
@@ -393,15 +247,15 @@
393 247 return $content;
394 248 }
395 249
396 250 // Get Form HTML.
397 - $form = $this->forms->get_html( $form_id, $post_id );
251 + $form = $this->forms->get_html( $form_id );
398 252
399 - // If an error occurred again, the default form doesn't exist in this ConvertKit account.
253 + // If an error occured again, the default form doesn't exist in this ConvertKit account.
400 254 // Just return the Post Content, unedited.
401 255 if ( is_wp_error( $form ) ) {
402 256 if ( $this->settings->debug_enabled() ) {
403 - $content .= '<!-- Kit append_form_to_content(): Default Form: ' . $form->get_error_message() . ' -->';
257 + $content .= '<!-- ConvertKit append_form_to_content(): Default Form: ' . $form->get_error_message() . ' -->';
404 258 }
405 259
406 260 return $content;
407 261 }
@@ -406,70 +260,23 @@
406 260 return $content;
407 261 }
408 262 }
409 263
410 - // If the Form HTML is empty, it's a modal form that has been set to load in the footer of the site.
411 - // We don't need to append anything to the content.
412 - if ( empty( $form ) ) {
413 - if ( $this->settings->debug_enabled() ) {
414 - $content .= '<!-- Kit append_form_to_content(): Form is non-inline, appended to footer. -->';
415 - }
416 -
417 - return $content;
418 - }
419 -
420 264 // If here, we have a ConvertKit Form.
421 - // Append form to Post's Content, based on the position setting.
422 - $form_position = $this->settings->get_default_form_position( get_post_type( $post_id ) );
265 + // Append form to Post's Content.
266 + $content = $content .= $form;
423 267
424 - if ( $this->settings->debug_enabled() ) {
425 - $content .= '<!-- Kit append_form_to_content(): Form Position: ' . esc_html( $form_position ) . ' -->';
426 - }
427 -
428 - switch ( $form_position ) {
429 - case 'before_after_content':
430 - $content = $form . $content . $form;
431 - break;
432 -
433 - case 'before_content':
434 - $content = $form . $content;
435 - break;
436 -
437 - case 'after_element':
438 - $element = $this->settings->get_default_form_position_element( get_post_type( $post_id ) );
439 - $index = $this->settings->get_default_form_position_element_index( get_post_type( $post_id ) );
440 -
441 - // Check if DOMDocument is installed.
442 - // It should be installed as mosts hosts include php-dom and php-xml modules.
443 - // If not, fallback to using preg_match_all(), which is less reliable.
444 - if ( ! class_exists( 'DOMDocument' ) ) {
445 - $content = $this->inject_form_after_element_fallback( $content, $element, $index, $form );
446 - break;
447 - }
448 -
449 - // Use DOMDocument.
450 - $content = $this->inject_form_after_element( $content, $element, $index, $form );
451 - break;
452 -
453 - case 'after_content':
454 - default:
455 - // Default behaviour < 2.5.8 was to append the Form after the content.
456 - $content .= $form;
457 - break;
458 - }
459 -
460 268 /**
461 269 * Filter the Post's Content, which includes a ConvertKit Form, immediately before it is output.
462 270 *
463 271 * @since 1.9.6
464 272 *
465 - * @param string $content Post Content
466 - * @param string $form ConvertKit Form HTML
467 - * @param int $post_id Post ID
468 - * @param int $form_id ConvertKit Form ID
469 - * @param string $form_position Form Position setting for the Post's Type.
273 + * @param string $content Post Content
274 + * @param string $form ConvertKit Form HTML
275 + * @param int $post_id Post ID
276 + * @param int $form_id ConvertKit Form ID
470 277 */
471 - $content = apply_filters( 'convertkit_frontend_append_form', $content, $form, $post_id, $form_id, $form_position );
278 + $content = apply_filters( 'convertkit_frontend_append_form', $content, $form, $post_id, $form_id );
472 279
473 280 return $content;
474 281
475 282 }
@@ -474,219 +281,8 @@
474 281
475 282 }
476 283
477 284 /**
478 - * Injects the form after the given element and index, using DOMDocument.
479 - *
480 - * @since 2.6.2
481 - *
482 - * @param string $content Page / Post Content.
483 - * @param string $tag HTML tag to insert form after.
484 - * @param int $index Number of $tag elements to find before inserting form.
485 - * @param string $form Form HTML to inject.
486 - * @return string
487 - */
488 - private function inject_form_after_element( $content, $tag, $index, $form ) {
489 -
490 - // If the form is empty, don't inject anything.
491 - if ( empty( $form ) ) {
492 - return $content;
493 - }
494 -
495 - // Load the content into the parser.
496 - $parser = new ConvertKit_HTML_Parser( $content, LIBXML_HTML_NODEFDTD );
497 -
498 - // Find the element to append the form to.
499 - // item() is a zero based index.
500 - $element_node = $parser->html->getElementsByTagName( $tag )->item( $index - 1 );
501 -
502 - // If the element could not be found, either the number of elements by tag name is less
503 - // than the requested position the form be inserted in, or no element exists.
504 - // Append the form to the original content and return.
505 - if ( is_null( $element_node ) ) {
506 - return $content . $form;
507 - }
508 -
509 - // Load the form into the parser.
510 - $form_parser = new ConvertKit_HTML_Parser( $form, LIBXML_HTML_NODEFDTD );
511 - $form_body = $form_parser->html->getElementsByTagName( 'body' )->item( 0 );
512 -
513 - // Collect nodes first to avoid live NodeList mutation issues.
514 - $nodes_to_insert = array();
515 - foreach ( $form_body->childNodes as $child ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
516 - $nodes_to_insert[] = $parser->html->importNode( $child, true );
517 - }
518 -
519 - // Inject the form node(s) after the element node e.g. after the paragraph, heading etc.
520 - $next_sibling = $element_node->nextSibling; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
521 - foreach ( $nodes_to_insert as $node ) {
522 - $element_node->parentNode->insertBefore( $node, $element_node->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
523 - }
524 -
525 - // Return modified HTML string.
526 - return $parser->get_body_html();
527 -
528 - }
529 -
530 - /**
531 - * Injects the form after the given element and index, using preg_match_all().
532 - * This is less reliable than DOMDocument, and is called if DOMDocument is
533 - * not installed on the server.
534 - *
535 - * @since 2.6.2
536 - *
537 - * @param string $content Page / Post Content.
538 - * @param string $tag HTML tag to insert form after.
539 - * @param int $index Number of $tag elements to find before inserting form.
540 - * @param string $form Form HTML to inject.
541 - * @return string
542 - */
543 - private function inject_form_after_element_fallback( $content, $tag, $index, $form ) {
544 -
545 - // If the form is empty, don't inject anything.
546 - if ( empty( $form ) ) {
547 - return $content;
548 - }
549 -
550 - // Calculate tag length.
551 - $tag_length = ( strlen( $tag ) + 3 );
552 -
553 - // Find all closing elements.
554 - preg_match_all( '/<\/' . $tag . '>/', $content, $matches );
555 -
556 - // If no elements exist, just append the form.
557 - if ( count( $matches[0] ) === 0 ) {
558 - $content = $content . $form;
559 - return $content;
560 - }
561 -
562 - // If the number of elements is less than the index, we don't have enough elements to add the form to.
563 - // Just add the form after the content.
564 - if ( count( $matches[0] ) <= $index ) {
565 - $content = $content . $form;
566 - return $content;
567 - }
568 -
569 - // Iterate through the content to find the element at the configured index e.g. find the 4th closing paragraph.
570 - $offset = 0;
571 - foreach ( $matches[0] as $element_index => $element ) {
572 - $position = strpos( $content, $element, $offset );
573 - if ( ( $element_index + 1 ) === $index ) {
574 - return substr( $content, 0, $position + 4 ) . $form . substr( $content, $position + 4 );
575 - }
576 -
577 - // Increment offset.
578 - $offset = $position + 1;
579 - }
580 -
581 - // If here, something went wrong.
582 - // Just add the form after the content.
583 - $content = $content . $form;
584 - return $content;
585 -
586 - }
587 -
588 - /**
589 - * Registers the ConvertKit Form block to before or after the Query Loop block, when viewing a Category archive.
590 - *
591 - * See append_form_block_on_category_archive() configures the block to display the applicable category's Form.
592 - *
593 - * @since 2.4.9.1
594 - *
595 - * @param array $hooked_blocks The list of hooked block types.
596 - * @param string $position The relative position of the hooked blocks.
597 - * @param string $anchor_block The anchor block type.
598 - * @param WP_Block_Template|WP_Post|array $context The block template, template part, wp_navigation post type, or pattern that the anchor block belongs to.
599 - * @return array
600 - */
601 - public function maybe_register_form_block_on_category_archive( $hooked_blocks, $position, $anchor_block, $context ) {
602 -
603 - // Don't append if we're not viewing a category archive.
604 - if ( ! is_category() ) {
605 - return $hooked_blocks;
606 - }
607 -
608 - if ( $context instanceof WP_Block_Template && $context->slug !== 'archive' ) {
609 - return $hooked_blocks;
610 - }
611 -
612 - // Don't append if the anchor block isn't the Query Loop block.
613 - if ( $anchor_block !== 'core/query' ) {
614 - return $hooked_blocks;
615 - }
616 -
617 - // Don't append if the Category's form position setting is not defined.
618 - $form_position = $this->get_term_form_position();
619 - if ( ! $form_position ) {
620 - // Unhook this function as we don't need to check again in this request, as we'll
621 - // never output a form on the Category archive.
622 - remove_filter( 'hooked_block_types', array( $this, 'maybe_register_form_block_on_category_archive' ), 10 );
623 -
624 - return $hooked_blocks;
625 - }
626 -
627 - // Don't append if the position doesn't match.
628 - if ( $form_position !== $position ) {
629 - return $hooked_blocks;
630 - }
631 -
632 - // Hook the ConvertKit Form block.
633 - $hooked_blocks[] = 'convertkit/form';
634 -
635 - // Unhook this function as we don't need to check again in this request, as
636 - // we have now appended the form.
637 - remove_filter( 'hooked_block_types', array( $this, 'maybe_register_form_block_on_category_archive' ), 10 );
638 -
639 - return $hooked_blocks;
640 -
641 - }
642 -
643 - /**
644 - * Configures the ConvertKit Form block that was hooked below the Query Loop block by maybe_register_form_block_on_category_archive,
645 - * defining the Form ID based on the current Category's Form ID.
646 - *
647 - * @since 2.4.9.1
648 - *
649 - * @param array $parsed_hooked_block The parsed block array for the given hooked block type, or null to suppress the block.
650 - * @return null|array
651 - */
652 - public function append_form_block_to_category_archive( $parsed_hooked_block ) {
653 -
654 - // Sanity check that we're still viewing a Category archive.
655 - if ( ! is_category() ) {
656 - // Returning null will unregister the Form block from displaying.
657 - return null;
658 - }
659 -
660 - // Get Category archive being viewed.
661 - $category = get_category( get_query_var( 'cat' ) );
662 -
663 - // Bail if the Category could be found.
664 - if ( is_wp_error( $category ) || is_null( $category ) ) {
665 - // Returning null will unregister the Form block from displaying.
666 - return null;
667 - }
668 -
669 - // Load Term Settings.
670 - $term_settings = new ConvertKit_Term( $category->term_id );
671 -
672 - // Bail if no Form specified for the Category.
673 - if ( ! $term_settings->has_form() ) {
674 - // Returning null will unregister the Form block from displaying.
675 - return null;
676 - }
677 -
678 - // Define the form block attributes to display the given Form ID.
679 - $parsed_hooked_block['attrs'] = array(
680 - 'id' => absint( $term_settings->get_form() ),
681 - );
682 -
683 - // Return the Form block with its attributes.
684 - return $parsed_hooked_block;
685 -
686 - }
687 -
688 - /**
689 285 * Returns the Post, Category or Plugin ConvertKit Form ID for the given Post.
690 286 *
691 287 * If the Post specifies a form to use, returns that Form ID.
692 288 * If the Post uses the 'Default' setting, and an assigned Category has a Form ID, uses the Category's Form ID.
@@ -752,53 +348,16 @@
752 348 // If a Form ID exists, return it now.
753 349 if ( $term_settings->has_form() ) {
754 350 return $term_settings->get_form();
755 351 }
756 -
757 - // If the Term specifies that no Form should be used, return false.
758 - if ( $term_settings->uses_no_form() ) {
759 - return false;
760 - }
761 352 }
762 353
763 - // If here, all Terms were set to display the Default Form.
764 - // Therefore use the Plugin's Default Form.
354 + // If here, use the Plugin's Default Form.
765 355 return $this->settings->get_default_form( get_post_type( $post_id ) );
766 356
767 357 }
768 358
769 359 /**
770 - * Returns the Form Position setting for the currently viewed Category.
771 - *
772 - * @since 2.4.9.1
773 - *
774 - * @return bool|string
775 - */
776 - private function get_term_form_position() {
777 -
778 - // Get Category archive being viewed.
779 - $category = get_category( get_query_var( 'cat' ) );
780 -
781 - // Bail if the Category could be found.
782 - if ( is_wp_error( $category ) || is_null( $category ) ) {
783 - return false;
784 - }
785 -
786 - // Load Term Settings.
787 - $term_settings = new ConvertKit_Term( $category->term_id );
788 -
789 - // Return false if no form position is defined i.e. we don't want to display
790 - // it on the Category archive.
791 - if ( ! $term_settings->has_form_position() ) {
792 - return false;
793 - }
794 -
795 - // Return form position.
796 - return $term_settings->get_form_position();
797 -
798 - }
799 -
800 - /**
801 360 * Enqueue scripts.
802 361 *
803 362 * @since 1.9.6
804 363 */
@@ -803,31 +362,49 @@
803 362 * @since 1.9.6
804 363 */
805 364 public function enqueue_scripts() {
806 365
807 - // Get ConvertKit Settings and Post's Settings.
808 - $settings = new ConvertKit_Settings();
366 + // Get Post.
367 + $post = get_post();
809 368
810 - // Bail if the no scripts setting is enabled.
811 - if ( $settings->scripts_disabled() ) {
369 + // Bail if no Post could be fetched.
370 + if ( ! $post ) {
812 371 return;
813 372 }
814 373
815 - // Enqueue frontend JS.
816 - convertkit_enqueue_frontend_js();
374 + // Get ConvertKit Settings and Post's Settings.
375 + $settings = new ConvertKit_Settings();
376 + $convertkit_post = new ConvertKit_Post( $post->ID );
817 377
818 - // Define variables.
378 + // Register scripts that we might use.
379 + wp_register_script(
380 + 'convertkit-js',
381 + CONVERTKIT_PLUGIN_URL . 'resources/frontend/js/convertkit.js',
382 + array(),
383 + CONVERTKIT_PLUGIN_VERSION,
384 + true
385 + );
819 386 wp_localize_script(
820 387 'convertkit-js',
821 388 'convertkit',
822 389 array(
823 - 'ajaxurl' => rest_url( 'kit/v1/subscriber/store-email-as-id-in-cookie' ),
390 + 'ajaxurl' => admin_url( 'admin-ajax.php' ),
824 391 'debug' => $settings->debug_enabled(),
825 - 'nonce' => wp_create_nonce( 'wp_rest' ),
392 + 'nonce' => wp_create_nonce( 'convertkit' ),
826 393 'subscriber_id' => $this->subscriber_id,
394 + 'tag' => ( ( is_singular() && $convertkit_post->has_tag() ) ? $convertkit_post->get_tag() : false ),
395 + 'post_id' => $post->ID,
827 396 )
828 397 );
829 398
399 + // Bail if the no scripts setting is enabled.
400 + if ( $settings->scripts_disabled() ) {
401 + return;
402 + }
403 +
404 + // Enqueue.
405 + wp_enqueue_script( 'convertkit-js' );
406 +
830 407 }
831 408
832 409 /**
833 410 * Gets the subscriber ID from the request (either the cookie or the URL).
@@ -839,9 +416,9 @@
839 416 // Use ConvertKit_Subscriber class to fetch and validate the subscriber ID.
840 417 $subscriber = new ConvertKit_Subscriber();
841 418 $subscriber_id = $subscriber->get_subscriber_id();
842 419
843 - // If an error occurred, the subscriber ID in the request/cookie is not a valid subscriber.
420 + // If an error occured, the subscriber ID in the request/cookie is not a valid subscriber.
844 421 if ( is_wp_error( $subscriber_id ) ) {
845 422 return;
846 423 }
847 424
@@ -849,10 +426,10 @@
849 426
850 427 }
851 428
852 429 /**
853 - * Outputs a non-inline forms if defined in the Plugin's settings >
854 - * Default Forms (Site Wide) setting.
430 + * Outputs a non-inline form if defined in the Plugin's settings >
431 + * Default Non-Inline Form (Global) setting.
855 432 *
856 433 * @since 2.3.3
857 434 */
858 435 public function output_global_non_inline_form() {
@@ -866,48 +443,33 @@
866 443 if ( ! $this->settings->has_non_inline_form() ) {
867 444 return;
868 445 }
869 446
870 - // Bail if the Page, Post or Custom Post Type's Form setting is set to 'None'
871 - // and the Plugin is set to honor this setting.
872 - if ( $this->post_settings !== false && $this->post_settings->uses_no_form() && $this->settings->non_inline_form_honor_none_setting() ) {
447 + // Get form.
448 + $convertkit_forms = new ConvertKit_Resource_Forms();
449 + $form = $convertkit_forms->get_by_id( (int) $this->settings->get_non_inline_form() );
450 +
451 + // Bail if the Form doesn't exist (this shouldn't happen, but you never know).
452 + if ( ! $form ) {
873 453 return;
874 454 }
875 455
876 - // Determine if the Non-inline Form Limit per Session setting is enabled.
877 - $limit_per_session = $this->settings->non_inline_form_limit_per_session();
456 + // Add the form to the scripts array so it is included in the output.
457 + add_filter(
458 + 'convertkit_output_scripts_footer',
459 + function ( $scripts ) use ( $form ) {
878 460
879 - // Get form.
880 - $convertkit_forms = new ConvertKit_Resource_Forms();
461 + $scripts[] = array(
462 + 'async' => true,
463 + 'data-uid' => $form['uid'],
464 + 'src' => $form['embed_js'],
465 + );
881 466
882 - // Iterate through forms.
883 - foreach ( $this->settings->get_non_inline_form() as $form_id ) {
884 - // Get Form.
885 - $form = $convertkit_forms->get_by_id( (int) $form_id );
467 + return $scripts;
886 468
887 - // Bail if the Form doesn't exist (this shouldn't happen, but you never know).
888 - if ( ! $form ) {
889 - continue;
890 469 }
470 + );
891 471
892 - // Add the form to the scripts array so it is included in the output.
893 - add_filter(
894 - 'convertkit_output_scripts_footer',
895 - function ( $scripts ) use ( $form, $limit_per_session ) {
896 -
897 - $scripts[] = array(
898 - 'async' => true,
899 - 'data-uid' => $form['uid'],
900 - 'src' => $form['embed_js'],
901 - 'data-kit-limit-per-session' => $limit_per_session ? '1' : '0',
902 - );
903 -
904 - return $scripts;
905 -
906 - }
907 - );
908 - }
909 -
910 472 }
911 473
912 474 /**
913 475 * Outputs any JS <script> tags registered with the convertkit_output_scripts_footer
@@ -916,13 +478,8 @@
916 478 * @since 2.1.4
917 479 */
918 480 public function output_scripts_footer() {
919 481
920 - // Don't output scripts if the request is for a search page or 404.
921 - if ( is_search() || is_404() ) {
922 - return;
923 - }
924 -
925 482 // Define array of scripts.
926 483 $scripts = array();
927 484
928 485 /**
@@ -952,13 +509,8 @@
952 509 * @param array $script Form script key/value pairs to output as <script> tag.
953 510 */
954 511 $script = apply_filters( 'convertkit_output_script_footer', $script );
955 512
956 - // Skip script if it is limited by the Non-inline Form Limit per Session setting.
957 - if ( $this->is_script_output_limited_by_session( $script ) ) {
958 - continue;
959 - }
960 -
961 513 // Build output.
962 514 $output = '<script';
963 515 foreach ( $script as $attribute => $value ) {
964 516 // If the value is true, just output the attribute.
@@ -995,38 +547,8 @@
995 547 // Output scripts.
996 548 foreach ( $output_scripts as $output_script ) {
997 549 echo $output_script . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
998 550 }
999 -
1000 - }
1001 -
1002 - /**
1003 - * Checks if a script is limited by the Non-inline Form Limit per Session setting.
1004 - *
1005 - * @since 3.0.0
1006 - *
1007 - * @param array $script Script.
1008 - * @return bool
1009 - */
1010 - private function is_script_output_limited_by_session( $script ) {
1011 -
1012 - // Get Settings, if they have not yet been loaded.
1013 - if ( ! $this->settings ) {
1014 - $this->settings = new ConvertKit_Settings();
1015 - }
1016 -
1017 - // Display script if the "Display Limit" setting isn't enabled.
1018 - if ( ! $this->settings->non_inline_form_limit_per_session() ) {
1019 - return false;
1020 - }
1021 -
1022 - // Display script if the "Display Limit" setting should not be applied to this script.
1023 - if ( ! isset( $script['data-kit-limit-per-session'] ) ) {
1024 - return false;
1025 - }
1026 -
1027 - // Display script if this is the first time the visitor has seen any non-inline form.
1028 - return isset( $_COOKIE['ck_non_inline_form_displayed'] );
1029 551
1030 552 }
1031 553
1032 554 }