This commit is contained in:
emmymayo
2025-02-05 23:15:46 +01:00
commit 7269c99357
16995 changed files with 3389680 additions and 0 deletions
@@ -0,0 +1,21 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
interface CategoryInterface {
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string;
}
@@ -0,0 +1,46 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\WP\Functions as WPFunctions;
class Date implements CategoryInterface {
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string {
$actionMapping = [
'd' => 'd',
'dordinal' => 'jS',
'dtext' => 'l',
'm' => 'm',
'mtext' => 'F',
'y' => 'Y',
];
$wp = new WPFunctions();
$date = $wp->currentTime('timestamp');
if (
($newsletter instanceof NewsletterEntity)
&& ($newsletter->getSentAt() instanceof \DateTimeInterface)
&& ($newsletter->getStatus() === NewsletterEntity::STATUS_SENT)
) {
$date = $newsletter->getSentAt()->getTimestamp();
}
if (!empty($actionMapping[$shortcodeDetails['action']])) {
return $wp->dateI18n($actionMapping[$shortcodeDetails['action']], $date);
}
return ($shortcodeDetails['action'] === 'custom' && $shortcodeDetails['action_argument'] === 'format') ?
$wp->dateI18n($shortcodeDetails['action_argument_value'], $date) :
null;
}
}
@@ -0,0 +1,177 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Newsletter\Url as NewsletterUrl;
use MailPoet\Settings\SettingsController;
use MailPoet\Settings\TrackingConfig;
use MailPoet\Subscription\SubscriptionUrlFactory;
use MailPoet\WP\Functions as WPFunctions;
class Link implements CategoryInterface {
const CATEGORY_NAME = 'link';
/** @var SettingsController */
private $settings;
/** @var NewsletterUrl */
private $newsletterUrl;
/** @var WPFunctions */
private $wp;
/** @var TrackingConfig */
private $trackingConfig;
public function __construct(
SettingsController $settings,
NewsletterUrl $newsletterUrl,
WPFunctions $wp,
TrackingConfig $trackingConfig
) {
$this->settings = $settings;
$this->newsletterUrl = $newsletterUrl;
$this->wp = $wp;
$this->trackingConfig = $trackingConfig;
}
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string {
$subscriptionUrlFactory = SubscriptionUrlFactory::getInstance();
switch ($shortcodeDetails['action']) {
case 'subscription_unsubscribe_url':
return self::processUrl(
$shortcodeDetails['action'],
$subscriptionUrlFactory->getConfirmUnsubscribeUrl(
$wpUserPreview ? null : $subscriber,
$queue ? $queue->getId() : null
),
$queue,
$wpUserPreview
);
case 'subscription_instant_unsubscribe_url':
return self::processUrl(
$shortcodeDetails['action'],
$subscriptionUrlFactory->getUnsubscribeUrl(
$wpUserPreview ? null : $subscriber,
$queue ? $queue->getId() : null
),
$queue,
$wpUserPreview
);
case 'subscription_manage_url':
return self::processUrl(
$shortcodeDetails['action'],
$subscriptionUrlFactory->getManageUrl($wpUserPreview ? null : $subscriber),
$queue,
$wpUserPreview
);
case 'newsletter_view_in_browser_url':
$url = $this->newsletterUrl->getViewInBrowserUrl(
$newsletter,
$wpUserPreview ? null : $subscriber,
$queue,
$wpUserPreview
);
return self::processUrl($shortcodeDetails['action'], $url, $queue, $wpUserPreview);
case 'subscription_re_engage_url':
$url = $subscriptionUrlFactory->getReEngagementUrl($wpUserPreview ? null : $subscriber);
return self::processUrl($shortcodeDetails['action'], $url, $queue, $wpUserPreview);
default:
$shortcode = self::getFullShortcode($shortcodeDetails['action']);
$url = $this->wp->applyFilters(
'mailpoet_newsletter_shortcode_link',
$shortcode,
$newsletter,
$subscriber,
$queue,
$shortcodeDetails['arguments'],
$wpUserPreview
);
return ($url !== $shortcode) ?
self::processUrl($shortcodeDetails['action'], $url, $queue, $wpUserPreview) :
null;
}
}
public function processUrl($action, $url, ?SendingQueueEntity $queue, $wpUserPreview = false): string {
if ($wpUserPreview) return $url;
return ($queue && $this->trackingConfig->isEmailTrackingEnabled()) ?
self::getFullShortcode($action) :
$url;
}
public function processShortcodeAction(
$shortcodeAction,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
$wpUserPreview = false
): ?string {
$subscriptionUrlFactory = SubscriptionUrlFactory::getInstance();
switch ($shortcodeAction) {
case 'subscription_unsubscribe_url':
$url = $subscriptionUrlFactory->getConfirmUnsubscribeUrl(
$subscriber,
$queue ? $queue->getId() : null
);
break;
case 'subscription_instant_unsubscribe_url':
$url = $subscriptionUrlFactory->getUnsubscribeUrl(
$subscriber,
$queue ? $queue->getId() : null
);
break;
case 'subscription_manage_url':
$url = $subscriptionUrlFactory->getManageUrl($subscriber);
break;
case 'newsletter_view_in_browser_url':
$url = $this->newsletterUrl->getViewInBrowserUrl(
$newsletter,
$subscriber,
$queue,
false
);
break;
case 'subscription_re_engage_url':
$url = $subscriptionUrlFactory->getReEngagementUrl($subscriber);
break;
default:
$shortcode = self::getFullShortcode($shortcodeAction);
$url = $this->wp->applyFilters(
'mailpoet_newsletter_shortcode_link',
$shortcode,
$newsletter,
$subscriber,
$queue,
$wpUserPreview
);
$url = ($url !== $shortcodeAction) ? $url : null;
break;
}
return $url;
}
private function getFullShortcode($action): string {
return sprintf('[link:%s]', $action);
}
}
@@ -0,0 +1,100 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\WP\Functions as WPFunctions;
use MailPoet\WP\Posts as WPPosts;
class Newsletter implements CategoryInterface {
/** @var NewslettersRepository */
private $newslettersRepository;
private WPFunctions $wp;
public function __construct(
NewslettersRepository $newslettersRepository,
WPFunctions $wp
) {
$this->newslettersRepository = $newslettersRepository;
$this->wp = $wp;
}
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string {
switch ($shortcodeDetails['action']) {
case 'subject':
return ($newsletter instanceof NewsletterEntity) ? $newsletter->getSubject() : null;
case 'total':
return (string)substr_count($content, 'data-post-id');
case 'post_title':
preg_match_all('/data-post-id="(\d+)"/ism', $content, $posts);
$postIds = array_unique($posts[1]);
$latestPost = (!empty($postIds)) ? $this->getLatestWPPost($postIds) : null;
if ($latestPost) {
// When a user with role author publish a post containing "&" in the title, the character is saved as "&amp;" in the database.
// Removing HTML tags from the title because
$title = $this->wp->wpStripAllTags($latestPost['post_title']);
// Decoding special characters such as &amp; to &, etc.
return htmlspecialchars_decode($title);
}
return null;
case 'number':
if (!($newsletter instanceof NewsletterEntity)) return null;
if ($newsletter->getType() !== NewsletterEntity::TYPE_NOTIFICATION_HISTORY) {
return null;
}
$sentNewsletters = $this->newslettersRepository->countBy([
'parent' => $newsletter->getParent(),
'status' => NewsletterEntity::STATUS_SENT,
]);
return (string)++$sentNewsletters;
default:
return null;
}
}
public function ensureConsistentQueryType(\WP_Query $query) {
// Queries with taxonomies are autodetected as 'is_archive=true' and 'is_home=false'
// while queries without them end up being 'is_archive=false' and 'is_home=true'.
// This is to fix that by always enforcing constistent behavior.
$query->is_archive = true; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
$query->is_home = false; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
}
private function getLatestWPPost($postIds) {
// set low priority to execute 'ensureConstistentQueryType' before any other filter
$filterPriority = defined('PHP_INT_MIN') ? constant('PHP_INT_MIN') : ~PHP_INT_MAX;
$this->wp->addAction('pre_get_posts', [$this, 'ensureConsistentQueryType'], $filterPriority);
$posts = new \WP_Query(
[
'post_type' => WPPosts::getTypes(),
'post__in' => $postIds,
'posts_per_page' => 1,
'ignore_sticky_posts' => true,
'orderby' => 'post_date',
'order' => 'DESC',
]
);
$this->wp->removeAction('pre_get_posts', [$this, 'ensureConsistentQueryType'], $filterPriority);
return (!empty($posts->posts[0])) && ($posts->posts[0] instanceof \WP_Post) ?
$posts->posts[0]->to_array() :
false;
}
}
@@ -0,0 +1,50 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\WP\Functions as WPFunctions;
class Site implements CategoryInterface {
/** @var WPFunctions */
private $wp;
public function __construct(
WPFunctions $wp
) {
$this->wp = $wp;
}
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string {
switch ($shortcodeDetails['action']) {
case 'title':
// Decoding special characters such as &amp; to &, etc.
return htmlspecialchars_decode($this->wp->getBloginfo('name'));
case 'homepage_url':
return $this->wp->getBloginfo('url');
case 'homepage_link':
return sprintf(
'<a target="_blank" href="%s">%s</a>',
$this->wp->escUrl($this->wp->getBloginfo('url')),
$this->wp->escHtml($this->wp->getBloginfo('name'))
);
default:
return null;
}
}
}
@@ -0,0 +1,81 @@
<?php declare(strict_types = 1);
namespace MailPoet\Newsletter\Shortcodes\Categories;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberCustomFieldEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Subscribers\SubscriberCustomFieldRepository;
use MailPoet\Subscribers\SubscribersRepository;
use MailPoet\WP\Functions as WPFunctions;
class Subscriber implements CategoryInterface {
/** @var SubscribersRepository */
private $subscribersRepository;
/** @var SubscriberCustomFieldRepository */
private $subscriberCustomFieldRepository;
public function __construct(
SubscribersRepository $subscribersRepository,
SubscriberCustomFieldRepository $subscriberCustomFieldRepository
) {
$this->subscribersRepository = $subscribersRepository;
$this->subscriberCustomFieldRepository = $subscriberCustomFieldRepository;
}
public function process(
array $shortcodeDetails,
NewsletterEntity $newsletter = null,
SubscriberEntity $subscriber = null,
SendingQueueEntity $queue = null,
string $content = '',
bool $wpUserPreview = false
): ?string {
if (!($subscriber instanceof SubscriberEntity)) {
return $shortcodeDetails['shortcode'];
}
$defaultValue = ($shortcodeDetails['action_argument'] === 'default') ?
$shortcodeDetails['action_argument_value'] :
'';
switch ($shortcodeDetails['action']) {
case 'firstname':
return (!empty($subscriber->getFirstName())) ? htmlspecialchars($subscriber->getFirstName()) : $defaultValue;
case 'lastname':
return !empty($subscriber->getLastName()) ? htmlspecialchars($subscriber->getLastName()) : $defaultValue;
case 'email':
return $subscriber->getEmail();
case 'displayname':
if ($subscriber->getWpUserId()) {
$wpUser = WPFunctions::get()->getUserdata($subscriber->getWpUserId());
return $wpUser->user_login; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
}
return $defaultValue;
case 'count':
return (string)$this->getSubscribersCountWithSubscribedStatus();
default:
if (
preg_match('/cf_(\d+)/', $shortcodeDetails['action'], $customField) &&
!empty($subscriber->getId())
) {
$customField = $this->subscriberCustomFieldRepository->findOneBy([
'subscriber' => $subscriber,
'customField' => $customField[1],
]);
return ($customField instanceof SubscriberCustomFieldEntity && !empty($customField->getValue()))
? htmlspecialchars($customField->getValue())
: $defaultValue;
}
return null;
}
}
private function getSubscribersCountWithSubscribedStatus(): int {
return $this->subscribersRepository->countBy(['status' => SubscriberEntity::STATUS_SUBSCRIBED, 'deletedAt' => null]);
}
}
@@ -0,0 +1,227 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes;
if (!defined('ABSPATH')) exit;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Newsletter\Shortcodes\Categories\CategoryInterface;
use MailPoet\Newsletter\Shortcodes\Categories\Date;
use MailPoet\Newsletter\Shortcodes\Categories\Link;
use MailPoet\Newsletter\Shortcodes\Categories\Newsletter;
use MailPoet\Newsletter\Shortcodes\Categories\Site;
use MailPoet\Newsletter\Shortcodes\Categories\Subscriber;
use MailPoet\WP\Functions as WPFunctions;
class Shortcodes {
/** @var NewsletterEntity|null */
private $newsletter;
/** @var SubscriberEntity|null */
private $subscriber;
/** @var SendingQueueEntity|null */
private $queue;
/** @var bool */
private $wpUserPreview = false;
/** @var Date */
private $dateCategory;
/** @var Link */
private $linkCategory;
/** @var Newsletter */
private $newsletterCategory;
/** @var Subscriber */
private $subscriberCategory;
/** @var Site */
private $siteCategory;
/** @var WPFunctions */
private $wp;
public function __construct(
Date $dateCategory,
Link $linkCategory,
Newsletter $newsletterCategory,
Subscriber $subscriberCategory,
Site $siteCategory,
WPFunctions $wp
) {
$this->dateCategory = $dateCategory;
$this->linkCategory = $linkCategory;
$this->newsletterCategory = $newsletterCategory;
$this->subscriberCategory = $subscriberCategory;
$this->siteCategory = $siteCategory;
$this->wp = $wp;
}
public function setNewsletter(NewsletterEntity $newsletter = null): void {
$this->newsletter = $newsletter;
}
public function setSubscriber(SubscriberEntity $subscriber = null): void {
$this->subscriber = $subscriber;
}
public function setQueue(SendingQueueEntity $queue = null): void {
$this->queue = $queue;
}
public function setWpUserPreview(bool $wpUserPreview): void {
$this->wpUserPreview = $wpUserPreview;
}
public function extract($content, $categories = false) {
$categories = (is_array($categories)) ? implode('|', $categories) : false;
// match: [category:shortcode] or [category|category|...:shortcode]
// dot not match: [category://shortcode] - avoids matching http/ftp links
$regex = sprintf(
'/\[%s:(?!\/\/).*?\]/i',
($categories) ? '(?:' . $categories . ')' : '(?:\w+)'
);
preg_match_all($regex, (string)$content, $shortcodes);
$shortcodes = $shortcodes[0];
return (count($shortcodes)) ?
array_values(array_unique($shortcodes)) :
false;
}
/**
* Parse a MailPoet-style shortcode.
* The syntax is [category:action | argument:argument_value], it can have a single argument.
*/
public function match($shortcode) {
preg_match(
'/\[(?P<category>\w+)?:(?P<action>\w+)(?:.*?\|.*?(?P<argument>\w+):(?P<argument_value>.*?))?\]/',
$shortcode,
$match
);
// If argument exists, copy it to the arguments array
if (!empty($match['argument'])) {
$match['arguments'] = [$match['argument'] => isset($match['argument_value']) ? $match['argument_value'] : ''];
}
return $match;
}
/**
* Parse a WordPress-style shortcode.
* The syntax is [category:action arg1="value1" arg2="value2"], it can have multiple arguments.
*/
public function matchWPShortcode($shortcode) {
$atts = $this->wp->shortcodeParseAtts(trim($shortcode, '[]/'));
if (empty($atts[0])) {
return [];
}
$shortcodeName = $atts[0];
list($category, $action) = explode(':', $shortcodeName);
$shortcodeDetails = [];
$shortcodeDetails['category'] = $category;
$shortcodeDetails['action'] = $action;
$shortcodeDetails['arguments'] = [];
foreach ($atts as $attrName => $attrValue) {
if (is_numeric($attrName)) {
continue; // Skip unnamed attributes
}
$shortcodeDetails['arguments'][$attrName] = $attrValue;
// Make a shortcut to the first argument
if (!isset($shortcodeDetails['argument'])) {
$shortcodeDetails['argument'] = $attrName;
$shortcodeDetails['argument_value'] = $attrValue;
}
}
return $shortcodeDetails;
}
public function process($shortcodes, $content = '') {
$processedShortcodes = [];
foreach ($shortcodes as $shortcode) {
$shortcodeDetails = $this->match($shortcode);
if (empty($shortcodeDetails)) {
// Wrong MailPoet shortcode syntax, try to parse as a native WP shortcode
$shortcodeDetails = $this->matchWPShortcode($shortcode);
}
$shortcodeDetails['shortcode'] = $shortcode;
$shortcodeDetails['category'] = !empty($shortcodeDetails['category']) ?
$shortcodeDetails['category'] :
'';
$shortcodeDetails['action'] = !empty($shortcodeDetails['action']) ?
$shortcodeDetails['action'] :
'';
$shortcodeDetails['action_argument'] = !empty($shortcodeDetails['argument']) ?
$shortcodeDetails['argument'] :
'';
$shortcodeDetails['action_argument_value'] = !empty($shortcodeDetails['argument_value']) ?
$shortcodeDetails['argument_value'] :
'';
$shortcodeDetails['arguments'] = !empty($shortcodeDetails['arguments']) ?
$shortcodeDetails['arguments'] : [];
$category = strtolower($shortcodeDetails['category']);
$categoryClass = $this->getCategoryObject($category);
if ($categoryClass instanceof CategoryInterface) {
$processedShortcodes[] = $categoryClass->process(
$shortcodeDetails,
$this->newsletter,
$this->subscriber,
$this->queue,
$content,
$this->wpUserPreview
);
} else {
$customShortcode = $this->wp->applyFilters(
'mailpoet_newsletter_shortcode',
$shortcode,
$this->newsletter,
$this->subscriber,
$this->queue,
$content,
$shortcodeDetails['arguments'],
$this->wpUserPreview
);
$processedShortcodes[] = ($customShortcode === $shortcode) ?
false :
$customShortcode;
}
}
return $processedShortcodes;
}
public function replace($content, $contentSource = null, $categories = null) {
$shortcodes = $this->extract($content, $categories);
if (!$shortcodes) {
return $content;
}
// if content contains only shortcodes (e.g., [newsletter:post_title]) but their processing
// depends on some other content (e.g., "post_id" inside a rendered newsletter),
// then we should use that content source when processing shortcodes
$processedShortcodes = $this->process(
$shortcodes,
($contentSource) ? $contentSource : $content
);
return str_replace($shortcodes, $processedShortcodes, $content);
}
private function getCategoryObject($category): ?CategoryInterface {
if ($category === 'link') {
return $this->linkCategory;
} elseif ($category === 'date') {
return $this->dateCategory;
} elseif ($category === 'newsletter') {
return $this->newsletterCategory;
} elseif ($category === 'subscriber') {
return $this->subscriberCategory;
} elseif ($category === 'site') {
return $this->siteCategory;
}
return null;
}
}
@@ -0,0 +1,155 @@
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Newsletter\Shortcodes;
if (!defined('ABSPATH')) exit;
use MailPoet\CustomFields\CustomFieldsRepository;
use MailPoet\Entities\NewsletterLinkEntity;
class ShortcodesHelper {
/** @var CustomFieldsRepository */
private $customFieldsRepository;
public function __construct(
CustomFieldsRepository $customFieldsRepository
) {
$this->customFieldsRepository = $customFieldsRepository;
}
public function getShortcodes(): array {
$shortcodes = [
__('Subscriber', 'mailpoet') => [
[
'text' => __('First Name', 'mailpoet'),
'shortcode' => '[subscriber:firstname | default:reader]',
],
[
'text' => __('Last Name', 'mailpoet'),
'shortcode' => '[subscriber:lastname | default:reader]',
],
[
'text' => __('Email Address', 'mailpoet'),
'shortcode' => '[subscriber:email]',
],
[
'text' => __('WordPress User Display Name', 'mailpoet'),
'shortcode' => '[subscriber:displayname | default:member]',
],
[
'text' => __('Total Number of Subscribers', 'mailpoet'),
'shortcode' => '[subscriber:count]',
],
],
__('Newsletter', 'mailpoet') => [
[
'text' => __('Newsletter Subject', 'mailpoet'),
'shortcode' => '[newsletter:subject]',
],
],
__('Post Notifications', 'mailpoet') => [
[
'text' => __('Total Number of Posts or Pages', 'mailpoet'),
'shortcode' => '[newsletter:total]',
],
[
'text' => __('Most Recent Post Title', 'mailpoet'),
'shortcode' => '[newsletter:post_title]',
],
[
'text' => __('Issue Number', 'mailpoet'),
'shortcode' => '[newsletter:number]',
],
],
__('Date', 'mailpoet') => [
[
'text' => __('Current day of the month number', 'mailpoet'),
'shortcode' => '[date:d]',
],
[
'text' => __('Current day of the month in ordinal form, i.e. 2nd, 3rd, 4th, etc.', 'mailpoet'),
'shortcode' => '[date:dordinal]',
],
[
'text' => __('Full name of current day', 'mailpoet'),
'shortcode' => '[date:dtext]',
],
[
'text' => __('Current month number', 'mailpoet'),
'shortcode' => '[date:m]',
],
[
'text' => __('Full name of current month', 'mailpoet'),
'shortcode' => '[date:mtext]',
],
[
'text' => __('Year', 'mailpoet'),
'shortcode' => '[date:y]',
],
],
__('Links', 'mailpoet') => [
[
'text' => __('Unsubscribe link', 'mailpoet'),
'shortcode' => sprintf(
'<a target="_blank" href="%s">%s</a>',
NewsletterLinkEntity::UNSUBSCRIBE_LINK_SHORT_CODE,
__('Unsubscribe', 'mailpoet')
),
],
[
'text' => __('Edit subscription page link', 'mailpoet'),
'shortcode' => sprintf(
'<a target="_blank" href="%s">%s</a>',
'[link:subscription_manage_url]',
__('Manage subscription', 'mailpoet')
),
],
[
'text' => __('View in browser link', 'mailpoet'),
'shortcode' => sprintf(
'<a target="_blank" href="%s">%s</a>',
'[link:newsletter_view_in_browser_url]',
__('View in your browser', 'mailpoet')
),
],
],
__('Site', 'mailpoet') => [
[
'text' => __('Site title', 'mailpoet'),
'shortcode' => '[site:title]',
],
[
'text' => __('Homepage link', 'mailpoet'),
'shortcode' => sprintf(
'<a target="_blank" href="%s">%s</a>',
'[site:homepage_url]',
'[site:title]'
),
],
[
'text' => __('Homepage URL', 'mailpoet'),
'shortcode' => '[site:homepage_url]',
],
],
];
$customFields = $this->getCustomFields();
if (count($customFields) > 0) {
$shortcodes[__('Subscriber', 'mailpoet')] = array_merge(
$shortcodes[__('Subscriber', 'mailpoet')],
$customFields
);
}
return $shortcodes;
}
public function getCustomFields(): array {
$customFields = $this->customFieldsRepository->findAll();
return array_map(function($customField) {
return [
'text' => $customField->getName(),
'shortcode' => '[subscriber:cf_' . $customField->getId() . ']',
];
}, $customFields);
}
}
@@ -0,0 +1 @@
<?php