diff --git a/assets/js/src/segments/dynamic/list.jsx b/assets/js/src/segments/dynamic/list.jsx index fac6287ac1..00f7288702 100644 --- a/assets/js/src/segments/dynamic/list.jsx +++ b/assets/js/src/segments/dynamic/list.jsx @@ -91,6 +91,21 @@ const itemActions = [ {MailPoet.I18n.t('edit')} ), + display: (item) => ( + !item.is_plugin_missing + ), + }, + { + name: 'edit_disabled', + className: 'mailpoet-hide-on-mobile mailpoet-disabled', + link: (item) => ( + + {MailPoet.I18n.t('edit')} + + ), + display: (item) => ( + item.is_plugin_missing + ), }, { name: 'view_subscribers', @@ -126,12 +141,22 @@ function renderItem(item, actions) { { item.description } - - { parseInt(item.count_all, 10).toLocaleString() } - - - { parseInt(item.count_subscribed, 10).toLocaleString() } - + { item.is_plugin_missing + ? ( + + { item.missing_plugin_message } + + ) + : ( + <> + + { parseInt(item.count_all, 10).toLocaleString() } + + + { parseInt(item.count_subscribed, 10).toLocaleString() } + + + )} { MailPoet.Date.short(item.created_at) }
diff --git a/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php b/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php index 5b37e6dea6..0e1cb9b9d8 100644 --- a/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php +++ b/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php @@ -5,6 +5,7 @@ namespace MailPoet\API\JSON\ResponseBuilders; use MailPoet\Entities\DynamicSegmentFilterEntity; use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SubscriberEntity; +use MailPoet\Segments\SegmentDependencyValidator; use MailPoet\Segments\SegmentSubscribersRepository; use MailPoet\WP\Functions; @@ -20,18 +21,24 @@ class DynamicSegmentsResponseBuilder { /** @var SegmentSubscribersRepository */ private $segmentSubscriberRepository; + /** @var SegmentDependencyValidator */ + private $segmentDependencyValidator; + public function __construct( Functions $wp, SegmentSubscribersRepository $segmentSubscriberRepository, - SegmentsResponseBuilder $segmentsResponseBuilder + SegmentsResponseBuilder $segmentsResponseBuilder, + SegmentDependencyValidator $segmentDependencyValidator ) { $this->segmentsResponseBuilder = $segmentsResponseBuilder; $this->segmentSubscriberRepository = $segmentSubscriberRepository; $this->wp = $wp; + $this->segmentDependencyValidator = $segmentDependencyValidator; } public function build(SegmentEntity $segmentEntity) { $data = $this->segmentsResponseBuilder->build($segmentEntity); + $data = $this->addMissingPluginProperties($segmentEntity, $data); // So far we allow dynamic segments to have only one filter $filter = $segmentEntity->getDynamicFilters()->first(); if (!$filter instanceof DynamicSegmentFilterEntity) { @@ -48,11 +55,29 @@ class DynamicSegmentsResponseBuilder { return $data; } + private function addMissingPluginProperties(SegmentEntity $segment, array $data): array { + $missingPlugins = $this->segmentDependencyValidator->getMissingPluginsBySegment($segment); + 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 + ); + } else { + $data['is_plugin_missing'] = false; + $data['missing_plugin_message'] = null; + } + return $data; + } + private function buildListingItem(SegmentEntity $segment): array { $data = $this->segmentsResponseBuilder->build($segment); + $data = $this->addMissingPluginProperties($segment, $data); $data['subscribers_url'] = $this->wp->adminUrl( 'admin.php?page=mailpoet-subscribers#/filter[segment=' . $segment->getId() . ']' ); + $data['count_all'] = $this->segmentSubscriberRepository->getSubscribersCount((int)$segment->getId()); $data['count_subscribed'] = $this->segmentSubscriberRepository->getSubscribersCount((int)$segment->getId(), SubscriberEntity::STATUS_SUBSCRIBED); return $data; diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 94cf3b3aa5..2895ad42ef 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -261,6 +261,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Segments\SegmentListingRepository::class)->setPublic(true); $container->autowire(\MailPoet\Segments\SegmentsSimpleListRepository::class)->setPublic(true); $container->autowire(\MailPoet\Segments\SegmentSaveController::class)->setPublic(true); + $container->autowire(\MailPoet\Segments\SegmentDependencyValidator::class)->setPublic(true); $container->autowire(\MailPoet\Segments\DynamicSegments\DynamicSegmentsListingRepository::class)->setPublic(true); $container->autowire(\MailPoet\Segments\DynamicSegments\FilterHandler::class)->setPublic(true); $container->autowire(\MailPoet\Segments\DynamicSegments\Filters\EmailAction::class)->setPublic(true); diff --git a/lib/Segments/DynamicSegments/FilterHandler.php b/lib/Segments/DynamicSegments/FilterHandler.php index 428ecb2c93..dc0c8c6abe 100644 --- a/lib/Segments/DynamicSegments/FilterHandler.php +++ b/lib/Segments/DynamicSegments/FilterHandler.php @@ -11,6 +11,7 @@ use MailPoet\Segments\DynamicSegments\Filters\EmailAction; use MailPoet\Segments\DynamicSegments\Filters\UserRole; use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory; use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct; +use MailPoet\Segments\SegmentDependencyValidator; use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder; use MailPoetVendor\Doctrine\ORM\EntityManager; @@ -30,18 +31,23 @@ class FilterHandler { /** @var EntityManager */ private $entityManager; + /** @var SegmentDependencyValidator */ + private $segmentDependencyValidator; + public function __construct( EntityManager $entityManager, EmailAction $emailAction, UserRole $userRole, WooCommerceProduct $wooCommerceProduct, - WooCommerceCategory $wooCommerceCategory + WooCommerceCategory $wooCommerceCategory, + SegmentDependencyValidator $segmentDependencyValidator ) { $this->emailAction = $emailAction; $this->userRole = $userRole; $this->wooCommerceProduct = $wooCommerceProduct; $this->wooCommerceCategory = $wooCommerceCategory; $this->entityManager = $entityManager; + $this->segmentDependencyValidator = $segmentDependencyValidator; } public function apply(QueryBuilder $queryBuilder, SegmentEntity $segment): QueryBuilder { @@ -54,7 +60,12 @@ class FilterHandler { ->createQueryBuilder() ->select("DISTINCT $subscribersTable.id as inner_subscriber_id") ->from($subscribersTable); - $this->applyFilter($subscribersIdsQuery, $filter); + // When a required plugin is missing we want to return empty result + if ($this->segmentDependencyValidator->getMissingPluginByFilter($filter)) { + $subscribersIdsQuery->andWhere('1 = 0'); + } else { + $this->applyFilter($subscribersIdsQuery, $filter); + } $filterSelects[] = $subscribersIdsQuery->getSQL(); $queryBuilder->setParameters(array_merge( $subscribersIdsQuery->getParameters(), diff --git a/lib/Segments/SegmentDependencyValidator.php b/lib/Segments/SegmentDependencyValidator.php new file mode 100644 index 0000000000..0f62ad8702 --- /dev/null +++ b/lib/Segments/SegmentDependencyValidator.php @@ -0,0 +1,55 @@ + [ + 'id' => 'woocommerce/woocommerce.php', + 'name' => 'WooCommerce', + ], + ]; + + /** @var WPFunctions */ + private $wp; + + public function __construct(WPFunctions $wp) { + $this->wp = $wp; + } + + /** + * @return string[] + */ + public function getMissingPluginsBySegment(SegmentEntity $segment): array { + $missingPlugins = []; + foreach ($segment->getDynamicFilters() as $dynamicFilter) { + $missingPlugin = $this->getMissingPluginByFilter($dynamicFilter); + if (!$missingPlugin) { + continue; + } + $missingPlugins[] = $missingPlugin['name']; + } + return $missingPlugins; + } + + public function getMissingPluginByFilter(DynamicSegmentFilterEntity $dynamicSegmentFilter): ?array { + $requiredPlugin = $this->getRequiredPluginName($dynamicSegmentFilter); + if (isset($requiredPlugin['id']) && !$this->wp->isPluginActive($requiredPlugin['id'])) { + return $requiredPlugin; + } + return null; + } + + private function getRequiredPluginName(DynamicSegmentFilterEntity $dynamicSegmentFilter): ?array { + if (isset(self::REQUIRED_PLUGINS_BY_TYPE[$dynamicSegmentFilter->getFilterData()->getFilterType()])) { + return self::REQUIRED_PLUGINS_BY_TYPE[$dynamicSegmentFilter->getFilterData()->getFilterType()]; + } + + return null; + } +} diff --git a/views/segments.html b/views/segments.html index ca6d7e9af0..3e53ce4e54 100644 --- a/views/segments.html +++ b/views/segments.html @@ -117,6 +117,7 @@ 'nameColumn': __('Name'), 'subscribersCountColumn': __('Number of subscribers'), 'updatedAtColumn': __('Modified on'), + 'missingPluginMessageColumn': __('Missing plugin message'), 'loadingDynamicSegmentItems': __('Loading data…'), 'noDynamicSegmentItemsFound': __('No segments found'), 'numberOfItemsSingular': __('1 item'),