Add multiple emails support with any of and all of for machine-opened

[MAILPOET-3957]
This commit is contained in:
Rostislav Wolny
2022-01-13 13:06:54 +01:00
committed by Veljko V
parent 743276c057
commit ea8bfdc863
5 changed files with 50 additions and 18 deletions

View File

@ -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<Props> = ({ 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<Props> = ({ filt
>
<option value={AnyValueTypes.ANY}>{MailPoet.I18n.t('anyOf')}</option>
<option value={AnyValueTypes.ALL}>{MailPoet.I18n.t('allOf')}</option>
<option value={AnyValueTypes.NONE}>{MailPoet.I18n.t('noneOf')}</option>
{segment.action === EmailActionTypes.OPENED ? <option value={AnyValueTypes.NONE}>{MailPoet.I18n.t('noneOf')}</option> : null}
</Select>
</Grid.CenteredRow>
<Grid.CenteredRow>

View File

@ -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'])];

View File

@ -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 {

View File

@ -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')

View File

@ -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();