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 / EmailEditor / Integrations / MailPoet / EmailEditor.php
mailpoet / lib / EmailEditor / Integrations / MailPoet Last commit date
Blocks 10 months ago Coupons 1 month ago Endpoints 2 months ago Patterns 1 month ago PersonalizationTags 3 days ago ProductCollection 1 month ago Templates 2 months ago AutomationEmailContextProvider.php 1 month ago AutomationEmailPreviewOrderProvider.php 1 month ago BlockEmailContentDetector.php 1 month ago Cli.php 2 weeks ago DependencyNotice.php 10 months ago EditorPageRenderer.php 1 week ago EmailApiController.php 1 week ago EmailEditor.php 2 months ago EmailEditorPreviewEmail.php 9 months ago Logger.php 10 months ago MailPoetCssInliner.php 8 months ago MailpoetCssInlinerFactory.php 1 year ago PersonalizationTagManager.php 4 days ago index.php 2 years ago
EmailEditor.php
188 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\EmailEditor\Integrations\MailPoet;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\API\REST\API;
9 use MailPoet\EmailEditor\Integrations\MailPoet\Endpoints\GenerateSubjectSuggestionsEndpoint;
10 use MailPoet\EmailEditor\Integrations\MailPoet\Patterns\PatternsController;
11 use MailPoet\EmailEditor\Integrations\MailPoet\Templates\TemplatesController;
12 use MailPoet\Newsletter\NewslettersRepository;
13 use MailPoet\WP\Functions as WPFunctions;
14 use MailPoet\WPCOM\DotcomHelperFunctions;
15
16 class EmailEditor {
17 const MAILPOET_EMAIL_POST_TYPE = 'mailpoet_email';
18
19 private WPFunctions $wp;
20
21 private EmailApiController $emailApiController;
22
23 private EditorPageRenderer $editorPageRenderer;
24
25 private PatternsController $patternsController;
26
27 private Cli $cli;
28
29 private EmailEditorPreviewEmail $emailEditorPreviewEmail;
30
31 private PersonalizationTagManager $personalizationTagManager;
32
33 private TemplatesController $templatesController;
34
35 private DotcomHelperFunctions $dotcomHelperFunctions;
36
37 private NewslettersRepository $newslettersRepository;
38
39 public function __construct(
40 WPFunctions $wp,
41 EmailApiController $emailApiController,
42 EditorPageRenderer $editorPageRenderer,
43 EmailEditorPreviewEmail $emailEditorPreviewEmail,
44 PatternsController $patternsController,
45 TemplatesController $templatesController,
46 Cli $cli,
47 DotcomHelperFunctions $dotcomHelperFunctions,
48 PersonalizationTagManager $personalizationTagManager,
49 NewslettersRepository $newslettersRepository
50 ) {
51 $this->wp = $wp;
52 $this->emailApiController = $emailApiController;
53 $this->editorPageRenderer = $editorPageRenderer;
54 $this->patternsController = $patternsController;
55 $this->templatesController = $templatesController;
56 $this->cli = $cli;
57 $this->dotcomHelperFunctions = $dotcomHelperFunctions;
58 $this->emailEditorPreviewEmail = $emailEditorPreviewEmail;
59 $this->personalizationTagManager = $personalizationTagManager;
60 $this->newslettersRepository = $newslettersRepository;
61 }
62
63 public function initialize(): void {
64 $this->cli->initialize();
65 $this->wp->addFilter('woocommerce_email_editor_post_types', [$this, 'addEmailPostType']);
66 $this->wp->addAction('rest_delete_mailpoet_email', [$this->emailApiController, 'trashEmail'], 10, 1);
67 $this->wp->addFilter('woocommerce_is_email_editor_page', [$this, 'isEditorPage'], 10, 1);
68 $this->wp->addFilter('replace_editor', [$this, 'replaceEditor'], 10, 2);
69 $this->wp->addFilter('woocommerce_email_editor_send_preview_email', [$this->emailEditorPreviewEmail, 'sendPreviewEmail'], 10, 1);
70 $this->wp->addFilter('woocommerce_email_editor_send_preview_email_personalizer_context', [$this, 'extendPreviewPersonalizerContext'], 10, 1);
71 $this->wp->addFilter('rest_pre_insert_mailpoet_email', [$this, 'preserveAutomationEmailStatus'], 10, 2);
72 $this->patternsController->registerPatterns();
73 // Skip classic templates in Garden environment.
74 if (!$this->dotcomHelperFunctions->isGarden()) {
75 $this->templatesController->initialize();
76 }
77 $this->extendEmailPostApi();
78 $this->registerApiRoutes();
79 $this->personalizationTagManager->initialize();
80 }
81
82 public function addEmailPostType(array $postTypes): array {
83 $postTypes[] = [
84 'name' => self::MAILPOET_EMAIL_POST_TYPE,
85 'args' => [
86 'labels' => [
87 'name' => __('Emails', 'mailpoet'),
88 'singular_name' => __('Email', 'mailpoet'),
89 ],
90 'rewrite' => ['slug' => self::MAILPOET_EMAIL_POST_TYPE],
91 ],
92 ];
93 return $postTypes;
94 }
95
96 public function isEditorPage(bool $isEditorPage): bool {
97 if ($isEditorPage) {
98 return $isEditorPage;
99 }
100 // We need to check early if we are on the email editor page. The check runs early so we can't use current_screen() here.
101 if ($this->wp->isAdmin() && isset($_GET['post']) && isset($_GET['action']) && $_GET['action'] === 'edit' && is_numeric($_GET['post'])) {
102 $post = $this->wp->getPost((int)$_GET['post']);
103 return $post && $post->post_type === self::MAILPOET_EMAIL_POST_TYPE; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
104 }
105 return false;
106 }
107
108 private function registerApiRoutes(): void {
109 $this->wp->addAction(API::REST_API_INIT_ACTION, function (API $api) {
110 $api->registerPostRoute(
111 'email/generate-subject-suggestions',
112 GenerateSubjectSuggestionsEndpoint::class
113 );
114 });
115 }
116
117 public function extendEmailPostApi() {
118 $this->wp->registerRestField(self::MAILPOET_EMAIL_POST_TYPE, 'mailpoet_data', [
119 'get_callback' => [$this->emailApiController, 'getEmailData'],
120 'update_callback' => [$this->emailApiController, 'saveEmailData'],
121 'schema' => $this->emailApiController->getEmailDataSchema(),
122 ]);
123 }
124
125 public function replaceEditor($replace, $post) {
126 $currentScreen = get_current_screen();
127 if ($post->post_type === self::MAILPOET_EMAIL_POST_TYPE && $currentScreen) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
128 $this->editorPageRenderer->render();
129 return true;
130 }
131 return $replace;
132 }
133
134 /**
135 * Extend preview personalizer context with automation sample data.
136 * This is called by WooCommerce Email Editor when rendering preview in browser.
137 *
138 * @param array<string, mixed> $context
139 * @return array<string, mixed>
140 */
141 public function extendPreviewPersonalizerContext(array $context): array {
142 // Get the current post being previewed
143 $post = $this->wp->getPost();
144 if (!$post || $post->post_type !== self::MAILPOET_EMAIL_POST_TYPE) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
145 return $context;
146 }
147
148 $newsletter = $this->newslettersRepository->findOneBy(['wpPost' => $post->ID]);
149 if (!$newsletter || (!$newsletter->isAutomation() && !$newsletter->isAutomationTransactional())) {
150 return $context;
151 }
152
153 // Get automation ID and extend tags
154 $automationId = $newsletter->getOptionValue('automationId');
155 if (!$automationId) {
156 return $context;
157 }
158
159 // Extend personalization tags based on automation subjects
160 $this->personalizationTagManager->extendPersonalizationTagsByAutomationSubjects((int)$automationId);
161
162 // Context is populated via woocommerce_email_editor_send_preview_email_personalizer_context filter
163 // which extensions can hook into to add their sample data
164 return $context;
165 }
166
167 /**
168 * Preserve the 'private' status for automation emails when updating via REST API.
169 * This prevents the block editor from changing the status to 'draft' during autosave.
170 *
171 * @param \stdClass $preparedPost The prepared post data for insertion.
172 * @param \WP_REST_Request $request The REST request object.
173 * @return \stdClass The modified post data.
174 */
175 public function preserveAutomationEmailStatus($preparedPost, $request) {
176 if (empty($preparedPost->ID)) {
177 return $preparedPost;
178 }
179
180 $newsletter = $this->newslettersRepository->findOneBy(['wpPost' => $preparedPost->ID]);
181 if ($newsletter && ($newsletter->isAutomation() || $newsletter->isAutomationTransactional())) {
182 $preparedPost->post_status = 'private'; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
183 }
184
185 return $preparedPost;
186 }
187 }
188