diff --git a/includes/widgets/button.php b/includes/widgets/button.php index c12c76300398..c534ad5f3406 100644 --- a/includes/widgets/button.php +++ b/includes/widgets/button.php @@ -2,6 +2,7 @@ namespace Elementor; use Elementor\Includes\Widgets\Traits\Button_Trait; +use Elementor\Modules\Promotions\Controls\Promotion_Control; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. @@ -85,28 +86,6 @@ public function has_widget_inner_wrapper(): bool { return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ); } - /** - * Get widget upsale data. - * - * Retrieve the widget promotion data. - * - * @since 3.19.0 - * @access protected - * - * @return array Widget promotion data. - */ - protected function get_upsale_data() { - return [ - 'condition' => ! Utils::has_pro(), - 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ), - 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), - 'title' => esc_html__( 'Convert visitors into customers', 'elementor' ), - 'description' => esc_html__( 'Get the Call to Action widget and grow your toolbox with Elementor Pro.', 'elementor' ), - 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-button-widget/' ), - 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), - ]; - } - protected function register_controls() { $this->start_controls_section( 'section_button', @@ -117,6 +96,14 @@ protected function register_controls() { $this->register_button_content_controls(); + $this->add_control( + Utils::CTA . '_promotion', + [ + 'label' => esc_html__( 'Call to Action widget', 'elementor' ), + 'type' => Promotion_Control::TYPE, + ] + ); + $this->end_controls_section(); $this->start_controls_section( diff --git a/includes/widgets/image-carousel.php b/includes/widgets/image-carousel.php index fd7628e3211f..b5ec58ed9ec9 100644 --- a/includes/widgets/image-carousel.php +++ b/includes/widgets/image-carousel.php @@ -6,6 +6,7 @@ } use Elementor\Core\Kits\Documents\Tabs\Global_Colors; +use Elementor\Modules\Promotions\Controls\Promotion_Control; /** * Elementor image carousel widget. @@ -91,27 +92,6 @@ public function get_style_depends(): array { return [ 'e-swiper', 'widget-image-carousel' ]; } - /** - * Get widget upsale data. - * - * Retrieve the widget promotion data. - * - * @since 3.18.0 - * @access protected - * - * @return array Widget promotion data. - */ - protected function get_upsale_data() { - return [ - 'condition' => ! Utils::has_pro(), - 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ), - 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), - 'description' => esc_html__( 'Gain complete freedom to design every slide with Elementor"s Pro Carousel.', 'elementor' ), - 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-image-carousel-widget/' ), - 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), - ]; - } - public function has_widget_inner_wrapper(): bool { return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ); } @@ -395,6 +375,14 @@ protected function register_controls() { ] ); + $this->add_control( + Utils::IMAGE_CAROUSEL . '_promotion', + [ + 'label' => esc_html__( 'Carousel PRO widget', 'elementor' ), + 'type' => Promotion_Control::TYPE, + ] + ); + $this->end_controls_section(); $this->start_controls_section( diff --git a/includes/widgets/testimonial.php b/includes/widgets/testimonial.php index 23a7445e67e7..654759cdc439 100644 --- a/includes/widgets/testimonial.php +++ b/includes/widgets/testimonial.php @@ -7,6 +7,7 @@ use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; +use Elementor\Modules\Promotions\Controls\Promotion_Control; /** * Elementor testimonial widget. @@ -95,27 +96,6 @@ public function has_widget_inner_wrapper(): bool { return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ); } - /** - * Get widget upsale data. - * - * Retrieve the widget promotion data. - * - * @since 3.18.0 - * @access protected - * - * @return array Widget promotion data. - */ - protected function get_upsale_data() { - return [ - 'condition' => ! Utils::has_pro(), - 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ), - 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), - 'description' => esc_html__( 'Use interesting masonry layouts and other overlay features with Elementor\'s Pro Gallery widget.', 'elementor' ), - 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-testimonial-widget/' ), - 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), - ]; - } - /** * Register testimonial widget controls. * @@ -262,6 +242,14 @@ protected function register_controls() { ] ); + $this->add_control( + Utils::TESTIMONIAL_WIDGET . '_promotion', + [ + 'label' => esc_html__( 'Loop Carousel widget', 'elementor' ), + 'type' => Promotion_Control::TYPE, + ] + ); + $this->end_controls_section(); // Content. diff --git a/includes/widgets/video.php b/includes/widgets/video.php index 5653d8ab12ba..00201d69a02d 100644 --- a/includes/widgets/video.php +++ b/includes/widgets/video.php @@ -2,6 +2,7 @@ namespace Elementor; use Elementor\Modules\DynamicTags\Module as TagsModule; +use Elementor\Modules\Promotions\Controls\Promotion_Control; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. @@ -110,28 +111,6 @@ public function has_widget_inner_wrapper(): bool { return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ); } - /** - * Register video widget controls. - * - * Adds different input fields to allow the user to change and customize the widget settings. - * - * @since 3.19.0 - * @access protected - * - * @return array Widget promotion data. - */ - protected function get_upsale_data() { - return [ - 'condition' => ! Utils::has_pro(), - 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ), - 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), - 'title' => esc_html__( "Grab your visitors' attention", 'elementor' ), - 'description' => esc_html__( 'Get the Video Playlist widget and grow your toolbox with Elementor Pro.', 'elementor' ), - 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-video-widget/' ), - 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), - ]; - } - /** * Register video widget controls. * @@ -626,6 +605,14 @@ protected function register_controls() { ] ); + $this->add_control( + Utils::VIDEO_PLAYLIST . '_promotion', + [ + 'label' => esc_html__( 'Video Playlist widget', 'elementor' ), + 'type' => Promotion_Control::TYPE, + ] + ); + $this->end_controls_section(); $this->start_controls_section( diff --git a/modules/promotions/promotion-data.php b/modules/promotions/promotion-data.php index 8a5e76c6d1f2..b2ab813c1c3c 100644 --- a/modules/promotions/promotion-data.php +++ b/modules/promotions/promotion-data.php @@ -17,6 +17,10 @@ public function get_promotion_data( $force_request = false ): array { return [ Utils::ANIMATED_HEADLINE => $this->get_animated_headline_data( $assets_data ), + Utils::VIDEO_PLAYLIST => $this->get_video_playlist_data( $assets_data ), + Utils::CTA => $this->get_cta_button_data( $assets_data ), + Utils::IMAGE_CAROUSEL => $this->get_image_carousel_data( $assets_data ), + Utils::TESTIMONIAL_WIDGET => $this->get_testimonial_widget_data( $assets_data ), ]; } @@ -48,6 +52,74 @@ private function get_animated_headline_data( $assets_data ) { return $this->filter_data( Utils::ANIMATED_HEADLINE, $data ); } + private function get_video_playlist_data( $assets_data ) { + $data = [ + 'image' => esc_url( $assets_data[ Utils::VIDEO_PLAYLIST ] ?? '' ), + 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), + 'title' => esc_html__( 'Showcase Video Playlists', 'elementor' ), + 'description' => [ + esc_html__( 'Embed videos with full control.', 'elementor' ), + esc_html__( 'Adjust layout and playback settings.', 'elementor' ), + esc_html__( 'Seamlessly customize video appearance.', 'elementor' ), + ], + 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), + 'upgrade_url' => 'https://go.elementor.com/go-pro-video-widget/', + ]; + + return $this->filter_data( Utils::VIDEO_PLAYLIST, $data ); + } + + private function get_cta_button_data( $assets_data ) { + $data = [ + 'image' => esc_url( $assets_data[ Utils::CTA ] ?? '' ), + 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), + 'title' => esc_html__( 'Boost Conversions with CTAs', 'elementor' ), + 'description' => [ + esc_html__( 'Combine text, buttons, and images.', 'elementor' ), + esc_html__( 'Add hover animations and CSS effects.', 'elementor' ), + esc_html__( 'Create unique, interactive designs.', 'elementor' ), + ], + 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), + 'upgrade_url' => 'https://go.elementor.com/go-pro-button-widget/', + ]; + + return $this->filter_data( Utils::CTA, $data ); + } + + private function get_image_carousel_data( $assets_data ) { + $data = [ + 'image' => esc_url( $assets_data[ Utils::IMAGE_CAROUSEL ] ?? '' ), + 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), + 'title' => esc_html__( 'Design Custom Carousels', 'elementor' ), + 'description' => [ + esc_html__( 'Create flexible custom carousels.', 'elementor' ), + esc_html__( 'Adjust transitions and animations easily.', 'elementor' ), + esc_html__( 'Showcase multiple items with style.', 'elementor' ), + ], + 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), + 'upgrade_url' => 'https://go.elementor.com/go-pro-image-carousel-widget/', + ]; + + return $this->filter_data( Utils::IMAGE_CAROUSEL, $data ); + } + + private function get_testimonial_widget_data( $assets_data ) { + $data = [ + 'image' => esc_url( $assets_data[ Utils::TESTIMONIAL_WIDGET ] ?? '' ), + 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ), + 'title' => esc_html__( 'Upgrade Your Testimonials', 'elementor' ), + 'description' => [ + esc_html__( 'Display reviews in a rotating carousel.', 'elementor' ), + esc_html__( 'Boost credibility with dynamic testimonials.', 'elementor' ), + esc_html__( 'Customize layouts for visual appeal.', 'elementor' ), + ], + 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ), + 'upgrade_url' => 'https://go.elementor.com/go-pro-testimonial-widget/', + ]; + + return $this->filter_data( Utils::TESTIMONIAL_WIDGET, $data ); + } + private function filter_data( $widget_name, $asset_data ): array { return Filtered_Promotions_Manager::get_filtered_promotion_data( $asset_data, "elementor/widgets/{$widget_name}/custom_promotion", 'upgrade_url' ); } diff --git a/tests/playwright/sanity/modules/promotions/promotions.test.ts b/tests/playwright/sanity/modules/promotions/promotions.test.ts index c4d9e739deb9..2cd4dcd6c758 100644 --- a/tests/playwright/sanity/modules/promotions/promotions.test.ts +++ b/tests/playwright/sanity/modules/promotions/promotions.test.ts @@ -62,16 +62,36 @@ test.describe( 'Promotion tests @promotions', () => { promotionsHelper = new PromotionsHelper( page, testInfo ), container = await editor.addElement( { elType: 'container' }, 'document' ); - await editor.addWidget( 'heading', container ); + await test.step( 'Free to Pro - react animated headline modal visible', async () => { + await editor.addWidget( 'heading', container ); + await editor.openPanelTab( 'content' ); + await promotionsHelper.modalPromotionModalVisibilityTest( 'animated_headline_promotion' ); + } ); - await editor.openPanelTab( 'content' ); + await test.step( 'Free to Pro - react video playlist modal visible', async () => { + await editor.addWidget( 'video', container ); + await editor.openPanelTab( 'content' ); + await promotionsHelper.modalPromotionModalVisibilityTest( 'video_playlist_promotion' ); + } ); - await test.step( 'Free to Pro - react modals screenshot tests', async () => { - const promotionControls = [ 'animated_headline_promotion' ]; - for ( const effect of promotionControls ) { - await promotionsHelper.modalPromotionModalVisibilityTest( effect ); - } + await test.step( 'Free to Pro - react cta button modal visible', async () => { + await editor.addWidget( 'button', container ); + await editor.openPanelTab( 'content' ); + await promotionsHelper.modalPromotionModalVisibilityTest( 'cta_promotion' ); } ); + + await test.step( 'Free to Pro - react image carousel modal visible', async () => { + await editor.addWidget( 'image-carousel', container ); + await editor.openPanelTab( 'content' ); + await promotionsHelper.modalPromotionModalVisibilityTest( 'image_carousel_promotion' ); + } ); + + await test.step( 'Free to Pro - react testimonial modal visible', async () => { + await editor.addWidget( 'testimonial', container ); + await editor.openPanelTab( 'content' ); + await promotionsHelper.modalPromotionModalVisibilityTest( 'testimonial_widget_promotion' ); + } ); + } ); test( 'Context Menu Promotions - Free to Pro', async ( { page, apiRequests }, testInfo ) => {