PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
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 / ViewInBrowserRenderer.php
mailpoet / lib / Newsletter / ViewInBrowser Last commit date
ViewInBrowserController.php 1 month ago ViewInBrowserRenderer.php 2 months ago index.php 3 years ago
ViewInBrowserRenderer.php
237 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 Automattic\WooCommerce\EmailEditor\Email_Editor_Container;
9 use Automattic\WooCommerce\EmailEditor\Engine\Personalizer;
10 use MailPoet\Entities\NewsletterEntity;
11 use MailPoet\Entities\SendingQueueEntity;
12 use MailPoet\Entities\SubscriberEntity;
13 use MailPoet\Newsletter\Links\Links;
14 use MailPoet\Newsletter\Renderer\Renderer;
15 use MailPoet\Newsletter\Shortcodes\Shortcodes;
16 use MailPoet\Newsletter\Url as NewsletterUrl;
17 use MailPoet\Settings\TrackingConfig;
18 use MailPoet\WP\Emoji;
19
20 class ViewInBrowserRenderer {
21 private const OPTION_RENDER_AS_PREVIEW = 'renderAsPreview';
22 private const OPTION_SANITIZE_RENDERED_QUEUE_LINKS = 'sanitizeRenderedQueueLinks';
23 private const OPTION_SHORTCODES_PREVIEW = 'shortcodesPreview';
24 private const OPTION_REPLACE_SUBSCRIBER_TRACKING = 'replaceSubscriberTracking';
25 private const OPTION_PERSONALIZER_PREVIEW = 'personalizerPreview';
26 private const OPTION_REPLACE_VIEW_IN_BROWSER_URL = 'replaceViewInBrowserUrlWithPublicShareUrl';
27
28 /** @var Emoji */
29 private $emoji;
30
31 /** @var TrackingConfig */
32 private $trackingConfig;
33
34 /** @var Renderer */
35 private $renderer;
36
37 /** @var Shortcodes */
38 private $shortcodes;
39
40 /** @var Links */
41 private $links;
42
43 /** @var NewsletterUrl */
44 private $newsletterUrl;
45
46 private Personalizer $personalizer;
47
48 public function __construct(
49 Emoji $emoji,
50 TrackingConfig $trackingConfig,
51 Shortcodes $shortcodes,
52 Renderer $renderer,
53 Links $links,
54 NewsletterUrl $newsletterUrl
55 ) {
56 $this->emoji = $emoji;
57 $this->trackingConfig = $trackingConfig;
58 $this->renderer = $renderer;
59 $this->shortcodes = $shortcodes;
60 $this->links = $links;
61 $this->newsletterUrl = $newsletterUrl;
62 $this->personalizer = Email_Editor_Container::container()->get(Personalizer::class);
63 }
64
65 public function render(
66 bool $isPreview,
67 NewsletterEntity $newsletter,
68 ?SubscriberEntity $subscriber = null,
69 ?SendingQueueEntity $queue = null
70 ) {
71 return $this->renderWithContext(
72 $newsletter,
73 $subscriber,
74 $queue,
75 $this->buildRenderOptionsForPreview($isPreview)
76 );
77 }
78
79 public function renderPublicShare(
80 NewsletterEntity $newsletter,
81 ?SendingQueueEntity $queue = null
82 ): string {
83 // An empty SubscriberEntity (not null) is intentional: the subscriber
84 // shortcode handler treats null as "leave the shortcode in place" but
85 // resolves `default:` arguments against any SubscriberEntity instance.
86 return $this->renderWithContext(
87 $newsletter,
88 new SubscriberEntity(),
89 $queue,
90 $this->buildRenderOptionsForPublicShare()
91 );
92 }
93
94 /**
95 * @param array{
96 * renderAsPreview: bool,
97 * sanitizeRenderedQueueLinks: bool,
98 * shortcodesPreview: bool,
99 * replaceSubscriberTracking: bool,
100 * personalizerPreview: bool,
101 * replaceViewInBrowserUrlWithPublicShareUrl: bool
102 * } $options
103 */
104 private function renderWithContext(
105 NewsletterEntity $newsletter,
106 ?SubscriberEntity $subscriber,
107 ?SendingQueueEntity $queue,
108 array $options
109 ): string {
110 $renderAsPreview = $options[self::OPTION_RENDER_AS_PREVIEW];
111 $sanitizeRenderedQueueLinks = $options[self::OPTION_SANITIZE_RENDERED_QUEUE_LINKS];
112 $shortcodesPreview = $options[self::OPTION_SHORTCODES_PREVIEW];
113 $replaceSubscriberTracking = $options[self::OPTION_REPLACE_SUBSCRIBER_TRACKING];
114 $personalizerPreview = $options[self::OPTION_PERSONALIZER_PREVIEW];
115 $replaceViewInBrowserUrlWithPublicShareUrl = $options[self::OPTION_REPLACE_VIEW_IN_BROWSER_URL];
116
117 $isTrackingEnabled = $this->trackingConfig->isEmailTrackingEnabled();
118
119 if ($queue && $queue->getNewsletterRenderedBody()) {
120 $body = $queue->getNewsletterRenderedBody();
121 if (is_array($body)) {
122 $newsletterBody = $body['html'];
123 } else {
124 $newsletterBody = '';
125 }
126 $newsletterBody = $this->emoji->decodeEmojisInBody($newsletterBody);
127 // rendered newsletter body has shortcodes converted to links; we need to
128 // isolate "view in browser", "unsubscribe" and "manage subscription" links
129 // and convert them to shortcodes, which later will be replaced with "#" when
130 // newsletter is previewed
131 if ($sanitizeRenderedQueueLinks && preg_match($this->links->getLinkRegex(), $newsletterBody)) {
132 $newsletterBody = $this->links->convertHashedLinksToShortcodesAndUrls(
133 $newsletterBody,
134 $queue->getId(),
135 $convertAll = true
136 );
137 // remove open tracking link
138 $newsletterBody = str_replace(Links::DATA_TAG_OPEN, '', $newsletterBody);
139 }
140 } else {
141 if ($renderAsPreview) {
142 $newsletterBody = $this->renderer->renderAsPreview($newsletter, 'html');
143 } else {
144 $newsletterBody = $this->renderer->render($newsletter, $sendingTask = null, 'html');
145 }
146 }
147 $this->prepareShortcodes(
148 $newsletter,
149 $subscriber,
150 $queue,
151 $shortcodesPreview
152 );
153 $renderedNewsletter = $this->shortcodes->replace($newsletterBody);
154 if ($replaceViewInBrowserUrlWithPublicShareUrl) {
155 $renderedNewsletter = str_replace(
156 $this->newsletterUrl->getViewInBrowserUrl($newsletter, null, $queue, true),
157 $this->newsletterUrl->getPublicShareUrl($newsletter),
158 $renderedNewsletter
159 );
160 }
161 if ($replaceSubscriberTracking && $queue && $subscriber && $isTrackingEnabled) {
162 $renderedNewsletter = $this->links->replaceSubscriberData(
163 $subscriber->getId(),
164 $queue->getId(),
165 $renderedNewsletter
166 );
167 }
168 if ($newsletter->getWpPostId() !== null) {
169 $this->personalizer->set_context([
170 'recipient_email' => $subscriber ? $subscriber->getEmail() : null,
171 'is_user_preview' => $personalizerPreview,
172 'newsletter_id' => $newsletter->getId(),
173 'queue_id' => $queue ? $queue->getId() : null,
174 ]);
175 $renderedNewsletter = $this->personalizer->personalize_content($renderedNewsletter);
176 }
177 return $renderedNewsletter;
178 }
179
180 /**
181 * @return array{
182 * renderAsPreview: bool,
183 * sanitizeRenderedQueueLinks: bool,
184 * shortcodesPreview: bool,
185 * replaceSubscriberTracking: bool,
186 * personalizerPreview: bool,
187 * replaceViewInBrowserUrlWithPublicShareUrl: bool
188 * }
189 */
190 private function buildRenderOptionsForPreview(bool $isPreview): array {
191 return [
192 self::OPTION_RENDER_AS_PREVIEW => $isPreview,
193 self::OPTION_SANITIZE_RENDERED_QUEUE_LINKS => $isPreview,
194 self::OPTION_SHORTCODES_PREVIEW => $isPreview,
195 self::OPTION_REPLACE_SUBSCRIBER_TRACKING => !$isPreview,
196 self::OPTION_PERSONALIZER_PREVIEW => $isPreview,
197 self::OPTION_REPLACE_VIEW_IN_BROWSER_URL => false,
198 ];
199 }
200
201 /**
202 * @return array{
203 * renderAsPreview: bool,
204 * sanitizeRenderedQueueLinks: bool,
205 * shortcodesPreview: bool,
206 * replaceSubscriberTracking: bool,
207 * personalizerPreview: bool,
208 * replaceViewInBrowserUrlWithPublicShareUrl: bool
209 * }
210 */
211 private function buildRenderOptionsForPublicShare(): array {
212 return [
213 // Keep no-queue public share fallback in preview mode to avoid
214 // send-time preprocessing side effects and keep shortcode behavior
215 // consistent with the rendering mode.
216 self::OPTION_RENDER_AS_PREVIEW => true,
217 self::OPTION_SANITIZE_RENDERED_QUEUE_LINKS => true,
218 self::OPTION_SHORTCODES_PREVIEW => true,
219 self::OPTION_REPLACE_SUBSCRIBER_TRACKING => false,
220 self::OPTION_PERSONALIZER_PREVIEW => true,
221 self::OPTION_REPLACE_VIEW_IN_BROWSER_URL => true,
222 ];
223 }
224
225 private function prepareShortcodes(
226 NewsletterEntity $newsletter,
227 ?SubscriberEntity $subscriber,
228 ?SendingQueueEntity $queue,
229 bool $wpUserPreview
230 ) {
231 $this->shortcodes->setQueue($queue);
232 $this->shortcodes->setNewsletter($newsletter);
233 $this->shortcodes->setWpUserPreview($wpUserPreview);
234 $this->shortcodes->setSubscriber($subscriber);
235 }
236 }
237