Skip to content

Commit

Permalink
Add flag to Subscribe APIs to prevent default variant subscribe behavior
Browse files Browse the repository at this point in the history
This flag complements the change in variant subscription behavior
introduced in v2.2. Some clients need to have an option to subscribe
multi-variant newsletter list without actually subscribing any variants
(either default or all of them) automatically.

If the flag is set, variant subscription is suppressed and client needs
to subscribe the variants separately without use of the flag.

remp/remp#1279
  • Loading branch information
rootpd committed Jun 28, 2023
1 parent 39e4512 commit 85782bf
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Added validation for restricting the use of the same email variant in `NewBatchFromFactory` and `NewTemplateFormFactory`. remp/remp#1230
- Added configurable batch size to the `worker:mail` command; use `--batch-size=NUMBER` to set your own batch size. remp/remp#1238
- Fixed display issues of link stats table to display url in max. 3 lines and forbid horizontal scroll in table. remp/remp#1278
- Added flag `force_no_variant_subscription` to `/api/v1/users/subscribe` and `/api/v1/users/bulk-subscribe` APIs enabling client to prevent _default variant_ subscribe behavior (changed in the v2.2). remp/remp#1279

## Archive

Expand Down
14 changes: 12 additions & 2 deletions Mailer/extensions/mailer-module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,15 @@ API call subscribes email address to the given newsletter. Newsletter has to be
Currently, there's no API endpoint for that and the newsletter needs to be created manually.
Please visit `/list/new` to create a newsletter via web admin.

If newsletter list has variants, following behavior applies:

- For `is_multi_variant=true` newsletter **without** the default variant, all variants are subscribed when user subscribes to the newsletter.
- For `is_multi_variant=true` newsletter **with** the default variant, only the default variant is subscribed when user subscribes to the newsletter.
- For `is_multi_variant=false` newsletter **without** the default variant, no variant is subscribed automatically when user subscribes to the newsletter. Variant should be provided explicitly for this scenario.
- For `is_multi_Variant=false` newsletter **with** the default variant, the default variant is subscribed automatically unless the variant was provided explicitly.

Please be aware, that the described variant subscription behavior can be suppressed by sending `force_no_variant_subscription=true`. If sent, no variant is subscribed, even if it was provided explicitly.

##### *Headers:*

| Name | Value | Required | Description |
Expand All @@ -1385,6 +1394,7 @@ Please visit `/list/new` to create a newsletter via web admin.
"variant_id": 123, // Integer; ID of the newsletter variant to subscribe
"variant_code": "author.123", // String; Code of the newsletter variant to subscribe
"send_accompanying_emails": true, // Boolean; Whether to send welcome or goodbye email to the subscribed/unsubscribed user. Defaults to TRUE.
"force_no_variant_subscription": true, // Boolean; If list_id has variants, flag indicates whether the default behavior should be suppressed and no variant subscribed. Defaults to FALSE.

// optional RTM parameters for tracking "what" made the user unsubscribe
"rtm_params": { // Object; optional RTM parameters for pairing which email caused the user to unsubscribe. RTM params are generated into the email links automatically.
Expand Down Expand Up @@ -1544,7 +1554,6 @@ Bulk subscribe allows subscribing and unsubscribing multiple users in one batch.

"variant_id": 3, // Integer; ID of the variant of newsletter list you're subscribing user to. Must belong to provided list.
"variant_code": "author.123", // String; Code of the newsletter variant to subscribe

"subscribe": false, // Boolean; indicates if you want to subscribe or unsubscribe user

// optional RTM parameters used only if `subscribe:false` for tracking "what" made the user unsubscribe
Expand All @@ -1556,7 +1565,8 @@ Bulk subscribe allows subscribing and unsubscribing multiple users in one batch.
},

// optional
"send_accompanying_emails": true // Boolean; Flag whether to send welcome or goodbye email to the user whom subscription is being changed. Defaults to TRUE.
"send_accompanying_emails": true, // Boolean; Flag whether to send welcome or goodbye email to the user whom subscription is being changed. Defaults to TRUE.
"force_no_variant_subscription": true // Boolean; If list_id has variants, flag indicates whether the default behavior should be suppressed and no variant subscribed. Defaults to FALSE.
}
//...
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function handle(array $params): ResponseInterface
'subscribe' => $item['subscribe'],
'rtm_params' => $this->getRtmParams($item),
'send_accompanying_emails' => $item['send_accompanying_emails'] ?? true,
'force_no_variant_subscription' => $item['force_no_variant_subscription'] ?? false,
];
}

Expand All @@ -65,6 +66,7 @@ public function handle(array $params): ResponseInterface
variantId: $user['variant_id'],
sendWelcomeEmail: $user['send_accompanying_emails'],
rtmParams: $rtmParams,
forceNoVariantSubscription: $user['force_no_variant_subscription'],
);
} else {
// if email doesn't exist, no need to unsubscribe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ protected function processUserSubscription($payload): array
variantId: $variantID,
sendWelcomeEmail: $payload['send_accompanying_emails'] ?? true,
rtmParams: $this->getRtmParams($payload),
forceNoVariantSubscription: $payload['force_no_variant_subscription'] ?? false,
);

$subscribedVariantsData = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
},
"send_accompanying_emails": {
"type": "boolean"
},
"force_no_variant_subscription": {
"type": "boolean"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
"send_accompanying_emails": {
"type": "boolean"
},
"force_no_variant_subscription": {
"type": "boolean"
},
"rtm_params": {
"title": "RTM params",
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function add(
int $subscribeEmailTemplateId = null,
int $unSubscribeEmailTemplateId = null,
bool $isMultiVariant = false,
int $defaultVariantId = null,
): ActiveRow {
$result = $this->insert([
'mail_type_category_id' => $categoryId,
Expand All @@ -57,6 +58,7 @@ public function add(
'created_at' => new DateTime(),
'updated_at' => new DateTime(),
'is_multi_variant' => $isMultiVariant,
'default_variant_id' => $defaultVariantId,
]);

if (is_numeric($result)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public function subscribeUser(
int $variantId = null,
bool $sendWelcomeEmail = true,
array $rtmParams = [],
bool $forceNoVariantSubscription = false,
): ActiveRow {
if ($variantId === null) {
$variantId = $mailType->default_variant_id;
Expand Down Expand Up @@ -155,20 +156,23 @@ public function subscribeUser(
$this->emitUserSubscribedEvent($userId, $email, $mailType->id, $sendWelcomeEmail, $rtmParams);
}

if ($variantId) {
$variantSubscribed = $this->userSubscriptionVariantsRepository->variantSubscribed($actual, $variantId);
if (!$variantSubscribed) {
if (!$mailType->is_multi_variant) {
$this->userSubscriptionVariantsRepository->removeSubscribedVariants($actual);
if (!$forceNoVariantSubscription) {
if ($variantId) {
$variantSubscribed = $this->userSubscriptionVariantsRepository->variantSubscribed($actual, $variantId);
if (!$variantSubscribed) {
if (!$mailType->is_multi_variant) {
$this->userSubscriptionVariantsRepository->removeSubscribedVariants($actual);
}
$this->userSubscriptionVariantsRepository->addVariantSubscription($actual, $variantId);
}
} elseif (!$variantId && $mailType->is_multi_variant) {
// subscribe all mail variants for multi_variant type without default variant
foreach ($this->listVariantsRepository->getVariantsForType($mailType)->fetchAll() as $variant) {
$this->userSubscriptionVariantsRepository->addVariantSubscription($actual, $variant->id);
}
$this->userSubscriptionVariantsRepository->addVariantSubscription($actual, $variantId);
}
} elseif (!$variantId && $mailType->is_multi_variant) {
// subscribe all mail variants for multi_variant type without default variant
foreach ($this->listVariantsRepository->getVariantsForType($mailType)->fetchAll() as $variant) {
$this->userSubscriptionVariantsRepository->addVariantSubscription($actual, $variant->id);
}
}

return $actual;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,4 +286,77 @@ public function testFailingSubscribeWithInvalidVariantCode()
])->count('*');
$this->assertFalse($isSubscribed);
}

/**
* @dataProvider forceNoVariantSubscriptionDataProvider
*/
public function testUseOfForceNoVariantSubscriptionFlag(bool $multi, bool $default)
{
$mailType = $this->createMailTypeWithCategory(
categoryName: "category1",
typeCode: "code1",
typeName: "name1",
isMultiVariant: $multi,
);
$variant = $this->createMailTypeVariant($mailType, 'Foo', 'foo');

if ($default) {
$defaultVariant = $this->createMailTypeVariant($mailType, 'Bar', 'bar');
$this->listsRepository->update($mailType, [
'default_variant_id' => $defaultVariant->id,
]);
}

$payload = [
'user_id' => 123,
'email' => '[email protected]',
'list_code' => $mailType->code,
'variant_code' => $variant->code,
'force_no_variant_subscription' => true,
];

$params = [
'raw' => Json::encode($payload)
];

/** @var JsonApiResponse $response */
$response = $this->handler->handle($params);
$this->assertInstanceOf(JsonApiResponse::class, $response);
$this->assertEquals(IResponse::S200_OK, $response->getCode());

$userSubscription = $this->userSubscriptionsRepository->getUserSubscription(
mailType: $mailType,
userId: $payload['user_id'],
email: $payload['email']
);
$this->assertTrue((bool) $userSubscription->subscribed);

$isVariantSubscribed = (bool) $this->userSubscriptionVariantsRepository->getTable()->where([
'mail_user_subscription.user_id' => $payload['user_id'],
'mail_user_subscription.user_email' => $payload['email'],
])->count('*');
$this->assertFalse($isVariantSubscribed);
}

public function forceNoVariantSubscriptionDataProvider()
{
return [
'NoMultiVariant_NoDefaultVariant' => [
'multi' => false,
'default' => false,
],
'WithMultiVariant_NoDefaultVariant' => [
'multi' => true,
'default' => false,
],
'NoMultiVariant_WithDefaultVariant' => [
'multi' => false,
'default' => true,
],
'WithMultiVariant_WithDefaultVariant' => [
'multi' => true,
'default' => true,
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ protected function createMailTypeWithCategory(
string $typeCode = 'code',
string $typeName = 'name',
bool $publicListing = true,
bool $isMultiVariant = false
bool $isMultiVariant = false,
int $defaultVariantId = null,
) {
$listCategory = $this->createMailTypeCategory($categoryName);

Expand All @@ -168,6 +169,7 @@ protected function createMailTypeWithCategory(
description: 'XXX',
publicListing: $publicListing,
isMultiVariant: $isMultiVariant,
defaultVariantId: $defaultVariantId,
);
}

Expand Down

0 comments on commit 85782bf

Please sign in to comment.