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 / Segments / RestApi / Endpoints / AbstractSegmentsListingEndpoint.php
mailpoet / lib / Segments / RestApi / Endpoints Last commit date
AbstractSegmentsListingEndpoint.php 1 month ago DynamicSegmentsBulkActionEndpoint.php 2 months ago DynamicSegmentsListingEndpoint.php 1 month ago SegmentRequestValidationTrait.php 2 months ago SegmentsBulkActionEndpoint.php 2 months ago SegmentsEndpoint.php 2 months ago SegmentsListingEndpoint.php 1 month ago index.php 2 months ago
AbstractSegmentsListingEndpoint.php
172 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\Segments\RestApi\Endpoints;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\API\REST\AbstractListingEndpoint;
9 use MailPoet\API\REST\ApiException;
10 use MailPoet\API\REST\ListingRequestValidationTrait;
11 use MailPoet\API\REST\Request;
12 use MailPoet\API\REST\Response;
13 use MailPoet\Listing\Handler as ListingHandler;
14 use MailPoet\Validator\Builder;
15
16 abstract class AbstractSegmentsListingEndpoint extends AbstractListingEndpoint {
17 use SegmentRequestValidationTrait;
18 // Reused only for the shared `yyyy-MM-dd` date filter validators
19 // (validateDateFilter / validateDateRange); pagination and sort use the
20 // segment-specific SegmentRequestValidationTrait above.
21 use ListingRequestValidationTrait;
22
23 /** @var string[] */
24 private $allowedSortFields;
25
26 /** @var int */
27 private $defaultPerPage;
28
29 /**
30 * @param string[] $allowedSortFields
31 */
32 public function __construct(
33 ListingHandler $listingHandler,
34 array $allowedSortFields,
35 int $defaultPerPage
36 ) {
37 parent::__construct($listingHandler);
38 $this->allowedSortFields = $allowedSortFields;
39 $this->defaultPerPage = $defaultPerPage;
40 }
41
42 public function handle(Request $request): Response {
43 $this->validateListingRequest($request);
44 return parent::handle($request);
45 }
46
47 public static function getRequestSchema(): array {
48 $schema = parent::getRequestSchema();
49 $schema['limit'] = Builder::integer();
50 $schema['offset'] = Builder::integer();
51 $schema['sort_by'] = Builder::string();
52 $schema['sort_order'] = Builder::string();
53 return $schema;
54 }
55
56 abstract protected function allowsSearch(): bool;
57
58 /**
59 * Filter keys this listing accepts in the `filter` request param. Each
60 * listing declares its own so unknown keys are rejected with a 400.
61 *
62 * @return string[]
63 */
64 abstract protected function getAllowedFilters(): array;
65
66 protected function getListingValidationErrorPrefix(): string {
67 return 'segments';
68 }
69
70 protected function getDefaultGroup(): ?string {
71 return 'all';
72 }
73
74 protected function validateListingRequest(Request $request): void {
75 $this->validateGroup(is_string($request->getParam('group')) ? (string)$request->getParam('group') : null);
76 $orderParam = $request->getParam('order') ?? $request->getParam('sort_order');
77 $this->validateOrder(is_string($orderParam) ? (string)$orderParam : null, $this->getDefaultSortOrder());
78
79 $orderbyParam = $request->getParam('orderby') ?? $request->getParam('sort_by');
80 $orderby = is_string($orderbyParam) && $orderbyParam !== ''
81 ? (string)$orderbyParam
82 : $this->getDefaultSortBy();
83 if (!in_array($orderby, $this->allowedSortFields, true)) {
84 throw new ApiException(
85 sprintf(
86 // translators: %s is the list of supported sort fields.
87 __('Unsupported sort field. Allowed values are: %s.', 'mailpoet'),
88 implode(', ', $this->allowedSortFields)
89 ),
90 400,
91 'mailpoet_segments_invalid_orderby'
92 );
93 }
94
95 $this->validatePage($request->getParam('page'));
96 $this->validateOffset($request->getParam('offset'));
97 $this->validatePerPage($request->getParam('per_page') ?? $request->getParam('limit'), $this->defaultPerPage);
98
99 if (!$this->allowsSearch() && is_string($request->getParam('search')) && trim((string)$request->getParam('search')) !== '') {
100 throw new ApiException(
101 __('Search is not supported for this listing.', 'mailpoet'),
102 400,
103 'mailpoet_segments_search_not_supported'
104 );
105 }
106
107 $this->validateFilters($request);
108 }
109
110 protected function validateFilters(Request $request): void {
111 $filters = $request->getParam('filter');
112 if ($filters === null || $filters === []) {
113 return;
114 }
115 if (!is_array($filters)) {
116 throw new ApiException(
117 __('Filters must be an object.', 'mailpoet'),
118 400,
119 'mailpoet_segments_invalid_filter'
120 );
121 }
122
123 $allowed = $this->getAllowedFilters();
124 // Rebuild with verified string keys so the typed validators below receive an
125 // array<string, mixed> rather than the request's array<mixed, mixed>.
126 $normalizedFilters = [];
127 foreach ($filters as $key => $value) {
128 if (!is_string($key) || !in_array($key, $allowed, true)) {
129 throw new ApiException(
130 __('Unsupported segments filter.', 'mailpoet'),
131 400,
132 'mailpoet_segments_invalid_filter'
133 );
134 }
135 $normalizedFilters[$key] = $value;
136 }
137
138 $this->validateScoreFilter($normalizedFilters);
139
140 foreach ([['created_from', 'created_to'], ['updated_from', 'updated_to']] as [$fromKey, $toKey]) {
141 if (!in_array($fromKey, $allowed, true)) {
142 continue;
143 }
144 $from = $this->validateDateFilter($normalizedFilters, $fromKey);
145 $to = $this->validateDateFilter($normalizedFilters, $toKey);
146 $this->validateDateRange($from, $to);
147 }
148 }
149
150 /**
151 * @param array<string, mixed> $filters
152 */
153 private function validateScoreFilter(array $filters): void {
154 foreach (['score_min', 'score_max'] as $key) {
155 if (!array_key_exists($key, $filters) || $filters[$key] === '') {
156 continue;
157 }
158 if (!is_numeric($filters[$key])) {
159 throw new ApiException(
160 __('The engagement score filter must be numeric.', 'mailpoet'),
161 400,
162 'mailpoet_segments_invalid_' . $key
163 );
164 }
165 }
166 }
167
168 protected function getDefaultPerPage(): int {
169 return $this->defaultPerPage;
170 }
171 }
172