PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.2
ShopBuilder – WooCommerce Builder For Elementor v3.2.2
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
shopbuilder / app / Controllers / BuilderController.php

BuilderController.php in ShopBuilder – WooCommerce Builder For Elementor 3.2.2, at app/Controllers/BuilderController.php

674 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main BuilderController class.
4 *
5 * @package RadiusTheme\SB
6 */
7
8 namespace RadiusTheme\SB\Controllers;
9
10 use RadiusTheme\SB\Helpers\Fns;
11 use RadiusTheme\SB\Helpers\BuilderFns;
12 use RadiusTheme\SB\Models\ElementList;
13 use RadiusTheme\SB\Traits\SingletonTrait;
14 use RadiusTheme\SB\Controllers\Builder\BuilderCpt;
15 use RadiusTheme\SB\Controllers\Hooks\BuilderHooks;
16 use RadiusTheme\SB\Elementor\Controls\ImageSelectorControl;
17 use RadiusTheme\SB\Elementor\Controls\Select2AjaxControl;
18
19 // Do not allow directly accessing this file.
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit( 'This script cannot be accessed directly.' );
22 }
23
24 /**
25 * Builder Controller
26 */
27 class BuilderController {
28 /**
29 * @var array
30 */
31 private static $cache = [];
32
33 /**
34 * Builder page id.
35 *
36 * @var integer
37 */
38 private $builder_page_id = 0;
39
40 /**
41 * Page Edit By.
42 *
43 * @var string
44 */
45 private $page_edit_with = '';
46
47 /**
48 * Singleton Trait
49 */
50 use SingletonTrait;
51
52 /**
53 * Construct function
54 */
55 private function __construct() {
56 $this->builder_page_id = BuilderFns::builder_page_id_by_page();
57 $this->page_edit_with = Fns::page_edit_with( $this->builder_page_id );
58
59 if ( ! is_admin() ) {
60 BuilderHooks::instance();
61 }
62
63 BuilderCpt::instance();
64 if ( defined( 'ELEMENTOR_VERSION' ) ) {
65 $this->elementor_init();
66 $this->both_builder_frontend();
67 add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'editor_scripts' ] );
68 }
69 // RT Select2 Ajax.
70 add_action( 'wp_ajax_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
71 add_action( 'wp_ajax_nopriv_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] );
72 // Select2 ajax save data.
73 add_action( 'wp_ajax_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
74 add_action( 'wp_ajax_nopriv_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
75 }
76
77 /**
78 * Apply for frontend.
79 *
80 * @return void
81 */
82 public function both_builder_frontend() {
83 add_action( 'rtsb/builder/template/before/content', [ $this, 'builder_template_before_content' ] );
84 add_action( 'rtsb/builder/template/after/content', [ $this, 'builder_template_after_content' ] );
85 }
86
87 /**
88 * Register Category
89 *
90 * @return void
91 */
92 public function elementor_init() {
93 add_action(
94 'init',
95 function () {
96 if ( Fns::should_load_elementor_scripts() ) {
97 add_action( 'elementor/elements/categories_registered', [ $this, 'add_elementor_widget_categories' ] );
98 add_action( 'elementor/widgets/register', [ $this, 'init_widgets' ] );
99 add_action( 'elementor/controls/register', [ $this, 'init_controls' ] );
100 add_filter( 'elementor/editor/localize_settings', [ $this, 'promotePremiumWidgets' ] );
101 add_action( 'elementor/icons_manager/additional_tabs', [ $this, 'rtsb_icons' ] );
102 }
103 }
104 );
105 }
106
107 /**
108 * Register Category
109 *
110 * @param object $elements_manager Category hooks.
111 *
112 * @return void
113 */
114 public function add_elementor_widget_categories( $elements_manager ) {
115 $categories = [];
116 $builder_id = get_queried_object_id();
117 $id = Fns::wpml_object_id( $builder_id, BuilderFns::$post_type_tb, 'default' );
118 $type = BuilderFns::builder_type( $id );
119
120 if ( $type && 'popup-builder' !== $type ) {
121 $builder_type = ! empty( BuilderFns::builder_page_types()[ $type ] ) ? BuilderFns::builder_page_types()[ $type ] : '';
122 $builder_type = str_replace( [ 'My Account - ', 'Endpoint: ' ], '', $builder_type );
123 $categories['rtsb-shopbuilder'] = [
124 'title' => esc_html__( 'ShopBuilder', 'shopbuilder' ) . ' - ' . ucfirst( $builder_type ),
125 'icon' => 'fa fa-plug',
126 ];
127 }
128 if ( 'quick-view' !== $type ) {
129 $categories['rtsb-shopbuilder-general'] = [
130 'title' => esc_html__( 'Shopbuilder - General', 'shopbuilder' ),
131 'icon' => 'fa fa-plug',
132 ];
133 }
134 $categories = apply_filters( 'rtsb_elementor_widgets_category_lists', $categories );
135
136 $other_categories = $elements_manager->get_categories();
137 $categories = array_merge(
138 array_slice( $other_categories, 0, 1 ),
139 $categories,
140 array_slice( $other_categories, 1 )
141 );
142
143 $set_categories = function ( $categories ) use ( $elements_manager ) {
144 $elements_manager->categories = $categories;
145 };
146
147 $set_categories->call( $elements_manager, $categories );
148 }
149
150 /**
151 * Init Controls
152 *
153 * Include controls files and register them
154 *
155 * @param object $controls_manager Controls Manager.
156 *
157 * @since 1.0.0
158 */
159 public function init_controls( $controls_manager ) {
160 $controls_manager->register( new ImageSelectorControl() );
161 $controls_manager->register( new Select2AjaxControl() );
162 }
163
164 /**
165 * Init Widgets
166 *
167 * Include widget files and register them
168 *
169 * @param object $widgets_manager Widgets Manager.
170 *
171 * @return void
172 *
173 * @since 1.0.0
174 */
175 public function init_widgets( $widgets_manager ) {
176
177 $get_list = ElementList::instance()->get_list( true, 'active' );
178 foreach ( $get_list as $element ) {
179 if ( isset( $element['active'] ) && 'on' !== $element['active'] ) {
180 continue;
181 }
182
183 if ( ! empty( $element['package'] ) && 'pro-disabled' === $element['package'] ) {
184 continue;
185 }
186
187 if ( empty( $element['base_class'] ) || ! class_exists( $element['base_class'] ) ) {
188 continue;
189 }
190
191 if ( ! empty( $element['category'] ) ) {
192 $widget = false;
193 $import = apply_filters( 'rtsb_import_status', false );
194 switch ( $element['category'] ) {
195 case 'product':
196 if ( BuilderFns::is_product() || $import ) {
197 $widget = new $element['base_class']();
198 }
199 break;
200 case 'shop':
201 if ( BuilderFns::is_archive() || BuilderFns::is_shop() || $import ) {
202 $widget = new $element['base_class']();
203 }
204 break;
205 case 'archive':
206 if ( BuilderFns::is_archive() || $import ) {
207 $widget = new $element['base_class']();
208 }
209 break;
210 case 'cart':
211 if ( BuilderFns::is_cart() || $import ) {
212 $widget = new $element['base_class']();
213 }
214 break;
215 case 'checkout':
216 if ( BuilderFns::is_checkout() || $import ) {
217 $widget = new $element['base_class']();
218 }
219 break;
220 case 'general':
221 $widget = new $element['base_class']();
222 break;
223 default:
224 }
225 $widget = apply_filters( 'rtsb/element/list/init/widgets', $widget, $element );
226
227 if ( $widget && is_object( $widget ) ) {
228 $widgets_manager->register( $widget );
229 }
230 }
231 }
232 }
233
234 /**
235 * Adding custom icons in Elementor
236 *
237 * @param array $tabs Tabs.
238 *
239 * @return array
240 */
241 public function rtsb_icons( $tabs = [] ) {
242 $custom_icons = Fns::get_custom_icon_names();
243
244 $tabs['shopbuilder-icons'] = [
245 'name' => 'rtsb-fonts',
246 'label' => esc_html__( 'ShopBuilder Icons', 'shopbuilder' ),
247 'labelIcon' => 'fab fa-elementor',
248 'prefix' => 'rtsb-icon-',
249 'displayPrefix' => 'rtsb-icon',
250 'url' => rtsb()->get_assets_uri( 'css/frontend/rtsb-fonts.css' ),
251 'icons' => $custom_icons,
252 'ver' => '1.0',
253 ];
254
255 return $tabs;
256 }
257
258 /**
259 * Editor JS.
260 *
261 * @return void
262 */
263 public function editor_scripts() {
264 $version = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? time() : RTSB_VERSION;
265
266 wp_enqueue_script(
267 'rtsb-editor-script',
268 rtsb()->get_assets_uri( 'js/backend/editor.js' ),
269 [
270 'jquery',
271 'elementor-editor',
272 'jquery-elementor-select2',
273 ],
274 $version,
275 true
276 );
277 $params = [
278 'isEditorForBuilder' => false,
279 ];
280 if ( BuilderFns::is_builder_preview() ) {
281 $params['isEditorForBuilder'] = true;
282 }
283 wp_localize_script( 'rtsb-editor-script', 'rtsbTemplateBuilderEditorScript', $params );
284 wp_enqueue_style( 'rtsb-el-editor-style', rtsb()->get_assets_uri( 'css/backend/elementor-editor.css' ), [], $version );
285 }
286
287 /**
288 * Before Content for Elementor.
289 *
290 * @return void
291 */
292 public function builder_template_before_content() {
293 /**
294 * Before Header-Footer page template content.
295 *
296 * Fires before the content of Elementor Header-Footer page template.
297 *
298 * @since 2.0.0
299 */
300 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
301 do_action( 'elementor/page_templates/header-footer/before_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
302 }
303
304 $parent_class = apply_filters( 'rtsb/builder/content/parent_class', [] );
305
306 if ( BuilderFns::is_product() ) {
307 $product_id = Fns::get_prepared_product_id();
308 $parent_class = wc_get_product_class( $parent_class, $product_id );
309 if ( function_exists( 'rtwpvs' ) ) {
310 $_product = Fns::get_product();
311 if ( $_product->is_type( 'variable' ) ) {
312 $parent_class[] = 'rtwpvs-product';
313 $beside_label = function_exists( 'rtwpvsp' ) && rtwpvs()->get_option( 'attribute_on_click_behavior' );
314 if ( $beside_label ) {
315 $parent_class[] = 'rtwpvs-selected-term-beside-label';
316 }
317 }
318 }
319 }
320
321 if ( BuilderFns::is_shop() ) {
322 $parent_class[] = 'shop';
323 }
324
325 if ( BuilderFns::is_archive() ) {
326 $parent_class[] = 'archive';
327 }
328
329 if ( BuilderFns::is_checkout() ) {
330 $parent_class[] = 'checkout-page ';
331 }
332
333 ?>
334 <!-- Before Content start -->
335 <div class="<?php echo esc_attr( implode( ' ', $parent_class ) ); ?>">
336 <?php
337 if ( BuilderFns::is_checkout() ) {
338 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
339 return;
340 }
341 ?>
342 <!--
343 woocommerce-checkout added for fix issue with payment method ( Revolut Pay )
344 -->
345 <form name="checkout" method="post" class="rtsb-woocommerce-checkout woocommerce-checkout checkout" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data">
346 <?php
347 }
348 }
349
350 /**
351 * After Content for Elementor.
352 *
353 * @return void
354 */
355 public function builder_template_after_content() {
356 /**
357 * After Header-Footer page template content.
358 *
359 * Fires after the content of Elementor Header-Footer page template.
360 *
361 * @since 2.0.0
362 */
363 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
364 do_action( 'elementor/page_templates/header-footer/after_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
365 }
366
367 if ( BuilderFns::is_checkout() ) {
368 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
369 return;
370 }
371 ?>
372 </form>
373 <?php
374 }
375 ?>
376 </div>
377 <!-- After Content end -->
378 <?php
379 }
380
381 /**
382 * Ajax callback for rt-select2
383 *
384 * @return void
385 */
386 public function select2_ajax_posts_filter_autocomplete() {
387 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
388 wp_send_json_error( [] );
389 }
390 $query_per_page = 15;
391 $post_type = 'post';
392 $source_name = 'post_type';
393 $paged = absint( $_POST['page'] ?? 1 );
394 if ( ! empty( $_POST['post_type'] ) ) {
395 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
396 $post_type = sanitize_text_field( $_POST['post_type'] );
397 }
398
399 if ( ! empty( $_POST['source_name'] ) ) {
400 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
401 $source_name = sanitize_text_field( $_POST['source_name'] );
402 }
403
404 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
405 $search = ! empty( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
406 $results = $post_list = []; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found
407 switch ( $source_name ) {
408 case 'taxonomy':
409 $args = [
410 'hide_empty' => false,
411 'orderby' => 'name',
412 'order' => 'ASC',
413 'search' => $search,
414 'number' => '5',
415 ];
416
417 if ( 'all' !== $post_type ) {
418 $args['taxonomy'] = $post_type;
419 }
420
421 $post_list = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
422 break;
423 case 'user':
424 $users = [];
425
426 foreach ( get_users( [ 'search' => "*{$search}*" ] ) as $user ) {
427 $user_id = $user->ID;
428 $user_name = $user->display_name;
429 $users[ $user_id ] = $user_name;
430 }
431
432 $post_list = $users;
433 break;
434 default:
435 $post_list = $this->get_query_data( $post_type, $query_per_page, $search, $paged );
436 }
437
438 $pagination = true;
439 if ( count( $post_list ) < $query_per_page ) {
440 $pagination = false;
441 }
442 if ( ! empty( $post_list ) ) {
443 foreach ( $post_list as $key => $item ) {
444 $results[] = [
445 'text' => $item,
446 'id' => $key,
447 ];
448 }
449 }
450 wp_send_json(
451 [
452 'results' => $results,
453 'pagination' => [ 'more' => $pagination ],
454 ]
455 );
456 }
457
458
459 /**
460 * Ajax callback for rt-select2
461 *
462 * @return void
463 */
464 public function select2_ajax_get_posts_value_titles() {
465
466 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
467 wp_send_json_error( [] );
468 }
469
470 if ( empty( $_POST['id'] ) ) {
471 wp_send_json_error( [] );
472 }
473
474 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
475 if ( empty( array_filter( $_POST['id'] ) ) ) {
476 wp_send_json_error( [] );
477 }
478 $ids = array_map( 'intval', $_POST['id'] );
479 $source_name = ! empty( $_POST['source_name'] ) ? sanitize_text_field( $_POST['source_name'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
480
481 switch ( $source_name ) {
482 case 'taxonomy':
483 $args = [
484 'hide_empty' => false,
485 'orderby' => 'name',
486 'order' => 'ASC',
487 'include' => implode( ',', $ids ),
488 ];
489
490 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
491 if ( 'all' !== $_POST['post_type'] ) {
492 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
493 $args['taxonomy'] = sanitize_text_field( $_POST['post_type'] );
494 }
495
496 $response = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
497 break;
498 case 'user':
499 $users = [];
500
501 foreach ( get_users( [ 'include' => $ids ] ) as $user ) {
502 $user_id = $user->ID;
503 $user_name = $user->display_name . '-' . $user->ID;
504 $users[ $user_id ] = $user_name;
505 }
506
507 $response = $users;
508 break;
509 default:
510 $post_info = get_posts(
511 [
512 'post_type' => sanitize_text_field( $_POST['post_type'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
513 'include' => implode( ',', $ids ),
514 ]
515 );
516 $response = wp_list_pluck( $post_info, 'post_title', 'ID' );
517 }
518
519 if ( ! empty( $response ) ) {
520 wp_send_json_success( [ 'results' => $response ] );
521 } else {
522 wp_send_json_error( [] );
523 }
524 }
525
526
527 /**
528 * Ajax callback for rt-select2
529 *
530 * @param string $post_type Post type.
531 * @param int $limit Limit.
532 * @param string $search Search.
533 * @param int $paged Paged.
534 *
535 * @return array
536 */
537 public function get_query_data( $post_type = 'any', $limit = 10, $search = '', $paged = 1 ) {
538 global $wpdb;
539 $where = '';
540 $data = [];
541
542 if ( - 1 == $limit ) {
543 $limit = '';
544 } elseif ( 0 == $limit ) {
545 $limit = 'limit 0,1';
546 } else {
547 $offset = 0;
548 if ( $paged ) {
549 $offset = ( $paged - 1 ) * $limit;
550 }
551 $limit = $wpdb->prepare( ' limit %d, %d', esc_sql( $offset ), esc_sql( $limit ) );
552 }
553
554 if ( 'any' === $post_type ) {
555 $in_search_post_types = get_post_types( [ 'exclude_from_search' => false ] );
556 if ( empty( $in_search_post_types ) ) {
557 $where .= ' AND 1=0 ';
558 } else {
559 $where .= " AND {$wpdb->posts}.post_type IN ('" . join(
560 "', '",
561 array_map( 'esc_sql', $in_search_post_types )
562 ) . "')";
563 }
564 } elseif ( ! empty( $post_type ) ) {
565 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", esc_sql( $post_type ) );
566 }
567
568 if ( ! empty( $search ) ) {
569 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title LIKE %s", '%' . esc_sql( $search ) . '%' );
570 }
571
572 // Add a query for shop_coupon post-type to check 'show on frontend' meta.
573 if ( 'shop_coupon' === $post_type ) {
574 $where .= " AND {$wpdb->posts}.ID IN (
575 SELECT post_id FROM {$wpdb->postmeta}
576 WHERE meta_key = 'rtsb_show_on_frontend'
577 AND meta_value = 'on'
578 )";
579 }
580
581 $query = "select post_title,ID from $wpdb->posts where post_status = 'publish' {$where} {$limit}";
582 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
583
584 if ( ! empty( $results ) ) {
585 foreach ( $results as $row ) {
586 $data[ $row->ID ] = $row->post_title . ' [#' . $row->ID . ']';
587 }
588 }
589
590 return $data;
591 }
592
593 /**
594 * Promotion.
595 *
596 * @param array $config Config.
597 * @return array
598 */
599 public function promotePremiumWidgets( $config ) {
600 if ( rtsb()->has_pro() ) {
601 return $config;
602 }
603
604 if ( ! empty( $config['initial_document']['panel']['elements_categories']['rtsb-shopbuilder']['title'] ) ) {
605 $title = $config['initial_document']['panel']['elements_categories']['rtsb-shopbuilder']['title'];
606
607 if ( 'ShopBuilder - Shop' === $title || 'ShopBuilder - Archive' === $title ) {
608 if ( ! isset( $config['promotionWidgets'] ) || ! is_array( $config['promotionWidgets'] ) ) {
609 $config['promotionWidgets'] = [];
610 }
611
612 $pro_widgets = [
613 [
614 'name' => 'rtsb-ajax-product-filters',
615 'title' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
616 'description' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
617 'icon' => 'rtsb-el-custom rtsb-element icon-rtsb-ajax-product-filters rtsb-promotional-element',
618 'categories' => '[ "rtsb-shopbuilder" ]',
619 ],
620 ];
621
622 $config['promotionWidgets'] = array_merge( $config['promotionWidgets'], $pro_widgets );
623
624 return $config;
625 }
626 }
627
628 return $config;
629 }
630
631 /**
632 * Get Icons.
633 *
634 * @return array
635 */
636 public function get_icons() {
637 return [
638 'heart-empty',
639 'heart',
640 'eye',
641 'exchange',
642 'plus',
643 'minus',
644 'avatar',
645 'pay',
646 'share',
647 'clock',
648 'check-alt',
649 'check',
650 'delete',
651 'marker',
652 'list',
653 'list-2',
654 'power',
655 'cart',
656 'cart-2',
657 'cart-3',
658 'downloads',
659 'zoom',
660 'user-edit',
661 'grid',
662 'filter',
663 'billing',
664 'login',
665 'payment',
666 'search',
667 'edit',
668 'coupon',
669 'arrows-cw',
670 'trash-empty',
671 ];
672 }
673 }
674