diff --git a/resources/views/messages/show.blade.php b/resources/views/messages/show.blade.php index c961448a..00bdcbbf 100644 --- a/resources/views/messages/show.blade.php +++ b/resources/views/messages/show.blade.php @@ -41,7 +41,7 @@ function resizeTextArea(element) { {{ __('Subject') }}: - {{ $message->subject }} + {{ $subject }} {{ __('From') }}: diff --git a/src/Http/Controllers/MessagesController.php b/src/Http/Controllers/MessagesController.php index f844a411..d55dc5e1 100644 --- a/src/Http/Controllers/MessagesController.php +++ b/src/Http/Controllers/MessagesController.php @@ -10,7 +10,8 @@ use Sendportal\Base\Facades\Sendportal; use Sendportal\Base\Models\Message; use Sendportal\Base\Repositories\Messages\MessageTenantRepositoryInterface; -use Sendportal\Base\Services\Content\MergeContent; +use Sendportal\Base\Services\Content\MergeContentService; +use Sendportal\Base\Services\Content\MergeSubjectService; use Sendportal\Base\Services\Messages\DispatchMessage; class MessagesController extends Controller @@ -21,17 +22,22 @@ class MessagesController extends Controller /** @var DispatchMessage */ protected $dispatchMessage; - /** @var MergeContent */ - protected $mergeContent; + /** @var MergeContentService */ + protected $mergeContentService; + + /** @var MergeSubjectService */ + protected $mergeSubjectService; public function __construct( MessageTenantRepositoryInterface $messageRepo, DispatchMessage $dispatchMessage, - MergeContent $mergeContent + MergeContentService $mergeContentService, + MergeSubjectService $mergeSubjectService ) { $this->messageRepo = $messageRepo; $this->dispatchMessage = $dispatchMessage; - $this->mergeContent = $mergeContent; + $this->mergeContentService = $mergeContentService; + $this->mergeSubjectService = $mergeSubjectService; } /** @@ -82,9 +88,10 @@ public function show(int $messageId): View { $message = $this->messageRepo->find(Sendportal::currentWorkspaceId(), $messageId); - $content = $this->mergeContent->handle($message); + $content = $this->mergeContentService->handle($message); + $subject = $this->mergeSubjectService->handle($message); - return view('sendportal::messages.show', compact('content', 'message')); + return view('sendportal::messages.show', compact('content', 'message', 'subject')); } /** diff --git a/src/Http/Controllers/Webview/WebviewController.php b/src/Http/Controllers/Webview/WebviewController.php index 94fc674c..5c107e4b 100644 --- a/src/Http/Controllers/Webview/WebviewController.php +++ b/src/Http/Controllers/Webview/WebviewController.php @@ -8,14 +8,14 @@ use Illuminate\Contracts\View\View as ViewContract; use Sendportal\Base\Http\Controllers\Controller; use Sendportal\Base\Models\Message; -use Sendportal\Base\Services\Content\MergeContent; +use Sendportal\Base\Services\Content\MergeContentService; class WebviewController extends Controller { - /** @var MergeContent */ + /** @var MergeContentService */ private $merger; - public function __construct(MergeContent $merger) + public function __construct(MergeContentService $merger) { $this->merger = $merger; } diff --git a/src/Services/Content/MergeContent.php b/src/Services/Content/MergeContentService.php similarity index 97% rename from src/Services/Content/MergeContent.php rename to src/Services/Content/MergeContentService.php index 764afd72..39f80747 100644 --- a/src/Services/Content/MergeContent.php +++ b/src/Services/Content/MergeContentService.php @@ -12,7 +12,7 @@ use Sendportal\Pro\Repositories\AutomationScheduleRepository; use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles; -class MergeContent +class MergeContentService { use NormalizeTags; @@ -117,7 +117,6 @@ protected function compileTags(string $content): string 'webview_url' ]; - // NOTE: regex doesn't seem to work here - I think it may be due to all the tags and inverted commas in html? foreach ($tags as $tag) { $content = $this->normalizeTags($content, $tag); } diff --git a/src/Services/Content/MergeSubjectService.php b/src/Services/Content/MergeSubjectService.php new file mode 100644 index 00000000..b1b77abb --- /dev/null +++ b/src/Services/Content/MergeSubjectService.php @@ -0,0 +1,52 @@ +compileTags($message); + + return $this->mergeSubscriberTags($messageSubject, $message); + } + + protected function compileTags(Message $message): string + { + $tags = [ + 'email', + 'first_name', + 'last_name', + ]; + + $messageSubject = $message->subject; + + foreach ($tags as $tag) { + $messageSubject = $this->normalizeTags($messageSubject, $tag); + } + + return $messageSubject; + } + + protected function mergeSubscriberTags(string $messageSubject, Message $message): string + { + $tags = [ + 'email' => $message->recipient_email, + 'first_name' => $message->subscriber ? $message->subscriber->first_name : '', + 'last_name' => $message->subscriber ? $message->subscriber->last_name : '', + ]; + + foreach ($tags as $key => $replace) { + $messageSubject = str_ireplace('{{' . $key . '}}', $replace, $messageSubject); + } + + return $messageSubject; + } +} diff --git a/src/Services/Messages/DispatchMessage.php b/src/Services/Messages/DispatchMessage.php index 75eea178..584cdaf4 100644 --- a/src/Services/Messages/DispatchMessage.php +++ b/src/Services/Messages/DispatchMessage.php @@ -10,7 +10,8 @@ use Sendportal\Base\Models\CampaignStatus; use Sendportal\Base\Models\EmailService; use Sendportal\Base\Models\Message; -use Sendportal\Base\Services\Content\MergeContent; +use Sendportal\Base\Services\Content\MergeContentService; +use Sendportal\Base\Services\Content\MergeSubjectService; class DispatchMessage { @@ -20,21 +21,26 @@ class DispatchMessage /** @var RelayMessage */ protected $relayMessage; - /** @var MergeContent */ - protected $mergeContent; + /** @var MergeContentService */ + protected $mergeContentService; + + /** @var MergeSubjectService */ + protected $mergeSubjectService; /** @var MarkAsSent */ protected $markAsSent; public function __construct( - MergeContent $mergeContent, + MergeContentService $mergeContentService, + MergeSubjectService $mergeSubjectService, ResolveEmailService $resolveEmailService, RelayMessage $relayMessage, MarkAsSent $markAsSent ) { + $this->mergeContentService = $mergeContentService; + $this->mergeSubjectService = $mergeSubjectService; $this->resolveEmailService = $resolveEmailService; $this->relayMessage = $relayMessage; - $this->mergeContent = $mergeContent; $this->markAsSent = $markAsSent; } @@ -49,6 +55,8 @@ public function handle(Message $message): ?string return null; } + $message = $this->mergeSubject($message); + $mergedContent = $this->getMergedContent($message); $emailService = $this->getEmailService($message); @@ -62,12 +70,25 @@ public function handle(Message $message): ?string return $messageId; } + /** + * The message's subject is merged and persisted to the database + * so that we have a permanent record of the merged tags at the + * time of dispatch. + */ + protected function mergeSubject(Message $message): Message + { + $message->subject = $this->mergeSubjectService->handle($message); + $message->save(); + + return $message; + } + /** * @throws Exception */ protected function getMergedContent(Message $message): string { - return $this->mergeContent->handle($message); + return $this->mergeContentService->handle($message); } /** @@ -108,13 +129,13 @@ protected function isValidMessage(Message $message): bool return false; } - if (! $message->isCampaign()) { + if (!$message->isCampaign()) { return true; } $campaign = Campaign::find($message->source_id); - if (! $campaign) { + if (!$campaign) { return false; } diff --git a/src/Services/Messages/DispatchTestMessage.php b/src/Services/Messages/DispatchTestMessage.php index 8c6c7269..d6498fdb 100644 --- a/src/Services/Messages/DispatchTestMessage.php +++ b/src/Services/Messages/DispatchTestMessage.php @@ -10,7 +10,7 @@ use Sendportal\Base\Models\EmailService; use Sendportal\Base\Models\Message; use Sendportal\Base\Repositories\Campaigns\CampaignTenantRepositoryInterface; -use Sendportal\Base\Services\Content\MergeContent; +use Sendportal\Base\Services\Content\MergeContentService; class DispatchTestMessage { @@ -20,7 +20,7 @@ class DispatchTestMessage /** @var RelayMessage */ protected $relayMessage; - /** @var MergeContent */ + /** @var MergeContentService */ protected $mergeContent; /** @var CampaignTenantRepositoryInterface */ @@ -28,7 +28,7 @@ class DispatchTestMessage public function __construct( CampaignTenantRepositoryInterface $campaignTenant, - MergeContent $mergeContent, + MergeContentService $mergeContent, ResolveEmailService $resolveEmailService, RelayMessage $relayMessage ) { diff --git a/tests/Feature/Content/MergeContentTest.php b/tests/Feature/Content/MergeContentTest.php index 1c072f13..5091d621 100644 --- a/tests/Feature/Content/MergeContentTest.php +++ b/tests/Feature/Content/MergeContentTest.php @@ -10,7 +10,7 @@ use Sendportal\Base\Models\Campaign; use Sendportal\Base\Models\Message; use Sendportal\Base\Models\Template; -use Sendportal\Base\Services\Content\MergeContent; +use Sendportal\Base\Services\Content\MergeContentService; use Tests\TestCase; class MergeContentTest extends TestCase @@ -145,8 +145,8 @@ private function generateCampaignMessage(?string $campaignContent, ?string $temp private function mergeContent(Message $message): string { - /** @var MergeContent $mergeContent */ - $mergeContent = app(MergeContent::class); + /** @var MergeContentService $mergeContent */ + $mergeContent = app(MergeContentService::class); return $mergeContent->handle($message); } diff --git a/tests/Feature/Content/MergeSubjectTest.php b/tests/Feature/Content/MergeSubjectTest.php new file mode 100644 index 00000000..078baa3d --- /dev/null +++ b/tests/Feature/Content/MergeSubjectTest.php @@ -0,0 +1,115 @@ +generateCampaignMessage($subject, 'foo@bar.com', 'foo', 'bar'); + + // when + $mergedSubject = $this->mergeSubject($message); + + // then + self::assertEquals('Hi, foo@bar.com', $mergedSubject); + } + + /** @test */ + public function the_first_name_tag_is_replaced_with_the_subscriber_first_name() + { + // given + $subject = 'Hi, {{first_name}}'; + $message = $this->generateCampaignMessage($subject, 'foo@bar.com', 'foo', 'bar'); + + // when + $mergedSubject = $this->mergeSubject($message); + + // then + self::assertEquals('Hi, foo', $mergedSubject); + } + + /** @test */ + public function the_last_name_tag_is_replaced_with_the_subscriber_last_name() + { + // given + $subject = 'Hi, {{last_name}}'; + $message = $this->generateCampaignMessage($subject, 'foo@bar.com', 'foo', 'bar'); + + // when + $mergedSubject = $this->mergeSubject($message); + + // then + self::assertEquals('Hi, bar', $mergedSubject); + } + + /** @test */ + public function multiple_different_tags_are_replaced() + { + // given + $subject = 'Hi, {{first_name}} {{ last_name }} ({{email }})'; + $message = $this->generateCampaignMessage($subject, 'foo@bar.com', 'foo', 'bar'); + + // when + $mergedSubject = $this->mergeSubject($message); + + // then + self::assertEquals('Hi, foo bar (foo@bar.com)', $mergedSubject); + } + + private function generateCampaignMessage( + string $campaignSubject, + string $email, + string $firstName, + string $lastName + ): Message { + /** @var Campaign $campaign */ + $campaign = Campaign::factory()->create([ + 'content' => '

Content

', + 'subject' => $campaignSubject, + 'workspace_id' => Sendportal::currentWorkspaceId() + ]); + + /** @var Subscriber $subscriber */ + $subscriber = Subscriber::factory()->create([ + 'workspace_id' => Sendportal::currentWorkspaceId(), + 'email' => $email, + 'first_name' => $firstName, + 'last_name' => $lastName, + ]); + + return Message::factory()->create([ + 'workspace_id' => Sendportal::currentWorkspaceId(), + 'subscriber_id' => $subscriber->id, + 'source_type' => Campaign::class, + 'source_id' => $campaign->id, + 'subject' => $campaignSubject, + 'recipient_email' => $email, + ]); + } + + private function mergeSubject(Message $message): string + { + /** @var MergeSubjectService $mergeSubject */ + $mergeSubject = app(MergeSubjectService::class); + + return $mergeSubject->handle($message); + } +}