PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.4.0
ShopBuilder – WooCommerce Builder For Elementor v3.4.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
← All changes | app/Controllers/Admin/Ajax/ModalTemplate.php +318 -140 2.1.123.4.0 View file →
@@ -3,9 +3,11 @@
3 3 namespace RadiusTheme\SB\Controllers\Admin\Ajax;
4 4
5 5 use Elementor\Plugin;
6 6 use RadiusTheme\SB\Helpers\BuilderFns;
7 +use RadiusTheme\SB\Helpers\Cache;
7 8 use RadiusTheme\SB\Helpers\Fns;
9 +use RadiusTheme\SB\Models\TemplateSettings;
8 10 use RadiusTheme\SB\Traits\SingletonTrait;
9 11 use Elementor\Core\Files\Uploads_Manager;
10 12
11 13 // Do not allow directly accessing this file.
@@ -27,9 +29,9 @@
27 29 */
28 30 private function __construct() {
29 31 add_action( 'wp_ajax_rtsb_builder_modal_template', [ $this, 'response' ] );
30 32 add_action( 'wp_ajax_rtsb_modal_product_search', [ $this, 'product_search' ] );
31 - add_action( 'wp_ajax_rtsb_modal_category_search', [ $this, 'category_search' ] );
33 + add_action( 'wp_ajax_rtsb_modal_term_search', [ $this, 'term_search' ] );
32 34 }
33 35
34 36 /**
35 37 * Popups For Create Template
@@ -35,9 +37,9 @@
35 37 * Popups For Create Template
36 38 *
37 39 * @return void
38 40 */
39 - public function response() {
41 + public function response() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
40 42 $title = '<h2>' . esc_html__( 'Template Settings', 'shopbuilder' ) . '</h2>';
41 43 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
42 44 $return = [
43 45 'success' => false,
@@ -54,9 +56,18 @@
54 56 'content' => esc_html__( 'Permission Denied...', 'shopbuilder' ),
55 57 ];
56 58 wp_send_json( $return );
57 59 }
60 + if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
61 + $return = [
62 + 'success' => true,
63 + 'title' => $title,
64 + 'content' => '<h2 style="text-align: center;">' . esc_html__( 'Permission Denied. Please Install elementor', 'shopbuilder' ) . '</h2>',
65 + ];
58 66
67 + wp_send_json( $return );
68 + }
69 +
59 70 add_filter( 'option_' . Uploads_Manager::UNFILTERED_FILE_UPLOADS_KEY, '__return_true' );
60 71 Plugin::$instance->files_manager->clear_cache();
61 72
62 73 // user capability check.
@@ -62,21 +73,23 @@
62 73 // user capability check.
63 74 $user = wp_get_current_user();
64 75 $allowed_roles = [ 'editor', 'administrator', 'author' ];
65 76
66 - if ( ! array_intersect( $allowed_roles, $user->roles ) ) {
77 + if ( ! array_intersect( $allowed_roles, Fns::get_current_user_roles() ) ) {
67 78 wp_die( esc_html__( 'You don\'t have permission to perform this action', 'shopbuilder' ) );
68 79 }
69 80
70 81 // Check if the user is not logged in and the provided 'user_id' in the request does not match the currently logged-in user's ID.
82 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.PHP.YodaConditions.NotYoda
71 83 if ( ! is_user_logged_in() && $user->ID !== sanitize_text_field( $_REQUEST['user_id'] ) ) {
72 84 wp_die( esc_html__( 'You don\'t have proper authorization to perform this action', 'shopbuilder' ) );
73 85 }
74 86
75 - $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : null;
76 - $layout_id = isset( $_POST['layout_id'] ) ? absint( $_POST['layout_id'] ) : null;
87 + $post_id = isset( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : null;
88 + $layout_id = isset( $_REQUEST['layout_id'] ) ? absint( $_REQUEST['layout_id'] ) : null;
77 89
78 90 $template_type = null;
91 + $product_page_for = 'all_products';
79 92 $template_default = null;
80 93 $url = '';
81 94 $tmp_title = '';
82 95 $_rtsb_import_id = '';
@@ -82,15 +95,18 @@
82 95 $_rtsb_import_id = '';
83 96 $edit_by = did_action( 'elementor/loaded' ) ? 'elementor' : 'elementor';
84 97 if ( $post_id ) {
85 98 $tmp_title = get_the_title( $post_id );
86 - $type = get_post_meta( $post_id, BuilderFns::template_type_meta_key() );
87 - $template_type = isset( $type[0] ) ? $type[0] : '';
88 - $template_default = absint( BuilderFns::builder_page_id_by_type( $template_type ) );
99 + $template_type = get_post_meta( $post_id, BuilderFns::template_type_meta_key(), true );
100 + $options = BuilderFns::option_name( $template_type );
101 + $template_default = TemplateSettings::instance()->get_option( $options );
89 102 $edit_by = Fns::page_edit_with( $post_id );
90 103 $action = 'edit';
104 + if ( rtsb()->has_pro() ) {
105 + $product_page_for = get_post_meta( $post_id, '_is_product_page_template_for', true );
106 + }
91 107
92 - // TODO:: This Condition Will remove after release Gutenberg Addons.
108 + /* This Condition Will remove after release Gutenberg Addons. */
93 109 if ( 'gutenberg' == $edit_by ) {
94 110 $action = 'elementor';
95 111 $edit_by = 'elementor';
96 112 }
@@ -108,20 +124,8 @@
108 124 );
109 125
110 126 $_rtsb_import_id = get_post_meta( $post_id, '_rtsb_import_id', true );
111 127 }
112 -
113 - $status = $_REQUEST['status'] ?? '';
114 - $post_args = [ 'timeout' => 120 ];
115 - $post_args['body'] = [
116 - 'status' => $status,
117 - ];
118 - $layoutRequest = wp_remote_post( rtsb()->BASE_API, $post_args );
119 - $layoutData = [];
120 - if ( ! is_wp_error( $layoutRequest ) && ! empty( $layoutRequest['body'] ) ) {
121 - $layoutData = json_decode( $layoutRequest['body'], true );
122 - }
123 -
124 128 ob_start();
125 129
126 130 ?>
127 131 <form action="<?php echo esc_url( admin_url( 'edit.php?post_type=rtsb_builder' ) ); ?>" autocomplete="off" data-imported-id="<?php echo esc_attr( $_rtsb_import_id ); ?>">
@@ -137,10 +141,9 @@
137 141 placeholder="<?php esc_attr_e( 'Enter Template Name', 'shopbuilder' ); ?>"
138 142 value="<?php echo esc_attr( $tmp_title ); ?>"
139 143 autocomplete="off"
140 144 >
141 - <span class="message"
142 - style="display: none; color:red"><?php esc_html_e( 'This field is required', 'shopbuilder' ); ?></span>
145 + <span class="message" style="display: none; color:red"><?php esc_html_e( 'This field is required', 'shopbuilder' ); ?></span>
143 146 </div>
144 147 <div class="rtsb-template-type rtsb-tb-field-wraper">
145 148 <label for="rtsb_tb_template_type"><?php esc_html_e( 'Select Template Type', 'shopbuilder' ); ?></label>
146 149 <select class="rtsb-field" id="rtsb_tb_template_type" name="rtsb_tb_template_type">
@@ -152,37 +155,118 @@
152 155 <?php } ?>
153 156 </select>
154 157 </div>
155 158
156 - <div class="rtsb-product-page-field rtsb-tb-field-wraper" style="display:none;">
159 + <div class="rtsb-product-page-for rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;" >
160 + <label for="product_page_for">
161 + <?php esc_html_e( 'Product Template For', 'shopbuilder' ); ?>
162 + <?php if ( ! rtsb()->has_pro() ) { ?>
163 + <div class="card-label">
164 + <span class="rtsb-btn-import pro-btn">
165 + <?php echo esc_html( 'PRO' ); ?>
166 + </span>
167 + </div>
168 + <?php } ?>
169 + </label>
170 +
171 + <select class="rtsb-field" id="product_page_for" name="product_page_for">
172 + <?php
173 + $builder_page_types = [
174 + 'all_products' => esc_html__( 'All Products', 'shopbuilder' ),
175 + 'product_cats' => esc_html__( 'Product Categories', 'shopbuilder' ),
176 + 'product_brands' => esc_html__( 'Product Brands', 'shopbuilder' ),
177 + 'product_tags' => esc_html__( 'Product Tags', 'shopbuilder' ),
178 + 'specific_products' => esc_html__( 'Selected Products', 'shopbuilder' ),
179 + ];
180 + // Only expose the brand option when the `product_brand` taxonomy is
181 + // registered (WC 9.4+ native, or a brand plugin). Hides gracefully
182 + // on sites without brand support.
183 + if ( ! taxonomy_exists( 'product_brand' ) ) {
184 + unset( $builder_page_types['product_brands'] );
185 + }
186 + foreach ( $builder_page_types as $key => $value ) {
187 + ?>
188 + <option <?php echo esc_attr( $key === $product_page_for ? 'selected="selected"' : '' ); ?> value="<?php echo esc_attr( $key ); ?>"> <?php echo esc_html( $value ); ?> </option>
189 + <?php } ?>
190 + </select>
191 + </div>
192 +
193 + <?php if ( ! rtsb()->has_pro() ) { ?>
194 + <div class="rtsb-product-page-for rtsb-tb-field-wraper" style="display:none;" >
195 + <label for="product_page_for"> </label>
196 + <span class="elementor-pro-notice"><a target="_blank" href="<?php echo esc_url( rtsb()->pro_version_link() ); ?>">Upgrade to PRO</a> to unlock Product Categories, Product Tags, Selected Products</span>
197 + </div>
198 + <?php } ?>
199 +
200 + <!-- Product Page For Categories -->
201 + <div class="rtsb-categories-page-field rtsb-product-page-for-the-categories rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
157 202 <?php
158 - $default_items = '';
159 - $product_id = get_post_meta( $post_id, BuilderFns::$product_template_meta, true );
160 - if ( $product_id ) {
161 - $default_items = '<option selected="selected" value="' . $product_id . '">' . get_the_title( $product_id ) . ' - ( ID ' . $product_id . ' )</option>';
203 + $default_items_link = '';
204 + $default_items = '';
205 + $categories_name = apply_filters( 'rtsb/template/builder/selected/categories', [], $post_id, $template_type );
206 + if ( ! empty( $categories_name ) && is_array( $categories_name ) ) {
207 + foreach ( $categories_name as $c_name ) {
208 + $cat = get_term_by( 'slug', $c_name, 'product_cat' );
209 + $title_cat = $cat->name;
210 + $link = get_term_link( $cat );
211 + if ( ! is_wp_error( $link ) ) {
212 + $default_items_link .= '<a target="_blank" href="' . get_term_link( $cat ) . '">' . $title_cat . '</a>';
213 + }
214 + $default_items .= '<option selected="selected" value="' . $c_name . '">' . $title_cat . '</option>';
215 + }
162 216 }
163 217 ?>
164 - <label for="rtsb_product_page_preview"><?php esc_html_e( 'Select Product For Preview', 'shopbuilder' ); ?></label>
165 - <select class="rtsb-field" id="rtsb_product_page_preview" name="rtsb_product_page_preview">
218 + <label for="rtsb_page_for_the_products">
219 + <?php esc_html_e( 'Select Product Categories', 'shopbuilder' ); ?>
220 + <?php if ( ! rtsb()->has_pro() ) { ?>
221 + <div class="card-label">
222 + <span class="rtsb-btn-import pro-btn">
223 + <?php echo esc_html( 'PRO' ); ?>
224 + </span>
225 + </div>
226 + <?php } ?>
227 + </label>
228 + <select class="rtsb-field" id="rtsb_page_for_the_categories" name="rtsb_page_for_the_categories" multiple="multiple">
166 229 <?php Fns::print_html( $default_items, true ); ?>
167 230 </select>
168 - <p style="margin:0;"> This Product is only used for preview And Elementor edit page. </p>
231 + <p style="margin:0;">Select a Product Category to apply this template. You can select multiple Categories. Keep it blank to apply to all Categories.
232 + <?php
233 + if ( ! empty( $default_items_link ) ) {
234 + ?>
235 + <span style="display: flex; gap: 3px 7px; flex-wrap: wrap; margin-top: 10px;"> <?php Fns::print_html( 'View Category Archive Pages: ' . $default_items_link ); ?> </span>
236 + <?php
237 + }
238 + ?>
239 + </p>
169 240 </div>
170 241
171 - <div class="rtsb-product-page-field rtsb-page-for-the-products rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
242 + <?php if ( ! rtsb()->has_pro() ) { ?>
243 + <div class="rtsb-categories-page-field rtsb-product-page-for-the-categories rtsb-tb-field-wraper" style="display:none;">
244 + <label for="product_page_for"> </label>
245 + <span class="elementor-pro-notice"><a target="_blank" href="<?php echo esc_url( rtsb()->pro_version_link() ); ?>">Upgrade to PRO</a> to unlock Categories Base Prodcut Page.</span>
246 + </div>
247 + <?php } ?>
248 +
249 + <!-- Product Page for Selected Product Tags-->
250 + <div class="rtsb-product-tags-page-field rtsb-product-page-for-the-tags rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
172 251 <?php
173 252 $default_items_link = '';
174 253 $default_items = '';
175 - $product_ids = apply_filters( 'rtsb/product/page/builder/selected/products', [], $post_id );
176 - if ( ! empty( $product_ids ) && is_array( $product_ids ) ) {
177 - foreach ( $product_ids as $p_id ) {
178 - $title = get_the_title( $p_id );
179 - $default_items_link .= '<a target="_blank" href="' . get_the_permalink( $p_id ) . '">' . $title . '</a>';
180 - $default_items .= '<option selected="selected" value="' . $p_id . '">' . $title . ' - ( ID ' . $p_id . ' )</option>';
254 + $tags_name = apply_filters( 'rtsb/template/builder/selected/tags', [], $post_id, $template_type );
255 + if ( ! empty( $tags_name ) && is_array( $tags_name ) ) {
256 + foreach ( $tags_name as $tg_name ) {
257 + $tag = get_term_by( 'slug', $tg_name, 'product_tag' );
258 + $title_tag = $tag->name;
259 + $link = get_term_link( $tag );
260 + if ( ! is_wp_error( $link ) ) {
261 + $default_items_link .= '<a target="_blank" href="' . get_term_link( $tag ) . '">' . $title_tag . '</a>';
262 + }
263 + $default_items .= '<option selected="selected" value="' . $tg_name . '">' . $title_tag . '</option>';
181 264 }
182 265 }
183 266 ?>
184 - <label for="rtsb_page_for_the_products "><?php esc_html_e( 'Layout For the Products ', 'shopbuilder' ); ?>
267 + <label for="rtsb_page_for_the_products_tags">
268 + <?php esc_html_e( 'Select Product Tags', 'shopbuilder' ); ?>
185 269 <?php if ( ! rtsb()->has_pro() ) { ?>
186 270 <div class="card-label">
187 271 <span class="rtsb-btn-import pro-btn">
188 272 <?php echo esc_html( 'PRO' ); ?>
@@ -189,34 +273,47 @@
189 273 </span>
190 274 </div>
191 275 <?php } ?>
192 276 </label>
193 - <select class="rtsb-field" id="rtsb_page_for_the_products" name="rtsb_page_for_the_products" multiple="multiple">
277 + <select class="rtsb-field" id="rtsb_page_for_the_products_tags" name="rtsb_page_for_the_products_tags" multiple="multiple">
194 278 <?php Fns::print_html( $default_items, true ); ?>
195 279 </select>
196 - <p style="margin:0;"> The Products Display in this layout. <span style="display:inline-flex; gap :10px"> <?php Fns::print_html( ! empty( $default_items_link ) ? 'Visit: ' . $default_items_link : '' ); ?> </span>
280 + <p style="margin:0;">Select a Product Tags to apply this template. You can select multiple Tags. Keep it blank to apply to All.
281 + <?php
282 + if ( ! empty( $default_items_link ) ) {
283 + ?>
284 + <span style="display: flex; gap: 3px 7px; flex-wrap: wrap; margin-top: 10px;"> <?php Fns::print_html( 'View Tags Archive Pages: ' . $default_items_link ); ?> </span>
285 + <?php
286 + }
287 + ?>
197 288 </p>
198 289 </div>
199 290
200 - <div class="rtsb-categories-page-field rtsb-page-for-the-categories rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
291 +
292 + <!-- Product Page for Selected Product Brands -->
293 + <?php if ( taxonomy_exists( 'product_brand' ) ) : ?>
294 + <div class="rtsb-product-brands-page-field rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
201 295 <?php
202 296 $default_items_link = '';
203 297 $default_items = '';
204 - $categories_name = apply_filters( 'rtsb/archive/page/builder/selected/categories', [], $post_id );
205 - if ( ! empty( $categories_name ) && is_array( $categories_name ) ) {
206 - foreach ( $categories_name as $c_name ) {
207 - $cat = get_term_by( 'slug', $c_name, 'product_cat' );
208 - $title = $cat->name;
209 - $link = get_term_link( $cat );
298 + $brands_name = apply_filters( 'rtsb/template/builder/selected/brands', [], $post_id, $template_type );
299 + if ( ! empty( $brands_name ) && is_array( $brands_name ) ) {
300 + foreach ( $brands_name as $b_name ) {
301 + $brand = get_term_by( 'slug', $b_name, 'product_brand' );
302 + if ( empty( $brand ) || is_wp_error( $brand ) ) {
303 + continue;
304 + }
305 + $title_brand = $brand->name;
306 + $link = get_term_link( $brand );
210 307 if ( ! is_wp_error( $link ) ) {
211 - $default_items_link .= '<a target="_blank" href="' . get_term_link( $cat ) . '">' . $title . '</a>';
308 + $default_items_link .= '<a target="_blank" href="' . esc_url( $link ) . '">' . esc_html( $title_brand ) . '</a>';
212 309 }
213 - $default_items .= '<option selected="selected" value="' . $c_name . '">' . $title . '</option>';
310 + $default_items .= '<option selected="selected" value="' . esc_attr( $b_name ) . '">' . esc_html( $title_brand ) . '</option>';
214 311 }
215 312 }
216 313 ?>
217 - <label for="rtsb_page_for_the_products">
218 - <?php esc_html_e( 'Layout For the Products categories', 'shopbuilder' ); ?>
314 + <label for="rtsb_page_for_the_product_brands">
315 + <?php esc_html_e( 'Select Product Brands', 'shopbuilder' ); ?>
219 316 <?php if ( ! rtsb()->has_pro() ) { ?>
220 317 <div class="card-label">
221 318 <span class="rtsb-btn-import pro-btn">
222 319 <?php echo esc_html( 'PRO' ); ?>
@@ -223,15 +320,88 @@
223 320 </span>
224 321 </div>
225 322 <?php } ?>
226 323 </label>
227 - <select class="rtsb-field" id="rtsb_page_for_the_categories" name="rtsb_page_for_the_categories" multiple="multiple">
324 + <select class="rtsb-field" id="rtsb_page_for_the_product_brands" name="rtsb_page_for_the_product_brands" multiple="multiple">
228 325 <?php Fns::print_html( $default_items, true ); ?>
229 326 </select>
230 - <p style="margin:0;"> The Product Categories Display in this layout. <span style="display:inline-flex; gap :10px"> <?php Fns::print_html( ! empty( $default_items_link ) ? 'Visit: ' . $default_items_link : '' ); ?> </span>
327 + <p style="margin:0;">Select a Product Brand to apply this template. You can select multiple Brands. Keep it blank to apply to all.
328 + <?php
329 + if ( ! empty( $default_items_link ) ) {
330 + ?>
331 + <span style="display: flex; gap: 3px 7px; flex-wrap: wrap; margin-top: 10px;"> <?php Fns::print_html( 'View Brand Archive Pages: ' . $default_items_link ); ?> </span>
332 + <?php
333 + }
334 + ?>
231 335 </p>
232 336 </div>
233 337
338 + <?php if ( ! rtsb()->has_pro() ) { ?>
339 + <div class="rtsb-product-brands-page-field rtsb-tb-field-wraper" style="display:none;">
340 + <label for="product_page_for"> </label>
341 + <span class="elementor-pro-notice"><a target="_blank" href="<?php echo esc_url( rtsb()->pro_version_link() ); ?>">Upgrade to PRO</a> to unlock Brand Base Product Page.</span>
342 + </div>
343 + <?php } ?>
344 + <?php endif; ?>
345 +
346 + <?php do_action( 'rtsb/builder/modal/extra_fields', $post_id, $template_type, $product_page_for ); ?>
347 +
348 + <!-- Product Page for Selected Product -->
349 + <div class="rtsb-page-for-the-products rtsb-tb-field-wraper <?php echo esc_attr( ! rtsb()->has_pro() ? 'pro-disable' : '' ); ?>" style="display:none;">
350 + <?php
351 + $default_items_link = '';
352 + $default_items = '';
353 + $product_ids = apply_filters( 'rtsb/product/page/builder/selected/products', [], $post_id );
354 + if ( ! empty( $product_ids ) && is_array( $product_ids ) ) {
355 + foreach ( $product_ids as $p_id ) {
356 + $p_title = get_the_title( $p_id );
357 + $default_items_link .= '<a target="_blank" href="' . get_the_permalink( $p_id ) . '">' . $p_title . '</a>';
358 + $default_items .= '<option selected="selected" value="' . $p_id . '">' . $p_title . ' - ( ID ' . $p_id . ' )</option>';
359 + }
360 + }
361 + ?>
362 + <label for="rtsb_page_for_the_products "><?php esc_html_e( 'Select Products ', 'shopbuilder' ); ?>
363 + <?php if ( ! rtsb()->has_pro() ) { ?>
364 + <div class="card-label">
365 + <span class="rtsb-btn-import pro-btn">
366 + <?php echo esc_html( 'PRO' ); ?>
367 + </span>
368 + </div>
369 + <?php } ?>
370 + </label>
371 + <select class="rtsb-field" id="rtsb_page_for_the_products" name="rtsb_page_for_the_products" multiple="multiple">
372 + <?php Fns::print_html( $default_items, true ); ?>
373 + </select>
374 + <p style="margin:0;">Select a Product to apply this template. You can select multiple Products. Keep it blank to apply to all Products.
375 + <?php
376 + if ( ! empty( $default_items_link ) ) {
377 + ?>
378 + <span style="display: flex; gap: 3px 7px; flex-wrap: wrap; margin-top: 10px;"> <?php Fns::print_html( 'View Product Pages: ' . $default_items_link ); ?> </span>
379 + <?php
380 + }
381 + ?>
382 + </p>
383 + </div>
384 +
385 + <div class="rtsb-product-page-preview-field rtsb-tb-field-wraper" style="display:none;">
386 + <?php
387 + $default_items = '';
388 + $product_id = get_post_meta( $post_id, BuilderFns::$product_template_meta, true );
389 + if ( $product_id && get_post_status( $product_id ) ) {
390 + $default_items = '<option selected="selected" value="' . $product_id . '">' . get_the_title( $product_id ) . ' - ( ID ' . $product_id . ' )</option>';
391 + }
392 + if ( $product_id && ! get_post_status( $product_id ) ) {
393 + delete_post_meta( $post_id, BuilderFns::$product_template_meta );
394 + }
395 + ?>
396 + <label for="rtsb_product_page_preview"><?php esc_html_e( 'Select Preview Product', 'shopbuilder' ); ?></label>
397 + <select class="rtsb-field" id="rtsb_product_page_preview" name="rtsb_product_page_preview">
398 + <?php Fns::print_html( $default_items, true ); ?>
399 + </select>
400 + <p style="margin:0;">Select a Product for preview and Elementor editing purposes only.</p>
401 + </div>
402 +
403 +
234 404 <div class="rtsb-template-edit-with rtsb-tb-field-wraper">
235 405 <label for="rtsb_tb_template_edit_with"><?php esc_html_e( 'Select Editor Type', 'shopbuilder' ); ?></label>
236 406 <select class="rtsb-field" id="rtsb_tb_template_edit_with" name="rtsb_tb_template_edit_with"
237 407 required>
@@ -242,33 +412,65 @@
242 412 </div>
243 413 <div class="rtsb-template-setdefaults rtsb-tb-field-wraper">
244 414 <label for="default_template"> <?php esc_html_e( 'Set as Active Template', 'shopbuilder' ); ?></label>
245 415 <?php
416 + $singleton_types = apply_filters(
417 + 'rtsb/builder/singleton_types',
418 + array_keys( BuilderFns::builder_page_types() )
419 + );
420 + $is_pool_type = $template_type && ! in_array( $template_type, $singleton_types, true );
421 + if ( $post_id && $is_pool_type ) {
422 + $template_default = 'on' === get_post_meta( $post_id, '_rtsb_tb_enabled_in_pool', true ) ? $post_id : 0;
423 + }
246 424 if ( $post_id && 'product' === $template_type ) {
247 - $product_ids = apply_filters( 'rtsb/product/page/builder/selected/products', [], $post_id );
248 - $set_default = BuilderFns::get_specific_product_as_default( $post_id );
249 - if ( ! empty( $product_ids ) && $set_default ) {
250 - $template_default = $post_id;
425 + if ( 'specific_products' === $product_page_for ) {
426 + $set_default = BuilderFns::get_specific_product_as_default( $post_id );
427 + if ( $set_default ) {
428 + $template_default = $post_id;
429 + }
430 + if ( ! $set_default && $template_default === $post_id ) {
431 + $template_default = '';
432 + }
433 + } else {
434 + $set_default_option_name = '';
435 + if ( 'product_cats' === $product_page_for ) {
436 + $set_default_option_name = BuilderFns::option_name_product_page_specific_cat_set_default( $post_id );
437 + } elseif ( 'product_tags' === $product_page_for ) {
438 + $set_default_option_name = BuilderFns::option_name_product_page_specific_tag_set_default( $post_id );
439 + } elseif ( 'product_brands' === $product_page_for ) {
440 + $set_default_option_name = BuilderFns::option_name_product_page_specific_brand_set_default( $post_id );
441 + }
442 + $default_id = ! empty( $set_default_option_name ) && TemplateSettings::instance()->get_option( $set_default_option_name );
443 + if ( $default_id ) {
444 + $template_default = $post_id;
445 + }
251 446 }
252 447 } elseif ( $post_id && 'archive' === $template_type ) {
253 - $categories_name = apply_filters( 'rtsb/archive/page/builder/selected/categories', [], $post_id );
448 + $categories_name = apply_filters( 'rtsb/template/builder/selected/categories', [], $post_id, $template_type );
254 449 $set_default = BuilderFns::get_specific_category_as_default( $post_id );
255 450 if ( ! empty( $categories_name ) && $set_default ) {
256 451 $template_default = $post_id;
452 + } else {
453 + $option_name = BuilderFns::option_name( $template_type );
454 + $is_set_default = TemplateSettings::instance()->get_option( $option_name );
455 + $set_default = $is_set_default;
257 456 }
457 + if ( ! $set_default && $template_default === $post_id ) {
458 + $template_default = '';
459 + }
258 460 }
259 461
462 + $template_default = apply_filters( 'rtsb/builder/modal/template_default', $template_default, $post_id, $template_type );
260 463 ?>
261 464 <span class="rtsb-switch-wrapper"
262 - title="<?php esc_html_e( 'Only publish post can set default ', 'shopbuilder' ); ?>">
465 + title="<?php esc_html_e( 'Switch on to set as active template', 'shopbuilder' ); ?>">
263 466 <label class="rtsb-switch">
264 467 <input class="rtsb_set_default rtsb-field"
265 468 type="checkbox"
266 469 id="default_template"
267 - class="rtsb-field"
268 470 name="default_template"
269 471 value="default_template"
270 - <?php echo esc_attr( ( $post_id && absint( $post_id ) === absint( $template_default ) ) ? 'checked' : '' ); ?>
472 + <?php echo esc_attr( ( $post_id && ( absint( $post_id ) === absint( $template_default ) ) ) ? 'checked' : '' ); ?>
271 473 >
272 474 <span class="rtsb-slider rtsb-round ">
273 475 <span class="rtsb-loader"></span>
274 476 </span>
@@ -275,32 +477,29 @@
275 477 </label>
276 478 </span>
277 479 </div>
278 480 <!-- TODO: Moday Layout -->
279 - <?php if ( ! $post_id ) { ?>
280 - <div class="set-default-layout-wrapper rtsb-tb-field-wraper">
281 - <label>
282 - <?php esc_html_e( 'Pre-built Templates ', 'shopbuilder' ); ?>
283 - <span id="modallabelPrefix"></span>
284 - </label>
285 - <div class="set-default-layout">
286 - <?php
287 - $default_item = [
288 - 'template_type' => 'default',
289 - 'image_url' => \Elementor\Utils::get_placeholder_image_src(),
290 - 'preview_link' => '',
291 - 'title' => __( 'Blank Template', 'shopbuilder' ),
292 - ];
293 -
294 - $this->get_modal_card_html( $default_item );
295 -
296 - if ( ! empty( $layoutData['layouts'] ) ) {
297 - foreach ( $layoutData['layouts'] as $item ) {
298 - $this->get_modal_card_html( $item );
299 - }
300 - }
301 - ?>
481 + <?php
482 + if ( ! $post_id ) {
483 + if ( defined( 'ELEMENTOR_PATH' ) && class_exists( '\Elementor\Utils' ) ) {
484 + $placeholderImageSrc = \Elementor\Utils::get_placeholder_image_src();
485 + } else {
486 + $placeholderImageSrc = '#';
487 + }
488 + ?>
489 + <div class="set-default-layout-wrapper rtsb-tb-field-wraper" style="opacity: 0" >
490 + <div style="display: flex; justify-content: space-between;">
491 + <label>
492 + <?php esc_html_e( 'Pre-built Templates ', 'shopbuilder' ); ?>
493 + <span id="modallabelPrefix"></span>
494 + </label>
495 + <div class="rtsb-tb-button-wrapper">
496 + <a class="btn" href="https://shopbuilderwp.com/themes/" target="_blank" style="opacity: 1; visibility: visible;">View Out Themes</a>
497 + </div>
302 498 </div>
499 + <div class="set-default-layout" data-has-pro="<?php echo esc_attr( rtsb()->has_pro() ); ?>" data-rest-url="<?php echo esc_url( rtsb()->BASE_API ); ?>" data-placeholder-image-src="<?php echo esc_url( $placeholderImageSrc ); ?>">
500 + <!-- Layout Will Add Via Ajax-->
501 + </div>
303 502 </div>
304 503 <?php } ?>
305 504 <input type="hidden" id="page_id" name="page_id" value="<?php echo esc_attr( $post_id ); ?>">
306 505 </div>
@@ -338,55 +537,20 @@
338 537 wp_send_json( $return );
339 538 wp_die();
340 539 }
341 540
342 - public function default_layout_template_html( $key, $is_checked, $builder, $value = [] ) {
343 - $layout_type = $key . ( $builder ? '_' . $builder : null );
344 - ?>
345 - <!-- Elementor -->
346 - <label class="layout-container type-<?php echo esc_attr( $key ); ?>"
347 - data-layout-type='<?php echo esc_attr( $layout_type ); ?>'>
348 - <input <?php echo esc_attr( $is_checked ); ?>
349 - class="rtsb-field" type="radio"
350 - value="<?php echo ! empty( $value['import_file'] ) ? esc_attr( $value['import_file'] ) : ''; ?>"
351 - name="import_default_layout"/>
352 -
353 - <span class="checkmark dashicons"></span>
354 - <div class="image-wrapper">
355 - <?php if ( ! empty( $value['image'] ) ) { ?>
356 - <img src="<?php echo esc_url( $value['image'] ); ?>" alt="">
357 - <?php } ?>
358 - </div>
359 - <?php if ( ! empty( $value['text_label'] ) ) { ?>
360 - <div class="image-label">
361 - <span class="label-text"><?php echo esc_html( $value['text_label'] ); ?></span>
362 - <?php if ( ! empty( $value['live_preview'] ) ) { ?>
363 - <a target="_blank" class="btn-live-preview" href="<?php echo esc_url( $value['live_preview'] ); ?>">
364 - <span class="dashicons dashicons-visibility"></span>
365 - <?php esc_html_e( 'Live Preview', 'shopbuilder' ); ?>
366 - </a>
367 - <?php } ?>
368 - </div>
369 - <?php } ?>
370 - </label>
371 - <?php
372 - }
373 -
374 541 /**
375 542 * Get Modal Card Markup.
376 543 *
377 - * @param $item
378 - * @param $checked
544 + * @param array $item Item.
379 545 *
380 546 * @return void
381 547 */
382 548 public function get_modal_card_html( $item ) {
383 -
384 549 ?>
385 550 <div class="layout-container rtsb-template-item type-<?php echo esc_attr( $item['template_type'] ); ?>"
386 551 data-layout-type='<?php echo esc_attr( $item['template_type'] ); ?>'>
387 552 <input class="rtsb-field" type="hidden" value="<?php echo esc_attr( $item['id'] ?? '' ); ?>" name="import_default_layout"/>
388 -
389 553 <div class="image-wrapper">
390 554 <?php if ( $item['image_url'] ) : ?>
391 555 <img src="<?php echo esc_url( $item['image_url'] ); ?>" alt="<?php echo esc_attr( $item['title'] ); ?>">
392 556 <?php endif; ?>
@@ -391,9 +555,10 @@
391 555 <img src="<?php echo esc_url( $item['image_url'] ); ?>" alt="<?php echo esc_attr( $item['title'] ); ?>">
392 556 <?php endif; ?>
393 557
394 558 <?php if ( 'default' != $item['template_type'] && ( ! rtsb()->has_pro() ) ) : ?>
395 - <div class="card-label">
559 + <div class="card-label lllllll">
560 + label
396 561 <span class="rtsb-btn-import <?php echo esc_attr( $item['status'] ?? 'free' ); ?>-btn">
397 562 <?php echo esc_html( $item['status'] ?? 'Free' ); ?>
398 563 </span>
399 564 </div>
@@ -411,9 +576,12 @@
411 576 <?php echo esc_html__( 'Preview', 'shopbuilder' ); ?>
412 577 </a>
413 578
414 579
415 - <?php if ( rtsb()->has_pro() || $item['status'] == 'free' ) : ?>
580 + <?php
581 + // phpcs:ignore WordPress.PHP.YodaConditions.NotYoda
582 + if ( rtsb()->has_pro() || $item['status'] == 'free' ) :
583 + ?>
416 584 <a class="rtsb-btn-import import-btn rtsb-import-layout">
417 585 <svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
418 586 <path d="M11 12.2295C10.9048 12.2296 10.8106 12.2113 10.7226 12.1757C10.6347 12.14 10.5547 12.0878 10.4874 12.0219C10.4201 11.956 10.3668 11.8778 10.3304 11.7917C10.294 11.7056 10.2753 11.6134 10.2754 11.5202L10.2754 0.912773C10.2754 0.72466 10.3517 0.544251 10.4876 0.411235C10.6235 0.278219 10.8078 0.203491 11 0.203491C11.1922 0.203491 11.3765 0.278219 11.5124 0.411235C11.6483 0.544251 11.7246 0.72466 11.7246 0.912773L11.7246 11.5202C11.7246 11.7083 11.6483 11.8887 11.5124 12.0218C11.3765 12.1548 11.1922 12.2295 11 12.2295Z"
419 587 fill="white"></path>
@@ -488,30 +656,33 @@
488 656 'content' => esc_html__( 'Empty string Not allowed...', 'shopbuilder' ),
489 657 ];
490 658 wp_send_json( $return );
491 659 }
492 - $query = $wpdb->prepare(
493 - "SELECT ID, post_title
494 - FROM $wpdb->posts
495 - WHERE post_type = 'product'
496 - AND post_status = 'publish'
497 - AND post_title LIKE %s
660 + /** @noinspection SqlNoDataSourceInspection */
661 + /** @noinspection SqlResolve */
662 + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
663 + $query = $wpdb->prepare(
664 + "SELECT ID, post_title
665 + FROM $wpdb->posts
666 + WHERE post_type = 'product'
667 + AND post_status = 'publish'
668 + AND post_title LIKE %s
498 669 LIMIT %d",
499 670 '%' . $search . '%',
500 671 10
501 672 );
502 -
503 - $_product = wp_cache_get( md5( $query ), 'rtsb-product-query' );
673 + $cache_key = md5( $query );
674 + $_product = wp_cache_get( $cache_key, 'shopbuilder' );
504 675 if ( false === $_product ) {
505 676 $_product = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
506 - wp_cache_set( md5( $query ), $_product, 'rtsb-product-query' );
677 + wp_cache_set( $cache_key, $_product, 'shopbuilder' );
678 + Cache::set_data_cache_key( $cache_key );
507 679 }
508 -
509 680 $product_list = [];
510 681 foreach ( $_product as $product ) {
511 682 $product_list['items'][] = [
512 683 'id' => $product->ID,
513 - 'text' => $product->post_title . ' - ( ID ' . $product->ID . ' )',
684 + 'text' => html_entity_decode( $product->post_title, ENT_QUOTES | ENT_HTML5 ) . ' - (ID#' . $product->ID . ')',
514 685 ];
515 686 }
516 687
517 688 wp_send_json_success( $product_list );
@@ -522,9 +693,9 @@
522 693 * Popups For Create Template
523 694 *
524 695 * @return void
525 696 */
526 - public function category_search() {
697 + public function term_search() {
527 698
528 699 if ( ! wp_verify_nonce( Fns::get_nonce(), rtsb()->nonceText ) ) {
529 700 $return = [
530 701 'success' => false,
@@ -540,17 +711,24 @@
540 711 ];
541 712 wp_send_json( $return );
542 713 }
543 714
544 - $search = isset( $_REQUEST['search'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Missing
545 - $args = [
546 - 'taxonomy' => [ 'product_cat' ], // taxonomy name
715 + $search = isset( $_REQUEST['search'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Missing
716 + $taxonomy = isset( $_REQUEST['taxonomy'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['taxonomy'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Missing
717 + if ( ! $taxonomy ) {
718 + $return = [
719 + 'success' => false,
720 + 'content' => esc_html__( 'Invalid taxonomy', 'shopbuilder' ),
721 + ];
722 + wp_send_json( $return );
723 + }
724 + $args = [
725 + 'taxonomy' => [ $taxonomy ], // taxonomy name.
547 726 'orderby' => 'name',
548 727 'order' => 'ASC',
549 728 'hide_empty' => false,
550 729 'name__like' => $search,
551 730 ];
552 -
553 731 $terms = get_terms( $args );
554 732 $count = count( $terms );
555 733 $term_list = [];
556 734 if ( $count > 0 ) {
@@ -556,9 +734,9 @@
556 734 if ( $count > 0 ) {
557 735 foreach ( $terms as $term ) {
558 736 $term_list['items'][] = [
559 737 'id' => $term->slug,
560 - 'text' => $term->name,
738 + 'text' => html_entity_decode( $term->name, ENT_QUOTES | ENT_HTML5 ),
561 739 ];
562 740 }
563 741 }
564 742 wp_send_json_success( $term_list );