PluginProbe ʕ •ᴥ•ʔ
OttoKit: All-in-One Automation Platform / 1.1.36
OttoKit: All-in-One Automation Platform v1.1.36
1.1.37 1.1.36 1.1.35 1.1.34 1.1.33 1.1.32 1.1.31 1.1.30 1.1.29 1.1.28 1.1.27 1.1.9 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.47 1.0.48 1.0.49 1.0.50 1.0.51 1.0.52 1.0.53 1.0.54 1.0.55 1.0.56 1.0.57 1.0.58 1.0.59 1.0.60 1.0.61 1.0.62 1.0.63 1.0.64 1.0.65 1.0.66 1.0.67 1.0.68 1.0.69 1.0.7 1.0.70 1.0.71 1.0.72 1.0.73 1.0.74 1.0.75 1.0.76 1.0.77 1.0.78 1.0.79 1.0.8 1.0.80 1.0.81 1.0.82 1.0.83 1.0.84 1.0.85 1.0.86 1.0.87 1.0.88 1.0.89 1.0.9 1.0.90 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
suretriggers / src / Integrations / storeengine / triggers / product-purchased.php
suretriggers / src / Integrations / storeengine / triggers Last commit date
product-purchased.php 4 months ago
product-purchased.php
259 lines
1 <?php
2 /**
3 * ProductPurchased.
4 * php version 5.6
5 *
6 * @category ProductPurchased
7 * @package SureTriggers
8 * @author BSF <username@example.com>
9 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
10 * @link https://www.brainstormforce.com/
11 * @since 1.0.0
12 */
13
14 namespace SureTriggers\Integrations\StoreEngine\Triggers;
15
16 use SureTriggers\Controllers\AutomationController;
17 use SureTriggers\Traits\SingletonLoader;
18
19 if ( ! class_exists( 'ProductPurchased' ) ) :
20
21 /**
22 * ProductPurchased
23 *
24 * @category ProductPurchased
25 * @package SureTriggers
26 * @author BSF <username@example.com>
27 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
28 * @link https://www.brainstormforce.com/
29 * @since 1.0.0
30 *
31 * @psalm-suppress UndefinedTrait
32 */
33 class ProductPurchased {
34
35 /**
36 * Integration type.
37 *
38 * @var string
39 */
40 public $integration = 'StoreEngine';
41
42 /**
43 * Trigger name.
44 *
45 * @var string
46 */
47 public $trigger = 'se_product_purchased';
48
49 use SingletonLoader;
50
51 /**
52 * Constructor
53 *
54 * @since 1.0.0
55 */
56 public function __construct() {
57 add_filter( 'sure_trigger_register_trigger', [ $this, 'register' ] );
58 }
59
60 /**
61 * Register action.
62 *
63 * @param array $triggers trigger data.
64 * @return array
65 */
66 public function register( $triggers ) {
67 $triggers[ $this->integration ][ $this->trigger ] = [
68 'label' => __( 'Product Purchased', 'suretriggers' ),
69 'action' => 'se_product_purchased',
70 'common_action' => 'storeengine/order_status_completed',
71 'function' => [ $this, 'trigger_listener' ],
72 'priority' => 10,
73 'accepted_args' => 3,
74 ];
75
76 return $triggers;
77 }
78
79 /**
80 * Trigger listener for order status transition.
81 *
82 * @param int $order_id The ID of the order.
83 * @param object $order The StoreEngine order object.
84 * @param array $status_transition Array containing 'from', 'to', and 'order' status transition data.
85 *
86 * @return void
87 */
88 public function trigger_listener( $order_id, $order, $status_transition ) {
89
90 if ( empty( $order_id ) || empty( $order ) ) {
91 return;
92 }
93
94 // Verify order object has required methods.
95 if ( ! method_exists( $order, 'get_items' ) || ! method_exists( $order, 'get_customer_id' ) || ! method_exists( $order, 'get_status' ) || ! method_exists( $order, 'get_total' ) || ! method_exists( $order, 'get_currency' ) ) {
96 return;
97 }
98
99 // Get order items.
100 $items = $order->get_items();
101 if ( empty( $items ) || ! is_array( $items ) ) {
102 return;
103 }
104 $context = [];
105
106 // Process each product in the order.
107 foreach ( $items as $item ) {
108 // Verify item has required methods.
109 if ( ! is_object( $item ) || ! method_exists( $item, 'get_product_id' ) || ! method_exists( $item, 'get_price_id' ) ) {
110 continue;
111 }
112
113 $product_id = $item->get_product_id();
114
115
116 // Get product details.
117 $product = get_post( $product_id );
118 if ( ! $product ) {
119 continue;
120 }
121
122 // Get user details.
123 $user_id = $order->get_customer_id();
124 $user = get_userdata( $user_id );
125
126 // Build context matching search_se_triggers_last_data structure.
127 $context = [
128 // Product information (flat structure).
129 'id' => $product_id,
130 'post_author' => $product->post_author,
131 'post_date' => $product->post_date,
132 'post_date_gmt' => $product->post_date_gmt,
133 'post_content' => $product->post_content,
134 'post_title' => $product->post_title,
135 'post_excerpt' => $product->post_excerpt,
136 'post_status' => $product->post_status,
137 'comment_status' => $product->comment_status,
138 'ping_status' => $product->ping_status,
139 'post_password' => $product->post_password,
140 'post_name' => $product->post_name,
141 'to_ping' => $product->to_ping,
142 'pinged' => $product->pinged,
143 'post_modified' => $product->post_modified,
144 'post_modified_gmt' => $product->post_modified_gmt,
145 'post_content_filtered' => $product->post_content_filtered,
146 'post_parent' => $product->post_parent,
147 'guid' => $product->guid,
148 'menu_order' => $product->menu_order,
149 'post_type' => $product->post_type,
150 'post_mime_type' => $product->post_mime_type,
151 'comment_count' => $product->comment_count,
152 'filter' => 'raw',
153 'featured_image' => get_post_thumbnail_id( $product_id ) ? get_post_thumbnail_id( $product_id ) : null,
154 'permalink' => get_permalink( $product_id ),
155
156 // User information (flat structure).
157 'wp_user_id' => $user_id,
158 'user_login' => $user ? $user->user_login : '',
159 'display_name' => $user ? $user->display_name : '',
160 'user_firstname' => $user ? get_user_meta( $user_id, 'first_name', true ) : '',
161 'user_lastname' => $user ? get_user_meta( $user_id, 'last_name', true ) : '',
162 'user_email' => $user ? $user->user_email : '',
163 'user_registered' => $user ? $user->user_registered : '',
164 'user_role' => $user ? $user->roles : [],
165
166 // Keep post ID for backwards compatibility.
167 'post' => $product_id,
168 ];
169
170 // Get all custom metas for the product - check with underscore prefix.
171 $custom_metas = [];
172 $all_meta = get_post_meta( $product_id );
173
174 // Filter StoreEngine specific metas (they start with underscore).
175 if ( is_array( $all_meta ) ) {
176 foreach ( $all_meta as $meta_key => $meta_value ) {
177 if ( is_string( $meta_key ) && strpos( $meta_key, '_storeengine_' ) === 0 ) {
178 // Remove underscore prefix for cleaner keys.
179 $clean_key = ltrim( $meta_key, '_' );
180 if ( is_array( $meta_value ) && isset( $meta_value[0] ) ) {
181 $custom_metas[ $clean_key ] = maybe_unserialize( $meta_value[0] );
182 }
183 }
184 }
185 }
186
187 $context['product_id'] = $product_id;
188 $context['custom_metas'] = $custom_metas;
189
190 // Check if product has membership integration using StoreEngine helper.
191 $price_id = $item->get_price_id();
192
193 if ( class_exists( '\StoreEngine\Utils\Helper' ) ) {
194 // Use StoreEngine's helper function to get integration data.
195 $membership_integration = \StoreEngine\Utils\Helper::get_integration_repository_by_price_id( 'storeengine/membership-addon', $price_id );
196 } else {
197 // Fallback if StoreEngine's helper is not available.
198 $membership_integration = null;
199 }
200
201 // Add membership details if this is a membership product.
202 if ( $membership_integration && ! empty( $membership_integration->integration ) ) {
203 $membership_plan_id = $membership_integration->integration->get_integration_id();
204 $access_group = get_post( $membership_plan_id );
205
206 if ( $access_group && 'storeengine_groups' === $access_group->post_type ) {
207 // Add membership information to context - matching search_se_triggers_last_data structure.
208 $context['membership_plan_id'] = $membership_plan_id;
209 $context['membership_plan_name'] = $access_group->post_title;
210 $context['membership_plan_slug'] = $access_group->post_name;
211
212 // Get membership meta data.
213 $membership_meta = [
214 'user_roles' => get_post_meta( $membership_plan_id, '_storeengine_membership_user_roles', true ),
215 'content_protects' => get_post_meta( $membership_plan_id, '_storeengine_membership_content_protect_types', true ),
216 'expiration' => get_post_meta( $membership_plan_id, '_storeengine_membership_expiration', true ),
217 'priority' => get_post_meta( $membership_plan_id, '_storeengine_membership_priority', true ),
218 'excluded_items' => get_post_meta( $membership_plan_id, '_storeengine_membership_content_protect_excluded_items', true ),
219 ];
220
221 $context['membership'] = array_filter( $membership_meta );
222
223 // Add user membership data if available.
224 if ( $user_id ) {
225 $user_membership_data = get_user_meta( $user_id, '_storeengine_user_membership_data', true );
226 if ( is_array( $user_membership_data ) && isset( $user_membership_data[ $membership_plan_id ] ) ) {
227 $context['user_membership_data'] = $user_membership_data[ $membership_plan_id ];
228 }
229 }
230
231 // Add order data for membership purchases - matching search_se_triggers_last_data.
232 $context['order'] = [
233 'order_id' => $order_id,
234 'order_status' => $order->get_status(),
235 'order_total' => $order->get_total(),
236 'currency' => $order->get_currency(),
237 ];
238 }
239 }
240 }
241
242 AutomationController::sure_trigger_handle_trigger(
243 [
244 'trigger' => $this->trigger,
245 'context' => $context,
246 ]
247 );
248 }
249 }
250
251 /**
252 * Ignore false positive
253 *
254 * @psalm-suppress UndefinedMethod
255 */
256 ProductPurchased::get_instance();
257
258 endif;
259