PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
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 / API / JSON / v1 / Newsletters.php
mailpoet / lib / API / JSON / v1 Last commit date
Analytics.php 3 years ago AutomatedLatestContent.php 2 months ago AutomaticEmails.php 3 years ago Captcha.php 1 year ago Coupons.php 2 years ago CustomFields.php 2 months ago DynamicProducts.php 1 year ago DynamicSegments.php 2 months ago FeatureFlags.php 3 years ago Forms.php 2 months ago Help.php 1 year ago ImportExport.php 2 months ago Mailer.php 1 year ago NewsletterLinks.php 2 months ago NewsletterTemplates.php 2 months ago Newsletters.php 2 months ago Premium.php 10 months ago RedirectResponse.php 1 year ago Segments.php 2 months ago SendingQueue.php 2 months ago Services.php 6 months ago Settings.php 2 months ago Setup.php 1 year ago StatisticsExport.php 3 months ago SubscriberStats.php 1 month ago Subscribers.php 2 months ago Tags.php 3 years ago UserFlags.php 2 years ago WoocommerceProductVariations.php 2 months ago WoocommerceSettings.php 3 years ago index.php 3 years ago
Newsletters.php
343 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\API\JSON\v1;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\API\JSON\Endpoint as APIEndpoint;
9 use MailPoet\API\JSON\Error as APIError;
10 use MailPoet\API\JSON\Response;
11 use MailPoet\API\JSON\ResponseBuilders\NewslettersResponseBuilder;
12 use MailPoet\Config\AccessControl;
13 use MailPoet\Doctrine\Validator\ValidationException;
14 use MailPoet\Entities\NewsletterEntity;
15 use MailPoet\Newsletter\NewsletterDeleteController;
16 use MailPoet\Newsletter\NewsletterResendController;
17 use MailPoet\Newsletter\NewsletterSaveController;
18 use MailPoet\Newsletter\NewslettersRepository;
19 use MailPoet\Newsletter\Preview\SendPreviewController;
20 use MailPoet\Newsletter\Preview\SendPreviewException;
21 use MailPoet\Newsletter\Url as NewsletterUrl;
22 use MailPoet\Subscribers\ConfirmationEmailCustomizer;
23 use MailPoet\UnexpectedValueException;
24 use MailPoet\WP\Emoji;
25 use MailPoet\WP\Functions as WPFunctions;
26
27 class Newsletters extends APIEndpoint {
28
29 /** @var WPFunctions */
30 private $wp;
31
32 public $permissions = [
33 'global' => AccessControl::PERMISSION_MANAGE_EMAILS,
34 ];
35
36 /** @var NewslettersRepository */
37 private $newslettersRepository;
38
39 /** @var NewslettersResponseBuilder */
40 private $newslettersResponseBuilder;
41
42 /** @var Emoji */
43 private $emoji;
44
45 /** @var SendPreviewController */
46 private $sendPreviewController;
47
48 /** @var NewsletterSaveController */
49 private $newsletterSaveController;
50
51 private NewsletterDeleteController $newsletterDeleteController;
52
53 /** @var NewsletterResendController */
54 private $newsletterResendController;
55
56 /** @var NewsletterUrl */
57 private $newsletterUrl;
58
59 /** @var ConfirmationEmailCustomizer */
60 private $confirmationEmailCustomizer;
61
62 public function __construct(
63 WPFunctions $wp,
64 NewslettersRepository $newslettersRepository,
65 NewslettersResponseBuilder $newslettersResponseBuilder,
66 Emoji $emoji,
67 SendPreviewController $sendPreviewController,
68 NewsletterSaveController $newsletterSaveController,
69 NewsletterDeleteController $newsletterDeleteController,
70 NewsletterResendController $newsletterResendController,
71 NewsletterUrl $newsletterUrl,
72 ConfirmationEmailCustomizer $confirmationEmailCustomizer
73 ) {
74 $this->wp = $wp;
75 $this->newslettersRepository = $newslettersRepository;
76 $this->newslettersResponseBuilder = $newslettersResponseBuilder;
77 $this->emoji = $emoji;
78 $this->sendPreviewController = $sendPreviewController;
79 $this->newsletterSaveController = $newsletterSaveController;
80 $this->newsletterDeleteController = $newsletterDeleteController;
81 $this->newsletterResendController = $newsletterResendController;
82 $this->newsletterUrl = $newsletterUrl;
83 $this->confirmationEmailCustomizer = $confirmationEmailCustomizer;
84 }
85
86 public function get($data = []) {
87 $newsletter = $this->getNewsletter($data);
88 if (!$newsletter) {
89 return $this->errorResponse([
90 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
91 ]);
92 }
93
94 $response = $this->newslettersResponseBuilder->build($newsletter, [
95 NewslettersResponseBuilder::RELATION_SEGMENTS,
96 NewslettersResponseBuilder::RELATION_OPTIONS,
97 NewslettersResponseBuilder::RELATION_QUEUE,
98 ]);
99 $response = $this->wp->applyFilters('mailpoet_api_newsletters_get_after', $response);
100 return $this->successResponse($response, ['preview_url' => $this->getViewInBrowserUrl($newsletter)]);
101 }
102
103 public function getWithStats($data = []) {
104 $newsletter = $this->getNewsletter($data);
105 if (!$newsletter) {
106 return $this->errorResponse([
107 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
108 ]);
109 }
110
111 $response = $this->newslettersResponseBuilder->build($newsletter, [
112 NewslettersResponseBuilder::RELATION_SEGMENTS,
113 NewslettersResponseBuilder::RELATION_OPTIONS,
114 NewslettersResponseBuilder::RELATION_QUEUE,
115 NewslettersResponseBuilder::RELATION_TOTAL_SENT,
116 NewslettersResponseBuilder::RELATION_STATISTICS,
117 ]);
118 $response = $this->wp->applyFilters('mailpoet_api_newsletters_get_after', $response);
119 if (!is_array($response)) {
120 $response = [];
121 }
122 $response['preview_url'] = $this->getViewInBrowserUrl($newsletter);
123 return $this->successResponse($response);
124 }
125
126 public function save($data = []) {
127 $data = $this->wp->applyFilters('mailpoet_api_newsletters_save_before', $data);
128 if (!is_array($data)) {
129 $data = [];
130 }
131 $newsletter = $this->newsletterSaveController->save($data);
132 $response = $this->newslettersResponseBuilder->build($newsletter, [
133 NewslettersResponseBuilder::RELATION_SEGMENTS,
134 ]);
135 $previewUrl = $this->getViewInBrowserUrl($newsletter);
136 $response = $this->wp->applyFilters('mailpoet_api_newsletters_save_after', $response);
137 return $this->successResponse($response, ['preview_url' => $previewUrl]);
138 }
139
140 public function updateShareVisibility($data = []) {
141 if (!is_array($data) || !isset($data['share_visibility']) || !is_string($data['share_visibility'])) {
142 return $this->badRequest([
143 APIError::BAD_REQUEST => __('You need to specify a sharing visibility.', 'mailpoet'),
144 ]);
145 }
146
147 $newsletter = $this->getNewsletter($data);
148 if (!$newsletter) {
149 return $this->errorResponse([
150 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
151 ]);
152 }
153
154 $newsletter = $this->newsletterSaveController->updateShareVisibility($newsletter, $data['share_visibility']);
155 $response = $this->newslettersResponseBuilder->build($newsletter);
156 return $this->successResponse($response);
157 }
158
159 public function restore($data = []) {
160 $newsletter = $this->getNewsletter($data);
161 if ($newsletter instanceof NewsletterEntity) {
162 $this->newslettersRepository->bulkRestore([$newsletter->getId()]);
163 $this->newslettersRepository->refresh($newsletter);
164 return $this->successResponse(
165 $this->newslettersResponseBuilder->build($newsletter),
166 ['count' => 1]
167 );
168 } else {
169 return $this->errorResponse([
170 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
171 ]);
172 }
173 }
174
175 public function trash($data = []) {
176 $newsletter = $this->getNewsletter($data);
177 if ($newsletter instanceof NewsletterEntity) {
178 $this->newslettersRepository->bulkTrash([$newsletter->getId()]);
179 $this->newslettersRepository->refresh($newsletter);
180 return $this->successResponse(
181 $this->newslettersResponseBuilder->build($newsletter),
182 ['count' => 1]
183 );
184 } else {
185 return $this->errorResponse([
186 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
187 ]);
188 }
189 }
190
191 public function delete($data = []) {
192 $newsletter = $this->getNewsletter($data);
193 if ($newsletter instanceof NewsletterEntity) {
194 $this->wp->doAction('mailpoet_api_newsletters_delete_before', [$newsletter->getId()]);
195 $this->newsletterDeleteController->bulkDelete([(int)$newsletter->getId()]);
196 $this->wp->doAction('mailpoet_api_newsletters_delete_after', [$newsletter->getId()]);
197 return $this->successResponse(null, ['count' => 1]);
198 } else {
199 return $this->errorResponse([
200 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
201 ]);
202 }
203 }
204
205 public function showPreview($data = []) {
206 if (empty($data['body'])) {
207 return $this->badRequest([
208 APIError::BAD_REQUEST => __('Newsletter data is missing.', 'mailpoet'),
209 ]);
210 }
211
212 $newsletter = $this->getNewsletter($data);
213 if (!$newsletter) {
214 return $this->errorResponse([
215 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
216 ]);
217 }
218
219 $newslettersTableName = $this->newslettersRepository->getTableName();
220 $newsletter->setBody(
221 json_decode($this->emoji->encodeForUTF8Column($newslettersTableName, 'body', $data['body']), true)
222 );
223 $this->newslettersRepository->flush();
224
225 $response = $this->newslettersResponseBuilder->build($newsletter);
226 return $this->successResponse($response, ['preview_url' => $this->getViewInBrowserUrl($newsletter)]);
227 }
228
229 public function sendPreview($data = []) {
230 if (empty($data['subscriber'])) {
231 return $this->badRequest([
232 APIError::BAD_REQUEST => __('Please specify receiver information.', 'mailpoet'),
233 ]);
234 }
235
236 $newsletter = $this->getNewsletter($data);
237 if (!$newsletter) {
238 return $this->errorResponse([
239 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
240 ]);
241 }
242
243 try {
244 $this->sendPreviewController->sendPreview($newsletter, $data['subscriber']);
245 } catch (SendPreviewException $e) {
246 return $this->errorResponse([APIError::BAD_REQUEST => $e->getMessage()]);
247 } catch (\Throwable $e) {
248 return $this->errorResponse([$e->getCode() => $e->getMessage()]);
249 }
250 return $this->successResponse($this->newslettersResponseBuilder->build($newsletter));
251 }
252
253 public function create($data = []) {
254 try {
255 $newsletter = $this->newsletterSaveController->save($data);
256 } catch (ValidationException $exception) {
257 return $this->badRequest(['Please specify a type.']);
258 }
259 $response = $this->newslettersResponseBuilder->build($newsletter);
260 return $this->successResponse($response);
261 }
262
263 public function resendToNonOpeners($data = []) {
264 $newsletter = $this->getNewsletter($data);
265 if (!$newsletter) {
266 return $this->errorResponse([
267 APIError::NOT_FOUND => __('This email does not exist.', 'mailpoet'),
268 ]);
269 }
270 $subject = isset($data['subject']) ? (string)$data['subject'] : '';
271 try {
272 $duplicate = $this->newsletterResendController->resendToNonOpeners($newsletter, $subject);
273 } catch (UnexpectedValueException $e) {
274 return $this->badRequest([
275 APIError::BAD_REQUEST => $e->getMessage(),
276 ]);
277 }
278 return $this->successResponse(
279 $this->newslettersResponseBuilder->build($duplicate),
280 ['count' => 1]
281 );
282 }
283
284 private function getNewsletter(array $data) {
285 return isset($data['id'])
286 ? $this->newslettersRepository->findOneById((int)$data['id'])
287 : null;
288 }
289
290 private function getViewInBrowserUrl(NewsletterEntity $newsletter): string {
291 $url = $this->newsletterUrl->getViewInBrowserUrl($newsletter);
292 // strip protocol to avoid mix content error
293 return preg_replace('/^https?:/i', '', $url);
294 }
295
296 /**
297 * Get all confirmation email newsletters for use in form editor.
298 * @return Response
299 */
300 public function getConfirmationEmails() {
301 $newsletters = $this->newslettersRepository->findBy([
302 'type' => NewsletterEntity::TYPE_CONFIRMATION_EMAIL_CUSTOMIZER,
303 'deletedAt' => null,
304 ]);
305
306 $result = [];
307 foreach ($newsletters as $newsletter) {
308 $id = $newsletter->getId();
309 if ($id === null) {
310 continue;
311 }
312 $result[] = [
313 'id' => $id,
314 'subject' => $newsletter->getSubject() ?: __('(no subject)', 'mailpoet'),
315 ];
316 }
317
318 return $this->successResponse($result);
319 }
320
321 /**
322 * Create a new confirmation email from the global default template.
323 * @return Response
324 */
325 public function createConfirmationEmail() {
326 // Get the global default confirmation email as a base
327 $defaultNewsletter = $this->confirmationEmailCustomizer->getNewsletter();
328
329 $newsletterData = [
330 'type' => NewsletterEntity::TYPE_CONFIRMATION_EMAIL_CUSTOMIZER,
331 'subject' => $defaultNewsletter->getSubject(),
332 'body' => json_encode($defaultNewsletter->getBody()),
333 ];
334
335 $newsletter = $this->newsletterSaveController->save($newsletterData);
336
337 return $this->successResponse([
338 'id' => $newsletter->getId(),
339 'subject' => $newsletter->getSubject(),
340 ]);
341 }
342 }
343