PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.3
MailPoet – Newsletters, Email Marketing, and Automation v5.34.3
5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Newsletter / ViewInBrowser / ViewInBrowserController.php
mailpoet / lib / Newsletter / ViewInBrowser Last commit date
ViewInBrowserController.php 1 week ago ViewInBrowserRenderer.php 2 months ago index.php 3 years ago
ViewInBrowserController.php
162 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Newsletter\ViewInBrowser;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\EmailEditor\Integrations\MailPoet\DependencyNotice;
9 use MailPoet\Entities\SubscriberEntity;
10 use MailPoet\Newsletter\NewslettersRepository;
11 use MailPoet\Newsletter\Sending\SendingQueuesRepository;
12 use MailPoet\Newsletter\Sharing\ShareMetadataBuilder;
13 use MailPoet\Newsletter\Sharing\ShareVisibility;
14 use MailPoet\Newsletter\Url as NewsletterUrl;
15 use MailPoet\Subscribers\LinkTokens;
16 use MailPoet\Subscribers\SubscribersRepository;
17
18 class ViewInBrowserController {
19 /** @var LinkTokens */
20 private $linkTokens;
21
22 /** @var NewsletterUrl */
23 private $newsletterUrl;
24
25 /** @var ViewInBrowserRenderer */
26 private $viewInBrowserRenderer;
27
28 /** @var SubscribersRepository */
29 private $subscribersRepository;
30
31 /** @var SendingQueuesRepository */
32 private $sendingQueuesRepository;
33
34 /** @var NewslettersRepository */
35 private $newslettersRepository;
36
37 /** @var DependencyNotice */
38 private $dependencyNotice;
39
40 /** @var ShareVisibility */
41 private $shareVisibility;
42
43 /** @var ShareMetadataBuilder */
44 private $shareMetadataBuilder;
45
46 public function __construct(
47 LinkTokens $linkTokens,
48 NewsletterUrl $newsletterUrl,
49 NewslettersRepository $newslettersRepository,
50 ViewInBrowserRenderer $viewInBrowserRenderer,
51 SendingQueuesRepository $sendingQueuesRepository,
52 DependencyNotice $dependencyNotice,
53 SubscribersRepository $subscribersRepository,
54 ShareVisibility $shareVisibility,
55 ShareMetadataBuilder $shareMetadataBuilder
56 ) {
57 $this->linkTokens = $linkTokens;
58 $this->viewInBrowserRenderer = $viewInBrowserRenderer;
59 $this->subscribersRepository = $subscribersRepository;
60 $this->sendingQueuesRepository = $sendingQueuesRepository;
61 $this->newsletterUrl = $newsletterUrl;
62 $this->dependencyNotice = $dependencyNotice;
63 $this->newslettersRepository = $newslettersRepository;
64 $this->shareVisibility = $shareVisibility;
65 $this->shareMetadataBuilder = $shareMetadataBuilder;
66 }
67
68 public function view(array $data) {
69 $data = $this->newsletterUrl->transformUrlDataObject($data);
70 $isPreview = !empty($data['preview']);
71 $newsletter = $this->getNewsletter($data);
72 $subscriber = $this->getSubscriber($data);
73 if ($newsletter->getWpPostId() && $this->dependencyNotice->checkDependenciesAndEventuallyShowNotice()) {
74 return '';
75 }
76
77 // the queue must belong to the validated newsletter; otherwise its stored
78 // body is content the requester's newsletter/hash pair does not authorise
79 $queue = isset($data['queue_id']) ? $this->sendingQueuesRepository->findOneById($data['queue_id']) : null;
80 if ($queue && (!$queue->getNewsletter() || $queue->getNewsletter()->getId() !== $newsletter->getId())) {
81 throw new \InvalidArgumentException("Invalid 'queue_id'");
82 }
83
84 // if queue and subscriber exist, subscriber must have received the newsletter
85 if (!$isPreview && $queue && $subscriber->getId() && !$this->sendingQueuesRepository->isSubscriberProcessed($queue, $subscriber)) {
86 throw new \InvalidArgumentException("Subscriber did not receive the newsletter yet");
87 }
88
89 $html = $this->viewInBrowserRenderer->render($isPreview, $newsletter, $subscriber, $queue);
90 if (!empty($data['embed_hide_background'])) {
91 // Public embed URLs may request this cosmetic-only presentation variant.
92 $html = $this->hideEmbedBackground($html);
93 }
94 if (!$isPreview && $this->shareVisibility->canShare($newsletter)) {
95 $publicUrl = $this->newsletterUrl->getPublicShareUrl($newsletter);
96 // Pass $publicUrl as both the share target and the replaceState target so the
97 // tokenised view-in-browser URL is scrubbed from the address bar on load.
98 return $this->shareMetadataBuilder->injectShareToolbar($html, $newsletter, $publicUrl, $publicUrl);
99 }
100 return $html;
101 }
102
103 private function hideEmbedBackground(string $html): string {
104 $style = '<style id="mailpoet-newsletter-embed-background">html,body{background:transparent!important;}body{padding:0!important;}</style>';
105 $headPosition = stripos($html, '</head>');
106 if ($headPosition !== false) {
107 return substr_replace($html, $style, $headPosition, 0);
108 }
109
110 $matches = [];
111 if (preg_match('/<html\b[^>]*>/i', $html, $matches, PREG_OFFSET_CAPTURE)) {
112 $position = $matches[0][1] + strlen($matches[0][0]);
113 return substr_replace($html, $style, $position, 0);
114 }
115
116 return $style . $html;
117 }
118
119 private function getNewsletter(array $data) {
120 // newsletter - ID is mandatory, hash must be set and valid
121 if (empty($data['newsletter_id'])) {
122 throw new \InvalidArgumentException("Missing 'newsletter_id'");
123 }
124 if (empty($data['newsletter_hash'])) {
125 throw new \InvalidArgumentException("Missing 'newsletter_hash'");
126 }
127
128 $newsletter = $this->newslettersRepository->findOneById($data['newsletter_id']);
129 if (!$newsletter) {
130 throw new \InvalidArgumentException("Invalid 'newsletter_id'");
131 }
132
133 if ($data['newsletter_hash'] !== $newsletter->getHash()) {
134 throw new \InvalidArgumentException("Invalid 'newsletter_hash'");
135 }
136 return $newsletter;
137 }
138
139 private function getSubscriber(array $data): SubscriberEntity {
140 // subscriber is optional; if exists, token must validate
141 $subscriber = null;
142 if (!empty($data['subscriber_id'])) {
143 $subscriber = $this->subscribersRepository->findOneById($data['subscriber_id']);
144 }
145 if ($subscriber && empty($data['subscriber_token'])) {
146 throw new \InvalidArgumentException("Missing 'subscriber_token'");
147 }
148
149 if ($subscriber && !$this->linkTokens->verifyToken($subscriber, $data['subscriber_token'])) {
150 throw new \InvalidArgumentException("Invalid 'subscriber_token'");
151 }
152
153 // if this is a preview and subscriber does not exist,
154 // attempt to set subscriber to the current logged-in WP user
155 if (!$subscriber && !empty($data['preview'])) {
156 $subscriber = $this->subscribersRepository->getCurrentWPUser();
157 }
158
159 return $subscriber ?? new SubscriberEntity();
160 }
161 }
162