diff --git a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx index e101617c6a..74a05aca4a 100644 --- a/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx +++ b/mailpoet/assets/js/src/segments/dynamic/dynamic_segments_filters/email_statistics_opens.tsx @@ -8,6 +8,7 @@ import Select from 'common/form/select/select'; import { Grid } from 'common/grid'; import { AnyValueTypes, + EmailActionTypes, EmailFormItem, SelectOption, WindowNewslettersList, @@ -42,12 +43,14 @@ export const EmailOpenStatisticsFields: React.FunctionComponent = ({ filt useEffect(() => { if ((segment.operator !== AnyValueTypes.ANY) && (segment.operator !== AnyValueTypes.ALL) - && (segment.operator !== AnyValueTypes.NONE) + && ((segment.operator !== AnyValueTypes.NONE) + || (segment.action === EmailActionTypes.MACHINE_OPENED) + ) ) { updateSegmentFilter({ operator: AnyValueTypes.ANY }, filterIndex); } }, [ - segment.newsletter_id, + segment.action, segment.operator, filterIndex, updateSegmentFilter, @@ -66,7 +69,7 @@ export const EmailOpenStatisticsFields: React.FunctionComponent = ({ filt > - + {segment.action === EmailActionTypes.OPENED ? : null} diff --git a/mailpoet/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php b/mailpoet/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php index 083f35b3db..5f2eaf161a 100644 --- a/mailpoet/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php +++ b/mailpoet/lib/API/JSON/ResponseBuilders/DynamicSegmentsResponseBuilder.php @@ -63,7 +63,7 @@ class DynamicSegmentsResponseBuilder { } if (($filter['segmentType'] === DynamicSegmentFilterData::TYPE_EMAIL)) { // compatibility with older filters - if ((($filter['action'] === EmailAction::ACTION_OPENED) || ($filter['action'] === EmailAction::ACTION_NOT_OPENED))) { + if ((($filter['action'] === EmailAction::ACTION_OPENED) || ($filter['action'] === EmailAction::ACTION_NOT_OPENED) || ($filter['action'] === EmailAction::ACTION_MACHINE_OPENED))) { if (isset($filter['newsletter_id']) && !isset($filter['newsletters'])) { // make sure the newsletters are an array $filter['newsletters'] = [intval($filter['newsletter_id'])]; diff --git a/mailpoet/lib/Segments/DynamicSegments/FilterDataMapper.php b/mailpoet/lib/Segments/DynamicSegments/FilterDataMapper.php index d806c8522a..9193233492 100644 --- a/mailpoet/lib/Segments/DynamicSegments/FilterDataMapper.php +++ b/mailpoet/lib/Segments/DynamicSegments/FilterDataMapper.php @@ -153,7 +153,7 @@ class FilterDataMapper { 'operator' => $data['operator'] ?? DynamicSegmentFilterData::OPERATOR_ANY, ]; - if (($data['action'] !== EmailAction::ACTION_OPENED) && ($data['action'] !== EmailAction::ACTION_NOT_OPENED)) { + if (($data['action'] === EmailAction::ACTION_CLICKED) || ($data['action'] === EmailAction::ACTION_NOT_CLICKED)) { if (empty($data['newsletter_id'])) throw new InvalidFilterException('Missing newsletter id', InvalidFilterException::MISSING_NEWSLETTER_ID); $filterData['newsletter_id'] = $data['newsletter_id']; } else { diff --git a/mailpoet/lib/Segments/DynamicSegments/Filters/EmailAction.php b/mailpoet/lib/Segments/DynamicSegments/Filters/EmailAction.php index de864d2f87..5bb04e405c 100644 --- a/mailpoet/lib/Segments/DynamicSegments/Filters/EmailAction.php +++ b/mailpoet/lib/Segments/DynamicSegments/Filters/EmailAction.php @@ -107,7 +107,7 @@ class EmailAction implements Filter { } private function applyForOpenedActions(QueryBuilder $queryBuilder, DynamicSegmentFilterData $filterData, string $parameterSuffix) { - $operator = $filterData->getParam('operator'); + $operator = $filterData->getParam('operator') ?? DynamicSegmentFilterData::OPERATOR_ANY; $action = $filterData->getAction(); if ($action === self::ACTION_NOT_OPENED) { @@ -130,7 +130,7 @@ class EmailAction implements Filter { $where = '1'; - if (($action === EmailAction::ACTION_OPENED) && ($operator === DynamicSegmentFilterData::OPERATOR_NONE)) { + if ($operator === DynamicSegmentFilterData::OPERATOR_NONE) { $queryBuilder = $queryBuilder->innerJoin( $subscribersTable, $statsSentTable, @@ -143,7 +143,7 @@ class EmailAction implements Filter { "statssent.subscriber_id = stats.subscriber_id AND stats.newsletter_id IN (:newsletters" . $parameterSuffix . ')' )->setParameter('newsletters' . $parameterSuffix, $newsletters, Connection::PARAM_INT_ARRAY); $where .= ' AND stats.id IS NULL'; - } elseif ($action === EmailAction::ACTION_OPENED) { + } else { $queryBuilder = $queryBuilder->innerJoin( $subscribersTable, $statsTable, @@ -155,13 +155,6 @@ class EmailAction implements Filter { $queryBuilder->groupBy('subscriber_id'); $queryBuilder->having('COUNT(1) = ' . count($newsletters)); } - } else { // Machine opens - $queryBuilder = $queryBuilder->innerJoin( - $subscribersTable, - $statsTable, - 'stats', - "stats.subscriber_id = $subscribersTable.id AND stats.newsletter_id = :newsletter" . $parameterSuffix - )->setParameter('newsletter' . $parameterSuffix, $newsletterId); } if (($action === EmailAction::ACTION_OPENED) && ($operator !== DynamicSegmentFilterData::OPERATOR_NONE)) { $queryBuilder->andWhere('stats.user_agent_type = :userAgentType') diff --git a/mailpoet/tests/integration/Segments/DynamicSegments/Filters/EmailActionTest.php b/mailpoet/tests/integration/Segments/DynamicSegments/Filters/EmailActionTest.php index 6338bfaf4a..3359abf37b 100644 --- a/mailpoet/tests/integration/Segments/DynamicSegments/Filters/EmailActionTest.php +++ b/mailpoet/tests/integration/Segments/DynamicSegments/Filters/EmailActionTest.php @@ -289,14 +289,14 @@ class EmailActionTest extends \MailPoetTest { $open->setUserAgent($userAgent); $this->entityManager->flush(); - $segmentFilter = $this->getSegmentFilter(EmailAction::ACTION_OPENED, ['newsletter_id' => (int)$this->newsletter->getId()]); + $segmentFilter = $this->getSegmentFilter(EmailAction::ACTION_OPENED, ['newsletters' => [(int)$this->newsletter->getId()]]); $statement = $this->emailAction->apply($this->getQueryBuilder(), $segmentFilter)->execute(); $this->assertInstanceOf(Statement::class, $statement); $result = $statement->rowCount(); expect($result)->equals(2); } - public function testMachineOpens() { + public function testMachineOpensAny() { $subscriberOpenedMachine = $this->createSubscriber('opened_machine@example.com'); $this->createStatsNewsletter($subscriberOpenedMachine, $this->newsletter); $open = $this->createStatisticsOpens($subscriberOpenedMachine, $this->newsletter); @@ -306,7 +306,43 @@ class EmailActionTest extends \MailPoetTest { $open->setUserAgent($userAgent); $this->entityManager->flush(); - $segmentFilter = $this->getSegmentFilter(EmailAction::ACTION_MACHINE_OPENED, ['newsletter_id' => (int)$this->newsletter->getId()]); + $segmentFilter = $this->getSegmentFilter( + EmailAction::ACTION_MACHINE_OPENED, + ['newsletters' => [ + (int)$this->newsletter->getId(), + (int)$this->newsletter2->getId(), + ]] + ); + $statement = $this->emailAction->apply($this->getQueryBuilder(), $segmentFilter)->execute(); + $this->assertInstanceOf(Statement::class, $statement); + $result = $statement->rowCount(); + expect($result)->equals(1); + } + + public function testMachineOpensAll() { + $subscriberOpenedMachine = $this->createSubscriber('opened_machine@example.com'); + $this->createStatsNewsletter($subscriberOpenedMachine, $this->newsletter); + $this->createStatsNewsletter($subscriberOpenedMachine, $this->newsletter2); + $open1 = $this->createStatisticsOpens($subscriberOpenedMachine, $this->newsletter); + $open1->setUserAgentType(UserAgentEntity::USER_AGENT_TYPE_MACHINE); + $open2 = $this->createStatisticsOpens($subscriberOpenedMachine, $this->newsletter2); + $open2->setUserAgentType(UserAgentEntity::USER_AGENT_TYPE_MACHINE); + $userAgent = new UserAgentEntity(UserAgentEntity::MACHINE_USER_AGENTS[0]); + $this->entityManager->persist($userAgent); + $open1->setUserAgent($userAgent); + $open2->setUserAgent($userAgent); + $this->entityManager->flush(); + + $segmentFilter = $this->getSegmentFilter( + EmailAction::ACTION_MACHINE_OPENED, + [ + 'newsletters' => [ + (int)$this->newsletter->getId(), + (int)$this->newsletter2->getId(), + ], + 'operator' => DynamicSegmentFilterData::OPERATOR_ALL, + ] + ); $statement = $this->emailAction->apply($this->getQueryBuilder(), $segmentFilter)->execute(); $this->assertInstanceOf(Statement::class, $statement); $result = $statement->rowCount();