Skip to content

Commit

Permalink
Merge branch '1279-force-no-variant-subscription' into 'master'
Browse files Browse the repository at this point in the history
Add flag to Subscribe APIs to prevent default variant subscribe behavior

See merge request remp/remp!783
  • Loading branch information
rootpd committed Jun 28, 2023
2 parents 39e4512 + 85782bf commit d5a7bc6
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' => 'example@example.com',
'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 d5a7bc6

Please sign in to comment.