Implement new WooCommerce dynamic segment based on the number of orders
[MAILPOET-3228]
This commit is contained in:
@ -10,13 +10,17 @@ import {
|
|||||||
WooCommerceFormItem,
|
WooCommerceFormItem,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { SegmentFormData } from '../segment_form_data';
|
import { SegmentFormData } from '../segment_form_data';
|
||||||
|
import { Grid } from '../../../common/grid';
|
||||||
|
import Input from '../../../common/form/input/input';
|
||||||
|
|
||||||
export const WooCommerceOptions = [
|
export const WooCommerceOptions = [
|
||||||
|
{ value: 'numberOfOrders', label: MailPoet.I18n.t('wooNumberOfOrders'), group: SegmentTypes.WooCommerce },
|
||||||
{ value: 'purchasedCategory', label: MailPoet.I18n.t('wooPurchasedCategory'), group: SegmentTypes.WooCommerce },
|
{ value: 'purchasedCategory', label: MailPoet.I18n.t('wooPurchasedCategory'), group: SegmentTypes.WooCommerce },
|
||||||
{ value: 'purchasedProduct', label: MailPoet.I18n.t('wooPurchasedProduct'), group: SegmentTypes.WooCommerce },
|
{ value: 'purchasedProduct', label: MailPoet.I18n.t('wooPurchasedProduct'), group: SegmentTypes.WooCommerce },
|
||||||
];
|
];
|
||||||
|
|
||||||
enum WooCommerceActionTypes {
|
enum WooCommerceActionTypes {
|
||||||
|
NUMBER_OF_ORDERS = 'numberOfOrders',
|
||||||
PURCHASED_CATEGORY = 'purchasedCategory',
|
PURCHASED_CATEGORY = 'purchasedCategory',
|
||||||
PURCHASED_PRODUCT = 'purchasedProduct',
|
PURCHASED_PRODUCT = 'purchasedProduct',
|
||||||
}
|
}
|
||||||
@ -35,6 +39,9 @@ export function validateWooCommerce(formItems: WooCommerceFormItem): boolean {
|
|||||||
if (formItems.action === 'purchasedProduct' && !formItems.product_id) {
|
if (formItems.action === 'purchasedProduct' && !formItems.product_id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (formItems.action === 'numberOfOrders' && (!formItems.number_of_orders_count || !formItems.number_of_orders_days || !formItems.number_of_orders_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +61,16 @@ export const WooCommerceFields: React.FunctionComponent<Props> = ({ onChange, it
|
|||||||
label: product.name,
|
label: product.name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const numberOfOrdersTypeOptions = [
|
||||||
|
{ value: '=', label: 'equals' },
|
||||||
|
{ value: '>', label: 'more than' },
|
||||||
|
{ value: '<', label: 'less than' },
|
||||||
|
];
|
||||||
|
|
||||||
|
let optionFields;
|
||||||
|
|
||||||
if (item.action === WooCommerceActionTypes.PURCHASED_PRODUCT) {
|
if (item.action === WooCommerceActionTypes.PURCHASED_PRODUCT) {
|
||||||
return (
|
optionFields = (
|
||||||
<Select
|
<Select
|
||||||
isFullWidth
|
isFullWidth
|
||||||
placeholder={MailPoet.I18n.t('selectWooPurchasedProduct')}
|
placeholder={MailPoet.I18n.t('selectWooPurchasedProduct')}
|
||||||
@ -68,9 +83,8 @@ export const WooCommerceFields: React.FunctionComponent<Props> = ({ onChange, it
|
|||||||
automationId="select-segment-product"
|
automationId="select-segment-product"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
} else if (item.action === WooCommerceActionTypes.PURCHASED_CATEGORY) {
|
||||||
|
optionFields = (
|
||||||
return (
|
|
||||||
<Select
|
<Select
|
||||||
isFullWidth
|
isFullWidth
|
||||||
placeholder={MailPoet.I18n.t('selectWooPurchasedCategory')}
|
placeholder={MailPoet.I18n.t('selectWooPurchasedCategory')}
|
||||||
@ -83,4 +97,51 @@ export const WooCommerceFields: React.FunctionComponent<Props> = ({ onChange, it
|
|||||||
automationId="select-segment-category"
|
automationId="select-segment-category"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else if (item.action === WooCommerceActionTypes.NUMBER_OF_ORDERS) {
|
||||||
|
if (!item.number_of_orders_type) {
|
||||||
|
item.number_of_orders_type = '=';
|
||||||
|
}
|
||||||
|
|
||||||
|
optionFields = (
|
||||||
|
<div>
|
||||||
|
<Grid.CenteredRow className="mailpoet-form-field">
|
||||||
|
<Select
|
||||||
|
options={numberOfOrdersTypeOptions}
|
||||||
|
value={find(['value', item.number_of_orders_type], numberOfOrdersTypeOptions)}
|
||||||
|
onChange={(option: SelectOption): void => compose([
|
||||||
|
onChange,
|
||||||
|
assign(item),
|
||||||
|
])({ number_of_orders_type: option.value })}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
value={item.number_of_orders_count || ''}
|
||||||
|
placeholder="count"
|
||||||
|
onChange={(event): void => compose([
|
||||||
|
onChange,
|
||||||
|
assign(item),
|
||||||
|
])({ number_of_orders_count: event.target.value })}
|
||||||
|
/>
|
||||||
|
<div>orders</div>
|
||||||
|
</Grid.CenteredRow>
|
||||||
|
<Grid.CenteredRow className="mailpoet-form-field">
|
||||||
|
<div>in the last</div>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
value={item.number_of_orders_days || ''}
|
||||||
|
placeholder="days"
|
||||||
|
onChange={(event): void => compose([
|
||||||
|
onChange,
|
||||||
|
assign(item),
|
||||||
|
])({ number_of_orders_days: event.target.value })}
|
||||||
|
/>
|
||||||
|
<div>days</div>
|
||||||
|
</Grid.CenteredRow>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionFields;
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,9 @@ const allowedItemKeys: string[] = [
|
|||||||
'days',
|
'days',
|
||||||
'opens',
|
'opens',
|
||||||
'operator',
|
'operator',
|
||||||
|
'number_of_orders_type',
|
||||||
|
'number_of_orders_count',
|
||||||
|
'number_of_orders_days',
|
||||||
];
|
];
|
||||||
|
|
||||||
function loadCount(formItem: AnyFormItem): Promise<Result | void> {
|
function loadCount(formItem: AnyFormItem): Promise<Result | void> {
|
||||||
|
@ -35,6 +35,9 @@ export interface WooCommerceFormItem extends FormItem {
|
|||||||
action?: string;
|
action?: string;
|
||||||
category_id?: string;
|
category_id?: string;
|
||||||
product_id?: string;
|
product_id?: string;
|
||||||
|
number_of_orders_type?: string;
|
||||||
|
number_of_orders_count?: number;
|
||||||
|
number_of_orders_days?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EmailFormItem extends FormItem {
|
export interface EmailFormItem extends FormItem {
|
||||||
|
@ -137,6 +137,8 @@ class DynamicSegments extends APIEndpoint {
|
|||||||
return WPFunctions::get()->__('Please select category.', 'mailpoet');
|
return WPFunctions::get()->__('Please select category.', 'mailpoet');
|
||||||
case InvalidFilterException::MISSING_VALUE:
|
case InvalidFilterException::MISSING_VALUE:
|
||||||
return WPFunctions::get()->__('Please fill all required values.', 'mailpoet');
|
return WPFunctions::get()->__('Please fill all required values.', 'mailpoet');
|
||||||
|
case InvalidFilterException::MISSING_NUMBER_OF_ORDERS_FIELDS:
|
||||||
|
return WPFunctions::get()->__('Please select a type for the comparison, a number of orders and a number of days.', 'mailpoet');
|
||||||
default:
|
default:
|
||||||
return WPFunctions::get()->__('An error occurred while saving data.', 'mailpoet');
|
return WPFunctions::get()->__('An error occurred while saving data.', 'mailpoet');
|
||||||
}
|
}
|
||||||
|
@ -271,8 +271,9 @@ class ContainerConfigurator implements IContainerConfigurator {
|
|||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\EmailAction::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\EmailAction::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\UserRole::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\UserRole::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct::class)->setPublic(true);
|
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory::class)->setPublic(true);
|
||||||
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders::class)->setPublic(true);
|
||||||
|
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\SegmentSaveController::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\SegmentSaveController::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\FilterDataMapper::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\FilterDataMapper::class)->setPublic(true);
|
||||||
// Services
|
// Services
|
||||||
|
@ -15,5 +15,6 @@ class InvalidFilterException extends InvalidStateException {
|
|||||||
const MISSING_PRODUCT_ID = 7;
|
const MISSING_PRODUCT_ID = 7;
|
||||||
const INVALID_EMAIL_ACTION = 8;
|
const INVALID_EMAIL_ACTION = 8;
|
||||||
const MISSING_VALUE = 9;
|
const MISSING_VALUE = 9;
|
||||||
|
const MISSING_NUMBER_OF_ORDERS_FIELDS = 10;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@ use MailPoet\Segments\DynamicSegments\Exceptions\InvalidFilterException;
|
|||||||
use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
|
use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
||||||
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
||||||
|
|
||||||
class FilterDataMapper {
|
class FilterDataMapper {
|
||||||
@ -87,6 +88,13 @@ class FilterDataMapper {
|
|||||||
} elseif ($data['action'] === WooCommerceProduct::ACTION_PRODUCT) {
|
} elseif ($data['action'] === WooCommerceProduct::ACTION_PRODUCT) {
|
||||||
if (!isset($data['product_id'])) throw new InvalidFilterException('Missing product', InvalidFilterException::MISSING_PRODUCT_ID);
|
if (!isset($data['product_id'])) throw new InvalidFilterException('Missing product', InvalidFilterException::MISSING_PRODUCT_ID);
|
||||||
$filterData['product_id'] = $data['product_id'];
|
$filterData['product_id'] = $data['product_id'];
|
||||||
|
} elseif ($data['action'] === WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS) {
|
||||||
|
if (!isset($data['number_of_orders_type']) || !isset($data['number_of_orders_count']) || !isset($data['number_of_orders_days'])) {
|
||||||
|
throw new InvalidFilterException('Missing required fields', InvalidFilterException::MISSING_NUMBER_OF_ORDERS_FIELDS);
|
||||||
|
}
|
||||||
|
$filterData['number_of_orders_type'] = $data['number_of_orders_type'];
|
||||||
|
$filterData['number_of_orders_count'] = $data['number_of_orders_count'];
|
||||||
|
$filterData['number_of_orders_days'] = $data['number_of_orders_days'];
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidFilterException("Unknown action " . $data['action'], InvalidFilterException::MISSING_ACTION);
|
throw new InvalidFilterException("Unknown action " . $data['action'], InvalidFilterException::MISSING_ACTION);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
|
|||||||
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\UserRole;
|
use MailPoet\Segments\DynamicSegments\Filters\UserRole;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
||||||
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
||||||
use MailPoet\Segments\SegmentDependencyValidator;
|
use MailPoet\Segments\SegmentDependencyValidator;
|
||||||
use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder;
|
use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder;
|
||||||
@ -29,6 +30,9 @@ class FilterHandler {
|
|||||||
/** @var WooCommerceCategory */
|
/** @var WooCommerceCategory */
|
||||||
private $wooCommerceCategory;
|
private $wooCommerceCategory;
|
||||||
|
|
||||||
|
/** @var WooCommerceNumberOfOrders */
|
||||||
|
private $wooCommerceNumberOfOrders;
|
||||||
|
|
||||||
/** @var EntityManager */
|
/** @var EntityManager */
|
||||||
private $entityManager;
|
private $entityManager;
|
||||||
|
|
||||||
@ -45,12 +49,14 @@ class FilterHandler {
|
|||||||
WooCommerceProduct $wooCommerceProduct,
|
WooCommerceProduct $wooCommerceProduct,
|
||||||
WooCommerceCategory $wooCommerceCategory,
|
WooCommerceCategory $wooCommerceCategory,
|
||||||
EmailOpensAbsoluteCountAction $emailOpensAbsoluteCount,
|
EmailOpensAbsoluteCountAction $emailOpensAbsoluteCount,
|
||||||
SegmentDependencyValidator $segmentDependencyValidator
|
SegmentDependencyValidator $segmentDependencyValidator,
|
||||||
|
WooCommerceNumberOfOrders $wooCommerceNumberOfOrders
|
||||||
) {
|
) {
|
||||||
$this->emailAction = $emailAction;
|
$this->emailAction = $emailAction;
|
||||||
$this->userRole = $userRole;
|
$this->userRole = $userRole;
|
||||||
$this->wooCommerceProduct = $wooCommerceProduct;
|
$this->wooCommerceProduct = $wooCommerceProduct;
|
||||||
$this->wooCommerceCategory = $wooCommerceCategory;
|
$this->wooCommerceCategory = $wooCommerceCategory;
|
||||||
|
$this->wooCommerceNumberOfOrders = $wooCommerceNumberOfOrders;
|
||||||
$this->entityManager = $entityManager;
|
$this->entityManager = $entityManager;
|
||||||
$this->segmentDependencyValidator = $segmentDependencyValidator;
|
$this->segmentDependencyValidator = $segmentDependencyValidator;
|
||||||
$this->emailOpensAbsoluteCount = $emailOpensAbsoluteCount;
|
$this->emailOpensAbsoluteCount = $emailOpensAbsoluteCount;
|
||||||
@ -127,6 +133,8 @@ class FilterHandler {
|
|||||||
$action = $filterData->getParam('action');
|
$action = $filterData->getParam('action');
|
||||||
if ($action === WooCommerceProduct::ACTION_PRODUCT) {
|
if ($action === WooCommerceProduct::ACTION_PRODUCT) {
|
||||||
return $this->wooCommerceProduct->apply($queryBuilder, $filter);
|
return $this->wooCommerceProduct->apply($queryBuilder, $filter);
|
||||||
|
} elseif ($action === WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS) {
|
||||||
|
return $this->wooCommerceNumberOfOrders->apply($queryBuilder, $filter);
|
||||||
}
|
}
|
||||||
return $this->wooCommerceCategory->apply($queryBuilder, $filter);
|
return $this->wooCommerceCategory->apply($queryBuilder, $filter);
|
||||||
default:
|
default:
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MailPoet\Segments\DynamicSegments\Filters;
|
||||||
|
|
||||||
|
use MailPoet\Entities\DynamicSegmentFilterEntity;
|
||||||
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder;
|
||||||
|
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
class WooCommerceNumberOfOrders implements Filter {
|
||||||
|
const ACTION_NUMBER_OF_ORDERS = 'numberOfOrders';
|
||||||
|
|
||||||
|
/** @var EntityManager */
|
||||||
|
private $entityManager;
|
||||||
|
|
||||||
|
public function __construct(EntityManager $entityManager) {
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apply(QueryBuilder $queryBuilder, DynamicSegmentFilterEntity $filter): QueryBuilder {
|
||||||
|
global $wpdb;
|
||||||
|
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
|
||||||
|
$filterData = $filter->getFilterData();
|
||||||
|
$type = $filterData->getParam('number_of_orders_type');
|
||||||
|
$count = $filterData->getParam('number_of_orders_count');
|
||||||
|
$days = $filterData->getParam('number_of_orders_days');
|
||||||
|
|
||||||
|
$date = Carbon::now()->subDays($days);
|
||||||
|
|
||||||
|
$queryBuilder->innerJoin(
|
||||||
|
$subscribersTable,
|
||||||
|
$wpdb->postmeta,
|
||||||
|
'postmeta',
|
||||||
|
"postmeta.meta_key = '_customer_user' AND $subscribersTable.wp_user_id=postmeta.meta_value"
|
||||||
|
)->leftJoin(
|
||||||
|
'postmeta',
|
||||||
|
$wpdb->posts,
|
||||||
|
'posts',
|
||||||
|
'posts.ID = postmeta.post_id AND posts.post_date >= :date AND postmeta.post_id NOT IN ( SELECT id FROM ' . $wpdb->posts . ' as p WHERE p.post_status IN ("wc-cancelled", "wc-failed"))'
|
||||||
|
)->setParameter(
|
||||||
|
'date', $date->toDateTimeString()
|
||||||
|
)->groupBy(
|
||||||
|
'inner_subscriber_id'
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($type === '=') {
|
||||||
|
$queryBuilder->having("COUNT(posts.ID) = :count");
|
||||||
|
} elseif ($type === '>') {
|
||||||
|
$queryBuilder->having("COUNT(posts.ID) > :count");
|
||||||
|
} elseif ($type === '<') {
|
||||||
|
$queryBuilder->having("COUNT(posts.ID) < :count");
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryBuilder->setParameter('count', $count);
|
||||||
|
|
||||||
|
return $queryBuilder;
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ use MailPoet\Segments\DynamicSegments\Exceptions\InvalidFilterException;
|
|||||||
use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
|
use MailPoet\Segments\DynamicSegments\Filters\EmailAction;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
use MailPoet\Segments\DynamicSegments\Filters\EmailOpensAbsoluteCountAction;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
|
||||||
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
|
||||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
||||||
|
|
||||||
class FilterDataMapperTest extends \MailPoetUnitTest {
|
class FilterDataMapperTest extends \MailPoetUnitTest {
|
||||||
@ -226,4 +227,35 @@ class FilterDataMapperTest extends \MailPoetUnitTest {
|
|||||||
$this->expectException(InvalidFilterException::class);
|
$this->expectException(InvalidFilterException::class);
|
||||||
$this->mapper->map($data);
|
$this->mapper->map($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItMapsWooCommerceNumberOfOrders() {
|
||||||
|
$data = [
|
||||||
|
'segmentType' => DynamicSegmentFilterData::TYPE_WOOCOMMERCE,
|
||||||
|
'action' => WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS,
|
||||||
|
'number_of_orders_type' => '=',
|
||||||
|
'number_of_orders_count' => 2,
|
||||||
|
'number_of_orders_days' => 1,
|
||||||
|
'some_mess' => 'mess',
|
||||||
|
];
|
||||||
|
|
||||||
|
$filter = $this->mapper->map($data);
|
||||||
|
|
||||||
|
unset($data['some_mess']);
|
||||||
|
$expectedResult = $data;
|
||||||
|
|
||||||
|
expect($filter)->isInstanceOf(DynamicSegmentFilterData::class);
|
||||||
|
expect($filter->getFilterType())->equals(DynamicSegmentFilterData::TYPE_WOOCOMMERCE);
|
||||||
|
expect($filter->getData())->equals($expectedResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItRaisesExceptionWhenMappingWooCommerceNumberOfOrders() {
|
||||||
|
$this->expectException(InvalidFilterException::class);
|
||||||
|
$this->expectExceptionMessage('Missing required fields');
|
||||||
|
$this->expectExceptionCode(InvalidFilterException::MISSING_NUMBER_OF_ORDERS_FIELDS);
|
||||||
|
|
||||||
|
$this->mapper->map([
|
||||||
|
'segmentType' => DynamicSegmentFilterData::TYPE_WOOCOMMERCE,
|
||||||
|
'action' => WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,7 @@
|
|||||||
'multipleDynamicSegmentsDeleted': __('%$1d segments were permanently deleted.'),
|
'multipleDynamicSegmentsDeleted': __('%$1d segments were permanently deleted.'),
|
||||||
'oneDynamicSegmentDeleted': __('1 segment was permanently deleted.'),
|
'oneDynamicSegmentDeleted': __('1 segment was permanently deleted.'),
|
||||||
|
|
||||||
|
'wooNumberOfOrders': __('# of orders'),
|
||||||
'wooPurchasedCategory': __('purchased in this category'),
|
'wooPurchasedCategory': __('purchased in this category'),
|
||||||
'wooPurchasedProduct': __('purchased this product'),
|
'wooPurchasedProduct': __('purchased this product'),
|
||||||
'selectWooPurchasedCategory': __('Search category'),
|
'selectWooPurchasedCategory': __('Search category'),
|
||||||
|
Reference in New Issue
Block a user