PluginProbe
MailPoet – Newsletters, Email Marketing, and Automation / 3.59.2
MailPoet – Newsletters, Email Marketing, and Automation v3.59.2
5.38.0 5.37.0 5.36.1 5.36.0 5.35.1 5.35.0 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 All 542 releases
mailpoet / lib / Models / Segment.php

Segment.php in MailPoet – Newsletters, Email Marketing, and Automation 3.59.2, at lib/Models/Segment.php

319 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace MailPoet\Models;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Entities\SegmentEntity;
9 use MailPoet\WooCommerce\Helper as WCHelper;
10 use MailPoet\WP\Functions as WPFunctions;
11
12 /**
13 * @property array $subscribersCount
14 * @property array $automatedEmailsSubjects
15 * @property string $name
16 * @property string $type
17 * @property string $description
18 * @property string $countConfirmations
19 */
20
21 class Segment extends Model {
22 public static $_table = MP_SEGMENTS_TABLE; // phpcs:ignore PSR2.Classes.PropertyDeclaration
23 const TYPE_WP_USERS = SegmentEntity::TYPE_WP_USERS;
24 const TYPE_WC_USERS = SegmentEntity::TYPE_WC_USERS;
25 const TYPE_DEFAULT = SegmentEntity::TYPE_DEFAULT;
26
27 public function __construct() {
28 parent::__construct();
29
30 $this->addValidations('name', [
31 'required' => WPFunctions::get()->__('Please specify a name.', 'mailpoet'),
32 ]);
33 }
34
35 public function delete() {
36 // delete all relations to subscribers
37 SubscriberSegment::where('segment_id', $this->id)->deleteMany();
38 return parent::delete();
39 }
40
41 public function newsletters() {
42 return $this->has_many_through(
43 __NAMESPACE__ . '\Newsletter',
44 __NAMESPACE__ . '\NewsletterSegment',
45 'segment_id',
46 'newsletter_id'
47 );
48 }
49
50 public function subscribers() {
51 return $this->has_many_through(
52 __NAMESPACE__ . '\Subscriber',
53 __NAMESPACE__ . '\SubscriberSegment',
54 'segment_id',
55 'subscriber_id'
56 );
57 }
58
59 public function duplicate($data = []) {
60 $duplicate = parent::duplicate($data);
61
62 if ($duplicate !== false) {
63 foreach ($this->subscribers()->findResultSet() as $relation) {
64 $newRelation = SubscriberSegment::create();
65 $newRelation->set('subscriber_id', $relation->id);
66 $newRelation->set('segment_id', $duplicate->id);
67 $newRelation->save();
68 }
69
70 return $duplicate;
71 }
72 return false;
73 }
74
75 public function addSubscriber($subscriberId) {
76 $relation = SubscriberSegment::create();
77 $relation->set('subscriber_id', $subscriberId);
78 $relation->set('segment_id', $this->id);
79 return $relation->save();
80 }
81
82 public function removeSubscriber($subscriberId) {
83 return SubscriberSegment::where('subscriber_id', $subscriberId)
84 ->where('segment_id', $this->id)
85 ->delete();
86 }
87
88 /**
89 * @deprecated Use the version in \MailPoet\Segments\SegmentSubscribersRepository::getSubscribersStatisticsCount
90 * @return $this
91 */
92 public function withSubscribersCount() {
93 trigger_error('Calling Segment::withSubscribersCount() is deprecated and will be removed. Use MailPoet\Segments\SegmentSubscribersRepository::getSubscribersStatisticsCount. ', E_USER_DEPRECATED);
94 $query = SubscriberSegment::tableAlias('relation')
95 ->where('relation.segment_id', $this->id)
96 ->join(
97 MP_SUBSCRIBERS_TABLE,
98 'subscribers.id = relation.subscriber_id',
99 'subscribers'
100 )
101 ->select_expr(
102 'SUM(CASE WHEN subscribers.status = "' . Subscriber::STATUS_SUBSCRIBED . '"
103 AND relation.status = "' . Subscriber::STATUS_SUBSCRIBED . '" THEN 1 ELSE 0 END)',
104 Subscriber::STATUS_SUBSCRIBED
105 )
106 ->select_expr(
107 'SUM(CASE WHEN subscribers.status = "' . Subscriber::STATUS_UNSUBSCRIBED . '"
108 OR relation.status = "' . Subscriber::STATUS_UNSUBSCRIBED . '" THEN 1 ELSE 0 END)',
109 Subscriber::STATUS_UNSUBSCRIBED
110 )
111 ->select_expr(
112 'SUM(CASE WHEN subscribers.status = "' . Subscriber::STATUS_INACTIVE . '"
113 AND relation.status != "' . Subscriber::STATUS_UNSUBSCRIBED . '" THEN 1 ELSE 0 END)',
114 Subscriber::STATUS_INACTIVE
115 )
116 ->select_expr(
117 'SUM(CASE WHEN subscribers.status = "' . Subscriber::STATUS_UNCONFIRMED . '"
118 AND relation.status != "' . Subscriber::STATUS_UNSUBSCRIBED . '" THEN 1 ELSE 0 END)',
119 Subscriber::STATUS_UNCONFIRMED
120 )
121 ->select_expr(
122 'SUM(CASE WHEN subscribers.status = "' . Subscriber::STATUS_BOUNCED . '"
123 AND relation.status != "' . Subscriber::STATUS_UNSUBSCRIBED . '" THEN 1 ELSE 0 END)',
124 Subscriber::STATUS_BOUNCED
125 )
126 ->whereNull('subscribers.deleted_at')
127 ->findOne();
128
129 if ($query instanceof SubscriberSegment) {
130 $this->subscribersCount = $query->asArray();
131 }
132
133 return $this;
134 }
135
136 public static function getWPSegment() {
137 $wpSegment = self::where('type', self::TYPE_WP_USERS)->findOne();
138
139 if ($wpSegment === false) {
140 // create the wp users segment
141 $wpSegment = Segment::create();
142 $wpSegment->hydrate([
143 'name' => WPFunctions::get()->__('WordPress Users', 'mailpoet'),
144 'description' =>
145 WPFunctions::get()->__('This list contains all of your WordPress users.', 'mailpoet'),
146 'type' => self::TYPE_WP_USERS,
147 ]);
148 $wpSegment->save();
149 }
150
151 return $wpSegment;
152 }
153
154 public static function getWooCommerceSegment() {
155 $wcSegment = self::where('type', self::TYPE_WC_USERS)->findOne();
156
157 if ($wcSegment === false) {
158 // create the WooCommerce customers segment
159 $wcSegment = Segment::create();
160 $wcSegment->hydrate([
161 'name' => WPFunctions::get()->__('WooCommerce Customers', 'mailpoet'),
162 'description' =>
163 WPFunctions::get()->__('This list contains all of your WooCommerce customers.', 'mailpoet'),
164 'type' => self::TYPE_WC_USERS,
165 ]);
166 $wcSegment->save();
167 }
168
169 return $wcSegment;
170 }
171
172 /**
173 * @deprecated Use the non static implementation in \MailPoet\Segments\WooCommerce::shouldShowWooCommerceSegment instead
174 */
175 public static function shouldShowWooCommerceSegment() {
176 $woocommerceHelper = new WCHelper();
177 $isWoocommerceActive = $woocommerceHelper->isWooCommerceActive();
178 $woocommerceUserExists = Segment::tableAlias('segment')
179 ->where('segment.type', Segment::TYPE_WC_USERS)
180 ->join(
181 MP_SUBSCRIBER_SEGMENT_TABLE,
182 'segment_subscribers.segment_id = segment.id',
183 'segment_subscribers'
184 )
185 ->limit(1)
186 ->findOne();
187
188 if (!$isWoocommerceActive && !$woocommerceUserExists) {
189 return false;
190 }
191 return true;
192 }
193
194 public static function getSegmentTypes() {
195 $types = [Segment::TYPE_DEFAULT, Segment::TYPE_WP_USERS];
196 if (Segment::shouldShowWooCommerceSegment()) {
197 $types[] = Segment::TYPE_WC_USERS;
198 }
199 return $types;
200 }
201
202 public static function groupBy($orm, $group = null) {
203 if ($group === 'trash') {
204 $orm->whereNotNull('deleted_at');
205 } else {
206 $orm->whereNull('deleted_at');
207 }
208 return $orm;
209 }
210
211 /**
212 * @deprecated Will be removed after 2021/07/30. Use MailPoet\Segments\SegmentsSimpleListRepository
213 */
214 public static function getSegmentsWithSubscriberCount($type = self::TYPE_DEFAULT) {
215 trigger_error('Calling Segment::getSegmentsWithSubscriberCount() is deprecated and will be removed. Use MailPoet\Segments\SegmentsSimpleListRepository. ', E_USER_DEPRECATED);
216 $query = self::selectMany([self::$_table . '.id', self::$_table . '.name'])
217 ->whereIn('type', Segment::getSegmentTypes())
218 ->selectExpr(
219 self::$_table . '.type, ' .
220 'COUNT(IF(' .
221 MP_SUBSCRIBER_SEGMENT_TABLE . '.status="' . Subscriber::STATUS_SUBSCRIBED . '"'
222 . ' AND ' .
223 MP_SUBSCRIBERS_TABLE . '.deleted_at IS NULL'
224 . ' AND ' .
225 MP_SUBSCRIBERS_TABLE . '.status="' . Subscriber::STATUS_SUBSCRIBED . '"'
226 . ', 1, NULL)) `subscribers`'
227 )
228 ->leftOuterJoin(
229 MP_SUBSCRIBER_SEGMENT_TABLE,
230 [self::$_table . '.id', '=', MP_SUBSCRIBER_SEGMENT_TABLE . '.segment_id'])
231 ->leftOuterJoin(
232 MP_SUBSCRIBERS_TABLE,
233 [MP_SUBSCRIBER_SEGMENT_TABLE . '.subscriber_id', '=', MP_SUBSCRIBERS_TABLE . '.id'])
234 ->groupBy(self::$_table . '.id')
235 ->groupBy(self::$_table . '.name')
236 ->groupBy(self::$_table . '.type')
237 ->orderByAsc(self::$_table . '.name')
238 ->whereNull(self::$_table . '.deleted_at');
239
240 if (!empty($type)) {
241 $query->where(self::$_table . '.type', $type);
242 }
243
244 return $query->findArray();
245 }
246
247 /**
248 * @deprecated Will be removed after 2021/07/30. Use MailPoet\Segments\SegmentsSimpleListRepository
249 */
250 public static function getSegmentsForImport() {
251 trigger_error('Calling Segment::getSegmentsForImport() is deprecated and will be removed. Use MailPoet\Segments\SegmentsSimpleListRepository. ', E_USER_DEPRECATED);
252 $segments = self::getSegmentsWithSubscriberCount($type = false);
253 return array_values(array_filter($segments, function($segment) {
254 return $segment['type'] !== Segment::TYPE_WC_USERS;
255 }));
256 }
257
258 /**
259 * @deprecated Will be removed after 2021/07/30. Use MailPoet\Segments\SegmentsSimpleListRepository
260 */
261 public static function getSegmentsForExport() {
262 trigger_error('Calling Segment::getSegmentsForExport() is deprecated and will be removed. Use MailPoet\Segments\SegmentsSimpleListRepository. ', E_USER_DEPRECATED);
263 return self::rawQuery(
264 '(SELECT segments.id, segments.name, COUNT(relation.subscriber_id) as subscribers ' .
265 'FROM ' . MP_SUBSCRIBER_SEGMENT_TABLE . ' relation ' .
266 'LEFT JOIN ' . self::$_table . ' segments ON segments.id = relation.segment_id ' .
267 'INNER JOIN ' . MP_SUBSCRIBERS_TABLE . ' subscribers ON subscribers.id = relation.subscriber_id ' .
268 'WHERE relation.segment_id IS NOT NULL ' .
269 'AND subscribers.deleted_at IS NULL ' .
270 'GROUP BY segments.id) ' .
271 'UNION ALL ' .
272 '(SELECT 0 as id, "' . WPFunctions::get()->__('Not in a List', 'mailpoet') . '" as name, COUNT(*) as subscribers ' .
273 'FROM ' . MP_SUBSCRIBERS_TABLE . ' subscribers ' .
274 'LEFT JOIN ' . MP_SUBSCRIBER_SEGMENT_TABLE . ' relation on relation.subscriber_id = subscribers.id ' .
275 'WHERE relation.subscriber_id is NULL ' .
276 'AND subscribers.deleted_at IS NULL ' .
277 'HAVING subscribers) ' .
278 'ORDER BY name'
279 )->findArray();
280 }
281
282 public static function getPublic() {
283 return self::getPublished()->where('type', self::TYPE_DEFAULT)->orderByAsc('name');
284 }
285
286 public static function bulkTrash($orm) {
287 $count = parent::bulkAction($orm, function($ids) {
288 Segment::rawExecute(join(' ', [
289 'UPDATE `' . Segment::$_table . '`',
290 'SET `deleted_at` = NOW()',
291 'WHERE `id` IN (' . rtrim(str_repeat('?,', count($ids)), ',') . ')',
292 'AND `type` = "' . Segment::TYPE_DEFAULT . '"',
293 ]), $ids);
294 });
295
296 return ['count' => $count];
297 }
298
299 public static function bulkDelete($orm) {
300 $count = parent::bulkAction($orm, function($ids) {
301 // delete segments (only default)
302 $segments = Segment::whereIn('id', $ids)
303 ->where('type', Segment::TYPE_DEFAULT)
304 ->findMany();
305 $ids = array_map(function($segment) {
306 return $segment->id;
307 }, $segments);
308 if (!$ids) {
309 return;
310 }
311 SubscriberSegment::whereIn('segment_id', $ids)
312 ->deleteMany();
313 Segment::whereIn('id', $ids)->deleteMany();
314 });
315
316 return ['count' => $count];
317 }
318 }
319