Save user agent on open
[MAILPOET-3735]
This commit is contained in:
@ -443,6 +443,7 @@ class Migrator {
|
||||
'newsletter_id int(11) unsigned NOT NULL,',
|
||||
'subscriber_id int(11) unsigned NOT NULL,',
|
||||
'queue_id int(11) unsigned NOT NULL,',
|
||||
'user_agent_id int(11) unsigned NULL,',
|
||||
'created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'KEY newsletter_id_subscriber_id (newsletter_id, subscriber_id),',
|
||||
|
@ -37,6 +37,12 @@ class StatisticsOpenEntity {
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\UserAgentEntity")
|
||||
* @var UserAgentEntity|null
|
||||
*/
|
||||
private $userAgent;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
@ -83,4 +89,12 @@ class StatisticsOpenEntity {
|
||||
public function setSubscriber($subscriber) {
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function getUserAgent(): ?UserAgentEntity {
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
public function setUserAgent(?UserAgentEntity $userAgent): void {
|
||||
$this->userAgent = $userAgent;
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ class Track {
|
||||
'queue' => $data->queue_id, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
]);
|
||||
}
|
||||
$data->userAgent = $_SERVER['HTTP_USER_AGENT'] ?? null;
|
||||
return $this->_validateTrackData($data);
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,21 @@ use MailPoet\Entities\SendingQueueEntity;
|
||||
use MailPoet\Entities\StatisticsOpenEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Statistics\StatisticsOpensRepository;
|
||||
use MailPoet\Statistics\UserAgentsRepository;
|
||||
|
||||
class Opens {
|
||||
/** @var StatisticsOpensRepository */
|
||||
private $statisticsOpensRepository;
|
||||
|
||||
public function __construct(StatisticsOpensRepository $statisticsOpensRepository) {
|
||||
/** @var UserAgentsRepository */
|
||||
private $userAgentsRepository;
|
||||
|
||||
public function __construct(
|
||||
StatisticsOpensRepository $statisticsOpensRepository,
|
||||
UserAgentsRepository $userAgentsRepository
|
||||
) {
|
||||
$this->statisticsOpensRepository = $statisticsOpensRepository;
|
||||
$this->userAgentsRepository = $userAgentsRepository;
|
||||
}
|
||||
|
||||
public function track($data, $displayImage = true) {
|
||||
@ -40,6 +48,9 @@ class Opens {
|
||||
return $this->returnResponse($displayImage);
|
||||
}
|
||||
$statistics = new StatisticsOpenEntity($newsletter, $queue, $subscriber);
|
||||
if (!empty($data->userAgent)) {
|
||||
$statistics->setUserAgent($this->userAgentsRepository->findOrCreate($data->userAgent));
|
||||
}
|
||||
$this->statisticsOpensRepository->persist($statistics);
|
||||
$this->statisticsOpensRepository->flush();
|
||||
$this->statisticsOpensRepository->recalculateSubscriberScore($subscriber);
|
||||
|
24
lib/Statistics/UserAgentsRepository.php
Normal file
24
lib/Statistics/UserAgentsRepository.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Statistics;
|
||||
|
||||
use MailPoet\Doctrine\Repository;
|
||||
use MailPoet\Entities\UserAgentEntity;
|
||||
|
||||
/**
|
||||
* @extends Repository<UserAgentEntity>
|
||||
*/
|
||||
class UserAgentsRepository extends Repository {
|
||||
protected function getEntityClassName() {
|
||||
return UserAgentEntity::class;
|
||||
}
|
||||
|
||||
public function findOrCreate(string $userAgent): UserAgentEntity {
|
||||
$hash = (string)crc32($userAgent);
|
||||
$userAgentEntity = $this->findOneBy(['hash' => $hash]);
|
||||
if ($userAgentEntity) return $userAgentEntity;
|
||||
$userAgentEntity = new UserAgentEntity($userAgent);
|
||||
$this->persist($userAgentEntity);
|
||||
return $userAgentEntity;
|
||||
}
|
||||
}
|
@ -7,17 +7,13 @@ use Codeception\Stub\Expected;
|
||||
use MailPoet\Entities\NewsletterEntity;
|
||||
use MailPoet\Entities\ScheduledTaskEntity;
|
||||
use MailPoet\Entities\SendingQueueEntity;
|
||||
use MailPoet\Entities\StatisticsOpenEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\ScheduledTask;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\StatisticsOpens;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Statistics\StatisticsOpensRepository;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
use MailPoet\Subscribers\LinkTokens;
|
||||
use MailPoet\Tasks\Sending as SendingTask;
|
||||
use MailPoetVendor\Idiorm\ORM;
|
||||
|
||||
class OpensTest extends \MailPoetTest {
|
||||
public $opens;
|
||||
@ -26,6 +22,9 @@ class OpensTest extends \MailPoetTest {
|
||||
public $subscriber;
|
||||
public $newsletter;
|
||||
|
||||
/** @var StatisticsOpensRepository */
|
||||
private $statisticsOpensRepository;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->cleanup();
|
||||
@ -68,7 +67,8 @@ class OpensTest extends \MailPoetTest {
|
||||
'preview' => false,
|
||||
];
|
||||
// instantiate class
|
||||
$this->opens = new Opens($this->diContainer->get(StatisticsOpensRepository::class));
|
||||
$this->statisticsOpensRepository = $this->diContainer->get(StatisticsOpensRepository::class);
|
||||
$this->opens = new Opens($this->statisticsOpensRepository);
|
||||
}
|
||||
|
||||
public function testItReturnsImageWhenTrackDataIsEmpty() {
|
||||
@ -119,15 +119,36 @@ class OpensTest extends \MailPoetTest {
|
||||
$opens->track($this->trackData);
|
||||
}
|
||||
|
||||
public function testItSavesNewUserAgent() {
|
||||
$this->trackData->userAgent = 'User agent';
|
||||
$opens = Stub::construct($this->opens, [$this->diContainer->get(StatisticsOpensRepository::class)], [
|
||||
'returnResponse' => null,
|
||||
], $this);
|
||||
$opens->track($this->trackData);
|
||||
$opens = $this->statisticsOpensRepository->findAll();
|
||||
expect($opens)->count(1);
|
||||
$open = $opens[0];
|
||||
$userAgent = $open->getUserAgent();
|
||||
expect($userAgent)->notNull();
|
||||
}
|
||||
|
||||
public function testItSavesOpenWithExistingUserAgent() {
|
||||
|
||||
}
|
||||
|
||||
public function testItOverridesOldUserAgent() {
|
||||
|
||||
}
|
||||
|
||||
public function _after() {
|
||||
$this->cleanup();
|
||||
}
|
||||
|
||||
public function cleanup() {
|
||||
ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . ScheduledTask::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsOpens::$_table);
|
||||
$this->truncateEntity(NewsletterEntity::class);
|
||||
$this->truncateEntity(SubscriberEntity::class);
|
||||
$this->truncateEntity(ScheduledTaskEntity::class);
|
||||
$this->truncateEntity(SendingQueueEntity::class);
|
||||
$this->truncateEntity(StatisticsOpenEntity::class);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user