diff --git a/lib/Cron/Workers/SendingQueue/Tasks/Links.php b/lib/Cron/Workers/SendingQueue/Tasks/Links.php index 7c4976049a..3e6689cded 100644 --- a/lib/Cron/Workers/SendingQueue/Tasks/Links.php +++ b/lib/Cron/Workers/SendingQueue/Tasks/Links.php @@ -9,6 +9,7 @@ use MailPoet\Models\Subscriber; use MailPoet\Router\Endpoints\Track; use MailPoet\Newsletter\Links\Links as NewsletterLinks; use MailPoet\Models\NewsletterLink as NewsletterLinkModel; +use MailPoet\Subscribers\LinkTokens; class Links { static function process($rendered_newsletter, $newsletter, $queue) { @@ -45,9 +46,10 @@ class Links { if (!$link_hash instanceof NewsletterLinkModel) { return ''; } + $link_tokens = new LinkTokens; $data = NewsletterLinks::createUrlDataObject( $subscriber->id, - $subscriber->getLinkToken(), + $link_tokens->getToken($subscriber), $queue->id, $link_hash->hash, false diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php index 24d89940ce..024136a8ea 100644 --- a/lib/Models/Subscriber.php +++ b/lib/Models/Subscriber.php @@ -3,6 +3,7 @@ namespace MailPoet\Models; use MailPoet\DI\ContainerWrapper; use MailPoet\Settings\SettingsController; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Util\Helpers; use function MailPoet\Util\array_column; use MailPoet\WP\Functions as WPFunctions; @@ -106,15 +107,6 @@ class Subscriber extends Model { return (bool)$this->is_woocommerce_user; } - function getLinkToken() { - if ($this->link_token === null) { - $this->link_token = self::generateToken($this->email); - // `$this->save()` fails if the subscriber has subscriptions, segments or custom fields - \ORM::rawExecute(sprintf('UPDATE %s SET link_token = ? WHERE email = ?', self::$_table), [$this->link_token, $this->email]); - } - return $this->link_token; - } - static function getCurrentWPUser() { $wp_user = WPFunctions::get()->wpGetCurrentUser(); if (empty($wp_user->ID)) { @@ -138,7 +130,7 @@ class Subscriber extends Model { } function verifyToken($token) { - $database_token = $this->getLinkToken(); + $database_token = (new LinkTokens)->getToken($this); $request_token = substr($token, 0, strlen($database_token)); return call_user_func( 'hash_equals', diff --git a/lib/Newsletter/Links/Links.php b/lib/Newsletter/Links/Links.php index ac7624be8b..19417a01a5 100644 --- a/lib/Newsletter/Links/Links.php +++ b/lib/Newsletter/Links/Links.php @@ -7,6 +7,7 @@ use MailPoet\Newsletter\Shortcodes\Categories\Link; use MailPoet\Newsletter\Shortcodes\Shortcodes; use MailPoet\Router\Endpoints\Track as TrackEndpoint; use MailPoet\Router\Router; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Util\Helpers; use MailPoet\Util\Security; use MailPoet\Util\pQuery\pQuery as DomParser; @@ -134,9 +135,10 @@ class Links { if (preg_match('/-/', $match)) { list(, $hash) = explode('-', $match); } + $link_tokens = new LinkTokens; $data = self::createUrlDataObject( $subscriber->id, - $subscriber->getLinkToken(), + $link_tokens->getToken($subscriber), $queue_id, $hash, $preview diff --git a/lib/Newsletter/Url.php b/lib/Newsletter/Url.php index 87a242d8c8..74ef97114b 100644 --- a/lib/Newsletter/Url.php +++ b/lib/Newsletter/Url.php @@ -4,6 +4,7 @@ namespace MailPoet\Newsletter; use MailPoet\Router\Router; use MailPoet\Router\Endpoints\ViewInBrowser as ViewInBrowserEndpoint; use MailPoet\Models\Subscriber as SubscriberModel; +use MailPoet\Subscribers\LinkTokens; class Url { const TYPE_ARCHIVE = 'display_archive'; @@ -16,8 +17,9 @@ class Url { $queue = false, $preview = false ) { + $link_tokens = new LinkTokens; if ($subscriber instanceof SubscriberModel) { - $subscriber->token = $subscriber->getLinkToken(); + $subscriber->token = $link_tokens->getToken($subscriber); } switch ($type) { case self::TYPE_ARCHIVE: diff --git a/lib/Subscribers/LinkTokens.php b/lib/Subscribers/LinkTokens.php index b38c38590e..030b650ad3 100644 --- a/lib/Subscribers/LinkTokens.php +++ b/lib/Subscribers/LinkTokens.php @@ -18,7 +18,7 @@ class LinkTokens { } function verifyToken(Subscriber $subscriber, $token) { - $database_token = $subscriber->getLinkToken(); + $database_token = $this->getToken($subscriber); $request_token = substr($token, 0, strlen($database_token)); return call_user_func( 'hash_equals', diff --git a/lib/Subscription/Pages.php b/lib/Subscription/Pages.php index e50c11b50e..ed087000e4 100644 --- a/lib/Subscription/Pages.php +++ b/lib/Subscription/Pages.php @@ -13,6 +13,7 @@ use MailPoet\Util\Helpers; use MailPoet\Util\Url as UrlHelper; use MailPoet\Form\Renderer as FormRenderer; use MailPoet\Form\Block\Date as FormBlockDate; +use MailPoet\Subscribers\LinkTokens; use MailPoet\WP\Functions as WPFunctions; class Pages { @@ -44,13 +45,17 @@ class Pages { /** @var WelcomeScheduler */ private $welcome_scheduler; + /** @var LinkTokens */ + private $link_tokens; + function __construct( NewSubscriberNotificationMailer $new_subscriber_notification_sender, WPFunctions $wp, SettingsController $settings, UrlHelper $url_helper, CaptchaRenderer $captcha_renderer, - WelcomeScheduler $welcome_scheduler + WelcomeScheduler $welcome_scheduler, + LinkTokens $link_tokens ) { $this->wp = $wp; $this->new_subscriber_notification_sender = $new_subscriber_notification_sender; @@ -58,6 +63,7 @@ class Pages { $this->url_helper = $url_helper; $this->captcha_renderer = $captcha_renderer; $this->welcome_scheduler = $welcome_scheduler; + $this->link_tokens = $link_tokens; } function init($action = false, $data = [], $init_shortcodes = false, $init_page_filters = false) { @@ -438,7 +444,7 @@ class Pages { $subscriber->email . '" />'; $form_html .= ''; $form_html .= '
'; diff --git a/lib/Subscription/Url.php b/lib/Subscription/Url.php index fe17bfe2df..b64225da50 100644 --- a/lib/Subscription/Url.php +++ b/lib/Subscription/Url.php @@ -6,6 +6,7 @@ use MailPoet\Router\Endpoints\Subscription as SubscriptionEndpoint; use MailPoet\Models\Subscriber; use MailPoet\Settings\Pages as SettingsPages; use MailPoet\Settings\SettingsController; +use MailPoet\Subscribers\LinkTokens; use MailPoet\WP\Functions as WPFunctions; class Url { @@ -43,10 +44,10 @@ class Url { if ($post === null || $action === null) return; $url = WPFunctions::get()->getPermalink($post); - + $link_tokens = new LinkTokens; if ($subscriber !== null) { $data = [ - 'token' => $subscriber->getLinkToken(), + 'token' => $link_tokens->getToken($subscriber), 'email' => $subscriber->email, ]; } elseif (is_null($data)) { diff --git a/tests/integration/Cron/Workers/SendingQueue/SendingQueueTest.php b/tests/integration/Cron/Workers/SendingQueue/SendingQueueTest.php index 6804e4c19d..5d1ad17233 100644 --- a/tests/integration/Cron/Workers/SendingQueue/SendingQueueTest.php +++ b/tests/integration/Cron/Workers/SendingQueue/SendingQueueTest.php @@ -31,6 +31,7 @@ use MailPoet\Referrals\ReferralDetector; use MailPoet\Router\Endpoints\Track; use MailPoet\Router\Router; use MailPoet\Settings\SettingsController; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Subscription\Captcha; use MailPoet\Subscription\Url; use MailPoet\Tasks\Sending as SendingTask; @@ -100,9 +101,10 @@ class SendingQueueTest extends \MailPoetTest { } private function getTrackedUnsubscribeURL() { + $link_tokens = new LinkTokens; $data = Links::createUrlDataObject( $this->subscriber->id, - $this->subscriber->getLinkToken(), + $link_tokens->getToken($this->subscriber), $this->queue->id, $this->newsletter_link->hash, false diff --git a/tests/integration/Router/Endpoints/TrackTest.php b/tests/integration/Router/Endpoints/TrackTest.php index fa18b7fdec..33a6992e04 100644 --- a/tests/integration/Router/Endpoints/TrackTest.php +++ b/tests/integration/Router/Endpoints/TrackTest.php @@ -12,6 +12,7 @@ use MailPoet\Router\Endpoints\Track; use MailPoet\Settings\SettingsController; use MailPoet\Statistics\Track\Clicks; use MailPoet\Statistics\Track\Opens; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Tasks\Sending as SendingTask; use MailPoet\Util\Cookies; @@ -41,12 +42,13 @@ class TrackTest extends \MailPoetTest { $link->newsletter_id = $newsletter->id; $link->queue_id = $queue->id; $this->link = $link->save(); + $link_tokens = new LinkTokens; // build track data $this->track_data = [ 'queue_id' => $queue->id, 'subscriber_id' => $subscriber->id, 'newsletter_id' => $newsletter->id, - 'subscriber_token' => $subscriber->getLinkToken(), + 'subscriber_token' => $link_tokens->getToken($subscriber), 'link_hash' => $link->hash, 'preview' => false, ]; diff --git a/tests/integration/Router/Endpoints/ViewInBrowserTest.php b/tests/integration/Router/Endpoints/ViewInBrowserTest.php index a9a8ebc367..62619be8ae 100644 --- a/tests/integration/Router/Endpoints/ViewInBrowserTest.php +++ b/tests/integration/Router/Endpoints/ViewInBrowserTest.php @@ -11,6 +11,7 @@ use MailPoet\Models\SendingQueue; use MailPoet\Models\Subscriber; use MailPoet\Router\Endpoints\ViewInBrowser; use MailPoet\Settings\SettingsController; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Tasks\Sending as SendingTask; use MailPoet\WP\Functions; @@ -33,12 +34,13 @@ class ViewInBrowserTest extends \MailPoetTest { $queue->setSubscribers([$subscriber->id]); $queue->updateProcessedSubscribers([$subscriber->id]); $this->queue = $queue->save(); + $link_tokens = new LinkTokens; // build browser preview data $this->browser_preview_data = [ 'queue_id' => $queue->id, 'subscriber_id' => $subscriber->id, 'newsletter_id' => $newsletter->id, - 'subscriber_token' => $subscriber->getLinkToken(), + 'subscriber_token' => $link_tokens->getToken($subscriber), 'preview' => false, ]; // instantiate class diff --git a/tests/integration/Statistics/Track/ClicksTest.php b/tests/integration/Statistics/Track/ClicksTest.php index 7d31055df5..7f2cb16a2b 100644 --- a/tests/integration/Statistics/Track/ClicksTest.php +++ b/tests/integration/Statistics/Track/ClicksTest.php @@ -12,6 +12,7 @@ use MailPoet\Models\StatisticsOpens; use MailPoet\Models\Subscriber; use MailPoet\Settings\SettingsController; use MailPoet\Statistics\Track\Clicks; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Tasks\Sending as SendingTask; use MailPoet\Util\Cookies; @@ -48,12 +49,13 @@ class ClicksTest extends \MailPoetTest { $link->newsletter_id = $newsletter->id; $link->queue_id = $queue->id; $this->link = $link->save(); + $link_tokens = new LinkTokens; // build track data $this->track_data = (object)[ 'queue' => $queue, 'subscriber' => $subscriber, 'newsletter' => $newsletter, - 'subscriber_token' => $subscriber->getLinkToken(), + 'subscriber_token' => $link_tokens->getToken($subscriber), 'link' => $link, 'preview' => false, ]; diff --git a/tests/integration/Statistics/Track/OpensTest.php b/tests/integration/Statistics/Track/OpensTest.php index d6aaeec61c..ec18cabccd 100644 --- a/tests/integration/Statistics/Track/OpensTest.php +++ b/tests/integration/Statistics/Track/OpensTest.php @@ -9,6 +9,7 @@ use MailPoet\Models\SendingQueue; use MailPoet\Models\StatisticsOpens; use MailPoet\Models\Subscriber; use MailPoet\Statistics\Track\Opens; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Tasks\Sending as SendingTask; class OpensTest extends \MailPoetTest { @@ -30,12 +31,13 @@ class OpensTest extends \MailPoetTest { $queue->setSubscribers([$subscriber->id]); $queue->updateProcessedSubscribers([$subscriber->id]); $this->queue = $queue->save(); + $link_tokens = new LinkTokens; // build track data $this->track_data = (object)[ 'queue' => $queue, 'subscriber' => $subscriber, 'newsletter' => $newsletter, - 'subscriber_token' => $subscriber->getLinkToken(), + 'subscriber_token' => $link_tokens->getToken($subscriber), 'preview' => false, ]; // instantiate class diff --git a/tests/integration/Subscription/PagesTest.php b/tests/integration/Subscription/PagesTest.php index b82a95b308..38084ad6ae 100644 --- a/tests/integration/Subscription/PagesTest.php +++ b/tests/integration/Subscription/PagesTest.php @@ -12,6 +12,7 @@ use MailPoet\Models\Segment; use MailPoet\Models\SendingQueue; use MailPoet\Models\Subscriber; use MailPoet\Models\SubscriberSegment; +use MailPoet\Subscribers\LinkTokens; use MailPoet\Subscribers\NewSubscriberNotificationMailer; use MailPoet\Subscription\Pages; @@ -28,9 +29,10 @@ class PagesTest extends \MailPoetTest { $this->subscriber->hydrate(Fixtures::get('subscriber_template')); $this->subscriber->status = Subscriber::STATUS_UNCONFIRMED; $this->subscriber->save(); + $link_tokens = new LinkTokens; expect($this->subscriber->getErrors())->false(); $this->test_data['email'] = $this->subscriber->email; - $this->test_data['token'] = $this->subscriber->getLinkToken(); + $this->test_data['token'] = $link_tokens->getToken($this->subscriber); $this->pages = ContainerWrapper::getInstance()->get(Pages::class); }