PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.2
ShopBuilder – WooCommerce Builder For Elementor v2.6.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 2.6.2, at app/Controllers/BuilderController.php

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