diff --git a/composer.json b/composer.json index aabcec11161..01980b17bff 100644 --- a/composer.json +++ b/composer.json @@ -107,7 +107,7 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2395", + "@putenv YOASTCS_THRESHOLD_ERRORS=2385", "@putenv YOASTCS_THRESHOLD_WARNINGS=251", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], diff --git a/packages/js/src/support/app.js b/packages/js/src/support/app.js index 6639d9955d0..049145a07b3 100644 --- a/packages/js/src/support/app.js +++ b/packages/js/src/support/app.js @@ -32,11 +32,17 @@ const openHelpScoutBeacon = () => { } }; +/* eslint-disable complexity */ + /** * @returns {JSX.Element} The app component. + * */ export const App = () => { - const isPremium = useSelectSupport( "selectPreference", [], "isPremium", false ); + const hasPremiumSubscription = useSelectSupport( "selectPreference", [], "hasPremiumSubscription", false ); + const hasWooSeoSubscription = useSelectSupport( "selectPreference", [], "hasWooSeoSubscription", false ); + const isWooCommerceActive = useSelectSupport( "selectPreference", [], "isWooCommerceActive", false ); + const hasAnyAddon = hasPremiumSubscription || hasWooSeoSubscription; const premiumUpsellConfig = useSelectSupport( "selectUpsellSettingsAsProps" ); const pluginUrl = useSelectSupport( "selectPreference", [], "pluginUrl", "" ); const linkParams = useSelectSupport( "selectLinkParams" ); @@ -48,7 +54,6 @@ export const App = () => { const githubLink = useSelectSupport( "selectLink", [], "https://yoa.st/github-repository-support-card" ); const contactSupportLink = useSelectSupport( "selectLink", [], "https://yoa.st/contact-support-to-unlock-premium-support-section" ); const { isPromotionActive } = useSelect( STORE_NAME ); - const isWooCommerceActive = useSelectSupport( "selectPreference", [], "isWooCommerceActive" ); const faq = useMemo( () => ( [ { @@ -87,7 +92,7 @@ export const App = () => { return (
-
+
@@ -182,7 +187,7 @@ export const App = () => { title={ (
{ __( "Contact our support team", "wordpress-seo" ) } - { isPremium && Premium } + { hasAnyAddon && Premium }
) } description={ ( @@ -203,7 +208,7 @@ export const App = () => { ) } > { ) } { ...premiumUpsellConfig } > -
+

{ __( "Our support team is here to answer any questions you may have. Fill out the (pop-up) contact form, and we'll get back to you as soon as possible!", "wordpress-seo" ) }

- { ! isPremium && + { ! hasAnyAddon &&
*/ protected $products = []; @@ -55,17 +69,24 @@ class HelpScout_Beacon implements Integration_Interface { */ protected $options; + /** + * The addon manager. + * + * @var WPSEO_Addon_Manager + */ + protected $addon_manager; + /** * The array of pages we need to show the beacon on with their respective beacon IDs. * - * @var array + * @var array */ protected $pages_ids; /** * The array of pages we need to show the beacon on. * - * @var array + * @var array */ protected $base_pages = [ 'wpseo_dashboard', @@ -106,10 +127,12 @@ class HelpScout_Beacon implements Integration_Interface { * @param Options_Helper $options The options helper. * @param WPSEO_Admin_Asset_Manager $asset_manager The asset manager. * @param Migration_Status $migration_status The migrations status. + * @param WPSEO_Addon_Manager $addon_manager The addon manager. */ - public function __construct( Options_Helper $options, WPSEO_Admin_Asset_Manager $asset_manager, Migration_Status $migration_status ) { + public function __construct( Options_Helper $options, WPSEO_Admin_Asset_Manager $asset_manager, Migration_Status $migration_status, WPSEO_Addon_Manager $addon_manager ) { $this->options = $options; $this->asset_manager = $asset_manager; + $this->addon_manager = $addon_manager; $this->ask_consent = ! $this->options->get( 'tracking' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information. if ( isset( $_GET['page'] ) && \is_string( $_GET['page'] ) ) { @@ -121,19 +144,16 @@ public function __construct( Options_Helper $options, WPSEO_Admin_Asset_Manager } $this->migration_status = $migration_status; + $beacon_id = $this->get_beacon_id(); foreach ( $this->base_pages as $page ) { - if ( $this->ask_consent ) { - // We want to be able to show surveys to people who have tracking on, so we give them a different beacon. - $this->pages_ids[ $page ] = $this->beacon_id_tracking_users; - } - else { - $this->pages_ids[ $page ] = $this->beacon_id; - } + $this->pages_ids[ $page ] = $beacon_id; } } /** * {@inheritDoc} + * + * @return void */ public function register_hooks() { \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_help_scout_script' ] ); @@ -247,7 +267,7 @@ protected function get_session_data() { /** * Returns basic info about the server software. * - * @return array + * @return array */ private function get_server_info() { $server_tracking_data = new WPSEO_Tracking_Server_Data(); @@ -441,12 +461,37 @@ private function get_language_settings() { /** * Returns the conditionals based on which this integration should be active. * - * @return array The array of conditionals. + * @return array The array of conditionals. */ public static function get_conditionals() { return [ Admin_Conditional::class ]; } + /** + * Get the beacon id to use based on the user's subscription and tracking settings. + * + * @return string The beacon id to use. + */ + private function get_beacon_id() { + // Case where the user has a Yoast WooCommerce SEO plan subscription (highest priority). + if ( $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ) ) { + return $this->beacon_id_woocommerce; + } + + // Case where the user has a Yoast SEO Premium plan subscription. + if ( $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) { + return $this->beacon_id_premium; + } + + // Case where the user has no plan active and tracking enabled. + if ( $this->ask_consent ) { + return $this->beacon_id_tracking_users; + } + + // Case where the user has no plan active and tracking disabled. + return $this->beacon_id; + } + /** * Allows filtering of the HelpScout settings. Hooked to admin_head to prevent timing issues, not too early, not too late. * @@ -464,8 +509,7 @@ protected function filter_settings() { * @param string $beacon_settings The HelpScout beacon settings. */ $helpscout_settings = \apply_filters( 'wpseo_helpscout_beacon_settings', $filterable_helpscout_setting ); - - $this->products = $helpscout_settings['products']; - $this->pages_ids = $helpscout_settings['pages_ids']; + $this->products = $helpscout_settings['products']; + $this->pages_ids = $helpscout_settings['pages_ids']; } } diff --git a/src/integrations/support-integration.php b/src/integrations/support-integration.php index 0444ce0ee26..d68a83c732d 100644 --- a/src/integrations/support-integration.php +++ b/src/integrations/support-integration.php @@ -2,6 +2,7 @@ namespace Yoast\WP\SEO\Integrations; +use WPSEO_Addon_Manager; use WPSEO_Admin_Asset_Manager; use Yoast\WP\SEO\Conditionals\Admin_Conditional; use Yoast\WP\SEO\Conditionals\User_Can_Manage_Wpseo_Options_Conditional; @@ -55,6 +56,13 @@ class Support_Integration implements Integration_Interface { */ private $woocommerce_conditional; + /** + * Holds the WPSEO_Addon_Manager. + * + * @var WPSEO_Addon_Manager + */ + private $addon_manager; + /** * Constructs Support_Integration. * @@ -63,25 +71,28 @@ class Support_Integration implements Integration_Interface { * @param Product_Helper $product_helper The Product_Helper. * @param Short_Link_Helper $shortlink_helper The Short_Link_Helper. * @param WooCommerce_Conditional $woocommerce_conditional The WooCommerce_Conditional. + * @param WPSEO_Addon_Manager $addon_manager The WPSEO_Addon_Manager. */ public function __construct( WPSEO_Admin_Asset_Manager $asset_manager, Current_Page_Helper $current_page_helper, Product_Helper $product_helper, Short_Link_Helper $shortlink_helper, - WooCommerce_Conditional $woocommerce_conditional + WooCommerce_Conditional $woocommerce_conditional, + WPSEO_Addon_Manager $addon_manager ) { $this->asset_manager = $asset_manager; $this->current_page_helper = $current_page_helper; $this->product_helper = $product_helper; $this->shortlink_helper = $shortlink_helper; $this->woocommerce_conditional = $woocommerce_conditional; + $this->addon_manager = $addon_manager; } /** * Returns the conditionals based on which this loadable should be active. * - * @return array + * @return array */ public static function get_conditionals() { return [ Admin_Conditional::class, User_Can_Manage_Wpseo_Options_Conditional::class ]; @@ -108,11 +119,11 @@ public function register_hooks() { /** * Adds the page. * - * @param array $pages The pages. + * @param array> $pages The pages. * - * @return array The pages. + * @return array> The pages. */ - public function add_page( $pages ) { + public function add_page( array $pages ) { $pages[] = [ 'wpseo_dashboard', '', @@ -165,19 +176,20 @@ public function remove_notices() { /** * Creates the script data. * - * @return array The script data. + * @return array>, bool, string>> The script data. */ public function get_script_data() { return [ 'preferences' => [ - 'isPremium' => $this->product_helper->is_premium(), - 'isRtl' => \is_rtl(), - 'pluginUrl' => \plugins_url( '', \WPSEO_FILE ), - 'upsellSettings' => [ + 'hasPremiumSubscription' => $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ), + 'hasWooSeoSubscription' => $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ), + 'isRtl' => \is_rtl(), + 'pluginUrl' => \plugins_url( '', \WPSEO_FILE ), + 'upsellSettings' => [ 'actionId' => 'load-nfd-ctb', 'premiumCtbId' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2', ], - 'isWooCommerceActive' => $this->woocommerce_conditional->is_met(), + 'isWooCommerceActive' => $this->woocommerce_conditional->is_met(), ], 'linkParams' => $this->shortlink_helper->get_query_params(), 'currentPromotions' => \YoastSEO()->classes->get( Promotion_Manager::class )->get_current_promotions(), diff --git a/tests/Unit/Integrations/Support_Integration_Test.php b/tests/Unit/Integrations/Support_Integration_Test.php index 076c2cfea50..5b6970249b2 100644 --- a/tests/Unit/Integrations/Support_Integration_Test.php +++ b/tests/Unit/Integrations/Support_Integration_Test.php @@ -4,6 +4,7 @@ use Brain\Monkey; use Mockery; +use WPSEO_Addon_Manager; use WPSEO_Admin_Asset_Manager; use Yoast\WP\SEO\Conditionals\Admin_Conditional; use Yoast\WP\SEO\Conditionals\User_Can_Manage_Wpseo_Options_Conditional; @@ -59,6 +60,13 @@ final class Support_Integration_Test extends TestCase { */ private $promotion_manager; + /** + * Holds the WPSEO_Addon_Manager. + * + * @var WPSEO_Addon_Manager + */ + private $addon_manager; + /** * Holds the container. * @@ -93,6 +101,7 @@ public function set_up() { $this->product_helper = Mockery::mock( Product_Helper::class ); $this->shortlink_helper = Mockery::mock( Short_Link_Helper::class ); $this->promotion_manager = Mockery::mock( Promotion_Manager::class ); + $this->addon_manager = Mockery::mock( WPSEO_Addon_Manager::class ); $this->container = $this->create_container_with( [ Promotion_Manager::class => $this->promotion_manager ] ); $this->woocommerce_conditional = Mockery::mock( WooCommerce_Conditional::class ); @@ -102,6 +111,7 @@ public function set_up() { $this->product_helper, $this->shortlink_helper, $this->woocommerce_conditional, + $this->addon_manager, ); } @@ -121,6 +131,7 @@ public function test_construct() { $this->product_helper, $this->shortlink_helper, $this->woocommerce_conditional, + $this->addon_manager ) ); } @@ -350,9 +361,16 @@ public function expect_get_script_data() { 'user_language' => 'en_US', ]; - $this->product_helper - ->expects( 'is_premium' ) + $this->addon_manager + ->expects( 'has_valid_subscription' ) + ->once() + ->with( WPSEO_Addon_Manager::PREMIUM_SLUG ) + ->andReturn( true ); + + $this->addon_manager + ->expects( 'has_valid_subscription' ) ->once() + ->with( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ) ->andReturn( false ); Monkey\Functions\expect( 'is_rtl' )->once()->andReturn( false ); @@ -388,14 +406,15 @@ public function test_get_script_data() { $expected = [ 'preferences' => [ - 'isPremium' => false, - 'isRtl' => false, - 'pluginUrl' => 'http://basic.wordpress.test/wp-content/worspress-seo', - 'upsellSettings' => [ + 'hasPremiumSubscription' => true, + 'hasWooSeoSubscription' => false, + 'isRtl' => false, + 'pluginUrl' => 'http://basic.wordpress.test/wp-content/worspress-seo', + 'upsellSettings' => [ 'actionId' => 'load-nfd-ctb', 'premiumCtbId' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2', ], - 'isWooCommerceActive' => false, + 'isWooCommerceActive' => false, ], 'linkParams' => $link_params, 'currentPromotions' => [ 'black-friday-promotion' ], diff --git a/tests/Unit/Main_Test.php b/tests/Unit/Main_Test.php index 2e552d38b8f..20b8cd58ae4 100644 --- a/tests/Unit/Main_Test.php +++ b/tests/Unit/Main_Test.php @@ -7,6 +7,7 @@ use Mockery; use wpdb; use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception; +use Yoast\WP\SEO\Integrations\Admin\HelpScout_Beacon; use Yoast\WP\SEO\Integrations\Third_Party\Elementor; use Yoast\WP\SEO\Integrations\Watchers\Indexable_Category_Permalink_Watcher; use Yoast\WP\SEO\Integrations\Watchers\Indexable_Permalink_Watcher; @@ -44,6 +45,7 @@ final class Main_Test extends TestCase { Indexable_Category_Permalink_Watcher::class, Indexable_Permalink_Watcher::class, Elementor::class, + HelpScout_Beacon::class, ]; /**