PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Extensions / SureCart / SureCart.php

SureCart.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar trunk, at includes/Extensions/SureCart/SureCart.php

478 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SureCart Extension
4 *
5 * @package NotificationX\Extensions
6 */
7
8 namespace NotificationX\Extensions\SureCart;
9 use NotificationX\GetInstance;
10 use NotificationX\Extensions\Extension;
11 use NotificationX\Extensions\GlobalFields;
12 use NotificationX\Admin\Entries;
13 use NotificationX\Core\Helper;
14 use NotificationX\Core\Rules;
15
16 /**
17 * SureCart Extension Class
18 * @method static SureCart get_instance($args = null)
19 */
20 class SureCart extends Extension {
21 use GetInstance;
22 public $priority = 8;
23 public $id = 'surecart';
24 public $doc_link = 'https://notificationx.com/docs/how-to-display-surecart-sales-alerts-using-notificationx/';
25 public $types = 'conversions';
26 public $img = NOTIFICATIONX_ADMIN_URL . 'images/extensions/sources/surecart.png';
27 public $module = 'modules_surecart';
28 public $module_priority = 35;
29 public $class = '\SureCart';
30
31 /**
32 * Initially Invoked when initialized.
33 */
34 public function __construct(){
35 parent::__construct();
36 }
37
38 public function init_extension()
39 {
40 $this->title = __('SureCart', 'notificationx');
41 $this->module_title = __('SureCart', 'notificationx');
42 }
43
44 public function init(){
45 parent::init();
46 add_action('surecart/checkout_confirmed', array( $this, 'save_new_records'), 10, 2);
47 add_filter('surecart/models/fulfillment/created', [$this, 'status_transition'], 10, 2);
48 add_filter('surecart/models/fulfillment/updated', [$this, 'status_transition'], 10, 2);
49 }
50
51 public function init_fields(){
52 parent::init_fields();
53 add_filter('nx_link_types', [$this, 'link_types']);
54 add_filter( 'nx_surecart_order_status', array( $this, 'order_status' ), 11 );
55 add_filter("nx_notification_link_{$this->id}", [$this, 'product_link'], 10, 3);
56 add_filter('nx_conversion_category_list', [$this, 'collections']);
57 add_filter('nx_conversion_product_list', [$this, 'product_lists']);
58
59 }
60
61 /**
62 * This functions is hooked
63 *
64 * @return void
65 */
66 public function admin_actions() {
67 parent::admin_actions();
68 add_filter("nx_can_entry_{$this->id}", array($this, 'check_order_status'), 10, 3);
69 }
70
71 public function public_actions(){
72 parent::public_actions();
73 }
74
75
76 public function check_order_status($return, $entry, $settings){
77 $done = !empty($settings['surecart_order_status']) ? $settings['surecart_order_status'] : ['processing'];
78 if( ( !empty( $entry['data']['status'] ) && in_array($entry['data']['status'], $done ) ) || ( !empty( $entry['data']['fulfillment_status'] ) && in_array($entry['data']['fulfillment_status'], $done ) ) || ( !empty( $entry['data']['shipment_status'] ) && in_array($entry['data']['shipment_status'], $done ) ) ){
79 return $return;
80 }
81 return false;
82 }
83
84 public function product_lists($products) {
85 $all_products = \SureCart\Models\Product::get();
86 $product_lists = [];
87 if( ! is_wp_error( $all_products ) ) {
88 foreach( $all_products as $product ) {
89 $product_lists[ $product->slug ] = $product->name;
90 }
91 }
92 $options = GlobalFields::get_instance()->normalize_fields($product_lists, 'source', $this->id, $products);
93 return $options;
94 }
95
96 public function collections($options) {
97 $collections = \SureCart\Models\ProductCollection::get();
98 $collection_list = [];
99 if( ! is_wp_error( $collections ) ) {
100 foreach( $collections as $collection ) {
101 $collection_list[ $collection->slug ] = $collection->name;
102 }
103 }
104 $options = GlobalFields::get_instance()->normalize_fields($collection_list, 'source', $this->id, $options);
105 return $options;
106 }
107
108 public function product_link($link, $post, $entry) {
109 if(!empty($entry['permalink']) && !empty( $post['link_type'] ) && $post['link_type'] === 'product_page' ){
110 $link = $entry['permalink'];
111 }
112 return $link;
113 }
114
115 public function order_status($options){
116 $order_status = [
117 'processing' => __( 'Processing','notificationx' ),
118 'unfulfilled' => __( 'Unfulfilled','notificationx' ),
119 'fulfilled' => __( 'Fulfilled','notificationx' ),
120 'shipped' => __( 'Shipped','notificationx' ),
121 'delivered' => __( 'Delivered','notificationx' ),
122 'not-shipped' => __( 'Not Shipped','notificationx' ),
123 ];
124 $options = GlobalFields::get_instance()->normalize_fields( $order_status, 'source', $this->id, $options);
125 return $options;
126 }
127
128 public function save_new_records($checkout, $request) {
129 foreach ($checkout->line_items->data as $product ) {
130 if( !empty( $product ) ) {
131 $single_notifications = $this->ordered_product($checkout, $request, $product );
132 $key = $checkout->order;
133 $this->save([
134 'source' => $this->id,
135 'entry_key' => $key,
136 'data' => $single_notifications,
137 ], true );
138 }
139 }
140 }
141
142 public function ordered_product($checkout, $request, $product ) {
143 $new_order = [];
144 $finalized = $checkout->where( $request->get_query_params() )->finalize( $request->get_body_params() );
145 $new_order = $this->prepare_order_data( $product, $finalized->customer, $new_order );
146 // Others information
147 if( !empty( $finalized->ip_address ) ) {
148 $new_order['ip'] = $finalized->ip_address;
149 }
150 if( !empty( $finalized->order ) ) {
151 $new_order['order'] = $finalized->order;
152 }
153 if( !empty( $finalized->order ) ) {
154 $new_order['order'] = $finalized->order;
155 }
156 if( !empty( $checkout->status ) ) {
157 $new_order['status'] = $checkout->status;
158 }
159 if( !empty( $checkout->updated_at ) ) {
160 $new_order['timestamp'] = $checkout->updated_at;
161 }
162 return $new_order;
163 }
164
165 public function prepare_order_data( $product, $customer, $return = [], $checkout = null ) {
166 $address_fields = ['city','country','line_1','line_2','postal_code'];
167 $customer_fields = ['first_name','last_name','email','name'];
168 // Get product information
169 if( !empty( $product->price->product->name ) ) {
170 $return['title'] = $product->price->product->name;
171 }
172 if( !empty( $product->price->product->id ) ) {
173 $return['product_id'] = $product->price->product->id;
174 }
175 if( !empty( $product->price->product->permalink ) ) {
176 $return['permalink'] = $product->price->product->permalink;
177 }
178 if( !empty( $product->price->product->image_url ) ) {
179 $return['image_url'] = $product->price->product->image_url;
180 }
181 // Get billing and shipping address
182 if( $customer->billing_matches_shipping ) {
183 if( is_object( $customer->shipping_address ) ) {
184 foreach ( $address_fields as $fields ) {
185 $return[$fields] = $customer->shipping_address->{$fields};
186 }
187 }else{
188 foreach ( $address_fields as $fields ) {
189 $return[$fields] = $checkout->shipping_address->{$fields};
190 }
191 }
192
193 }else{
194 if( is_object( $customer->billing_address ) ) {
195 foreach ( $address_fields as $fields ) {
196 $return[$fields] = $customer->billing_address->{$fields};
197 }
198 }else{
199 foreach ( $address_fields as $fields ) {
200 $return[$fields] = $checkout->billing_address->{$fields};
201 }
202 }
203 }
204 // Get customer information
205 foreach ($customer_fields as $customer_field) {
206 if( !empty( $customer->{$customer_field} ) ) {
207 $return[$customer_field] = $customer->{$customer_field};
208 }
209 }
210 return $return;
211 }
212
213 /**
214 * Image action callback
215 * @param array $image_data
216 * @param array $data
217 * @param stdClass $settings
218 * @return array
219 */
220 public function notification_image($image_data, $data, $settings) {
221 if (!$settings['show_default_image'] && $settings['show_notification_image'] === 'featured_image') {
222 if ( !empty( $data['image_url'] ) ) {
223 $image_data['url'] = $data['image_url'];
224 }
225 }
226 return $image_data;
227 }
228
229 public function saved_post($post, $data, $nx_id) {
230 $this->delete_notification(null, $nx_id);
231 $this->get_notification_ready($data);
232 }
233
234 public function get_notification_ready( $post = array() ) {
235 $orders = $this->get_orders( $post );
236 if ( is_array( $orders ) && ! empty( $orders ) ) {
237 $entries = [];
238 foreach ( $orders as $order ) {
239 $entries[] = [
240 'nx_id' => $post['nx_id'],
241 'source' => $this->id,
242 'entry_key' => $order['order'],
243 'data' => $order,
244 'updated_at' => Helper::mysql_time($order['updated_at']),
245 ];
246 }
247 $this->update_notifications($entries);
248 }
249 }
250
251 public function status_transition($data) {
252 $orders = Entries::get_instance()->get_entries(['entry_key' => $data['order'] ] );
253 if( !empty( $orders ) && count( $orders ) > 0 ) {
254 $entries = [];
255 foreach ( $orders as $order ) {
256 $update_data = !empty( $order) ? $order : [];
257 if( empty( $order ) || (empty( $data['object'] ) ) ) {
258 return $data;
259 }
260 $update_data['fulfillment_status'] = 'fulfilled';
261 $update_data['shipment_status'] = $data['shipment_status'];
262 unset($update_data['entry_id']);
263 unset($update_data['nx_id']);
264 unset($update_data['source']);
265 unset($update_data['entry_key']);
266 unset($update_data['created_at']);
267 unset($update_data['updated_at']);
268 $entries[] = [
269 'nx_id' => $order['nx_id'],
270 'source' => $this->id,
271 'entry_key' => $order['order'],
272 'data' => $update_data,
273 'updated_at' => Helper::mysql_time($data['updated_at']),
274 ];
275 }
276 $this->delete_notification($order['order'], $order['nx_id']);
277 $this->update_notifications($entries);
278 }else{
279 $get_orders = \SureCart\Models\Order::where( [ 'order_ids' => [ $data['order'] ] ])->with( [ 'checkout', 'checkout.charge', 'checkout.customer','checkout.line_items','line_item.price','price.product','checkout.shipping_address','checkout.billing_address','product.collection' ] )->paginate( [ 'per_page' => 1 ] );
280 if( count( $get_orders->data ) > 0 ) {
281 foreach ($get_orders->data as $order) {
282 foreach ($order->checkout->line_items->data as $product) {
283 $make_orders = [];
284 if( !empty( $order->fulfillment_status ) ) {
285 $make_orders['fulfillment_status'] = $order->fulfillment_status;
286 }
287 if( !empty( $order->shipment_status ) ) {
288 $make_orders['shipment_status'] = $order->shipment_status;
289 }
290 if( !empty( $order->status ) ) {
291 $make_orders['status'] = $order->status;
292 }
293 if( !empty( $order->checkout->ip_address ) ) {
294 $make_orders['ip'] = $order->checkout->ip_address;
295 }
296 if( !empty( $order->id ) ) {
297 $make_orders['order'] = $order->id;
298 }
299 if( !empty( $order->id ) ) {
300 $make_orders['updated_at'] = $order->updated_at;
301 }
302 if( !empty( $order->id ) ) {
303 $make_orders['timestamp'] = $order->updated_at;
304 }
305 $make_orders = $this->prepare_order_data( $product, $order->checkout->customer, $make_orders, $order->checkout );
306 $this->save([
307 'source' => $this->id,
308 'entry_key' => $data['order'],
309 'data' => $make_orders,
310 'updated_at'=> Helper::mysql_time($order->updated_at),
311 ], true );
312 }
313 }
314 }
315 }
316 return $data;
317 }
318
319 public function get_orders( $post = array() ) {
320 if( empty( $post ) ) {
321 return;
322 }
323 $dateFrom = !empty( $post['display_from'] ) ? gmdate('Y-m-d',strtotime('-'.$post['display_from'].' days',time())) : '';
324 $dateTo = gmdate('Y-m-d',strtotime('1 days',time()));
325 $amount = !empty( $post['display_last'] ) ? $post['display_last'] : 10;
326 $get_orders = \SureCart\Models\Order::with( [ 'checkout', 'checkout.charge', 'checkout.customer','checkout.line_items','line_item.price','price.product','checkout.shipping_address','checkout.billing_address','product.collection' ] )->paginate( [ 'per_page' => $amount ] );
327 $orders = [];
328 if( count( $get_orders->data ) > 0 ) {
329 foreach ($get_orders->data as $order) {
330 $createdAt = $order['created_at'];
331 if ($createdAt >= strtotime($dateFrom) && strtotime($createdAt) <= $dateTo) {
332 if( !empty( $order->checkout->line_items->data ) && count( $order->checkout->line_items->data ) > 0 ) {
333 foreach ($order->checkout->line_items->data as $product) {
334 $collections = \SureCart\Models\ProductCollection::where( [ 'product_ids' => [ $product->price->product->id ]] )->get();
335 $make_orders = [];
336 if(( $this->_excludes_product($product, $post, $collections) === $this->_show_purchaseof($product, $post, $collections))){
337 continue;
338 }
339 if( !empty( $order->fulfillment_status ) ) {
340 $make_orders['fulfillment_status'] = $order->fulfillment_status;
341 }
342 if( !empty( $order->shipment_status ) ) {
343 $make_orders['shipment_status'] = $order->shipment_status;
344 }
345 if( !empty( $order->status ) ) {
346 $make_orders['status'] = $order->status;
347 }
348 if( !empty( $order->checkout->ip_address ) ) {
349 $make_orders['ip'] = $order->checkout->ip_address;
350 }
351 if( !empty( $order->id ) ) {
352 $make_orders['order'] = $order->id;
353 }
354 if( !empty( $order->id ) ) {
355 $make_orders['updated_at'] = $order->updated_at;
356 }
357 if( !empty( $order->id ) ) {
358 $make_orders['timestamp'] = $order->updated_at;
359 }
360
361 $orders[] = $this->prepare_order_data( $product, $order->checkout->customer, $make_orders, $order->checkout );
362 }
363 }
364 }
365 }
366 }
367 return $orders;
368 }
369
370
371 public function _excludes_product( $product, $settings, $collections ) {
372 if( !empty( $settings['product_exclude_by'] ) && $settings['product_exclude_by'] === 'none' ) {
373 if( !empty( $settings['product_control'] ) && $settings['product_control'] === 'none' ) {
374 return true;
375 }
376 return false;
377 }
378 // Check product list
379 if( $settings['product_exclude_by'] == 'manual_selection' && !empty( $settings['exclude_products'] ) && count( $settings['exclude_products'] ) > 0 ) {
380 foreach ( $settings['exclude_products'] as $__product ) {
381 if( $__product['value'] == $product->price->product->slug ) {
382 return true;
383 }
384 }
385 }
386 // Check category list
387 if( $settings['product_exclude_by'] == 'product_category' && !empty( $settings['exclude_categories'] ) && count( $settings['exclude_categories'] ) > 0 ) {
388 foreach ($collections as $collection) {
389 if( in_array( $collection->slug, $settings['exclude_categories'] ) ) {
390 return true;
391 }
392 }
393 }
394 return false;
395 }
396
397 public function _show_purchaseof( $product, $settings, $collections ) {
398 if( !empty( $settings['product_control'] ) && $settings['product_control'] === 'none' ) {
399 if( !empty( $settings['product_exclude_by'] ) && $settings['product_exclude_by'] === 'none' ) {
400 return false;
401 }
402 return true;
403 }
404 // Check product list
405 if( $settings['product_control'] == 'manual_selection' && !empty( $settings['product_list'] ) && count( $settings['product_list'] ) > 0 ) {
406 foreach ( $settings['product_list'] as $__product ) {
407 if( $__product['value'] == $product->price->product->slug ) {
408 return true;
409 }
410 }
411 }
412 // Check category list
413 if( $settings['product_control'] == 'product_category' && !empty( $settings['category_list'] ) && count( $settings['category_list'] ) > 0 ) {
414 foreach ($collections as $collection) {
415 if( in_array( $collection->slug, $settings['category_list'] ) ) {
416 return true;
417 }
418 }
419 }
420 return false;
421 }
422
423 /**
424 * Adds option to Link Type field in Content tab.
425 *
426 * @param array $options
427 * @return array
428 */
429 public function link_types($options) {
430 $options = GlobalFields::get_instance()->normalize_fields([
431 'product_page' => __('Product Page', 'notificationx'),
432 ], 'source', $this->id, $options);
433
434 return $options;
435 }
436
437 public function fallback_data($data, $entry) {
438 $data['name'] = __('Someone', 'notificationx');
439 $data['first_name'] = __('Someone', 'notificationx');
440 $data['last_name'] = __('Someone', 'notificationx');
441 $data['anonymous_title'] = __('Anonymous Product', 'notificationx');
442 if(empty($entry['product_title']) && !empty($entry['title'])){
443 $data['product_title'] = $entry['title'];
444 }
445 return $data;
446 }
447
448 public function source_error_message($messages) {
449 if (!$this->class_exists()) {
450 $url = admin_url('plugin-install.php?s=surecart&tab=search&type=term');
451 $messages[$this->id] = [
452 'message' => sprintf( '%s <a href="%s" target="_blank">%s</a> %s',
453 __( 'You have to install', 'notificationx' ),
454 $url,
455 __( 'SureCart', 'notificationx' ),
456 __( 'plugin first.', 'notificationx' )
457 ),
458 'html' => true,
459 'type' => 'error',
460 'rules' => Rules::is('source', $this->id),
461 ];
462 }
463 return $messages;
464 }
465
466 public function doc(){
467 /* translators: %1$s: SureCart WordPress plugin installed & configured link URL, %2$s: documentation link URL, %3$s: 👉 NotificationX Integration with SureCart link URL */
468 return sprintf(__('<p>Make sure that you have the <a target="_blank" href="%1$s">SureCart WordPress plugin installed & configured</a> to use its campaign and selling data. For detailed guidelines, check out the step-by-step <a target="_blank" href="%2$s">documentation</a>.</p>
469 <a target="_blank" href="%3$s">👉 NotificationX Integration with SureCart</a>', 'notificationx'),
470 'https://wordpress.org/plugins/surecart/',
471 'https://notificationx.com/docs/how-to-display-surecart-sales-alerts-using-notificationx/',
472 'https://notificationx.com/surecart/'
473 );
474 }
475
476 }
477
478