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 / Config / Shortcodes.php
mailpoet / lib / Config Last commit date
PopulatorData 3 months ago AccessControl.php 2 years ago Activator.php 2 months ago AssetsLoader.php 4 weeks ago Capabilities.php 3 months ago Changelog.php 3 months ago DeactivationPoll.php 3 years ago DeferredAdminNotices.php 2 months ago Env.php 6 months ago Hooks.php 1 month ago HooksWooCommerce.php 1 month ago Initializer.php 1 month ago Installer.php 11 months ago Localizer.php 1 week ago Menu.php 1 month ago PersonalDataErasers.php 1 month ago PersonalDataExporters.php 1 month ago PluginActivatedHook.php 3 years ago Populator.php 4 weeks ago PrivacyPolicy.php 1 month ago Renderer.php 1 year ago RendererFactory.php 3 years ago RequirementsChecker.php 2 months ago Router.php 3 months ago ServicesChecker.php 3 years ago Shortcodes.php 1 week ago SilentUpgraderSkin.php 3 years ago SubscriberChangesNotifier.php 2 months ago TranslationUpdater.php 3 months ago TwigEnvironment.php 1 year ago TwigFileSystemCache.php 3 years ago Updater.php 2 weeks ago index.php 3 years ago
Shortcodes.php
328 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Config;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Entities\NewsletterEntity;
9 use MailPoet\Entities\SendingQueueEntity;
10 use MailPoet\Entities\SubscriberEntity;
11 use MailPoet\Form\Widget;
12 use MailPoet\Newsletter\Embed\NewsletterEmbedService;
13 use MailPoet\Newsletter\NewslettersRepository;
14 use MailPoet\Newsletter\Sharing\ShareVisibility;
15 use MailPoet\Newsletter\Shortcodes\Categories\Date;
16 use MailPoet\Newsletter\Shortcodes\Categories\Link;
17 use MailPoet\Newsletter\Shortcodes\Categories\Newsletter;
18 use MailPoet\Newsletter\Shortcodes\Categories\Site;
19 use MailPoet\Newsletter\Shortcodes\Categories\Subscriber as SubscriberCategory;
20 use MailPoet\Newsletter\Shortcodes\Shortcodes as NewsletterShortcodes;
21 use MailPoet\Newsletter\Url as NewsletterUrl;
22 use MailPoet\Segments\SegmentSubscribersRepository;
23 use MailPoet\Subscribers\SubscribersRepository;
24 use MailPoet\Subscription\Pages;
25 use MailPoet\WP\Functions as WPFunctions;
26 use MailPoetVendor\Carbon\CarbonImmutable;
27 use Throwable;
28
29 class Shortcodes {
30 const DEFAULT_ARCHIVE_LIMIT = 100;
31
32 /** @var Pages */
33 private $subscriptionPages;
34
35 /** @var WPFunctions */
36 private $wp;
37
38 /** @var SegmentSubscribersRepository */
39 private $segmentSubscribersRepository;
40
41 /** @var SubscribersRepository */
42 private $subscribersRepository;
43
44 /** @var NewsletterUrl */
45 private $newsletterUrl;
46
47 /** @var NewslettersRepository */
48 private $newslettersRepository;
49
50 /** @var ShareVisibility */
51 private $shareVisibility;
52
53 /** @var Date */
54 private $dateCategory;
55
56 /** @var Link */
57 private $linkCategory;
58
59 /** @var Newsletter */
60 private $newsletterCategory;
61
62 /** @var SubscriberCategory */
63 private $subscriberCategory;
64
65 /** @var Site */
66 private $siteCategory;
67
68 /** @var NewsletterEmbedService */
69 private $newsletterEmbedService;
70
71 public function __construct(
72 Pages $subscriptionPages,
73 WPFunctions $wp,
74 SegmentSubscribersRepository $segmentSubscribersRepository,
75 SubscribersRepository $subscribersRepository,
76 NewsletterUrl $newsletterUrl,
77 NewslettersRepository $newslettersRepository,
78 ShareVisibility $shareVisibility,
79 Date $dateCategory,
80 Link $linkCategory,
81 Newsletter $newsletterCategory,
82 SubscriberCategory $subscriberCategory,
83 Site $siteCategory,
84 NewsletterEmbedService $newsletterEmbedService
85 ) {
86 $this->subscriptionPages = $subscriptionPages;
87 $this->wp = $wp;
88 $this->segmentSubscribersRepository = $segmentSubscribersRepository;
89 $this->subscribersRepository = $subscribersRepository;
90 $this->newsletterUrl = $newsletterUrl;
91 $this->newslettersRepository = $newslettersRepository;
92 $this->shareVisibility = $shareVisibility;
93 $this->dateCategory = $dateCategory;
94 $this->linkCategory = $linkCategory;
95 $this->newsletterCategory = $newsletterCategory;
96 $this->subscriberCategory = $subscriberCategory;
97 $this->siteCategory = $siteCategory;
98 $this->newsletterEmbedService = $newsletterEmbedService;
99 }
100
101 public function init() {
102 // form widget shortcode
103 $this->wp->addShortcode('mailpoet_form', [$this, 'formWidget']);
104
105 // subscribers count shortcode
106 $this->wp->addShortcode('mailpoet_subscribers_count', [
107 $this, 'getSubscribersCount',
108 ]);
109 $this->wp->addShortcode('wysija_subscribers_count', [
110 $this, 'getSubscribersCount',
111 ]);
112
113 // archives page
114 $this->wp->addShortcode('mailpoet_archive', [
115 $this, 'getArchive',
116 ]);
117 $this->wp->addShortcode('mailpoet_newsletter', [
118 $this, 'getNewsletterEmbed',
119 ]);
120
121 $this->wp->addFilter('mailpoet_archive_email_processed_date', [
122 $this, 'renderArchiveDate',
123 ], 2);
124 $this->wp->addFilter('mailpoet_archive_email_subject_line', [
125 $this, 'renderArchiveSubject',
126 ], 2, 3);
127
128 // initialize subscription pages data
129 $this->subscriptionPages->init();
130 // initialize subscription management shortcodes
131 $this->subscriptionPages->initShortcodes();
132 }
133
134 public function getNewsletterEmbed($params = []): string {
135 if (!is_array($params)) {
136 $params = [];
137 }
138
139 return $this->newsletterEmbedService->render([
140 'newsletterId' => $params['id'] ?? null,
141 'height' => $params['height'] ?? null,
142 'width' => $params['width'] ?? null,
143 'showFallbackLink' => $params['show_fallback_link'] ?? true,
144 'fallbackLinkAlignment' => $params['fallback_link_alignment'] ?? 'center',
145 'iframeAlignment' => $params['iframe_alignment'] ?? 'center',
146 'showEmailBackground' => $params['show_email_background'] ?? true,
147 ]);
148 }
149
150 public function formWidget($params = []) {
151 // IMPORTANT: fixes conflict with MagicMember
152 $this->wp->removeShortcode('user_list');
153
154 if (isset($params['id']) && (int)$params['id'] > 0) {
155 $formWidget = new Widget();
156 return $formWidget->widget([
157 'form' => (int)$params['id'],
158 'form_type' => 'shortcode',
159 ]);
160 }
161 }
162
163 public function getSubscribersCount($params) {
164 if (!empty($params['segments'])) {
165 $segmentIds = array_map(function($segmentId) {
166 return (int)trim($segmentId);
167 }, explode(',', $params['segments']));
168 }
169
170 if (empty($segmentIds)) {
171 return $this->wp->numberFormatI18n(
172 $this->subscribersRepository->countBy(['status' => SubscriberEntity::STATUS_SUBSCRIBED, 'deletedAt' => null])
173 );
174 } else {
175 // A failed count must not break rendering of the email/shortcode.
176 try {
177 $count = $this->segmentSubscribersRepository->getSubscribersCountBySegmentIds($segmentIds, SubscriberEntity::STATUS_SUBSCRIBED);
178 } catch (Throwable $e) {
179 $count = 0;
180 }
181 return $this->wp->numberFormatI18n($count);
182 }
183 }
184
185 public function getArchive($params = '') {
186 $html = '';
187
188 $parsedParams = $this->getParsedArchiveParams($params);
189 $newsletters = $this->newslettersRepository->getArchives($parsedParams);
190
191 $subscriber = $this->subscribersRepository->getCurrentWPUser();
192
193 if (empty($newsletters)) {
194 return $this->wp->applyFilters(
195 'mailpoet_archive_no_newsletters',
196 __('Oops! There are no newsletters to display.', 'mailpoet')
197 );
198 } else {
199 $title = $this->wp->applyFilters('mailpoet_archive_title', '');
200 if (!empty($title) && is_scalar($title)) {
201 $html .= '<h3 class="mailpoet_archive_title">' . (string)$title . '</h3>';
202 }
203 $html .= '<ul class="mailpoet_archive">';
204 foreach ($newsletters as $newsletter) {
205 $queue = $newsletter->getLatestQueue();
206 $processedDate = $this->wp->applyFilters('mailpoet_archive_email_processed_date', $newsletter);
207 $subjectLine = $this->wp->applyFilters('mailpoet_archive_email_subject_line', $newsletter, $subscriber, $queue);
208
209 $html .= '<li>' .
210 '<span class="mailpoet_archive_date">' .
211 (is_scalar($processedDate) ? (string)$processedDate : '') .
212 '</span>
213 <span class="mailpoet_archive_subject">' .
214 (is_scalar($subjectLine) ? (string)$subjectLine : '') .
215 '</span>
216 </li>';
217 }
218 $html .= '</ul>';
219 }
220 return $html;
221 }
222
223 public function getParsedArchiveParams($params): array {
224 $parsedParams = [
225 'startDate' => null,
226 'endDate' => null,
227 'segmentIds' => [],
228 'subjectContains' => '',
229 'limit' => self::DEFAULT_ARCHIVE_LIMIT,
230 ];
231
232 if (!is_array($params)) {
233 return $parsedParams;
234 }
235
236 if (!empty($params['segments']) && is_string($params['segments'])) {
237 $parsedParams['segmentIds'] = array_map(function($segmentId) {
238 return (int)trim($segmentId);
239 }, explode(',', $params['segments']));
240 }
241
242 if (isset($params['start_date']) && is_string($params['start_date']) && $params['start_date'] !== '') {
243 try {
244 $parsedParams['startDate'] = new CarbonImmutable(trim($params['start_date']));
245 } catch (\Throwable $throwable) {
246 // Don't error out if invalid date
247 }
248 }
249
250 if (isset($params['end_date']) && is_string($params['end_date']) && $params['end_date'] !== '') {
251 try {
252 $parsedParams['endDate'] = new CarbonImmutable(trim($params['end_date']));
253 } catch (\Throwable $throwable) {
254 // Don't error out if invalid date
255 }
256 }
257
258 $lastDays = $params['in_the_last_days'] ?? null;
259 if (is_scalar($lastDays) && $lastDays > 0) {
260 $parsedParams['endDate'] = null;
261 $parsedParams['startDate'] = CarbonImmutable::now()->subDays(intval($lastDays))->startOfDay();
262 }
263
264 if (isset($params['subject_contains']) && is_string($params['subject_contains']) && $params['subject_contains'] !== '') {
265 $parsedParams['subjectContains'] = trim($params['subject_contains']);
266 }
267
268 $limit = $params['limit'] ?? null;
269 if (is_scalar($limit) && intval($limit) > 0) {
270 $parsedParams['limit'] = intval($limit);
271 }
272
273 return $parsedParams;
274 }
275
276 public function renderArchiveDate(NewsletterEntity $newsletter) {
277 $timestamp = null;
278 $processedAt = $newsletter->getProcessedAt();
279
280 if (!is_null($processedAt)) {
281 $timestamp = $processedAt->getTimestamp();
282 }
283
284 return $this->wp->dateI18n(
285 $this->wp->getOption('date_format'),
286 $timestamp
287 );
288 }
289
290 public function renderArchiveSubject(NewsletterEntity $newsletter, ?SubscriberEntity $subscriber, ?SendingQueueEntity $queue) {
291 if (is_null($subscriber)) {
292 $subscriber = new SubscriberEntity();
293 }
294
295 /**
296 * An ugly workaround to make sure state is not shared via NewsletterShortcodes service
297 * This should be replaced with injected service when state is removed from this service
298 * (i.e. after https://mailpoet.atlassian.net/browse/MAILPOET-4087 is done and merged to master)
299 */
300 $shortcodeProcessor = new NewsletterShortcodes(
301 $this->dateCategory,
302 $this->linkCategory,
303 $this->newsletterCategory,
304 $this->subscriberCategory,
305 $this->siteCategory,
306 $this->wp
307 );
308
309 $shortcodeProcessor->setNewsletter($newsletter);
310
311 $shortcodeProcessor->setSubscriber($subscriber);
312 $shortcodeProcessor->setQueue($queue);
313 $subject = (string)$shortcodeProcessor->replace($queue ? $queue->getNewsletterRenderedSubject() : '');
314 if ($newsletter->getType() === NewsletterEntity::TYPE_STANDARD && $this->shareVisibility->canShare($newsletter)) {
315 $previewUrl = $this->newsletterUrl->getPublicShareUrl($newsletter);
316 $linkTitle = __('Read in a new tab', 'mailpoet');
317 } else {
318 $previewUrl = $this->newsletterUrl->getViewInBrowserUrl($newsletter, $subscriber, $queue);
319 $linkTitle = __('Preview in a new tab', 'mailpoet');
320 }
321
322 return '<a href="' . $this->wp->escUrl($previewUrl) . '" target="_blank" rel="noopener noreferrer" title="'
323 . $this->wp->escAttr($linkTitle) . '">'
324 . $this->wp->escHtml($subject) .
325 '</a>';
326 }
327 }
328