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 / Newsletter / BlockPostQuery.php
mailpoet / lib / Newsletter Last commit date
Editor 2 months ago Embed 1 month ago Links 2 months ago Listing 9 months ago Options 2 years ago Preview 1 month ago Renderer 5 days ago RestApi 1 week ago Scheduler 5 days ago Segment 1 year ago Sending 1 week ago Sharing 1 month ago Shortcodes 4 days ago Statistics 1 week ago ViewInBrowser 1 month ago ApiDataSanitizer.php 3 years ago AutomatedLatestContent.php 2 months ago AutomaticEmailsRepository.php 3 years ago BlockPostQuery.php 2 months ago BulkActionController.php 2 months ago BulkActionException.php 2 months ago DynamicProducts.php 11 months ago NewsletterCoupon.php 2 months ago NewsletterDeleteController.php 2 years ago NewsletterHtmlSanitizer.php 2 years ago NewsletterPostsRepository.php 2 years ago NewsletterResendController.php 5 days ago NewsletterSaveController.php 1 month ago NewsletterValidator.php 1 year ago NewslettersRepository.php 2 weeks ago StatusController.php 2 months ago Url.php 2 months ago index.php 3 years ago
BlockPostQuery.php
200 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Newsletter;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use DateTimeInterface;
9
10 class BlockPostQuery {
11 const DEFAULT_POSTS_PER_PAGE = 10;
12
13 /**
14 * @var array{
15 * amount?: int,
16 * offset?: int,
17 * posts?: int[],
18 * contentType?: string,
19 * postStatus?: string,
20 * search?: string,
21 * sortBy?: 'newest' | 'DESC' | 'ASC',
22 * terms?: array{'taxonomy': string, 'id': int}[],
23 * inclusionType?: 'include'|'exclude',
24 * excludeOutOfStock?: bool,
25 * } $args
26 */
27 public $args = [];
28
29 /*** @var null|int[] \WP_Query::post__not_in */
30 public $postsToExclude = [];
31
32 /** @var int|false */
33 public $newsletterId = false;
34
35 /***
36 * Translates to \WP_Query::date_query => array{'column': 'post_date_gmt', 'after': date string}
37 *
38 * @var bool|DateTimeInterface|null
39 */
40 public $newerThanTimestamp = false;
41
42 /**
43 * If it's a dynamic block
44 * Dynamic blocks are not allowed to query none-public posts
45 *
46 * @var bool
47 */
48 public $dynamic = true;
49
50 /** @var int[] product IDs to include */
51 public $includeProductIds = [];
52
53 /**
54 * @param array{
55 * args?: array{
56 * amount?: int,
57 * offset?: int,
58 * posts?: int[],
59 * contentType?: string,
60 * postStatus?: string,
61 * search?: string,
62 * sortBy?: 'newest' | 'DESC' | 'ASC',
63 * terms?: array{'taxonomy': string, 'id': int}[],
64 * inclusionType?: 'include'|'exclude',
65 * excludeOutOfStock?: bool,
66 * },
67 * postsToExclude?: int[],
68 * newsletterId?: int|false|null,
69 * newerThanTimestamp?: bool|DateTimeInterface|null,
70 * dynamic?: bool,
71 * includeProductIds?: int[],
72 * } $query
73 * @return void
74 */
75 public function __construct(
76 array $query = []
77 ) {
78 $this->args = $query['args'] ?? [];
79 $this->postsToExclude = $query['postsToExclude'] ?? [];
80 $this->newsletterId = $query['newsletterId'] ?? false;
81 $this->newerThanTimestamp = $query['newerThanTimestamp'] ?? false;
82 $this->dynamic = $query['dynamic'] ?? true;
83 $this->includeProductIds = $query['includeProductIds'] ?? [];
84 }
85
86 public function getPostType(): string {
87 return $this->args['contentType'] ?? 'post';
88 }
89
90 public function getPostStatus(): string {
91 if ($this->dynamic) {
92 return 'publish';
93 }
94 return $this->args['postStatus'] ?? 'publish';
95 }
96
97 public function getOrder(): string {
98 return isset($this->args['sortBy']) && in_array($this->args['sortBy'], ['newest', 'DESC']) ? 'DESC' : 'ASC';
99 }
100
101 /**
102 * @see https://developer.wordpress.org/reference/classes/wp_query/#taxonomy-parameters
103 * @return array[] array{relation: string, taxonomy: string, field: string, terms: int/string/array, operator: string}
104 */
105 private function constructTaxonomiesQuery(): array {
106 $taxonomiesQuery = [];
107 if (isset($this->args['terms']) && is_array($this->args['terms'])) {
108 $taxonomies = [];
109 // Categorize terms based on their taxonomies
110 foreach ($this->args['terms'] as $term) {
111 $taxonomy = $term['taxonomy'];
112 if (!isset($taxonomies[$taxonomy])) {
113 $taxonomies[$taxonomy] = [];
114 }
115 $taxonomies[$taxonomy][] = $term['id'];
116 }
117
118 foreach ($taxonomies as $taxonomy => $terms) {
119 $tax = [
120 'taxonomy' => $taxonomy,
121 'field' => 'id',
122 'terms' => $terms,
123 ];
124 if (isset($this->args['inclusionType']) && $this->args['inclusionType'] === 'exclude') $tax['operator'] = 'NOT IN';
125 $taxonomiesQuery[] = $tax;
126 }
127 if (!empty($taxonomiesQuery)) {
128 // With exclusion we want to use 'AND', because we want posts that
129 // don't have excluded tags/categories. But with inclusion we want to
130 // use 'OR', because we want posts that have any of the included
131 // tags/categories
132 $taxonomiesQuery['relation'] = (isset($this->args['inclusionType']) && $this->args['inclusionType'] === 'exclude')
133 ? 'AND'
134 : 'OR';
135 }
136 }
137
138 // make $taxonomies_query nested to avoid conflicts with plugins that use taxonomies
139 return empty($taxonomiesQuery) ? [] : [$taxonomiesQuery];
140 }
141
142 public function getQueryParams(): array {
143 $postsPerPage = (!empty($this->args['amount']) && (int)$this->args['amount'] > 0)
144 ? (int)$this->args['amount']
145 : self::DEFAULT_POSTS_PER_PAGE;
146 $parameters = [
147 'posts_per_page' => $postsPerPage,
148 'post_type' => $this->getPostType(),
149 'post_status' => $this->getPostStatus(),
150 'orderby' => 'date',
151 'order' => $this->getOrder(),
152 ];
153 if (!empty($this->args['offset']) && (int)$this->args['offset'] > 0) {
154 $parameters['offset'] = (int)$this->args['offset'];
155 }
156 if (isset($this->args['search'])) {
157 $parameters['s'] = $this->args['search'];
158 }
159 if (isset($this->args['posts']) && is_array($this->args['posts'])) {
160 $parameters['post__in'] = $this->args['posts'];
161 $parameters['posts_per_page'] = -1; // Get all posts with matching IDs
162 }
163 if (!empty($this->postsToExclude)) {
164 $parameters['post__not_in'] = $this->postsToExclude;
165 }
166
167 // If specific product IDs are provided, override post__in
168 if (!empty($this->includeProductIds)) {
169 $parameters['post__in'] = $this->includeProductIds;
170 // Keep the posts_per_page limit to ensure we don't return too many products
171 }
172
173 // WP posts with the type attachment have always post_status `inherit`
174 if ($parameters['post_type'] === 'attachment' && $parameters['post_status'] === 'publish') {
175 $parameters['post_status'] = 'inherit';
176 }
177
178 // This enables using posts query filters for get_posts, where by default
179 // it is disabled.
180 // However, it also enables other plugins and themes to hook in and alter
181 // the query.
182 $parameters['suppress_filters'] = false;
183
184 if ($this->newerThanTimestamp instanceof DateTimeInterface) {
185 //Ensure UTC timezone
186 $after = new \DateTime('now', new \DateTimeZone('UTC'));
187 $after->setTimestamp($this->newerThanTimestamp->getTimestamp());
188 $parameters['date_query'] = [
189 [
190 'column' => 'post_date_gmt',
191 'after' => $after->format('Y-m-d H:i:s'),
192 ],
193 ];
194 }
195
196 $parameters['tax_query'] = $this->constructTaxonomiesQuery();
197 return $parameters;
198 }
199 }
200