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 / DynamicSegments.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
DynamicSegments.php
268 lines
1 <?php declare(strict_types = 1);
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;
10 use MailPoet\API\JSON\Response;
11 use MailPoet\API\JSON\ResponseBuilders\DynamicSegmentsResponseBuilder;
12 use MailPoet\Config\AccessControl;
13 use MailPoet\ConflictException;
14 use MailPoet\Doctrine\Validator\ValidationException;
15 use MailPoet\Entities\SegmentEntity;
16 use MailPoet\Newsletter\Segment\NewsletterSegmentRepository;
17 use MailPoet\Segments\DynamicSegments\Exceptions\InvalidFilterException;
18 use MailPoet\Segments\DynamicSegments\FilterDataMapper;
19 use MailPoet\Segments\DynamicSegments\SegmentSaveController;
20 use MailPoet\Segments\SegmentsRepository;
21 use MailPoet\Segments\SegmentSubscribersRepository;
22 use Throwable;
23
24 class DynamicSegments extends APIEndpoint {
25
26 public $permissions = [
27 'global' => AccessControl::PERMISSION_MANAGE_SEGMENTS,
28 ];
29
30 /** @var SegmentsRepository */
31 private $segmentsRepository;
32
33 /** @var DynamicSegmentsResponseBuilder */
34 private $segmentsResponseBuilder;
35
36 /** @var SegmentSaveController */
37 private $saveController;
38
39 /** @var SegmentSubscribersRepository */
40 private $segmentSubscribersRepository;
41
42 /** @var FilterDataMapper */
43 private $filterDataMapper;
44
45 /** @var NewsletterSegmentRepository */
46 private $newsletterSegmentRepository;
47
48 public function __construct(
49 DynamicSegmentsResponseBuilder $segmentsResponseBuilder,
50 SegmentsRepository $segmentsRepository,
51 SegmentSubscribersRepository $segmentSubscribersRepository,
52 FilterDataMapper $filterDataMapper,
53 SegmentSaveController $saveController,
54 NewsletterSegmentRepository $newsletterSegmentRepository
55 ) {
56 $this->segmentsResponseBuilder = $segmentsResponseBuilder;
57 $this->segmentsRepository = $segmentsRepository;
58 $this->saveController = $saveController;
59 $this->segmentSubscribersRepository = $segmentSubscribersRepository;
60 $this->filterDataMapper = $filterDataMapper;
61 $this->newsletterSegmentRepository = $newsletterSegmentRepository;
62 }
63
64 public function get($data = []) {
65 if (isset($data['id'])) {
66 $id = (int)$data['id'];
67 } else {
68 return $this->errorResponse([
69 Error::BAD_REQUEST => __('Missing mandatory argument `id`.', 'mailpoet'),
70 ]);
71 }
72
73 $segment = $this->segmentsRepository->findOneById($id);
74 if (!$segment instanceof SegmentEntity) {
75 return $this->errorResponse([
76 Error::NOT_FOUND => __('This segment does not exist.', 'mailpoet'),
77 ]);
78 }
79
80 return $this->successResponse($this->segmentsResponseBuilder->build($segment));
81 }
82
83 public function getCount($data = []) {
84 try {
85 $filterData = $this->filterDataMapper->map($data);
86 $count = $this->segmentSubscribersRepository->getDynamicSubscribersCount($filterData);
87 return $this->successResponse([
88 'count' => $count,
89 ]);
90 } catch (InvalidFilterException $e) {
91 return $this->errorResponse([
92 Error::BAD_REQUEST => $this->getErrorString($e),
93 ], [], Response::STATUS_BAD_REQUEST);
94 }
95 }
96
97 public function save($data) {
98 try {
99 $data['name'] = isset($data['name']) ? sanitize_text_field($data['name']) : '';
100 $data['description'] = isset($data['description']) ? sanitize_textarea_field($data['description']) : '';
101 $segment = $this->saveController->save($data);
102 return $this->successResponse($this->segmentsResponseBuilder->build($segment));
103 } catch (InvalidFilterException $e) {
104 return $this->errorResponse([
105 Error::BAD_REQUEST => $this->getErrorString($e),
106 ], [], Response::STATUS_BAD_REQUEST);
107 } catch (ConflictException $e) {
108 return $this->badRequest([
109 Error::BAD_REQUEST => __('Another record already exists. Please specify a different "name".', 'mailpoet'),
110 ]);
111 } catch (ValidationException $exception) {
112 return $this->badRequest([
113 Error::BAD_REQUEST => __('Please specify a name.', 'mailpoet'),
114 ]);
115 }
116 }
117
118 public function duplicate($data = []) {
119 $segment = $this->getSegment($data);
120
121 if ($segment instanceof SegmentEntity) {
122 try {
123 $duplicate = $this->saveController->duplicate($segment);
124 } catch (Throwable $e) {
125 return $this->errorResponse([
126 // translators: %s is the error message
127 Error::UNKNOWN => sprintf(__('Duplicating of segment failed: %s', 'mailpoet'), $e->getMessage()),
128 ], [], Response::STATUS_UNKNOWN);
129 }
130 return $this->successResponse(
131 $this->segmentsResponseBuilder->build($duplicate),
132 ['count' => 1]
133 );
134 } else {
135 return $this->errorResponse([
136 Error::NOT_FOUND => __('This segment does not exist.', 'mailpoet'),
137 ]);
138 }
139 }
140
141 private function getErrorString(InvalidFilterException $e) {
142 switch ($e->getCode()) {
143 case InvalidFilterException::MISSING_TYPE:
144 return __('The segment type is missing.', 'mailpoet');
145 case InvalidFilterException::INVALID_TYPE:
146 return __('The segment type is unknown.', 'mailpoet');
147 case InvalidFilterException::MISSING_ROLE:
148 return __('Please select a user role.', 'mailpoet');
149 case InvalidFilterException::MISSING_ACTION:
150 case InvalidFilterException::INVALID_EMAIL_ACTION:
151 return __('Please select an email action.', 'mailpoet');
152 case InvalidFilterException::MISSING_NEWSLETTER_ID:
153 return __('Please select an email.', 'mailpoet');
154 case InvalidFilterException::MISSING_PRODUCT_ID:
155 return __('Please select a product.', 'mailpoet');
156 case InvalidFilterException::MISSING_COUNTRY:
157 return __('Please select a country.', 'mailpoet');
158 case InvalidFilterException::MISSING_CATEGORY_ID:
159 return __('Please select a category.', 'mailpoet');
160 case InvalidFilterException::MISSING_VALUE:
161 return __('Please fill all required values.', 'mailpoet');
162 case InvalidFilterException::MISSING_NUMBER_OF_ORDERS_FIELDS:
163 return __('Please select a type for the comparison, a number of orders and a number of days.', 'mailpoet');
164 case InvalidFilterException::MISSING_TOTAL_SPENT_FIELDS:
165 case InvalidFilterException::MISSING_SINGLE_ORDER_VALUE_FIELDS:
166 case InvalidFilterException::MISSING_AVERAGE_SPENT_FIELDS:
167 return __('Please select a type for the comparison, an amount and a number of days.', 'mailpoet');
168 case InvalidFilterException::MISSING_FILTER:
169 return __('Please add at least one condition for filtering.', 'mailpoet');
170 case InvalidFilterException::MISSING_OPERATOR:
171 return __('Please select a type for the comparison.', 'mailpoet');
172 default:
173 return __('An error occurred while saving data.', 'mailpoet');
174 }
175 }
176
177 public function trash($data = []) {
178 if (!isset($data['id'])) {
179 return $this->errorResponse([
180 Error::BAD_REQUEST => __('Missing mandatory argument `id`.', 'mailpoet'),
181 ]);
182 }
183
184 $segment = $this->getSegment($data);
185 if ($segment === null) {
186 return $this->errorResponse([
187 Error::NOT_FOUND => __('This segment does not exist.', 'mailpoet'),
188 ]);
189 }
190
191 $activelyUsedErrors = $this->getErrorMessagesForSegmentsUsedInActiveNewsletters([$segment->getId()]);
192 if (count($activelyUsedErrors) > 0) {
193 return $this->badRequest($activelyUsedErrors);
194 }
195
196 $this->segmentsRepository->bulkTrash([$segment->getId()], SegmentEntity::TYPE_DYNAMIC);
197 return $this->successResponse(
198 $this->segmentsResponseBuilder->build($segment),
199 ['count' => 1]
200 );
201 }
202
203 public function getErrorMessagesForSegmentsUsedInActiveNewsletters(array $segmentIds): array {
204 $errors = [];
205 $activelyUsedNewslettersSubjects = $this->newsletterSegmentRepository->getSubjectsOfActivelyUsedEmailsForSegments($segmentIds);
206 foreach ($segmentIds as $segmentId) {
207 if (isset($activelyUsedNewslettersSubjects[$segmentId])) {
208 $segment = $this->getSegment(['id' => $segmentId]);
209 if ($segment) {
210 $errors[] = sprintf(
211 // translators: %1$s is the name of the segment, %2$s is a comma-separated list of emails for which the segment is used.
212 _x('Segment \'%1$s\' cannot be deleted because it’s used for \'%2$s\' email', 'Alert shown when trying to delete segment, which is assigned to any automatic emails.', 'mailpoet'),
213 $segment->getName(),
214 join("', '", $activelyUsedNewslettersSubjects[$segmentId])
215 );
216 }
217 }
218 }
219
220 return $errors;
221 }
222
223 public function restore($data = []) {
224 if (!isset($data['id'])) {
225 return $this->errorResponse([
226 Error::BAD_REQUEST => __('Missing mandatory argument `id`.', 'mailpoet'),
227 ]);
228 }
229
230 $segment = $this->getSegment($data);
231 if ($segment === null) {
232 return $this->errorResponse([
233 Error::NOT_FOUND => __('This segment does not exist.', 'mailpoet'),
234 ]);
235 }
236
237 $this->segmentsRepository->bulkRestore([$segment->getId()], SegmentEntity::TYPE_DYNAMIC);
238 return $this->successResponse(
239 $this->segmentsResponseBuilder->build($segment),
240 ['count' => 1]
241 );
242 }
243
244 public function delete($data = []) {
245 if (!isset($data['id'])) {
246 return $this->errorResponse([
247 Error::BAD_REQUEST => __('Missing mandatory argument `id`.', 'mailpoet'),
248 ]);
249 }
250
251 $segment = $this->getSegment($data);
252 if ($segment === null) {
253 return $this->errorResponse([
254 Error::NOT_FOUND => __('This segment does not exist.', 'mailpoet'),
255 ]);
256 }
257
258 $this->segmentsRepository->bulkDelete([$segment->getId()], SegmentEntity::TYPE_DYNAMIC);
259 return $this->successResponse(null, ['count' => 1]);
260 }
261
262 private function getSegment(array $data): ?SegmentEntity {
263 return isset($data['id'])
264 ? $this->segmentsRepository->findOneById((int)$data['id'])
265 : null;
266 }
267 }
268