diff --git a/app/Services/CleanupSubscriberIntegrationsService.php b/app/Services/CleanupSubscriberIntegrationsService.php index c7ef115..ec8268a 100644 --- a/app/Services/CleanupSubscriberIntegrationsService.php +++ b/app/Services/CleanupSubscriberIntegrationsService.php @@ -104,8 +104,8 @@ final class CleanupSubscriberIntegrationsService } $subscriberUid = $search['subscriber_uid']; - $phoneEnabled = $page->isPhoneFieldEnabledForSubscribers(); - $data = MailwizzSubscriberFormPayload::baseFields($subscriber, $config, $phoneEnabled); + /** @var array $data */ + $data = []; $couponField = $config->field_coupon_code; if (is_string($couponField) && $couponField !== '') { @@ -123,6 +123,10 @@ final class CleanupSubscriberIntegrationsService $data[$tagField] = MailwizzCheckboxlistTags::removeValueFromCsv($existingCsv, $tagValue); } + if ($data === []) { + return; + } + $service->updateSubscriber($listUid, $subscriberUid, $data); } diff --git a/app/Services/MailwizzService.php b/app/Services/MailwizzService.php index d35ea1d..51c2dab 100644 --- a/app/Services/MailwizzService.php +++ b/app/Services/MailwizzService.php @@ -202,7 +202,8 @@ final class MailwizzService $out = []; foreach ($data as $key => $value) { if (is_array($value)) { - $out[$key] = $value; + // Empty arrays are omitted by Laravel's multipart encoder (no KEY[] parts), so Mailwizz never clears checkboxlist fields. + $out[$key] = $value === [] ? '' : $value; continue; } diff --git a/tests/Feature/DestroySubscriberTest.php b/tests/Feature/DestroySubscriberTest.php index 31afe22..938edbe 100644 --- a/tests/Feature/DestroySubscriberTest.php +++ b/tests/Feature/DestroySubscriberTest.php @@ -194,6 +194,68 @@ class DestroySubscriberTest extends TestCase Http::assertSentCount(3); } + public function test_delete_clears_mailwizz_checkboxlist_when_only_configured_tag_is_present(): void + { + Http::fake(function (Request $request) { + $url = $request->url(); + if (str_contains($url, 'search-by-email')) { + return Http::response(['status' => 'success', 'data' => ['subscriber_uid' => 'sub-single-tag']]); + } + if ($request->method() === 'GET' && str_contains($url, '/subscribers/sub-single-tag') && ! str_contains($url, 'search-by-email')) { + return Http::response([ + 'status' => 'success', + 'data' => [ + 'record' => [ + 'TAGS' => 'preregister-source', + 'COUPON' => 'PREREG-OLD', + ], + ], + ]); + } + if ($request->method() === 'PUT' && str_contains($url, '/subscribers/sub-single-tag')) { + $body = $request->body(); + $this->assertStringContainsString('TAGS', $body); + $this->assertStringNotContainsString('preregister-source', $body); + $this->assertStringNotContainsString('TAGS[]', $body); + $this->assertStringContainsString('COUPON', $body); + + return Http::response(['status' => 'success']); + } + + return Http::response(['status' => 'error'], 500); + }); + + $user = User::factory()->create(['role' => 'user']); + $page = $this->makePageForDestroyTest($user); + MailwizzConfig::query()->create([ + 'preregistration_page_id' => $page->id, + 'api_key' => 'fake-api-key', + 'list_uid' => 'list-uid-1', + 'list_name' => 'Main list', + 'field_email' => 'EMAIL', + 'field_first_name' => 'FNAME', + 'field_last_name' => 'LNAME', + 'field_phone' => null, + 'field_coupon_code' => 'COUPON', + 'tag_field' => 'TAGS', + 'tag_value' => 'preregister-source', + ]); + + $subscriber = Subscriber::query()->create([ + 'preregistration_page_id' => $page->id, + 'first_name' => 'Solo', + 'last_name' => 'Tag', + 'email' => 'solo-tag@example.com', + 'coupon_code' => 'PREREG-LOCAL', + ]); + + $response = $this->actingAs($user)->delete(route('admin.pages.subscribers.destroy', [$page, $subscriber])); + + $response->assertRedirect(route('admin.pages.subscribers.index', $page)); + $this->assertDatabaseMissing('subscribers', ['id' => $subscriber->id]); + Http::assertSentCount(3); + } + public function test_delete_removes_coupon_code_in_weeztix_when_configured(): void { Http::fake(function (Request $request) {