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

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