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 / Abilities / WooCommerceMarketingStatus.php
mailpoet / lib / Abilities Last commit date
Abilities.php 1 month ago WooCommerceAutomationTemplates.php 1 month ago WooCommerceMarketingStatus.php 1 month ago index.php 1 month ago
WooCommerceMarketingStatus.php
267 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\Abilities;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use Automattic\WooCommerce\Abilities\AbilityDefinition;
9 use MailPoet\AutomaticEmails\WooCommerce\Events\AbandonedCart;
10 use MailPoet\AutomaticEmails\WooCommerce\Events\FirstPurchase;
11 use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedInCategory;
12 use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedProduct;
13 use MailPoet\Automation\Engine\Storage\AutomationStorage;
14 use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction;
15 use MailPoet\Automation\Integrations\WooCommerce\Triggers\AbandonedCart\AbandonedCartTrigger;
16 use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger;
17 use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromACategoryTrigger;
18 use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromATagTrigger;
19 use MailPoet\Config\AccessControl;
20 use MailPoet\Config\Hooks;
21 use MailPoet\DI\ContainerWrapper;
22 use MailPoet\Entities\SegmentEntity;
23 use MailPoet\Newsletter\NewslettersRepository;
24 use MailPoet\Segments\SegmentsRepository;
25 use MailPoet\Settings\SettingsController;
26 use MailPoet\Settings\TrackingConfig;
27 use MailPoet\WooCommerce\Helper as WooCommerceHelper;
28 use MailPoet\WooCommerce\Subscription;
29 use MailPoet\WooCommerce\TransactionalEmails;
30 use MailPoet\WP\Functions as WPFunctions;
31
32 if (!defined('ABSPATH')) exit;
33
34 if (!interface_exists(AbilityDefinition::class)) {
35 return;
36 }
37
38 class WooCommerceMarketingStatus implements AbilityDefinition {
39 private const TRACKING_LEVELS = [
40 TrackingConfig::LEVEL_FULL,
41 TrackingConfig::LEVEL_PARTIAL,
42 TrackingConfig::LEVEL_BASIC,
43 ];
44
45 public static function get_name(): string { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Required by WooCommerce's AbilityDefinition interface.
46 return 'mailpoet/get-woocommerce-marketing-status';
47 }
48
49 public static function get_registration_args(): array { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Required by WooCommerce's AbilityDefinition interface.
50 return [
51 'label' => __('Get MailPoet WooCommerce marketing status', 'mailpoet'),
52 'description' => __('Read MailPoet WooCommerce marketing, checkout opt-in, and email editor status.', 'mailpoet'),
53 'category' => 'woocommerce',
54 'output_schema' => self::getOutputSchema(),
55 'execute_callback' => [self::class, 'execute'],
56 'permission_callback' => [self::class, 'canReadStatus'],
57 'meta' => [
58 'show_in_rest' => true,
59 'mcp' => [
60 'public' => true,
61 'type' => 'tool',
62 ],
63 'annotations' => [
64 'readonly' => true,
65 'destructive' => false,
66 'idempotent' => true,
67 ],
68 ],
69 ];
70 }
71
72 public static function execute(): array {
73 $container = ContainerWrapper::getInstance();
74
75 /** @var SettingsController $settings */
76 $settings = $container->get(SettingsController::class);
77 /** @var WooCommerceHelper $woocommerceHelper */
78 $woocommerceHelper = $container->get(WooCommerceHelper::class);
79 /** @var NewslettersRepository $newslettersRepository */
80 $newslettersRepository = $container->get(NewslettersRepository::class);
81 /** @var SegmentsRepository $segmentsRepository */
82 $segmentsRepository = $container->get(SegmentsRepository::class);
83 /** @var AutomationStorage $automationStorage */
84 $automationStorage = $container->get(AutomationStorage::class);
85
86 $checkoutSegmentIds = array_values(array_unique(array_map('absint', (array)$settings->get(Subscription::OPTIN_SEGMENTS_SETTING_NAME, []))));
87 $position = $settings->get(Subscription::OPTIN_POSITION_SETTING_NAME, Hooks::DEFAULT_OPTIN_POSITION);
88 if (!is_string($position) || !array_key_exists($position, Hooks::OPTIN_HOOKS)) {
89 $position = Hooks::DEFAULT_OPTIN_POSITION;
90 }
91 $trackingLevel = $settings->get('tracking.level', TrackingConfig::LEVEL_FULL);
92 if (!is_string($trackingLevel) || !in_array($trackingLevel, self::TRACKING_LEVELS, true)) {
93 $trackingLevel = TrackingConfig::LEVEL_FULL;
94 }
95
96 return [
97 'checkout_optin' => [
98 'enabled' => (bool)$settings->get(Subscription::OPTIN_ENABLED_SETTING_NAME, false),
99 'message' => wp_strip_all_tags((string)$settings->get(Subscription::OPTIN_MESSAGE_SETTING_NAME, '')),
100 'position' => $position,
101 'segments' => self::formatSegments($segmentsRepository, $checkoutSegmentIds),
102 ],
103 'transactional_email_editor' => [
104 'enabled' => (bool)$settings->get('woocommerce.use_mailpoet_editor', false),
105 'template_configured' => absint($settings->get(TransactionalEmails::SETTING_EMAIL_ID, 0)) > 0,
106 ],
107 'legacy_automatic_emails' => [
108 'active_counts' => [
109 'abandoned_cart' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(AbandonedCart::SLUG),
110 'first_purchase' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(FirstPurchase::SLUG),
111 'purchased_in_category' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(PurchasedInCategory::SLUG),
112 'purchased_product' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(PurchasedProduct::SLUG),
113 ],
114 ],
115 'automations' => [
116 'active_email_counts' => self::getAutomationEmailCounts($automationStorage),
117 ],
118 'measurement' => [
119 'tracking_level' => $trackingLevel,
120 'analytics_enabled' => (bool)$settings->get('analytics.enabled', false),
121 'revenue_attribution_order_statuses' => $woocommerceHelper->getPurchaseStates(),
122 ],
123 ];
124 }
125
126 public static function canReadStatus(): bool {
127 return WPFunctions::get()->currentUserCan(AccessControl::PERMISSION_MANAGE_SETTINGS);
128 }
129
130 private static function getOutputSchema(): array {
131 return [
132 'type' => 'object',
133 'properties' => [
134 'checkout_optin' => [
135 'type' => 'object',
136 'properties' => [
137 'enabled' => ['type' => 'boolean'],
138 'message' => ['type' => 'string'],
139 'position' => [
140 'type' => 'string',
141 'enum' => array_keys(Hooks::OPTIN_HOOKS),
142 ],
143 'segments' => [
144 'type' => 'array',
145 'items' => [
146 'type' => 'object',
147 'properties' => [
148 'id' => ['type' => 'integer'],
149 'name' => ['type' => 'string'],
150 ],
151 'required' => ['id', 'name'],
152 'additionalProperties' => false,
153 ],
154 ],
155 ],
156 'required' => ['enabled', 'message', 'position', 'segments'],
157 'additionalProperties' => false,
158 ],
159 'transactional_email_editor' => [
160 'type' => 'object',
161 'properties' => [
162 'enabled' => ['type' => 'boolean'],
163 'template_configured' => ['type' => 'boolean'],
164 ],
165 'required' => ['enabled', 'template_configured'],
166 'additionalProperties' => false,
167 ],
168 'legacy_automatic_emails' => [
169 'type' => 'object',
170 'properties' => [
171 'active_counts' => [
172 'type' => 'object',
173 'properties' => [
174 'abandoned_cart' => ['type' => 'integer'],
175 'first_purchase' => ['type' => 'integer'],
176 'purchased_in_category' => ['type' => 'integer'],
177 'purchased_product' => ['type' => 'integer'],
178 ],
179 'required' => ['abandoned_cart', 'first_purchase', 'purchased_in_category', 'purchased_product'],
180 'additionalProperties' => false,
181 ],
182 ],
183 'required' => ['active_counts'],
184 'additionalProperties' => false,
185 ],
186 'automations' => [
187 'type' => 'object',
188 'properties' => [
189 'active_email_counts' => [
190 'type' => 'object',
191 'properties' => [
192 'abandoned_cart' => ['type' => 'integer'],
193 'order_completed' => ['type' => 'integer'],
194 'order_created' => ['type' => 'integer'],
195 'order_status_changed' => ['type' => 'integer'],
196 'purchased_in_category' => ['type' => 'integer'],
197 'purchased_product' => ['type' => 'integer'],
198 'purchased_with_tag' => ['type' => 'integer'],
199 ],
200 'required' => ['abandoned_cart', 'order_completed', 'order_created', 'order_status_changed', 'purchased_in_category', 'purchased_product', 'purchased_with_tag'],
201 'additionalProperties' => false,
202 ],
203 ],
204 'required' => ['active_email_counts'],
205 'additionalProperties' => false,
206 ],
207 'measurement' => [
208 'type' => 'object',
209 'properties' => [
210 'tracking_level' => [
211 'type' => 'string',
212 'enum' => self::TRACKING_LEVELS,
213 ],
214 'analytics_enabled' => ['type' => 'boolean'],
215 'revenue_attribution_order_statuses' => [
216 'type' => 'array',
217 'items' => ['type' => 'string'],
218 ],
219 ],
220 'required' => ['tracking_level', 'analytics_enabled', 'revenue_attribution_order_statuses'],
221 'additionalProperties' => false,
222 ],
223 ],
224 'required' => ['checkout_optin', 'transactional_email_editor', 'legacy_automatic_emails', 'automations', 'measurement'],
225 'additionalProperties' => false,
226 ];
227 }
228
229 private static function formatSegments(SegmentsRepository $segmentsRepository, array $segmentIds): array {
230 if (!$segmentIds) {
231 return [];
232 }
233
234 $segmentsById = [];
235 foreach ($segmentsRepository->findByIds($segmentIds) as $segment) {
236 if (!$segment instanceof SegmentEntity || $segment->getId() === null) {
237 continue;
238 }
239 $segmentsById[(int)$segment->getId()] = [
240 'id' => (int)$segment->getId(),
241 'name' => $segment->getName(),
242 ];
243 }
244
245 $selectedSegments = [];
246 foreach ($segmentIds as $segmentId) {
247 if (isset($segmentsById[$segmentId])) {
248 $selectedSegments[] = $segmentsById[$segmentId];
249 }
250 }
251
252 return $selectedSegments;
253 }
254
255 private static function getAutomationEmailCounts(AutomationStorage $automationStorage): array {
256 return [
257 'abandoned_cart' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([AbandonedCartTrigger::KEY], SendEmailAction::KEY),
258 'order_completed' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-completed'], SendEmailAction::KEY),
259 'order_created' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-created'], SendEmailAction::KEY),
260 'order_status_changed' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-status-changed'], SendEmailAction::KEY),
261 'purchased_in_category' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysFromACategoryTrigger::KEY], SendEmailAction::KEY),
262 'purchased_product' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysAProductTrigger::KEY], SendEmailAction::KEY),
263 'purchased_with_tag' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysFromATagTrigger::KEY], SendEmailAction::KEY),
264 ];
265 }
266 }
267