diff --git a/assets/css/src/components-plugin/_listing.scss b/assets/css/src/components-plugin/_listing.scss index 877c082a72..229a8c7cbc 100644 --- a/assets/css/src/components-plugin/_listing.scss +++ b/assets/css/src/components-plugin/_listing.scss @@ -437,6 +437,10 @@ a.mailpoet-listing-error { } } +a.mailpoet-listing-link-important { + color: $color-secondary !important; +} + @include respond-to(small-screen) { .mailpoet-listing { padding: 0; diff --git a/assets/js/src/segments/dynamic/list.jsx b/assets/js/src/segments/dynamic/list.jsx index 327011ca09..bc0f63a346 100644 --- a/assets/js/src/segments/dynamic/list.jsx +++ b/assets/js/src/segments/dynamic/list.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { Link, withRouter } from 'react-router-dom'; import MailPoet from 'mailpoet'; +import ReactStringReplace from 'react-string-replace'; import Listing from 'listing/listing.jsx'; import PropTypes from 'prop-types'; @@ -144,7 +145,24 @@ function renderItem(item, actions) { { item.is_plugin_missing ? ( - { item.missing_plugin_message } + { item.missing_plugin_message + && item.missing_plugin_message.message && item.missing_plugin_message.link + ? ( + <> + { ReactStringReplace( + item.missing_plugin_message.message, + /\[link](.*?)\[\/link]/g, + (match) => ( + {match} + ) + ) } + + ) + : ( + <> + { item.missing_plugin_message } + + )} ) : ( diff --git a/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php b/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php index e7c3f1fa2f..ec4b645dd9 100644 --- a/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php +++ b/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php @@ -93,10 +93,12 @@ class DynamicSegmentsResponseBuilder { if ($missingPlugins) { $missingPlugin = reset($missingPlugins); $data['is_plugin_missing'] = true; - $data['missing_plugin_message'] = sprintf( - __('Activate the %s plugin to see the number of subscribers and enable the editing of this segment.', 'mailpoet'), - $missingPlugin - ); + $data['missing_plugin_message'] = $this->segmentDependencyValidator->getCustomErrorMessage($missingPlugin) + ?: + sprintf( + __('Activate the %s plugin to see the number of subscribers and enable the editing of this segment.', 'mailpoet'), + $missingPlugin + ); } else { $data['is_plugin_missing'] = false; $data['missing_plugin_message'] = null; diff --git a/lib/Segments/DynamicSegments/FilterHandler.php b/lib/Segments/DynamicSegments/FilterHandler.php index 50dbe9e2c6..2f408d484c 100644 --- a/lib/Segments/DynamicSegments/FilterHandler.php +++ b/lib/Segments/DynamicSegments/FilterHandler.php @@ -34,6 +34,7 @@ class FilterHandler { $filters = $segment->getDynamicFilters(); $filterSelects = []; $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); + $pluginsForAllFiltersMissing = $this->segmentDependencyValidator->getMissingPluginsByAllFilters($filters); foreach ($filters as $filter) { $subscribersIdsQuery = $this->entityManager ->getConnection() @@ -41,7 +42,7 @@ class FilterHandler { ->select("DISTINCT $subscribersTable.id as inner_subscriber_id") ->from($subscribersTable); // When a required plugin is missing we want to return empty result - if ($this->segmentDependencyValidator->getMissingPluginsByFilter($filter)) { + if ($pluginsForAllFiltersMissing || $this->segmentDependencyValidator->getMissingPluginsByFilter($filter)) { $subscribersIdsQuery->andWhere('1 = 0'); } else { $this->filterFactory->getFilterForFilterEntity($filter)->apply($subscribersIdsQuery, $filter); diff --git a/lib/Segments/SegmentDependencyValidator.php b/lib/Segments/SegmentDependencyValidator.php index 48fecade3b..189b03ed9b 100644 --- a/lib/Segments/SegmentDependencyValidator.php +++ b/lib/Segments/SegmentDependencyValidator.php @@ -5,9 +5,16 @@ namespace MailPoet\Segments; use MailPoet\Entities\DynamicSegmentFilterData; use MailPoet\Entities\DynamicSegmentFilterEntity; use MailPoet\Entities\SegmentEntity; +use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; use MailPoet\WP\Functions as WPFunctions; +use MailPoetVendor\Doctrine\Common\Collections\Collection; class SegmentDependencyValidator { + private const MAILPOET_PREMIUM_PLUGIN = [ + 'id' => 'mailpoet-premium/mailpoet-premium.php', + 'name' => 'MailPoet Premium', + ]; + private const WOOCOMMERCE_PLUGIN = [ 'id' => 'woocommerce/woocommerce.php', 'name' => 'WooCommerce', @@ -28,12 +35,17 @@ class SegmentDependencyValidator { ], ]; + /** @var SubscribersFeature */ + private $subscribersFeature; + /** @var WPFunctions */ private $wp; public function __construct( + SubscribersFeature $subscribersFeature, WPFunctions $wp ) { + $this->subscribersFeature = $subscribersFeature; $this->wp = $wp; } @@ -41,8 +53,9 @@ class SegmentDependencyValidator { * @return string[] */ public function getMissingPluginsBySegment(SegmentEntity $segment): array { - $missingPluginNames = []; - foreach ($segment->getDynamicFilters() as $dynamicFilter) { + $dynamicFilters = $segment->getDynamicFilters(); + $missingPluginNames = $this->getMissingPluginsByAllFilters($dynamicFilters); + foreach ($dynamicFilters as $dynamicFilter) { $missingPlugins = $this->getMissingPluginsByFilter($dynamicFilter); if (!$missingPlugins) { continue; @@ -54,6 +67,21 @@ class SegmentDependencyValidator { return array_unique($missingPluginNames); } + /** + * @param Collection $dynamicFilters + */ + public function getMissingPluginsByAllFilters(Collection $dynamicFilters): array { + $missingPluginNames = []; + if (count($dynamicFilters) > 1 + && (!$this->wp->isPluginActive(self::MAILPOET_PREMIUM_PLUGIN['id']) + || !$this->subscribersFeature->hasValidPremiumKey() + || $this->subscribersFeature->check()) + ) { + $missingPluginNames[] = self::MAILPOET_PREMIUM_PLUGIN['name']; + } + return $missingPluginNames; + } + public function getMissingPluginsByFilter(DynamicSegmentFilterEntity $dynamicSegmentFilter): array { $config = $this->getRequiredPluginsConfig($dynamicSegmentFilter->getFilterData()->getFilterType() ?? ''); return $this->getMissingPlugins($config); @@ -80,4 +108,17 @@ class SegmentDependencyValidator { } return $missingPlugins; } + + public function getCustomErrorMessage($missingPlugin) { + if ($missingPlugin === self::MAILPOET_PREMIUM_PLUGIN['name'] + && $this->wp->isPluginActive(self::MAILPOET_PREMIUM_PLUGIN['id']) + && (!$this->subscribersFeature->hasValidPremiumKey() || $this->subscribersFeature->check()) + ) { + return [ + 'message' => $this->wp->__('Your current MailPoet plan does not support advanced segments. Please [link]upgrade to a MailPoet Premium plan[/link] to reactivate this segment.', 'mailpoet'), + 'link' => 'https://account.mailpoet.com', + ]; + } + return false; + } } diff --git a/lib/Util/License/Features/Subscribers.php b/lib/Util/License/Features/Subscribers.php index f0bc74c943..e2dfebc96f 100644 --- a/lib/Util/License/Features/Subscribers.php +++ b/lib/Util/License/Features/Subscribers.php @@ -79,7 +79,7 @@ class Subscribers { return $this->hasValidMssKey() && $this->settings->get(self::MSS_SUPPORT_SETTING_KEY) === 'premium'; } - private function hasValidPremiumKey() { + public function hasValidPremiumKey() { $state = $this->settings->get(self::PREMIUM_KEY_STATE); return $state === Bridge::KEY_VALID || $state === Bridge::KEY_EXPIRING; }