Require Premium plugin for multi-condition segments

[MAILPOET-3929]
This commit is contained in:
wxa
2021-12-06 18:08:31 +03:00
committed by Veljko V
parent bde9eb1761
commit 5e486462c0
6 changed files with 75 additions and 9 deletions

View File

@@ -437,6 +437,10 @@ a.mailpoet-listing-error {
} }
} }
a.mailpoet-listing-link-important {
color: $color-secondary !important;
}
@include respond-to(small-screen) { @include respond-to(small-screen) {
.mailpoet-listing { .mailpoet-listing {
padding: 0; padding: 0;

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { Link, withRouter } from 'react-router-dom'; import { Link, withRouter } from 'react-router-dom';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import ReactStringReplace from 'react-string-replace';
import Listing from 'listing/listing.jsx'; import Listing from 'listing/listing.jsx';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@@ -144,7 +145,24 @@ function renderItem(item, actions) {
{ item.is_plugin_missing { item.is_plugin_missing
? ( ? (
<td colSpan="2" className="column mailpoet-hide-on-mobile" data-colname={MailPoet.I18n.t('missingPluginMessageColumn')}> <td colSpan="2" className="column mailpoet-hide-on-mobile" data-colname={MailPoet.I18n.t('missingPluginMessageColumn')}>
{ item.missing_plugin_message
&& item.missing_plugin_message.message && item.missing_plugin_message.link
? (
<>
{ ReactStringReplace(
item.missing_plugin_message.message,
/\[link](.*?)\[\/link]/g,
(match) => (
<a className="mailpoet-listing-link-important" key="missingPluginMessageLink" href={item.missing_plugin_message.link} target="_blank" rel="noopener noreferrer">{match}</a>
)
) }
</>
)
: (
<>
{ item.missing_plugin_message } { item.missing_plugin_message }
</>
)}
</td> </td>
) )
: ( : (

View File

@@ -93,7 +93,9 @@ class DynamicSegmentsResponseBuilder {
if ($missingPlugins) { if ($missingPlugins) {
$missingPlugin = reset($missingPlugins); $missingPlugin = reset($missingPlugins);
$data['is_plugin_missing'] = true; $data['is_plugin_missing'] = true;
$data['missing_plugin_message'] = sprintf( $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'), __('Activate the %s plugin to see the number of subscribers and enable the editing of this segment.', 'mailpoet'),
$missingPlugin $missingPlugin
); );

View File

@@ -34,6 +34,7 @@ class FilterHandler {
$filters = $segment->getDynamicFilters(); $filters = $segment->getDynamicFilters();
$filterSelects = []; $filterSelects = [];
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName(); $subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
$pluginsForAllFiltersMissing = $this->segmentDependencyValidator->getMissingPluginsByAllFilters($filters);
foreach ($filters as $filter) { foreach ($filters as $filter) {
$subscribersIdsQuery = $this->entityManager $subscribersIdsQuery = $this->entityManager
->getConnection() ->getConnection()
@@ -41,7 +42,7 @@ class FilterHandler {
->select("DISTINCT $subscribersTable.id as inner_subscriber_id") ->select("DISTINCT $subscribersTable.id as inner_subscriber_id")
->from($subscribersTable); ->from($subscribersTable);
// When a required plugin is missing we want to return empty result // 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'); $subscribersIdsQuery->andWhere('1 = 0');
} else { } else {
$this->filterFactory->getFilterForFilterEntity($filter)->apply($subscribersIdsQuery, $filter); $this->filterFactory->getFilterForFilterEntity($filter)->apply($subscribersIdsQuery, $filter);

View File

@@ -5,9 +5,16 @@ namespace MailPoet\Segments;
use MailPoet\Entities\DynamicSegmentFilterData; use MailPoet\Entities\DynamicSegmentFilterData;
use MailPoet\Entities\DynamicSegmentFilterEntity; use MailPoet\Entities\DynamicSegmentFilterEntity;
use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SegmentEntity;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\WP\Functions as WPFunctions; use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Doctrine\Common\Collections\Collection;
class SegmentDependencyValidator { class SegmentDependencyValidator {
private const MAILPOET_PREMIUM_PLUGIN = [
'id' => 'mailpoet-premium/mailpoet-premium.php',
'name' => 'MailPoet Premium',
];
private const WOOCOMMERCE_PLUGIN = [ private const WOOCOMMERCE_PLUGIN = [
'id' => 'woocommerce/woocommerce.php', 'id' => 'woocommerce/woocommerce.php',
'name' => 'WooCommerce', 'name' => 'WooCommerce',
@@ -28,12 +35,17 @@ class SegmentDependencyValidator {
], ],
]; ];
/** @var SubscribersFeature */
private $subscribersFeature;
/** @var WPFunctions */ /** @var WPFunctions */
private $wp; private $wp;
public function __construct( public function __construct(
SubscribersFeature $subscribersFeature,
WPFunctions $wp WPFunctions $wp
) { ) {
$this->subscribersFeature = $subscribersFeature;
$this->wp = $wp; $this->wp = $wp;
} }
@@ -41,8 +53,9 @@ class SegmentDependencyValidator {
* @return string[] * @return string[]
*/ */
public function getMissingPluginsBySegment(SegmentEntity $segment): array { public function getMissingPluginsBySegment(SegmentEntity $segment): array {
$missingPluginNames = []; $dynamicFilters = $segment->getDynamicFilters();
foreach ($segment->getDynamicFilters() as $dynamicFilter) { $missingPluginNames = $this->getMissingPluginsByAllFilters($dynamicFilters);
foreach ($dynamicFilters as $dynamicFilter) {
$missingPlugins = $this->getMissingPluginsByFilter($dynamicFilter); $missingPlugins = $this->getMissingPluginsByFilter($dynamicFilter);
if (!$missingPlugins) { if (!$missingPlugins) {
continue; continue;
@@ -54,6 +67,21 @@ class SegmentDependencyValidator {
return array_unique($missingPluginNames); return array_unique($missingPluginNames);
} }
/**
* @param Collection<int, DynamicSegmentFilterEntity> $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 { public function getMissingPluginsByFilter(DynamicSegmentFilterEntity $dynamicSegmentFilter): array {
$config = $this->getRequiredPluginsConfig($dynamicSegmentFilter->getFilterData()->getFilterType() ?? ''); $config = $this->getRequiredPluginsConfig($dynamicSegmentFilter->getFilterData()->getFilterType() ?? '');
return $this->getMissingPlugins($config); return $this->getMissingPlugins($config);
@@ -80,4 +108,17 @@ class SegmentDependencyValidator {
} }
return $missingPlugins; 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;
}
} }

View File

@@ -79,7 +79,7 @@ class Subscribers {
return $this->hasValidMssKey() && $this->settings->get(self::MSS_SUPPORT_SETTING_KEY) === 'premium'; 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); $state = $this->settings->get(self::PREMIUM_KEY_STATE);
return $state === Bridge::KEY_VALID || $state === Bridge::KEY_EXPIRING; return $state === Bridge::KEY_VALID || $state === Bridge::KEY_EXPIRING;
} }