diff --git a/config/parameters.yml.dist b/config/parameters.yml.dist index 628f1e45..6de7d2ef 100644 --- a/config/parameters.yml.dist +++ b/config/parameters.yml.dist @@ -33,8 +33,8 @@ parameters: env(APP_POWERED_BY_PHPLIST): '0' app.preference_page_show_private_lists: '%%env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS)%%' env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS): '0' - app.rest_api_domain: '%%env(REST_API_DOMAIN)%%' - env(REST_API_DOMAIN): 'example.com' + app.rest_api_base_url: '%%env(REST_API_BASE_URL)%%' + env(REST_API_BASE_URL): 'https://example.com/api/v2' # Email configuration app.mailer_from: '%%env(MAILER_FROM)%%' diff --git a/config/services/services.yml b/config/services/services.yml index 5e7db66b..53a5f84d 100644 --- a/config/services/services.yml +++ b/config/services/services.yml @@ -53,6 +53,10 @@ services: autoconfigure: true public: true + PhpList\Core\Domain\Analytics\Service\UserMessageService: + autowire: true + autoconfigure: true + PhpList\Core\Domain\Messaging\Service\SendRateLimiter: autowire: true autoconfigure: true diff --git a/src/Domain/Analytics/Model/UserMessageView.php b/src/Domain/Analytics/Model/UserMessageView.php index 846c8e97..b391d3f3 100644 --- a/src/Domain/Analytics/Model/UserMessageView.php +++ b/src/Domain/Analytics/Model/UserMessageView.php @@ -85,6 +85,11 @@ public function setViewed(?DateTime $viewed): self return $this; } + public function setViewedNow(): self + { + return $this->setViewed(new DateTime()); + } + public function setIp(?string $ip): self { $this->ip = $ip; diff --git a/src/Domain/Analytics/Service/UserMessageService.php b/src/Domain/Analytics/Service/UserMessageService.php new file mode 100644 index 00000000..c5a1cc5b --- /dev/null +++ b/src/Domain/Analytics/Service/UserMessageService.php @@ -0,0 +1,56 @@ +subscriberRepository->findOneByUniqueId($uid); + $message = $this->messageRepository->findById($messageId); + + if ($subscriber === null || $message === null) { + return; + } + + $userMessage = $this->userMessageRepository->findByUserAndMessage($subscriber, $message); + if ($userMessage === null) { + return; + } + + $userMessage->setViewedNow(); + $message->getMetadata()->incrementViews(); + + $data = []; + foreach (['HTTP_USER_AGENT', 'HTTP_REFERER'] as $key) { + if (isset($metadata[$key])) { + $data[$key] = htmlspecialchars(strip_tags($metadata[$key])); + } + } + + $userMessageView = new UserMessageView(); + $userMessageView->setUserId($subscriber->getId()); + $userMessageView->setMessageId($messageId); + $userMessageView->setViewedNow(); + $userMessageView->setIp($metadata['client_ip'] ?? null); + $userMessageView->setData(serialize($data)); + + $this->entityManager->persist($userMessageView); + } +} diff --git a/src/Domain/Configuration/Service/Placeholder/UserTrackValueResolver.php b/src/Domain/Configuration/Service/Placeholder/UserTrackValueResolver.php index 4983fc28..8a5b626d 100644 --- a/src/Domain/Configuration/Service/Placeholder/UserTrackValueResolver.php +++ b/src/Domain/Configuration/Service/Placeholder/UserTrackValueResolver.php @@ -13,7 +13,7 @@ final class UserTrackValueResolver implements PlaceholderValueResolverInterface { public function __construct( private readonly ConfigProvider $config, - #[Autowire('%rest_api_domain%')] private readonly string $restApiDomain, + #[Autowire('%app.rest_api_base_url%')] private readonly string $restApiBaseUrl, ) { } @@ -24,7 +24,7 @@ public function name(): string public function __invoke(PlaceholderContext $ctx): string { - $base = $this->config->getValue(ConfigOption::Domain) ?? $this->restApiDomain; + $base = $this->config->getValue(ConfigOption::Domain) ?? $this->restApiBaseUrl; if ($ctx->isText() || empty($base)) { return ''; @@ -33,7 +33,7 @@ public function __invoke(PlaceholderContext $ctx): string return ''; + $expected = ''; // Normalize double quotes for comparison $this->assertSame($expected, $result); } @@ -86,7 +86,7 @@ public function testHtmlFallsBackToRestApiDomainWhenConfigMissing(): void $result = $resolver($ctx); - $expected = ''; + $expected = ''; $this->assertSame($expected, $result); } } diff --git a/tests/Unit/Domain/Messaging/Service/ForwardingGuardTest.php b/tests/Unit/Domain/Messaging/Service/ForwardingGuardTest.php index 8ac266f8..b1ee10b9 100644 --- a/tests/Unit/Domain/Messaging/Service/ForwardingGuardTest.php +++ b/tests/Unit/Domain/Messaging/Service/ForwardingGuardTest.php @@ -46,7 +46,7 @@ public function testAssertCanForwardReturnsSubscriber(): void $subscriber = new Subscriber(); $this->subscriberRepo->method('findOneByUniqueId')->with($uid)->willReturn($subscriber); - $this->userMessageRepo->method('findOneByUserAndMessage')->willReturn( + $this->userMessageRepo->method('findByUserAndMessage')->willReturn( $this->createMock(UserMessage::class) ); $this->forwardRepo->method('getCountByUserSince')->willReturn(1); @@ -82,7 +82,7 @@ public function testAssertCanForwardThrowsWhenMessageNotReceived(): void ); $this->subscriberRepo->method('findOneByUniqueId')->willReturn(new Subscriber()); - $this->userMessageRepo->method('findOneByUserAndMessage')->willReturn(null); + $this->userMessageRepo->method('findByUserAndMessage')->willReturn(null); $this->expectException(MessageNotReceivedException::class); $guard->assertCanForward('uid', $this->createMock(Message::class)); @@ -99,7 +99,7 @@ public function testAssertCanForwardThrowsWhenLimitExceeded(): void ); $this->subscriberRepo->method('findOneByUniqueId')->willReturn(new Subscriber()); - $this->userMessageRepo->method('findOneByUserAndMessage')->willReturn($this->createMock(UserMessage::class)); + $this->userMessageRepo->method('findByUserAndMessage')->willReturn($this->createMock(UserMessage::class)); $this->forwardRepo->method('getCountByUserSince')->willReturn(2); $this->expectException(ForwardLimitExceededException::class);