From cafe7c5785b011037dfae16ec6ebdc5bbf2214b5 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 18:29:42 +0800 Subject: [PATCH 01/24] Blocks: Use `get_block_wrapper_attributes` --- .../class-convertkit-block-broadcasts.php | 36 +++-- .../class-convertkit-block-form-trigger.php | 25 +++- .../blocks/class-convertkit-block-product.php | 17 ++- includes/blocks/class-convertkit-block.php | 131 +++++++++--------- .../class-convertkit-resource-products.php | 2 +- 5 files changed, 125 insertions(+), 86 deletions(-) diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index f441f0d12..d134c6f9a 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -441,10 +441,17 @@ public function get_default_values() { * * @since 1.9.7.4 * - * @param array $atts Block / Shortcode Attributes. - * @return string Output + * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param string $content Shortcode Content. + * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. + * @return string */ - public function render( $atts ) { + public function render( $atts, $content, $block_or_shortcode = false ) { + + // Gutenberg blocks pass $block_or_shortcode as a WP_Block. + // Shortcodes pass $block_or_shortcode as a string of the shortcode name. + // Page Builders: Let's find out! + $is_block = ( $block_or_shortcode instanceof WP_Block ); // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -473,17 +480,24 @@ public function render( $atts ) { } // Build HTML. - $html = $this->build_html( $posts, $atts ); + $html = $this->build_html( + $posts, + $atts, + true, + $this->get_css_classes(), + ( ! $is_block ? $this->get_css_styles( $atts ) : array() ) + ); /** * Filter the block's content immediately before it is output. * * @since 1.9.7.4 * - * @param string $html ConvertKit Broadcasts HTML. - * @param array $atts Block Attributes. + * @param string $html ConvertKit Broadcasts HTML. + * @param array $atts Block Attributes. + * @param bool $is_block Whether this is a Gutenberg block (false for shortcodes and page builders). */ - $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts ); + $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts, $is_block ); return $html; @@ -550,9 +564,11 @@ public function render_ajax() { * @param ConvertKit_Resource_Posts $posts ConvertKit Posts Resource class. * @param array $atts Block attributes. * @param bool $include_container Include container div in HTML. - * @return string HTML + * @param array $css_classes CSS classes to apply to block. + * @param array $css_styles CSS inline styles to apply to block. + * @return string */ - private function build_html( $posts, $atts, $include_container = true ) { + private function build_html( $posts, $atts, $include_container = true, $css_classes = array(), $css_styles = array() ) { // Get paginated subset of Posts. $broadcasts = $posts->get_paginated_subset( $atts['page'], $atts['limit'] ); @@ -565,7 +581,7 @@ private function build_html( $posts, $atts, $include_container = true ) { // Include container, if required. if ( $include_container ) { - $html .= '
get_atts_as_html_data_attributes( $atts ) . '>'; + $html .= '
get_atts_as_html_data_attributes( $atts ) . '>'; } // Start list. diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 8851e3935..ed9a0c3c1 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -363,10 +363,17 @@ public function get_default_values() { * * @since 2.2.0 * - * @param array $atts Block / Shortcode Attributes. - * @return string Output + * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param string $content Shortcode Content. + * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. + * @return string */ - public function render( $atts ) { + public function render( $atts, $content, $block_or_shortcode = false ) { + + // Gutenberg blocks pass $block_or_shortcode as a WP_Block. + // Shortcodes pass $block_or_shortcode as a string of the shortcode name. + // Page Builders: Let's find out! + $is_block = ( $block_or_shortcode instanceof WP_Block ); // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -376,7 +383,13 @@ public function render( $atts ) { $settings = new ConvertKit_Settings(); // Build HTML. - $html = $this->get_html( $atts['form'], $atts['text'], $atts['_css_classes'], $atts['_css_styles'], $this->is_block_editor_request() ); + $html = $this->get_html( + $atts['form'], + $atts['text'], + $this->get_css_classes(), + ( ! $is_block ? $this->get_css_styles( $atts ) : array() ), + $this->is_block_editor_request() + ); // Bail if an error occured. if ( is_wp_error( $html ) ) { @@ -409,7 +422,7 @@ public function render( $atts ) { * @param int $id Form ID. * @param string $button_text Button Text. * @param array $css_classes CSS classes to apply to link (typically included when using Gutenberg). - * @param array $css_styles CSS inline styles to apply to link (typically included when using Gutenberg). + * @param array $css_styles CSS inline styles to apply to link (typically included when using Shortcode or third party page builder module / widget). * @param bool $return_as_span If true, returns a instead of . Useful for the block editor so that the element is interactible. * @return WP_Error|string Button HTML */ @@ -467,7 +480,7 @@ private function get_html( $id, $button_text, $css_classes = array(), $css_style $html .= ''; + $html .= ' class="' . implode( ' ', map_deep( $css_classes, 'sanitize_html_class' ) ) . '" style="' . implode( ';', map_deep( $css_styles, 'esc_attr' ) ) . '">'; $html .= esc_html( $button_text ); if ( $return_as_span ) { diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index d64482d9a..3a1bfcead 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -414,10 +414,17 @@ public function get_default_values() { * * @since 1.9.8.5 * - * @param array $atts Block / Shortcode Attributes. - * @return string Output + * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param string $content Shortcode Content. + * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. + * @return string */ - public function render( $atts ) { + public function render( $atts, $content = '', $block_or_shortcode = false ) { + + // Gutenberg blocks pass $block_or_shortcode as a WP_Block. + // Shortcodes pass $block_or_shortcode as a string of the shortcode name. + // Page Builders: Let's find out! + $is_block = ( $block_or_shortcode instanceof WP_Block ); // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -437,8 +444,8 @@ public function render( $atts ) { 'discount_code' => $atts['discount_code'], 'checkout' => $atts['checkout'], 'disable_modal' => ( $atts['disable_modal_on_mobile'] && wp_is_mobile() ), - 'css_classes' => $atts['_css_classes'], - 'css_styles' => $atts['_css_styles'], + 'css_classes' => $this->get_css_classes(), + 'css_styles' => ! $is_block ? $this->get_css_styles( $atts ) : array(), 'return_as_span' => $this->is_block_editor_request(), ) ); diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index 1762b09ab..0a72f6f02 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -220,69 +220,8 @@ public function sanitize_and_declare_atts( $atts ) { } } - // Build CSS class(es) that might need to be added to the top level element for this block. - $atts['_css_classes'] = array( 'convertkit-' . $this->get_name() ); - $atts['_css_styles'] = array(); - - // If the block supports a text color, and a preset color was selected, add it to the - // array of CSS classes. - if ( $atts['textColor'] ) { - $atts['_css_classes'][] = 'has-text-color'; - $atts['_css_classes'][] = 'has-' . $atts['textColor'] . '-color'; - } - - // If the block supports a text color, and a custom hex color was selected, add it to the - // array of CSS inline styles. - if ( isset( $atts['style']['color'] ) && isset( $atts['style']['color']['text'] ) ) { - $atts['_css_classes'][] = 'has-text-color'; - $atts['_css_styles']['color'] = 'color:' . $atts['style']['color']['text']; - } - - // If the shortcode supports a text color, and a custom hex color was selected, add it to the - // array of CSS inline styles. - if ( isset( $atts['text_color'] ) && ! empty( $atts['text_color'] ) ) { - $atts['_css_classes'][] = 'has-text-color'; - $atts['_css_styles']['color'] = 'color:' . $atts['text_color']; - } - - // If the block supports a background color, and a preset color was selected, add it to the - // array of CSS classes. - if ( $atts['backgroundColor'] ) { - $atts['_css_classes'][] = 'has-background'; - $atts['_css_classes'][] = 'has-' . $atts['backgroundColor'] . '-background-color'; - } - - // If the block supports a background color, and a custom hex color was selected, add it to the - // array of CSS inline styles. - if ( isset( $atts['style']['color'] ) && isset( $atts['style']['color']['background'] ) ) { - $atts['_css_classes'][] = 'has-background'; - $atts['_css_styles']['background'] = 'background-color:' . $atts['style']['color']['background']; - } - - // If the block supports a font size, and a preset font size was selected, add it to the - // array of CSS classes. - if ( isset( $atts['fontSize'] ) && ! empty( $atts['fontSize'] ) ) { - $atts['_css_classes'][] = 'has-custom-font-size'; - $atts['_css_classes'][] = 'has-' . $atts['fontSize'] . '-font-size'; - } - - // If the block supports padding, and padding is set, add it to the - // array of CSS inline styles. - if ( isset( $atts['style']['spacing'] ) && isset( $atts['style']['spacing']['padding'] ) ) { - foreach ( $atts['style']['spacing']['padding'] as $position => $value ) { - $atts['_css_styles'][ 'padding-' . $position ] = 'padding-' . $position . ':' . $value; - } - } - - // If the shortcode supports a background color, and a custom hex color was selected, add it to the - // array of CSS inline styles. - if ( isset( $atts['background_color'] ) && ! empty( $atts['background_color'] ) ) { - $atts['_css_classes'][] = 'has-background'; - $atts['_css_styles']['background'] = 'background-color:' . $atts['background_color']; - } - // Remove some unused attributes, now they're declared above. - unset( $atts['style'] ); + unset( $atts['style'], $atts['backgroundColor'], $atts['textColor'], $atts['className'] ); return $atts; @@ -295,7 +234,7 @@ public function sanitize_and_declare_atts( $atts ) { * @since 1.9.6 * * @param array $atts Block or shortcode attributes. - * @return array Block or shortcode attributes + * @return array */ public function sanitize_atts( $atts ) { @@ -311,6 +250,71 @@ public function sanitize_atts( $atts ) { } + /** + * Builds CSS class(es) that might need to be added to the top level element's `class` attribute + * when using Gutenberg, to honor the block's styles and layout settings. + * + * @since 2.8.3 + * + * @return array + */ + public function get_css_classes() { + + // Get the block wrapper attributes string. + $wrapper_attributes = get_block_wrapper_attributes( + array( + 'class' => 'convertkit-' . $this->get_name(), + ) + ); + + // Extract the class attribute from the wrapper attributes string, returning as an array. + // Extract just the class attribute value from the wrapper attributes string. + $classes = array(); + if ( preg_match( '/class="([^"]*)"/', $wrapper_attributes, $matches ) ) { + return explode( ' ', $matches[1] ); + } + + // No class attribute exists for this block. + // Just return the block's name as the class. + return array( + 'convertkit-' . $this->get_name(), + ); + + } + + /** + * Builds inline CSS style(s) that might need to be added to the top level element's `style` attribute + * when using a shortcode or third party page builder module / widget. + * Gutenberg will automatically build these styles for the block using get_block_wrapper_attributes(). + * + * @since 2.8.3 + * + * @param array $atts Block or shortcode attributes. + * @return array + */ + public function get_css_styles( $atts ) { + + // Build inline CSS style(s) that might need to be added to the top level element when using a shortcode + // or third party page builder module / widget. + // Gutenberg will automatically build these styles for the block using get_block_wrapper_attributes(). + $styles = array(); + + // If the shortcode supports a text color, and a custom hex color was selected, add it to the + // array of CSS inline styles. + if ( isset( $atts['text_color'] ) && ! empty( $atts['text_color'] ) ) { + $styles['color'] = 'color:' . $atts['text_color']; + } + + // If the shortcode supports a background color, and a custom hex color was selected, add it to the + // array of CSS inline styles. + if ( isset( $atts['background_color'] ) && ! empty( $atts['background_color'] ) ) { + $styles['background'] = 'background-color:' . $atts['background_color']; + } + + return $styles; + + } + /** * Returns the given block / shortcode attributes array as HTML data-* attributes, which can be output * in a block's container. @@ -327,7 +331,6 @@ public function get_atts_as_html_data_attributes( $atts ) { $skip_keys = array( 'backgroundColor', 'textColor', - '_css_classes', '_css_styles', ); diff --git a/includes/class-convertkit-resource-products.php b/includes/class-convertkit-resource-products.php index ce618d246..37ea22d0c 100644 --- a/includes/class-convertkit-resource-products.php +++ b/includes/class-convertkit-resource-products.php @@ -177,7 +177,7 @@ public function get_html( $id, $button_text, $options = false ) { } $html .= sprintf( - ' class="wp-block-button__link %s" style="%s"%s>', + ' class="%s" style="%s"%s>', implode( ' ', map_deep( $options['css_classes'], 'sanitize_html_class' ) ), implode( ';', map_deep( $options['css_styles'], 'esc_attr' ) ), ( ! $options['disable_modal'] ? ' data-commerce' : '' ) From 6e51be47ea456cc1f2ca143fc29cffe1c694c7ec Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 18:43:58 +0800 Subject: [PATCH 02/24] Strip unnecessary classes --- includes/blocks/class-convertkit-block.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index 0a72f6f02..4becdbee5 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -271,14 +271,17 @@ public function get_css_classes() { // Extract just the class attribute value from the wrapper attributes string. $classes = array(); if ( preg_match( '/class="([^"]*)"/', $wrapper_attributes, $matches ) ) { - return explode( ' ', $matches[1] ); + $classes = explode( ' ', $matches[1] ); + } else { + $classes = array( + 'convertkit-' . $this->get_name(), + ); } - // No class attribute exists for this block. - // Just return the block's name as the class. - return array( - 'convertkit-' . $this->get_name(), - ); + // Remove some classes WordPress adds that we don't want, as they break the layout. + $classes = array_diff( $classes, array( 'alignfull', 'wp-block-post-content' ) ); + + return $classes; } From 8e918fcdd694cf339ab9429d0ad53b4bcc19ddb0 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 20:30:15 +0800 Subject: [PATCH 03/24] Skip empty values on data-* attributes --- includes/blocks/class-convertkit-block.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index 4becdbee5..f828624ce 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -346,6 +346,11 @@ public function get_atts_as_html_data_attributes( $atts ) { continue; } + // Skip empty values. + if ( empty( $value ) ) { + continue; + } + // Append to data string, replacing underscores with hyphens in the key name. $data .= ' data-' . strtolower( str_replace( '_', '-', $key ) ) . '="' . esc_attr( $value ) . '"'; } From 9212867c9d485fad8b86bf3e24a7a3dabbc12f6b Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 20:30:33 +0800 Subject: [PATCH 04/24] Broadcasts: add padding when a background color is specified --- resources/frontend/css/broadcasts.css | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/frontend/css/broadcasts.css b/resources/frontend/css/broadcasts.css index fd6a5c185..e9de60188 100644 --- a/resources/frontend/css/broadcasts.css +++ b/resources/frontend/css/broadcasts.css @@ -1,4 +1,5 @@ .convertkit-broadcasts.has-background, +.convertkit-broadcasts[data-background-color], .editor-styles-wrapper .convertkit-broadcasts.has-background { padding: 20px; } From 9437a1fdfa7c03c50e3d57566860b76354ecacca Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 20:53:16 +0800 Subject: [PATCH 05/24] Make $content an optional parameter --- includes/blocks/class-convertkit-block-broadcasts.php | 2 +- includes/blocks/class-convertkit-block-form-trigger.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index d134c6f9a..aa5ba1eca 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -446,7 +446,7 @@ public function get_default_values() { * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. * @return string */ - public function render( $atts, $content, $block_or_shortcode = false ) { + public function render( $atts, $content = '', $block_or_shortcode = false ) { // Gutenberg blocks pass $block_or_shortcode as a WP_Block. // Shortcodes pass $block_or_shortcode as a string of the shortcode name. diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index ed9a0c3c1..8e310a1c0 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -368,7 +368,7 @@ public function get_default_values() { * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. * @return string */ - public function render( $atts, $content, $block_or_shortcode = false ) { + public function render( $atts, $content = '', $block_or_shortcode = false ) { // Gutenberg blocks pass $block_or_shortcode as a WP_Block. // Shortcodes pass $block_or_shortcode as a string of the shortcode name. From 292f4b9898113273f31fee5e017f8c7fb1b6a9e8 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 21:06:50 +0800 Subject: [PATCH 06/24] Bump minimum supported WordPress version to 5.6 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 852e9a0af..4c34e6eca 100755 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: nathanbarry, growdev, travisnorthcutt, ggwicz Donate link: https://kit.com Tags: email marketing, email newsletter, subscribers, landing page, membership -Requires at least: 5.0 +Requires at least: 5.6 Tested up to: 6.8 Requires PHP: 7.1 Stable tag: 2.8.2 From 04ebcede73dc109e16b45c2a99619e69f9db9d78 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 3 Jul 2025 22:30:07 +0800 Subject: [PATCH 07/24] Buttons: Set default classes to render buttons using theme colors when no text or background colors selected --- includes/blocks/class-convertkit-block-form-trigger.php | 2 +- includes/blocks/class-convertkit-block-product.php | 2 +- includes/blocks/class-convertkit-block.php | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 8e310a1c0..1c464f8ab 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -386,7 +386,7 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { $html = $this->get_html( $atts['form'], $atts['text'], - $this->get_css_classes(), + $this->get_css_classes( array( 'wp-block-button__link', 'wp-element-button' ) ), ( ! $is_block ? $this->get_css_styles( $atts ) : array() ), $this->is_block_editor_request() ); diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index 3a1bfcead..b58451ae8 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -444,7 +444,7 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { 'discount_code' => $atts['discount_code'], 'checkout' => $atts['checkout'], 'disable_modal' => ( $atts['disable_modal_on_mobile'] && wp_is_mobile() ), - 'css_classes' => $this->get_css_classes(), + 'css_classes' => $this->get_css_classes( array( 'wp-block-button__link', 'wp-element-button' ) ), 'css_styles' => ! $is_block ? $this->get_css_styles( $atts ) : array(), 'return_as_span' => $this->is_block_editor_request(), ) diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index f828624ce..e03db7c79 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -258,12 +258,17 @@ public function sanitize_atts( $atts ) { * * @return array */ - public function get_css_classes() { + public function get_css_classes( $additional_classes = array() ) { // Get the block wrapper attributes string. $wrapper_attributes = get_block_wrapper_attributes( array( - 'class' => 'convertkit-' . $this->get_name(), + 'class' => implode( ' ', array_merge( + array( + 'convertkit-' . $this->get_name(), + ), + $additional_classes + ) ), ) ); From bd9318825d1eb0897d61afce6e9b60b97e89d02b Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Fri, 4 Jul 2025 08:07:31 +0800 Subject: [PATCH 08/24] Fix tests --- .../broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php | 4 ++-- .../blocks-shortcodes/PageShortcodeBroadcastsCest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php index 284188641..351676716 100644 --- a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php +++ b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php @@ -685,7 +685,7 @@ public function testBroadcastsBlockWithThemeColorParameters(EndToEndTester $I) $I->seeInSource('seeInSource('
seeInSource('seeInSource('
seeInSource('seeInSource('
seeInSource(' Date: Fri, 4 Jul 2025 08:17:57 +0800 Subject: [PATCH 09/24] Fix tests --- tests/EndToEnd/integrations/other/ElementorBroadcastsCest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/EndToEnd/integrations/other/ElementorBroadcastsCest.php b/tests/EndToEnd/integrations/other/ElementorBroadcastsCest.php index 38b0363c1..b36771d5a 100644 --- a/tests/EndToEnd/integrations/other/ElementorBroadcastsCest.php +++ b/tests/EndToEnd/integrations/other/ElementorBroadcastsCest.php @@ -284,7 +284,7 @@ public function testBroadcastsWidgetWithHexColorParameters(EndToEndTester $I) $I->seeInSource('seeInSource('
seeInSource(' Date: Fri, 4 Jul 2025 08:19:21 +0800 Subject: [PATCH 10/24] Coding standards --- includes/blocks/class-convertkit-block.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index e03db7c79..3536df247 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -256,6 +256,7 @@ public function sanitize_atts( $atts ) { * * @since 2.8.3 * + * @param array $additional_classes Additional classes to add to the block. * @return array */ public function get_css_classes( $additional_classes = array() ) { @@ -263,12 +264,15 @@ public function get_css_classes( $additional_classes = array() ) { // Get the block wrapper attributes string. $wrapper_attributes = get_block_wrapper_attributes( array( - 'class' => implode( ' ', array_merge( - array( - 'convertkit-' . $this->get_name(), - ), - $additional_classes - ) ), + 'class' => implode( + ' ', + array_merge( + array( + 'convertkit-' . $this->get_name(), + ), + $additional_classes + ) + ), ) ); From 3a82bd93f391226165660087dec94c85edd6c3ae Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Fri, 4 Jul 2025 08:47:55 +0800 Subject: [PATCH 11/24] Fix tests --- .../PageBlockBroadcastsCest.php | 43 ----------------- .../PageBlockFormTriggerCest.php | 44 ++---------------- .../products/PageBlockProductCest.php | 46 +------------------ tests/Support/Helper/KitProducts.php | 37 ++++++++++----- 4 files changed, 32 insertions(+), 138 deletions(-) diff --git a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php index 351676716..d92602446 100644 --- a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php +++ b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php @@ -740,49 +740,6 @@ public function testBroadcastsBlockWithHexColorParameters(EndToEndTester $I) $I->seeInSource('
setupKitPlugin($I); - $I->setupKitPluginResources($I); - - // Define a 'bad' block. This is difficult to do in Gutenberg, but let's assume it's possible. - $I->havePageInDatabase( - [ - 'post_name' => 'kit-page-broadcasts-block-parameter-escaping', - 'post_content' => '', - ] - ); - - // Load the Page on the frontend site. - $I->amOnPage('/kit-page-broadcasts-block-parameter-escaping'); - - // Wait for frontend web site to load. - $I->waitForElementVisible('body.page-template-default'); - - // Check that no PHP warnings or notices were output. - $I->checkNoWarningsAndNoticesOnScreen($I); - - // Confirm that the output is escaped. - $I->seeInSource('style="color:red" onmouseover="alert(1)""'); - $I->dontSeeInSource('style="color:red" onmouseover="alert(1)""'); - - // Test pagination. - $I->testBroadcastsPagination($I, 'Previous', 'Next'); - - // Confirm that the output is still escaped. - $I->seeInSource('style="color:red" onmouseover="alert(1)""'); - $I->dontSeeInSource('style="color:red" onmouseover="alert(1)""'); - } - /** * Deactivate and reset Plugin(s) after each test, if the test passes. * We don't use _after, as this would provide a screenshot of the Plugin diff --git a/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormTriggerCest.php b/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormTriggerCest.php index 9b94cee1d..c908c9ce0 100644 --- a/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormTriggerCest.php +++ b/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormTriggerCest.php @@ -287,7 +287,7 @@ public function testFormTriggerBlockWithThemeColorParameters(EndToEndTester $I) $I->seeFormTriggerOutput($I, $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL']); // Confirm that the chosen colors are applied as CSS styles. - $I->seeInSource('class="wp-block-button__link convertkit-formtrigger has-text-color has-' . $textColor . '-color has-background has-' . $backgroundColor . '-background-color'); + $I->seeInSource('class="convertkit-formtrigger wp-block-button__link wp-element-button wp-block-convertkit-formtrigger has-text-color has-' . $textColor . '-color has-background has-' . $backgroundColor . '-background-color'); } /** @@ -327,49 +327,13 @@ public function testFormTriggerBlockWithHexColorParameters(EndToEndTester $I) // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); + // Confirm that the chosen colors are applied as CSS styles. + $I->seeInSource('class="convertkit-formtrigger wp-block-button__link wp-element-button wp-block-convertkit-formtrigger has-text-color has-background'); + // Confirm that the block displays. $I->seeFormTriggerOutput($I, $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], 'Subscribe', $textColor, $backgroundColor); } - /** - * Test the Form Trigger block's parameters are correctly escaped on output, - * to prevent XSS. - * - * @since 2.0.5 - * - * @param EndToEndTester $I Tester. - */ - public function testFormTriggerBlockParameterEscaping(EndToEndTester $I) - { - // Setup Kit Plugin with no default form specified. - $I->setupKitPluginNoDefaultForms($I); - $I->setupKitPluginResources($I); - - // Define a 'bad' block. This is difficult to do in Gutenberg, but let's assume it's possible. - $I->havePageInDatabase( - [ - 'post_name' => 'kit-page-form-trigger-block-parameter-escaping', - 'post_content' => '', - ] - ); - - // Load the Page on the frontend site. - $I->amOnPage('/kit-page-form-trigger-block-parameter-escaping'); - - // Wait for frontend web site to load. - $I->waitForElementVisible('body.page-template-default'); - - // Check that no PHP warnings or notices were output. - $I->checkNoWarningsAndNoticesOnScreen($I); - - // Confirm that the output is escaped. - $I->seeInSource('style="color:red" onmouseover="alert(1)""'); - $I->dontSeeInSource('style="color:red" onmouseover="alert(1)""'); - - // Confirm that the Kit Form Trigger is displayed. - $I->seeFormTriggerOutput($I, $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], 'Subscribe'); - } - /** * Test the Form Trigger block displays a message with a link to the Plugin's * settings screen, when the Plugin has no credentials specified. diff --git a/tests/EndToEnd/products/PageBlockProductCest.php b/tests/EndToEnd/products/PageBlockProductCest.php index a5925dcff..9e3748978 100644 --- a/tests/EndToEnd/products/PageBlockProductCest.php +++ b/tests/EndToEnd/products/PageBlockProductCest.php @@ -516,7 +516,8 @@ public function testProductBlockWithHexColorParameters(EndToEndTester $I) productURL: $_ENV['CONVERTKIT_API_PRODUCT_URL'], text: 'Buy my product', textColor: $textColor, - backgroundColor: $backgroundColor + backgroundColor: $backgroundColor, + isBlock: true ); } @@ -632,49 +633,6 @@ public function testProductBlockRefreshButton(EndToEndTester $I) $I->publishAndViewGutenbergPage($I); } - /** - * Test the Product block's parameters are correctly escaped on output, - * to prevent XSS. - * - * @since 2.0.5 - * - * @param EndToEndTester $I Tester. - */ - public function testProductBlockParameterEscaping(EndToEndTester $I) - { - // Setup Kit Plugin with no default form specified. - $I->setupKitPluginNoDefaultForms($I); - $I->setupKitPluginResources($I); - - // Define a 'bad' block. This is difficult to do in Gutenberg, but let's assume it's possible. - $I->havePageInDatabase( - [ - 'post_name' => 'kit-page-product-block-parameter-escaping', - 'post_content' => '', - ] - ); - - // Load the Page on the frontend site. - $I->amOnPage('/kit-page-product-block-parameter-escaping'); - - // Wait for frontend web site to load. - $I->waitForElementVisible('body.page-template-default'); - - // Check that no PHP warnings or notices were output. - $I->checkNoWarningsAndNoticesOnScreen($I); - - // Confirm that the output is escaped. - $I->seeInSource('style="color:red" onmouseover="alert(1)""'); - $I->dontSeeInSource('style="color:red" onmouseover="alert(1)""'); - - // Confirm that the Kit Product is displayed. - $I->seeProductOutput( - $I, - productURL: $_ENV['CONVERTKIT_API_PRODUCT_URL'], - text: 'Buy my product' - ); - } - /** * Deactivate and reset Plugin(s) after each test, if the test passes. * We don't use _after, as this would provide a screenshot of the Plugin diff --git a/tests/Support/Helper/KitProducts.php b/tests/Support/Helper/KitProducts.php index 58f3815bb..868de2360 100644 --- a/tests/Support/Helper/KitProducts.php +++ b/tests/Support/Helper/KitProducts.php @@ -54,8 +54,9 @@ public function seeProductLink($I, $productURL, $text = false) * @param bool|string $text Test if the button text matches the given value. * @param bool|string $textColor Test if the given text color is applied. * @param bool|string $backgroundColor Test is the given background color is applied. + * @param bool $isBlock Test if this is a product block or shortcode. */ - public function seeProductOutput($I, $productURL, $text = false, $textColor = false, $backgroundColor = false) + public function seeProductOutput($I, $productURL, $text = false, $textColor = false, $backgroundColor = false, $isBlock = false) { // Confirm that the product stylesheet loaded. $I->seeInSource('seeInSource('class="convertkit-formtrigger wp-block-button__link wp-element-button wp-block-convertkit-formtrigger has-text-color has-background"'); // Confirm that the block displays. - $I->seeFormTriggerOutput($I, $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], 'Subscribe', $textColor, $backgroundColor); + $I->seeFormTriggerOutput( + $I, + formURL: $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], + text: 'Subscribe', + textColor: $textColor, + backgroundColor: $backgroundColor, + isBlock: true + ); } /** diff --git a/tests/EndToEnd/products/PageBlockProductCest.php b/tests/EndToEnd/products/PageBlockProductCest.php index 9e3748978..32c8c7f59 100644 --- a/tests/EndToEnd/products/PageBlockProductCest.php +++ b/tests/EndToEnd/products/PageBlockProductCest.php @@ -470,7 +470,7 @@ public function testProductBlockWithThemeColorParameters(EndToEndTester $I) ); // Confirm that the chosen colors are applied as CSS styles. - $I->seeInSource('class="wp-block-button__link convertkit-product has-text-color has-' . $textColor . '-color has-background has-' . $backgroundColor . '-background-color'); + $I->seeInSource('class="convertkit-product wp-block-button__link wp-element-button wp-block-convertkit-product has-text-color has-' . $textColor . '-color has-background has-' . $backgroundColor . '-background-color'); } /** diff --git a/tests/Support/Helper/KitForms.php b/tests/Support/Helper/KitForms.php index 09619157f..52531a8b7 100644 --- a/tests/Support/Helper/KitForms.php +++ b/tests/Support/Helper/KitForms.php @@ -81,8 +81,9 @@ public function seeFormOutput($I, $formID, $position = false, $element = false, * @param bool|string $text Test if the button text matches the given value. * @param bool|string $textColor Test if the given text color is applied. * @param bool|string $backgroundColor Test is the given background color is applied. + * @param bool $isBlock Test if this is a form trigger block or shortcode. */ - public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false) + public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false, $isBlock = false) { // Confirm that the button stylesheet loaded. $I->seeInSource('Buy now
'); + $result = $this->resource->get_html( + id: $_ENV['CONVERTKIT_API_PRODUCT_ID'], + button_text: 'Buy now', + ); + $this->assertSame($result, ''); + + // Test with CSS classes and styles. + $result = $this->resource->get_html( + id: $_ENV['CONVERTKIT_API_PRODUCT_ID'], + button_text: 'Buy now', + options: [ + 'css_classes' => array( 'wp-block-button__link', 'wp-element-button' ), + 'css_styles' => array( + 'color' => 'color:#000', + 'background' => 'background-color:#fff', + ), + ] + ); + $this->assertSame( + $result, + '' + ); } /** From 569233fe77c03ce0ffb24ddb220e40fc8b14a2e9 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Sat, 5 Jul 2025 10:00:39 +0800 Subject: [PATCH 17/24] Fix: Call `get_block_wrapper_attributes` in `get_css_styles`, to fetch block styles (margin, padding, spacing etc) --- .../class-convertkit-block-broadcasts.php | 14 +++-------- .../class-convertkit-block-form-trigger.php | 11 ++------ .../blocks/class-convertkit-block-product.php | 11 ++------ includes/blocks/class-convertkit-block.php | 25 ++++++++++--------- 4 files changed, 20 insertions(+), 41 deletions(-) diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index aa5ba1eca..638ee8dd8 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -442,16 +442,9 @@ public function get_default_values() { * @since 1.9.7.4 * * @param array $atts Block / Shortcode / Page Builder Module Attributes. - * @param string $content Shortcode Content. - * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. * @return string */ - public function render( $atts, $content = '', $block_or_shortcode = false ) { - - // Gutenberg blocks pass $block_or_shortcode as a WP_Block. - // Shortcodes pass $block_or_shortcode as a string of the shortcode name. - // Page Builders: Let's find out! - $is_block = ( $block_or_shortcode instanceof WP_Block ); + public function render( $atts ) { // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -485,7 +478,7 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { $atts, true, $this->get_css_classes(), - ( ! $is_block ? $this->get_css_styles( $atts ) : array() ) + $this->get_css_styles( $atts ) ); /** @@ -495,9 +488,8 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { * * @param string $html ConvertKit Broadcasts HTML. * @param array $atts Block Attributes. - * @param bool $is_block Whether this is a Gutenberg block (false for shortcodes and page builders). */ - $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts, $is_block ); + $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts ); return $html; diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 1c464f8ab..90ea4030d 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -364,16 +364,9 @@ public function get_default_values() { * @since 2.2.0 * * @param array $atts Block / Shortcode / Page Builder Module Attributes. - * @param string $content Shortcode Content. - * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. * @return string */ - public function render( $atts, $content = '', $block_or_shortcode = false ) { - - // Gutenberg blocks pass $block_or_shortcode as a WP_Block. - // Shortcodes pass $block_or_shortcode as a string of the shortcode name. - // Page Builders: Let's find out! - $is_block = ( $block_or_shortcode instanceof WP_Block ); + public function render( $atts ) { // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -387,7 +380,7 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { $atts['form'], $atts['text'], $this->get_css_classes( array( 'wp-block-button__link', 'wp-element-button' ) ), - ( ! $is_block ? $this->get_css_styles( $atts ) : array() ), + $this->get_css_styles( $atts ), $this->is_block_editor_request() ); diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index b58451ae8..643d2b3d5 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -415,16 +415,9 @@ public function get_default_values() { * @since 1.9.8.5 * * @param array $atts Block / Shortcode / Page Builder Module Attributes. - * @param string $content Shortcode Content. - * @param WP_Block|string|bool $block_or_shortcode WP_Block class, Shortcode Name or false if called from a page builder. * @return string */ - public function render( $atts, $content = '', $block_or_shortcode = false ) { - - // Gutenberg blocks pass $block_or_shortcode as a WP_Block. - // Shortcodes pass $block_or_shortcode as a string of the shortcode name. - // Page Builders: Let's find out! - $is_block = ( $block_or_shortcode instanceof WP_Block ); + public function render( $atts ) { // Parse attributes, defining fallback defaults if required // and moving some attributes (such as Gutenberg's styles), if defined. @@ -445,7 +438,7 @@ public function render( $atts, $content = '', $block_or_shortcode = false ) { 'checkout' => $atts['checkout'], 'disable_modal' => ( $atts['disable_modal_on_mobile'] && wp_is_mobile() ), 'css_classes' => $this->get_css_classes( array( 'wp-block-button__link', 'wp-element-button' ) ), - 'css_styles' => ! $is_block ? $this->get_css_styles( $atts ) : array(), + 'css_styles' => $this->get_css_styles( $atts ), 'return_as_span' => $this->is_block_editor_request(), ) ); diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index 3536df247..edd87f40f 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -296,8 +296,7 @@ public function get_css_classes( $additional_classes = array() ) { /** * Builds inline CSS style(s) that might need to be added to the top level element's `style` attribute - * when using a shortcode or third party page builder module / widget. - * Gutenberg will automatically build these styles for the block using get_block_wrapper_attributes(). + * when using Gutenberg, a shortcode or third party page builder module / widget. * * @since 2.8.3 * @@ -306,21 +305,23 @@ public function get_css_classes( $additional_classes = array() ) { */ public function get_css_styles( $atts ) { - // Build inline CSS style(s) that might need to be added to the top level element when using a shortcode - // or third party page builder module / widget. - // Gutenberg will automatically build these styles for the block using get_block_wrapper_attributes(). $styles = array(); - // If the shortcode supports a text color, and a custom hex color was selected, add it to the - // array of CSS inline styles. - if ( isset( $atts['text_color'] ) && ! empty( $atts['text_color'] ) ) { - $styles['color'] = 'color:' . $atts['text_color']; + // Get the block wrapper attributes string, extracting any styles that the block has set, + // such as margin, padding or block spacing. + $wrapper_attributes = get_block_wrapper_attributes(); + if ( preg_match( '/style="([^"]*)"/', $wrapper_attributes, $matches ) ) { + return array_filter( explode( ';', $matches[1] ) ); } - // If the shortcode supports a background color, and a custom hex color was selected, add it to the - // array of CSS inline styles. + // If here, no block styles were found. + // This might be a shortcode or third party page builder module / widget that has + // specific attributes set. + if ( isset( $atts['text_color'] ) && ! empty( $atts['text_color'] ) ) { + $styles[] = 'color:' . $atts['text_color']; + } if ( isset( $atts['background_color'] ) && ! empty( $atts['background_color'] ) ) { - $styles['background'] = 'background-color:' . $atts['background_color']; + $styles[] = 'background-color:' . $atts['background_color']; } return $styles; From 3d4ec1de3d64af5ab7a9567fffeab179f45ab280 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Sat, 5 Jul 2025 10:11:06 +0800 Subject: [PATCH 18/24] Blocks: Add support for margin and padding --- includes/blocks/broadcasts/block.json | 4 ++++ includes/blocks/class-convertkit-block-broadcasts.php | 4 ++++ .../blocks/class-convertkit-block-form-trigger.php | 8 +++----- includes/blocks/class-convertkit-block-product.php | 11 +++-------- includes/blocks/class-convertkit-block.php | 4 ++++ includes/blocks/form/block.json | 6 +++++- includes/blocks/formtrigger/block.json | 4 ++++ includes/blocks/product/block.json | 4 ++++ 8 files changed, 31 insertions(+), 14 deletions(-) diff --git a/includes/blocks/broadcasts/block.json b/includes/blocks/broadcasts/block.json index b074a7eaf..ac4b0bd72 100644 --- a/includes/blocks/broadcasts/block.json +++ b/includes/blocks/broadcasts/block.json @@ -61,6 +61,10 @@ "link": true, "background": true, "text": true + }, + "spacing": { + "margin": true, + "padding": true } }, "editorScript": "convertkit-gutenberg" diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index 638ee8dd8..212d78646 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -262,6 +262,10 @@ public function get_supports() { 'background' => true, 'text' => true, ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, + ), ); } diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 90ea4030d..98462e34a 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -227,11 +227,9 @@ public function get_supports() { 'typography' => array( 'fontSize' => true, ), - 'spacing' => array( - 'padding' => array( - 'horizontal', - 'vertical', - ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, ), ); diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index 643d2b3d5..963a54beb 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -260,14 +260,9 @@ public function get_supports() { // See: https://github.com/WordPress/gutenberg/issues/32417. '__experimentalSkipSerialization' => true, ), - 'typography' => array( - 'fontSize' => true, - ), - 'spacing' => array( - 'padding' => array( - 'horizontal', - 'vertical', - ), + 'spacing' => array( + 'margin' => true, + 'padding' => true, ), ); diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index edd87f40f..336daa5a5 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -95,6 +95,10 @@ public function get_supports() { return array( 'className' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true, + ), ); } diff --git a/includes/blocks/form/block.json b/includes/blocks/form/block.json index 2814000d9..0bf0ed062 100644 --- a/includes/blocks/form/block.json +++ b/includes/blocks/form/block.json @@ -23,7 +23,11 @@ } }, "supports": { - "className": true + "className": true, + "spacing": { + "margin": true, + "padding": true + } }, "editorScript": "convertkit-gutenberg" } \ No newline at end of file diff --git a/includes/blocks/formtrigger/block.json b/includes/blocks/formtrigger/block.json index 3c8348d14..6460132b0 100644 --- a/includes/blocks/formtrigger/block.json +++ b/includes/blocks/formtrigger/block.json @@ -36,6 +36,10 @@ "color": { "background": true, "text": true + }, + "spacing": { + "margin": true, + "padding": true } }, "editorScript": "convertkit-gutenberg" diff --git a/includes/blocks/product/block.json b/includes/blocks/product/block.json index cdd77a812..e25db1531 100644 --- a/includes/blocks/product/block.json +++ b/includes/blocks/product/block.json @@ -36,6 +36,10 @@ "color": { "background": true, "text": true + }, + "spacing": { + "margin": true, + "padding": true } }, "editorScript": "convertkit-gutenberg" From e62f3f6f87e9be3579b642fda3b1e85be3b29b23 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Sat, 5 Jul 2025 10:18:51 +0800 Subject: [PATCH 19/24] Coding standards --- includes/blocks/class-convertkit-block-broadcasts.php | 2 +- includes/blocks/class-convertkit-block-form-trigger.php | 2 +- includes/blocks/class-convertkit-block-product.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index 638ee8dd8..0a7bd088a 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -441,7 +441,7 @@ public function get_default_values() { * * @since 1.9.7.4 * - * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param array $atts Block / Shortcode / Page Builder Module Attributes. * @return string */ public function render( $atts ) { diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 90ea4030d..c04d5d311 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -363,7 +363,7 @@ public function get_default_values() { * * @since 2.2.0 * - * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param array $atts Block / Shortcode / Page Builder Module Attributes. * @return string */ public function render( $atts ) { diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index 643d2b3d5..d644468d0 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -414,7 +414,7 @@ public function get_default_values() { * * @since 1.9.8.5 * - * @param array $atts Block / Shortcode / Page Builder Module Attributes. + * @param array $atts Block / Shortcode / Page Builder Module Attributes. * @return string */ public function render( $atts ) { From 7cf61f0106ba18a8b5e0affeda453af9d181cace Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 7 Jul 2025 15:11:17 +0800 Subject: [PATCH 20/24] Add tests --- .../class-convertkit-block-broadcasts.php | 4 +- .../class-convertkit-block-form-trigger.php | 6 +-- .../blocks/class-convertkit-block-product.php | 8 ++-- includes/blocks/class-convertkit-block.php | 4 -- includes/blocks/form/block.json | 6 +-- .../PageBlockBroadcastsCest.php | 48 +++++++++++++++++++ .../PageBlockFormTriggerCest.php | 43 +++++++++++++++++ .../products/PageBlockProductCest.php | 43 +++++++++++++++++ tests/Support/Helper/KitForms.php | 11 ++++- tests/Support/Helper/KitProducts.php | 11 ++++- 10 files changed, 164 insertions(+), 20 deletions(-) diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index 9103f0822..54dd08017 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -263,8 +263,8 @@ public function get_supports() { 'text' => true, ), 'spacing' => array( - 'margin' => true, - 'padding' => true, + 'margin' => true, + 'padding' => true, ), ); diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 8823257fb..0e8cc2e92 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -227,9 +227,9 @@ public function get_supports() { 'typography' => array( 'fontSize' => true, ), - 'spacing' => array( - 'margin' => true, - 'padding' => true, + 'spacing' => array( + 'margin' => true, + 'padding' => true, ), ); diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index 98bad3833..02fc0b853 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -250,8 +250,8 @@ public function get_attributes() { public function get_supports() { return array( - 'className' => true, - 'color' => array( + 'className' => true, + 'color' => array( 'background' => true, 'text' => true, @@ -261,8 +261,8 @@ public function get_supports() { '__experimentalSkipSerialization' => true, ), 'spacing' => array( - 'margin' => true, - 'padding' => true, + 'margin' => true, + 'padding' => true, ), ); diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index 336daa5a5..edd87f40f 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -95,10 +95,6 @@ public function get_supports() { return array( 'className' => true, - 'spacing' => array( - 'margin' => true, - 'padding' => true, - ), ); } diff --git a/includes/blocks/form/block.json b/includes/blocks/form/block.json index 0bf0ed062..2814000d9 100644 --- a/includes/blocks/form/block.json +++ b/includes/blocks/form/block.json @@ -23,11 +23,7 @@ } }, "supports": { - "className": true, - "spacing": { - "margin": true, - "padding": true - } + "className": true }, "editorScript": "convertkit-gutenberg" } \ No newline at end of file diff --git a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php index d92602446..34e6d0cd4 100644 --- a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php +++ b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php @@ -740,6 +740,54 @@ public function testBroadcastsBlockWithHexColorParameters(EndToEndTester $I) $I->seeInSource('
setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's margin and padding pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the margin and padding pickers themselves, as they are Gutenberg supplied components, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-broadcasts-block-margin-padding-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-broadcasts-block-margin-padding-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays correctly with the expected number of Broadcasts. + $I->seeBroadcastsOutput( + $I, + [ + 'number_posts' => $_ENV['CONVERTKIT_API_BROADCAST_COUNT'], + ] + ); + + // Confirm that our stylesheet loaded. + $I->seeInSource('setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's margin and padding pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the margin and padding pickers themselves, as they are Gutenberg supplied components, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-form-trigger-block-margin-padding-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-form-trigger-block-margin-padding-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays and has the inline styles applied. + $I->seeFormTriggerOutput( + $I, + formURL: $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], + text: 'Subscribe', + styles: 'padding-top:var(--wp--preset--spacing--30);margin-top:var(--wp--preset--spacing--30)', + isBlock: true + ); + } + /** * Test the Form Trigger block displays a message with a link to the Plugin's * settings screen, when the Plugin has no credentials specified. diff --git a/tests/EndToEnd/products/PageBlockProductCest.php b/tests/EndToEnd/products/PageBlockProductCest.php index 32c8c7f59..c7cd9ea80 100644 --- a/tests/EndToEnd/products/PageBlockProductCest.php +++ b/tests/EndToEnd/products/PageBlockProductCest.php @@ -521,6 +521,49 @@ public function testProductBlockWithHexColorParameters(EndToEndTester $I) ); } + /** + * Test the Form Trigger block's margin and padding parameters works. + * + * @since 2.8.4 + * + * @param EndToEndTester $I Tester. + */ + public function testProductBlockWithMarginAndPaddingParameters(EndToEndTester $I) + { + // Setup Plugin and enable debug log. + $I->setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's margin and padding pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the margin and padding pickers themselves, as they are Gutenberg supplied components, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-product-block-margin-padding-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-product-block-margin-padding-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays and has the inline styles applied. + $I->seeProductOutput( + $I, + productURL: $_ENV['CONVERTKIT_API_PRODUCT_URL'], + text: 'Buy my product', + styles: 'padding-top:var(--wp--preset--spacing--30);margin-top:var(--wp--preset--spacing--30)', + isBlock: true + ); + } + /** * Test the Product block displays a message with a link to the Plugin's * settings screen, when the Plugin has Not connected to Kit. diff --git a/tests/Support/Helper/KitForms.php b/tests/Support/Helper/KitForms.php index 52531a8b7..59e02f853 100644 --- a/tests/Support/Helper/KitForms.php +++ b/tests/Support/Helper/KitForms.php @@ -81,9 +81,10 @@ public function seeFormOutput($I, $formID, $position = false, $element = false, * @param bool|string $text Test if the button text matches the given value. * @param bool|string $textColor Test if the given text color is applied. * @param bool|string $backgroundColor Test is the given background color is applied. + * @param bool|string $styles Test if the given styles are applied. * @param bool $isBlock Test if this is a form trigger block or shortcode. */ - public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false, $isBlock = false) + public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false, $styles = false, $isBlock = false) { // Confirm that the button stylesheet loaded. $I->seeInSource(' $this->get_default_value( 'paginate_label_next' ), ), - // get_supports() color attribute. + // get_supports() style, color and typography attributes. 'style' => array( 'type' => 'object', ), @@ -256,13 +256,17 @@ public function get_attributes() { public function get_supports() { return array( - 'className' => true, - 'color' => array( + 'className' => true, + 'color' => array( 'link' => true, 'background' => true, 'text' => true, ), - 'spacing' => array( + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + ), + 'spacing' => array( 'margin' => true, 'padding' => true, ), diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 0e8cc2e92..a5d7d4c50 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -159,7 +159,10 @@ public function get_attributes() { // The below are built in Gutenberg attributes registered in get_supports(). - // Color. + // get_supports() style, color and typography attributes. + 'style' => array( + 'type' => 'object', + ), 'backgroundColor' => array( 'type' => 'string', ), @@ -167,34 +170,6 @@ public function get_attributes() { 'type' => 'string', ), - // Typography. - 'fontSize' => array( - 'type' => 'string', - ), - - // Spacing/Dimensions > Padding. - 'style' => array( - 'type' => 'object', - 'visualizers' => array( - 'type' => 'object', - 'padding' => array( - 'type' => 'object', - 'top' => array( - 'type' => 'boolean', - ), - 'bottom' => array( - 'type' => 'boolean', - ), - 'left' => array( - 'type' => 'boolean', - ), - 'right' => array( - 'type' => 'boolean', - ), - ), - ), - ), - // Always required for Gutenberg. 'is_gutenberg_example' => array( 'type' => 'boolean', @@ -225,7 +200,8 @@ public function get_supports() { '__experimentalSkipSerialization' => true, ), 'typography' => array( - 'fontSize' => true, + 'fontSize' => true, + 'lineHeight' => true, ), 'spacing' => array( 'margin' => true, diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index 02fc0b853..f14d7a580 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -195,7 +195,10 @@ public function get_attributes() { // The below are built in Gutenberg attributes registered in get_supports(). - // Color. + // get_supports() style, color and typography attributes. + 'style' => array( + 'type' => 'object', + ), 'backgroundColor' => array( 'type' => 'string', ), @@ -203,34 +206,6 @@ public function get_attributes() { 'type' => 'string', ), - // Typography. - 'fontSize' => array( - 'type' => 'string', - ), - - // Spacing/Dimensions > Padding. - 'style' => array( - 'type' => 'object', - 'visualizers' => array( - 'type' => 'object', - 'padding' => array( - 'type' => 'object', - 'top' => array( - 'type' => 'boolean', - ), - 'bottom' => array( - 'type' => 'boolean', - ), - 'left' => array( - 'type' => 'boolean', - ), - 'right' => array( - 'type' => 'boolean', - ), - ), - ), - ), - // Always required for Gutenberg. 'is_gutenberg_example' => array( 'type' => 'boolean', @@ -250,8 +225,8 @@ public function get_attributes() { public function get_supports() { return array( - 'className' => true, - 'color' => array( + 'className' => true, + 'color' => array( 'background' => true, 'text' => true, @@ -260,7 +235,11 @@ public function get_supports() { // See: https://github.com/WordPress/gutenberg/issues/32417. '__experimentalSkipSerialization' => true, ), - 'spacing' => array( + 'typography' => array( + 'fontSize' => true, + 'lineHeight' => true, + ), + 'spacing' => array( 'margin' => true, 'padding' => true, ), diff --git a/includes/blocks/formtrigger/block.json b/includes/blocks/formtrigger/block.json index 6460132b0..3dba03250 100644 --- a/includes/blocks/formtrigger/block.json +++ b/includes/blocks/formtrigger/block.json @@ -37,6 +37,10 @@ "background": true, "text": true }, + "typography": { + "fontSize": true, + "lineHeight": true + }, "spacing": { "margin": true, "padding": true diff --git a/includes/blocks/product/block.json b/includes/blocks/product/block.json index e25db1531..534a3123d 100644 --- a/includes/blocks/product/block.json +++ b/includes/blocks/product/block.json @@ -37,6 +37,10 @@ "background": true, "text": true }, + "typography": { + "fontSize": true, + "lineHeight": true + }, "spacing": { "margin": true, "padding": true From 674831937783ebef53df213bddd39860450d4ab5 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Wed, 9 Jul 2025 14:45:06 +0800 Subject: [PATCH 23/24] Added tests --- .../PageBlockBroadcastsCest.php | 48 +++++++++++++++++++ .../PageBlockFormTriggerCest.php | 44 +++++++++++++++++ .../products/PageBlockProductCest.php | 44 +++++++++++++++++ tests/Support/Helper/KitForms.php | 23 ++++++--- tests/Support/Helper/KitProducts.php | 23 ++++++--- 5 files changed, 168 insertions(+), 14 deletions(-) diff --git a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php index 34e6d0cd4..b78dbe239 100644 --- a/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php +++ b/tests/EndToEnd/broadcasts/blocks-shortcodes/PageBlockBroadcastsCest.php @@ -788,6 +788,54 @@ public function testBroadcastsBlockWithMarginAndPaddingParameters(EndToEndTester $I->seeInSource('
setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's typography pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the typography picker itself, as it's a Gutenberg supplied component, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-broadcasts-block-typography-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-broadcasts-block-typography-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays correctly with the expected number of Broadcasts. + $I->seeBroadcastsOutput( + $I, + [ + 'number_posts' => $_ENV['CONVERTKIT_API_BROADCAST_COUNT'], + ] + ); + + // Confirm that our stylesheet loaded. + $I->seeInSource('setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's typography pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the typography picker itself, as it's a Gutenberg supplied component, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-form-trigger-block-typography-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-form-trigger-block-typography-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays and has the inline styles applied. + $I->seeFormTriggerOutput( + $I, + formURL: $_ENV['CONVERTKIT_API_FORM_FORMAT_MODAL_URL'], + text: 'Subscribe', + cssClasses: 'has-large-font-size', + styles: 'line-height:2', + isBlock: true + ); + } + /** * Test the Form Trigger block displays a message with a link to the Plugin's * settings screen, when the Plugin has no credentials specified. diff --git a/tests/EndToEnd/products/PageBlockProductCest.php b/tests/EndToEnd/products/PageBlockProductCest.php index c7cd9ea80..e723312db 100644 --- a/tests/EndToEnd/products/PageBlockProductCest.php +++ b/tests/EndToEnd/products/PageBlockProductCest.php @@ -564,6 +564,50 @@ public function testProductBlockWithMarginAndPaddingParameters(EndToEndTester $I ); } + /** + * Test the Product block's typography parameters works. + * + * @since 2.8.4 + * + * @param EndToEndTester $I Tester. + */ + public function testProductBlockWithTypographyParameters(EndToEndTester $I) + { + // Setup Plugin and enable debug log. + $I->setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // It's tricky to interact with Gutenberg's typography pickers, so we programmatically create the Page + // instead to then confirm the settings apply on the output. + // We don't need to test the typography picker itself, as it's a Gutenberg supplied component, and our + // other End To End tests confirm that the block can be added in Gutenberg etc. + $I->havePageInDatabase( + [ + 'post_name' => 'kit-page-product-block-typography-params', + 'post_content' => '', + ] + ); + + // Load the Page on the frontend site. + $I->amOnPage('/kit-page-product-block-typography-params'); + + // Wait for frontend web site to load. + $I->waitForElementVisible('body.page-template-default'); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that the block displays and has the inline styles applied. + $I->seeProductOutput( + $I, + productURL: $_ENV['CONVERTKIT_API_PRODUCT_URL'], + text: 'Buy my product', + cssClasses: 'has-large-font-size', + styles: 'line-height:2', + isBlock: true + ); + } + /** * Test the Product block displays a message with a link to the Plugin's * settings screen, when the Plugin has Not connected to Kit. diff --git a/tests/Support/Helper/KitForms.php b/tests/Support/Helper/KitForms.php index 59e02f853..a2f6b05c8 100644 --- a/tests/Support/Helper/KitForms.php +++ b/tests/Support/Helper/KitForms.php @@ -76,15 +76,16 @@ public function seeFormOutput($I, $formID, $position = false, $element = false, * * @since 2.2.0 * - * @param EndToEndTester $I Tester. - * @param string $formURL Form URL. - * @param bool|string $text Test if the button text matches the given value. - * @param bool|string $textColor Test if the given text color is applied. + * @param EndToEndTester $I Tester. + * @param string $formURL Form URL. + * @param bool|string $text Test if the button text matches the given value. + * @param bool|string $textColor Test if the given text color is applied. * @param bool|string $backgroundColor Test is the given background color is applied. - * @param bool|string $styles Test if the given styles are applied. - * @param bool $isBlock Test if this is a form trigger block or shortcode. + * @param bool|string $cssClasses Test if the given CSS classes are applied. + * @param bool|string $styles Test if the given styles are applied. + * @param bool $isBlock Test if this is a form trigger block or shortcode. */ - public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false, $styles = false, $isBlock = false) + public function seeFormTriggerOutput($I, $formURL, $text = false, $textColor = false, $backgroundColor = false, $cssClasses = false, $styles = false, $isBlock = false) { // Confirm that the button stylesheet loaded. $I->seeInSource('