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

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