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

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