diff --git a/mailpoet/lib/Segments/DynamicSegments/Filters/MailPoetCustomFields.php b/mailpoet/lib/Segments/DynamicSegments/Filters/MailPoetCustomFields.php index f76b5a8529..1424c0eb18 100644 --- a/mailpoet/lib/Segments/DynamicSegments/Filters/MailPoetCustomFields.php +++ b/mailpoet/lib/Segments/DynamicSegments/Filters/MailPoetCustomFields.php @@ -37,9 +37,8 @@ class MailPoetCustomFields implements Filter { $subscribersTable, $subscribersCustomFieldTable, 'subscribers_custom_field', - "$subscribersTable.id = subscribers_custom_field.subscriber_id" + "$subscribersTable.id = subscribers_custom_field.subscriber_id AND subscribers_custom_field.custom_field_id = $customFieldIdParam" ); - $queryBuilder->andWhere("subscribers_custom_field.custom_field_id = $customFieldIdParam"); $queryBuilder->setParameter($customFieldIdParam, $customFieldId); $valueParam = ':value' . $parameterSuffix; @@ -66,7 +65,13 @@ class MailPoetCustomFields implements Filter { $value = $filterData->getParam('value'); $operator = $filterData->getParam('operator'); $queryBuilder->setParameter($valueParam, $value); - if ($dateType === 'month') { + if ($operator === 'is_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NULL'); + return $queryBuilder; + } elseif ($operator === 'is_not_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NOT NULL'); + return $queryBuilder; + } elseif ($dateType === 'month') { return $this->applyForDateMonth($queryBuilder, $valueParam); } elseif ($dateType === 'year') { return $this->applyForDateYear($queryBuilder, $operator, $valueParam); @@ -106,10 +111,15 @@ class MailPoetCustomFields implements Filter { private function applyForCheckbox(QueryBuilder $queryBuilder, DynamicSegmentFilterEntity $filter): QueryBuilder { $filterData = $filter->getFilterData(); $value = $filterData->getParam('value'); + $operator = $filterData->getParam('operator'); - if ($value === '1') { + if ($operator === 'is_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NULL'); + } elseif ($operator === 'is_not_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NOT NULL'); + } elseif ($value === '1') { $queryBuilder->andWhere('subscribers_custom_field.value = 1'); - } else { + } elseif ($value === '0') { $queryBuilder->andWhere('subscribers_custom_field.value <> 1'); } return $queryBuilder; @@ -134,6 +144,10 @@ class MailPoetCustomFields implements Filter { } elseif ($operator === 'less_than') { $queryBuilder->andWhere("subscribers_custom_field.value < $valueParam"); $queryBuilder->setParameter($valueParam, $value); + } elseif ($operator === 'is_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NULL'); + } elseif ($operator === 'is_not_blank') { + $queryBuilder->andWhere('subscribers_custom_field.value IS NOT NULL'); } else { $queryBuilder->andWhere("subscribers_custom_field.value LIKE $valueParam"); $queryBuilder->setParameter($valueParam, '%' . Helpers::escapeSearch($value) . '%'); diff --git a/mailpoet/tests/integration/Segments/DynamicSegments/Filters/MailPoetCustomFieldsTest.php b/mailpoet/tests/integration/Segments/DynamicSegments/Filters/MailPoetCustomFieldsTest.php index d2d1044e4e..4e5a6b8941 100644 --- a/mailpoet/tests/integration/Segments/DynamicSegments/Filters/MailPoetCustomFieldsTest.php +++ b/mailpoet/tests/integration/Segments/DynamicSegments/Filters/MailPoetCustomFieldsTest.php @@ -276,6 +276,185 @@ class MailPoetCustomFieldsTest extends \MailPoetTest { $this->assertEqualsCanonicalizing([$this->subscribers[1]->getEmail(), $this->subscribers[2]->getEmail()], $emails); } + public function testTextInputWorksWithBlankOptions(): void { + $subscriber = $this->subscribers[1]; + $customField = $this->createCustomField(CustomFieldEntity::TYPE_TEXT); + $this->entityManager->persist(new SubscriberCustomFieldEntity($subscriber, $customField, '1')); + $this->entityManager->persist($customField); + $this->entityManager->flush(); + $blankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_TEXT, + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_TEXT, + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankData, $this->filter); + $this->assertEqualsCanonicalizing([$subscriber->getEmail()], $emails); + } + + public function testTextAreaWorksWithBlankOptions(): void { + $subscriber = $this->subscribers[1]; + $customField = $this->createCustomField(CustomFieldEntity::TYPE_TEXT); + $this->entityManager->persist(new SubscriberCustomFieldEntity($subscriber, $customField, '1')); + $this->entityManager->persist($customField); + $this->entityManager->flush(); + $blankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_TEXT, + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_TEXT, + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankData, $this->filter); + $this->assertEqualsCanonicalizing([$subscriber->getEmail()], $emails); + } + + public function testFullDateWorksWithBlankOptions(): void { + $customField = $this->createCustomField(CustomFieldEntity::TYPE_DATE); + $this->entityManager->persist($customField); + $this->entityManager->persist(new SubscriberCustomFieldEntity($this->subscribers[1], $customField, '2017-04-01 00:00:00')); + $this->entityManager->flush(); + $blankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'year_month_day', + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'year_month_day', + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[1]->getEmail()], $emails); + } + + public function testYearWorksWithBlankOptions(): void { + $customField = $this->createCustomField(CustomFieldEntity::TYPE_DATE); + $this->entityManager->persist($customField); + $this->entityManager->persist(new SubscriberCustomFieldEntity($this->subscribers[1], $customField, '2017-04-01 00:00:00')); + $this->entityManager->flush(); + $blankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'year', + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'year', + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[1]->getEmail()], $emails); + } + + public function testDateMonthWorksWithBlankOptions(): void { + $customField = $this->createCustomField(CustomFieldEntity::TYPE_DATE); + $this->entityManager->persist($customField); + $this->entityManager->persist(new SubscriberCustomFieldEntity($this->subscribers[1], $customField, '2017-04-01 00:00:00')); + $this->entityManager->flush(); + $blankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'month', + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_DATE, + 'date_type' => 'month', + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[1]->getEmail()], $emails); + } + + public function testRadioButtonsWorksWithBlankOptions(): void { + $subscriber = $this->subscribers[1]; + $customField = $this->createCustomField(CustomFieldEntity::TYPE_RADIO); + $this->entityManager->persist(new SubscriberCustomFieldEntity($subscriber, $customField, 'Option 2')); + $this->entityManager->persist($customField); + $this->entityManager->flush(); + $blankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_RADIO, + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_RADIO, + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$subscriber->getEmail()], $emails); + } + + public function testCheckboxWorksWithBlankOptions(): void { + $subscriber = $this->subscribers[1]; + $customField = $this->createCustomField(CustomFieldEntity::TYPE_CHECKBOX); + $this->entityManager->persist(new SubscriberCustomFieldEntity($subscriber, $customField, '1')); + $this->entityManager->persist($customField); + $this->entityManager->flush(); + $blankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_CHECKBOX, + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_CHECKBOX, + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$subscriber->getEmail()], $emails); + } + + public function testSelectWorksWithBlankOptions(): void { + $subscriber = $this->subscribers[1]; + $customField = $this->createCustomField(CustomFieldEntity::TYPE_SELECT); + $this->entityManager->persist(new SubscriberCustomFieldEntity($subscriber, $customField, 'Option 2')); + $this->entityManager->persist($customField); + $this->entityManager->flush(); + $blankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_SELECT, + 'operator' => 'is_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($blankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$this->subscribers[0]->getEmail(), $this->subscribers[2]->getEmail()], $emails); + $notBlankFilterData = new DynamicSegmentFilterData(DynamicSegmentFilterData::TYPE_USER_ROLE, MailPoetCustomFields::TYPE, [ + 'custom_field_id' => $customField->getId(), + 'custom_field_type' => CustomFieldEntity::TYPE_SELECT, + 'operator' => 'is_not_blank', + ]); + $emails = $this->tester->getSubscriberEmailsMatchingDynamicFilter($notBlankFilterData, $this->filter); + $this->assertEqualsCanonicalizing([$subscriber->getEmail()], $emails); + } + private function createSubscriber(string $email): SubscriberEntity { $subscriber = new SubscriberEntity(); $subscriber->setEmail($email);