From 85782bff647ac33be1ce0220af06f706e91e946b Mon Sep 17 00:00:00 2001 From: Peter Dulacka Date: Wed, 28 Jun 2023 09:40:09 +0000 Subject: [PATCH] Add flag to Subscribe APIs to prevent default variant subscribe behavior 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 --- CHANGELOG.md | 1 + Mailer/extensions/mailer-module/README.md | 14 +++- .../Handlers/Users/BulkSubscribeHandler.php | 2 + .../v1/Handlers/Users/SubscribeHandler.php | 1 + .../Handlers/Users/bulk-subscribe.schema.json | 3 + .../v1/Handlers/Users/subscribe.schema.json | 3 + .../src/Repositories/ListsRepository.php | 2 + .../UserSubscriptionsRepository.php | 26 ++++--- .../Handlers/Users/SubscribeHandlerTest.php | 73 +++++++++++++++++++ .../src/Tests/Feature/BaseFeatureTestCase.php | 4 +- 10 files changed, 115 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 798a4d233..88040de51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/Mailer/extensions/mailer-module/README.md b/Mailer/extensions/mailer-module/README.md index 52270aff1..33c6da49f 100644 --- a/Mailer/extensions/mailer-module/README.md +++ b/Mailer/extensions/mailer-module/README.md @@ -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 | @@ -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. @@ -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 @@ -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. } //... ] diff --git a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/BulkSubscribeHandler.php b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/BulkSubscribeHandler.php index 2aefb4762..934870a99 100644 --- a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/BulkSubscribeHandler.php +++ b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/BulkSubscribeHandler.php @@ -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, ]; } @@ -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 diff --git a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/SubscribeHandler.php b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/SubscribeHandler.php index db4d19583..97c51f239 100644 --- a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/SubscribeHandler.php +++ b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/SubscribeHandler.php @@ -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 = []; diff --git a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/bulk-subscribe.schema.json b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/bulk-subscribe.schema.json index f5bbae0b9..1ee1f0c38 100644 --- a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/bulk-subscribe.schema.json +++ b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/bulk-subscribe.schema.json @@ -83,6 +83,9 @@ }, "send_accompanying_emails": { "type": "boolean" + }, + "force_no_variant_subscription": { + "type": "boolean" } } } diff --git a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/subscribe.schema.json b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/subscribe.schema.json index c86c2d485..c4d6c6722 100644 --- a/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/subscribe.schema.json +++ b/Mailer/extensions/mailer-module/src/Api/v1/Handlers/Users/subscribe.schema.json @@ -55,6 +55,9 @@ "send_accompanying_emails": { "type": "boolean" }, + "force_no_variant_subscription": { + "type": "boolean" + }, "rtm_params": { "title": "RTM params", "type": "object", diff --git a/Mailer/extensions/mailer-module/src/Repositories/ListsRepository.php b/Mailer/extensions/mailer-module/src/Repositories/ListsRepository.php index 5530b5306..2b0167c44 100644 --- a/Mailer/extensions/mailer-module/src/Repositories/ListsRepository.php +++ b/Mailer/extensions/mailer-module/src/Repositories/ListsRepository.php @@ -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, @@ -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)) { diff --git a/Mailer/extensions/mailer-module/src/Repositories/UserSubscriptionsRepository.php b/Mailer/extensions/mailer-module/src/Repositories/UserSubscriptionsRepository.php index 1a4b632ac..02317fff2 100644 --- a/Mailer/extensions/mailer-module/src/Repositories/UserSubscriptionsRepository.php +++ b/Mailer/extensions/mailer-module/src/Repositories/UserSubscriptionsRepository.php @@ -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; @@ -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; } diff --git a/Mailer/extensions/mailer-module/src/Tests/Feature/Api/v1/Handlers/Users/SubscribeHandlerTest.php b/Mailer/extensions/mailer-module/src/Tests/Feature/Api/v1/Handlers/Users/SubscribeHandlerTest.php index 6cbe8c5ad..b2af6b0ab 100644 --- a/Mailer/extensions/mailer-module/src/Tests/Feature/Api/v1/Handlers/Users/SubscribeHandlerTest.php +++ b/Mailer/extensions/mailer-module/src/Tests/Feature/Api/v1/Handlers/Users/SubscribeHandlerTest.php @@ -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, + ], + ]; + } } diff --git a/Mailer/extensions/mailer-module/src/Tests/Feature/BaseFeatureTestCase.php b/Mailer/extensions/mailer-module/src/Tests/Feature/BaseFeatureTestCase.php index 62b0da428..60b76cd94 100644 --- a/Mailer/extensions/mailer-module/src/Tests/Feature/BaseFeatureTestCase.php +++ b/Mailer/extensions/mailer-module/src/Tests/Feature/BaseFeatureTestCase.php @@ -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); @@ -168,6 +169,7 @@ protected function createMailTypeWithCategory( description: 'XXX', publicListing: $publicListing, isMultiVariant: $isMultiVariant, + defaultVariantId: $defaultVariantId, ); }