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

672 lines 18.0 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 <form name="checkout" method="post" class="rtsb-woocommerce-checkout checkout" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data">
344 <?php
345 }
346 }
347
348 /**
349 * After Content for Elementor.
350 *
351 * @return void
352 */
353 public function builder_template_after_content() {
354 /**
355 * After Header-Footer page template content.
356 *
357 * Fires after the content of Elementor Header-Footer page template.
358 *
359 * @since 2.0.0
360 */
361 if ( did_action( 'elementor/loaded' ) && 'elementor' === $this->page_edit_with ) {
362 do_action( 'elementor/page_templates/header-footer/after_content' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
363 }
364
365 if ( BuilderFns::is_checkout() ) {
366 if ( ! apply_filters( 'rtsb/multi/step/checkout/widget', true ) ) {
367 return;
368 }
369 ?>
370 </form>
371 <?php
372 }
373 ?>
374 </div>
375 <!-- After Content end -->
376 <?php
377 }
378
379 /**
380 * Ajax callback for rt-select2
381 *
382 * @return void
383 */
384 public function select2_ajax_posts_filter_autocomplete() {
385 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
386 wp_send_json_error( [] );
387 }
388 $query_per_page = 15;
389 $post_type = 'post';
390 $source_name = 'post_type';
391 $paged = absint( $_POST['page'] ?? 1 );
392 if ( ! empty( $_POST['post_type'] ) ) {
393 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
394 $post_type = sanitize_text_field( $_POST['post_type'] );
395 }
396
397 if ( ! empty( $_POST['source_name'] ) ) {
398 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
399 $source_name = sanitize_text_field( $_POST['source_name'] );
400 }
401
402 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
403 $search = ! empty( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
404 $results = $post_list = []; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found
405 switch ( $source_name ) {
406 case 'taxonomy':
407 $args = [
408 'hide_empty' => false,
409 'orderby' => 'name',
410 'order' => 'ASC',
411 'search' => $search,
412 'number' => '5',
413 ];
414
415 if ( 'all' !== $post_type ) {
416 $args['taxonomy'] = $post_type;
417 }
418
419 $post_list = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
420 break;
421 case 'user':
422 $users = [];
423
424 foreach ( get_users( [ 'search' => "*{$search}*" ] ) as $user ) {
425 $user_id = $user->ID;
426 $user_name = $user->display_name;
427 $users[ $user_id ] = $user_name;
428 }
429
430 $post_list = $users;
431 break;
432 default:
433 $post_list = $this->get_query_data( $post_type, $query_per_page, $search, $paged );
434 }
435
436 $pagination = true;
437 if ( count( $post_list ) < $query_per_page ) {
438 $pagination = false;
439 }
440 if ( ! empty( $post_list ) ) {
441 foreach ( $post_list as $key => $item ) {
442 $results[] = [
443 'text' => $item,
444 'id' => $key,
445 ];
446 }
447 }
448 wp_send_json(
449 [
450 'results' => $results,
451 'pagination' => [ 'more' => $pagination ],
452 ]
453 );
454 }
455
456
457 /**
458 * Ajax callback for rt-select2
459 *
460 * @return void
461 */
462 public function select2_ajax_get_posts_value_titles() {
463
464 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
465 wp_send_json_error( [] );
466 }
467
468 if ( empty( $_POST['id'] ) ) {
469 wp_send_json_error( [] );
470 }
471
472 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
473 if ( empty( array_filter( $_POST['id'] ) ) ) {
474 wp_send_json_error( [] );
475 }
476 $ids = array_map( 'intval', $_POST['id'] );
477 $source_name = ! empty( $_POST['source_name'] ) ? sanitize_text_field( $_POST['source_name'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
478
479 switch ( $source_name ) {
480 case 'taxonomy':
481 $args = [
482 'hide_empty' => false,
483 'orderby' => 'name',
484 'order' => 'ASC',
485 'include' => implode( ',', $ids ),
486 ];
487
488 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
489 if ( 'all' !== $_POST['post_type'] ) {
490 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
491 $args['taxonomy'] = sanitize_text_field( $_POST['post_type'] );
492 }
493
494 $response = wp_list_pluck( get_terms( $args ), 'name', 'term_id' );
495 break;
496 case 'user':
497 $users = [];
498
499 foreach ( get_users( [ 'include' => $ids ] ) as $user ) {
500 $user_id = $user->ID;
501 $user_name = $user->display_name . '-' . $user->ID;
502 $users[ $user_id ] = $user_name;
503 }
504
505 $response = $users;
506 break;
507 default:
508 $post_info = get_posts(
509 [
510 'post_type' => sanitize_text_field( $_POST['post_type'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
511 'include' => implode( ',', $ids ),
512 ]
513 );
514 $response = wp_list_pluck( $post_info, 'post_title', 'ID' );
515 }
516
517 if ( ! empty( $response ) ) {
518 wp_send_json_success( [ 'results' => $response ] );
519 } else {
520 wp_send_json_error( [] );
521 }
522 }
523
524
525 /**
526 * Ajax callback for rt-select2
527 *
528 * @param string $post_type Post type.
529 * @param int $limit Limit.
530 * @param string $search Search.
531 * @param int $paged Paged.
532 *
533 * @return array
534 */
535 public function get_query_data( $post_type = 'any', $limit = 10, $search = '', $paged = 1 ) {
536 global $wpdb;
537 $where = '';
538 $data = [];
539
540 if ( - 1 == $limit ) {
541 $limit = '';
542 } elseif ( 0 == $limit ) {
543 $limit = 'limit 0,1';
544 } else {
545 $offset = 0;
546 if ( $paged ) {
547 $offset = ( $paged - 1 ) * $limit;
548 }
549 $limit = $wpdb->prepare( ' limit %d, %d', esc_sql( $offset ), esc_sql( $limit ) );
550 }
551
552 if ( 'any' === $post_type ) {
553 $in_search_post_types = get_post_types( [ 'exclude_from_search' => false ] );
554 if ( empty( $in_search_post_types ) ) {
555 $where .= ' AND 1=0 ';
556 } else {
557 $where .= " AND {$wpdb->posts}.post_type IN ('" . join(
558 "', '",
559 array_map( 'esc_sql', $in_search_post_types )
560 ) . "')";
561 }
562 } elseif ( ! empty( $post_type ) ) {
563 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", esc_sql( $post_type ) );
564 }
565
566 if ( ! empty( $search ) ) {
567 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title LIKE %s", '%' . esc_sql( $search ) . '%' );
568 }
569
570 // Add a query for shop_coupon post-type to check 'show on frontend' meta.
571 if ( 'shop_coupon' === $post_type ) {
572 $where .= " AND {$wpdb->posts}.ID IN (
573 SELECT post_id FROM {$wpdb->postmeta}
574 WHERE meta_key = 'rtsb_show_on_frontend'
575 AND meta_value = 'on'
576 )";
577 }
578
579 $query = "select post_title,ID from $wpdb->posts where post_status = 'publish' {$where} {$limit}";
580 $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
581
582 if ( ! empty( $results ) ) {
583 foreach ( $results as $row ) {
584 $data[ $row->ID ] = $row->post_title . ' [#' . $row->ID . ']';
585 }
586 }
587
588 return $data;
589 }
590
591 /**
592 * Promotion.
593 *
594 * @param array $config Config.
595 * @return array
596 */
597 public function promotePremiumWidgets( $config ) {
598 if ( rtsb()->has_pro() ) {
599 return $config;
600 }
601
602 if ( ! empty( $config['initial_document']['panel']['elements_categories']['rtsb-shopbuilder']['title'] ) ) {
603 $title = $config['initial_document']['panel']['elements_categories']['rtsb-shopbuilder']['title'];
604
605 if ( 'ShopBuilder - Shop' === $title || 'ShopBuilder - Archive' === $title ) {
606 if ( ! isset( $config['promotionWidgets'] ) || ! is_array( $config['promotionWidgets'] ) ) {
607 $config['promotionWidgets'] = [];
608 }
609
610 $pro_widgets = [
611 [
612 'name' => 'rtsb-ajax-product-filters',
613 'title' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
614 'description' => esc_html__( 'Ajax Product Filters', 'shopbuilder' ),
615 'icon' => 'rtsb-el-custom rtsb-element icon-rtsb-ajax-product-filters rtsb-promotional-element',
616 'categories' => '[ "rtsb-shopbuilder" ]',
617 ],
618 ];
619
620 $config['promotionWidgets'] = array_merge( $config['promotionWidgets'], $pro_widgets );
621
622 return $config;
623 }
624 }
625
626 return $config;
627 }
628
629 /**
630 * Get Icons.
631 *
632 * @return array
633 */
634 public function get_icons() {
635 return [
636 'heart-empty',
637 'heart',
638 'eye',
639 'exchange',
640 'plus',
641 'minus',
642 'avatar',
643 'pay',
644 'share',
645 'clock',
646 'check-alt',
647 'check',
648 'delete',
649 'marker',
650 'list',
651 'list-2',
652 'power',
653 'cart',
654 'cart-2',
655 'cart-3',
656 'downloads',
657 'zoom',
658 'user-edit',
659 'grid',
660 'filter',
661 'billing',
662 'login',
663 'payment',
664 'search',
665 'edit',
666 'coupon',
667 'arrows-cw',
668 'trash-empty',
669 ];
670 }
671 }
672