PluginProbe
Blocks – Reusable Content, Shortcodes & Site Variables / trunk
Blocks – Reusable Content, Shortcodes & Site Variables vtrunk
26.09.03.15 26.08.31.21 26.08.22.20 26.08.22.22 26.08.22.17 26.08.22.13 26.08.21.19 26.08.07.23 26.07.19.14 26.07.13.21 26.07.13.17 26.07.12.13 026.07.07.21 026.07.05.18 026.06.26.20 026.06.26.21 026.06.08.20 026.05.13.14 026.04.29.10 trunk 026.02.22.22 026.03.16.23 026.04.23.13
blocks / includes / admin / blocks-admin-actions.php

blocks-admin-actions.php in Blocks – Reusable Content, Shortcodes & Site Variables trunk, at includes/admin/blocks-admin-actions.php

375 lines 14.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Blocks
4 * @license GPL-2.0-or-later
5 */
6
7 defined( 'ABSPATH' ) || exit;
8
9 function blocks_handle_save_action() {
10 if ( ! isset( $_POST['post_ID'] ) ) {
11 wp_die( esc_html__( 'Missing required data.', 'blocks' ) );
12 }
13
14 $id = (int) $_POST['post_ID'];
15 check_admin_referer( 'blocks-save-cms-block_' . $id );
16
17 if ( ! current_user_can( 'blocks_edit_cms_block', $id ) ) {
18 wp_die( esc_html__( 'You are not allowed to edit this item.', 'blocks' ) );
19 }
20
21 $id = blocks_save( $id );
22
23 $query = array(
24 'message' => ( -1 === absint( $_POST['post_ID'] ) ) ? 'created' : 'saved',
25 'post' => $id,
26 'active-tab' => isset( $_POST['active-tab'] ) ? absint( $_POST['active-tab'] ) : 0,
27 );
28
29 wp_safe_redirect( add_query_arg( $query, menu_page_url( 'block', false ) ) );
30 exit();
31 }
32
33 function blocks_handle_copy_action() {
34 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Recommended -- absint handles sanitization, nonce checked below.
35 $id = empty( $_POST['post_ID'] )
36 ? ( isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : 0 )
37 : absint( $_POST['post_ID'] );
38 // phpcs:enable
39
40 check_admin_referer( 'blocks-copy-cms-block_' . $id );
41
42 if ( ! current_user_can( 'blocks_edit_cms_block', $id ) ) {
43 wp_die( esc_html__( 'You are not allowed to edit this item.', 'blocks' ) );
44 }
45
46 $query = array();
47
48 $cms_block = Blocks::get_instance( $id );
49 if ( $cms_block ) {
50 $new_cms_block = $cms_block->copy();
51 $new_cms_block->save();
52 $query['post'] = $new_cms_block->id();
53 $query['message'] = 'created';
54 }
55
56 wp_safe_redirect( add_query_arg( $query, menu_page_url( 'block', false ) ) );
57 exit();
58 }
59
60 function blocks_handle_delete_action() {
61 if ( ! empty( $_POST['post_ID'] ) ) {
62 check_admin_referer( 'blocks-delete-cms-block_' . absint( $_POST['post_ID'] ) ); // nosemgrep -- absint() casts to non-negative int; nonce action string, no SQL involved.
63 } elseif ( isset( $_REQUEST['post'] ) && ! is_array( $_REQUEST['post'] ) ) {
64 check_admin_referer( 'blocks-delete-cms-block_' . absint( $_REQUEST['post'] ) ); // nosemgrep -- absint() casts to non-negative int; nonce action string, no SQL involved.
65 } else {
66 check_admin_referer( 'bulk-posts' );
67 }
68
69 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- absint() via array_map sanitizes all values.
70 $posts = ! empty( $_POST['post_ID'] )
71 ? array_map( 'absint', (array) wp_unslash( $_POST['post_ID'] ) )
72 : ( isset( $_REQUEST['post'] ) ? array_map( 'absint', (array) wp_unslash( $_REQUEST['post'] ) ) : array() );
73
74 $deleted = 0;
75
76 foreach ( $posts as $post ) {
77 $post = Blocks::get_instance( absint( $post ) );
78
79 if ( empty( $post ) ) {
80 continue;
81 }
82
83 if ( ! current_user_can( 'blocks_delete_cms_block', $post->id() ) ) {
84 wp_die( esc_html__( 'You are not allowed to delete this item.', 'blocks' ) );
85 }
86
87 if ( ! $post->delete() ) {
88 wp_die( esc_html__( 'Error in deleting.', 'blocks' ) );
89 }
90
91 ++$deleted;
92 }
93
94 $query = array();
95 if ( ! empty( $deleted ) ) {
96 $query['message'] = 'deleted';
97 }
98
99 wp_safe_redirect( add_query_arg( $query, menu_page_url( 'block', false ) ) );
100 exit();
101 }
102
103 function blocks_current_action() {
104 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Just reading action parameter.
105 if ( isset( $_REQUEST['action'] ) && -1 !== $_REQUEST['action'] ) {
106 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
107 return sanitize_key( $_REQUEST['action'] );
108 }
109 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
110 if ( isset( $_REQUEST['action2'] ) && -1 !== $_REQUEST['action2'] ) {
111 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
112 return sanitize_key( $_REQUEST['action2'] );
113 }
114 return false;
115 }
116
117 /**
118 * Process block properties from POST data.
119 *
120 * @param array $existing_properties Existing properties.
121 * @return array Processed properties.
122 */
123 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in blocks_handle_save_action before calling this.
124 function blocks_process_properties( $existing_properties ) {
125 $properties = $existing_properties;
126
127 $properties['wsbenvolver'] = isset( $_POST['blocks-wsbenvolver'] )
128 ? absint( $_POST['blocks-wsbenvolver'] ) : 0;
129
130 $properties['wsbautop'] = isset( $_POST['blocks-wsbautop'] )
131 ? absint( $_POST['blocks-wsbautop'] ) : 0;
132
133 $properties['wsbtipoenvol'] = isset( $_POST['blocks-wsbtipoenvol'] )
134 ? absint( $_POST['blocks-wsbtipoenvol'] ) : 1;
135
136 $properties['wsbclaseenvol'] = '';
137 if ( isset( $_POST['blocks-wsbclaseenvol'] ) ) {
138 $classes = sanitize_text_field( wp_unslash( $_POST['blocks-wsbclaseenvol'] ) );
139 $class_array = array_filter( array_map( 'sanitize_html_class', explode( ' ', $classes ) ) );
140 $properties['wsbclaseenvol'] = implode( ' ', $class_array );
141 }
142
143 $properties['wsbtabvisual'] = isset( $_POST['blocks-wsbtabvisual'] )
144 ? absint( $_POST['blocks-wsbtabvisual'] ) : 0;
145
146 $properties['visibility'] = isset( $_POST['blocks-visibility'] )
147 ? sanitize_text_field( wp_unslash( $_POST['blocks-visibility'] ) ) : 'all';
148
149 $properties['popup_enabled'] = isset( $_POST['blocks-popup-enabled'] )
150 ? absint( $_POST['blocks-popup-enabled'] ) : 0;
151
152 $properties['popup_delay'] = isset( $_POST['blocks-popup-delay'] )
153 ? absint( $_POST['blocks-popup-delay'] ) : 5;
154
155 $properties['popup_scroll'] = isset( $_POST['blocks-popup-scroll'] )
156 ? absint( $_POST['blocks-popup-scroll'] ) : 50;
157
158 $properties['popup_cookie'] = isset( $_POST['blocks-popup-cookie'] )
159 ? absint( $_POST['blocks-popup-cookie'] ) : 7;
160
161 $properties['popup_close_delay'] = isset( $_POST['blocks-popup-close-delay'] )
162 ? (float) $_POST['blocks-popup-close-delay'] : 5.5;
163
164 $properties['popup_overlay_color'] = isset( $_POST['blocks-popup-overlay-color'] )
165 ? sanitize_hex_color( wp_unslash( $_POST['blocks-popup-overlay-color'] ) ) : '#000000';
166
167 $properties['popup_overlay_opacity'] = isset( $_POST['blocks-popup-overlay-opacity'] )
168 ? max( 0, min( 1, (float) $_POST['blocks-popup-overlay-opacity'] ) ) : 0.8;
169
170 $properties['popup_close_button'] = isset( $_POST['blocks-popup-close-button'] )
171 ? absint( $_POST['blocks-popup-close-button'] ) : 0;
172
173 $properties['popup_close_overlay'] = isset( $_POST['blocks-popup-close-overlay'] )
174 ? absint( $_POST['blocks-popup-close-overlay'] ) : 0;
175
176 $properties['popup_close_escape'] = isset( $_POST['blocks-popup-close-escape'] )
177 ? absint( $_POST['blocks-popup-close-escape'] ) : 0;
178
179 // Banner settings.
180 $properties['banner_enabled'] = isset( $_POST['blocks-banner-enabled'] )
181 ? absint( $_POST['blocks-banner-enabled'] ) : 0;
182
183 $properties['banner_position'] = isset( $_POST['blocks-banner-position'] )
184 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-position'] ) ) : 'bottom';
185
186 $properties['banner_bg_color'] = isset( $_POST['blocks-banner-bg-color'] )
187 ? sanitize_hex_color( wp_unslash( $_POST['blocks-banner-bg-color'] ) ) : '#1e3a5f';
188
189 $properties['banner_text_color'] = isset( $_POST['blocks-banner-text-color'] )
190 ? sanitize_hex_color( wp_unslash( $_POST['blocks-banner-text-color'] ) ) : '#ffffff';
191
192 $properties['banner_dismissible'] = isset( $_POST['blocks-banner-dismissible'] )
193 ? absint( $_POST['blocks-banner-dismissible'] ) : 0;
194
195 $properties['banner_cookie'] = isset( $_POST['blocks-banner-cookie'] )
196 ? absint( $_POST['blocks-banner-cookie'] ) : 7;
197
198 $properties['banner_sticky'] = isset( $_POST['blocks-banner-sticky'] )
199 ? absint( $_POST['blocks-banner-sticky'] ) : 0;
200
201 $properties['banner_padding'] = isset( $_POST['blocks-banner-padding'] )
202 ? absint( $_POST['blocks-banner-padding'] ) : 12;
203
204 $properties['banner_font_size'] = isset( $_POST['blocks-banner-font-size'] )
205 ? absint( $_POST['blocks-banner-font-size'] ) : 14;
206
207 $properties['banner_bg_opacity'] = isset( $_POST['blocks-banner-bg-opacity'] )
208 ? max( 0, min( 1, (float) $_POST['blocks-banner-bg-opacity'] ) ) : 0.8;
209
210 $properties['banner_bg_blur'] = isset( $_POST['blocks-banner-bg-blur'] )
211 ? max( 0, min( 20, absint( $_POST['blocks-banner-bg-blur'] ) ) ) : 6;
212
213 // Countdown timer settings.
214 $properties['banner_countdown_enabled'] = isset( $_POST['blocks-banner-countdown-enabled'] )
215 ? absint( $_POST['blocks-banner-countdown-enabled'] ) : 0;
216
217 $properties['banner_countdown_end'] = isset( $_POST['blocks-banner-countdown-end'] )
218 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-countdown-end'] ) ) : '';
219
220 $properties['banner_countdown_label'] = isset( $_POST['blocks-banner-countdown-label'] )
221 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-countdown-label'] ) ) : __( 'Ends in:', 'blocks' );
222
223 // Product dropdown settings.
224 $properties['banner_product_id'] = isset( $_POST['blocks-banner-product-id'] )
225 ? absint( $_POST['blocks-banner-product-id'] ) : '';
226
227 // Handle variation IDs - can come as array from checkboxes or as comma-separated string.
228 if ( isset( $_POST['blocks-banner-variation-ids'] ) ) {
229 $variation_ids = wp_unslash( $_POST['blocks-banner-variation-ids'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized per-type below.
230 if ( is_array( $variation_ids ) ) {
231 $variation_ids = array_map( 'absint', $variation_ids );
232 $variation_ids = array_filter( $variation_ids );
233 $properties['banner_variation_ids'] = implode( ',', $variation_ids );
234 } else {
235 $properties['banner_variation_ids'] = sanitize_text_field( wp_unslash( $variation_ids ) );
236 }
237 } else {
238 $properties['banner_variation_ids'] = '';
239 }
240
241 $properties['banner_button_text'] = isset( $_POST['blocks-banner-button-text'] )
242 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-button-text'] ) ) : __( 'Shop Now', 'blocks' );
243
244 $properties['banner_button_style'] = isset( $_POST['blocks-banner-button-style'] )
245 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-button-style'] ) ) : 'rainbow-shimmer';
246
247 $properties['banner_discount'] = isset( $_POST['blocks-banner-discount'] )
248 ? max( 5, min( 90, absint( $_POST['blocks-banner-discount'] ) ) ) : 35;
249
250 $valid_expiry = array( '30M', '1H', '2H', '3H', '24H' );
251 $properties['banner_expiry'] = isset( $_POST['blocks-banner-expiry'] ) && in_array( $_POST['blocks-banner-expiry'], $valid_expiry, true )
252 ? sanitize_text_field( wp_unslash( $_POST['blocks-banner-expiry'] ) ) : '2H';
253
254 if ( isset( $_POST['blocks-form'] ) ) {
255 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_kses_post handles sanitization.
256 $content = wp_unslash( $_POST['blocks-form'] );
257
258 if ( ! current_user_can( 'unfiltered_html' ) ) {
259 $content = wp_kses_post( $content );
260 }
261
262 $properties['form'] = $content;
263 }
264
265 return $properties;
266 }
267 // phpcs:enable WordPress.Security.NonceVerification.Missing
268
269 /**
270 * Save taxonomy terms for a block.
271 *
272 * @param int $post_id Post ID.
273 */
274 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in blocks_handle_save_action before calling this.
275 function blocks_save_taxonomies( $post_id ) {
276 $term_ids = array();
277
278 if ( ! empty( $_POST['new_category_name'] ) ) {
279 $new_cat_name = sanitize_text_field( wp_unslash( $_POST['new_category_name'] ) );
280 $new_term = wp_insert_term( $new_cat_name, 'blocks_category' );
281 if ( ! is_wp_error( $new_term ) ) {
282 $term_ids[] = $new_term['term_id'];
283 }
284 }
285
286 if ( isset( $_POST['blocks_category_new'] ) && is_array( $_POST['blocks_category_new'] ) ) {
287 $new_categories = array_map( 'sanitize_text_field', wp_unslash( $_POST['blocks_category_new'] ) );
288 foreach ( $new_categories as $new_cat_name ) {
289 if ( ! empty( $new_cat_name ) ) {
290 $existing = term_exists( $new_cat_name, 'blocks_category' );
291 if ( $existing ) {
292 $term_ids[] = $existing['term_id'];
293 } else {
294 $new_term = wp_insert_term( $new_cat_name, 'blocks_category' );
295 if ( ! is_wp_error( $new_term ) ) {
296 $term_ids[] = $new_term['term_id'];
297 }
298 }
299 }
300 }
301 }
302
303 if ( isset( $_POST['blocks_category'] ) && is_array( $_POST['blocks_category'] ) ) {
304 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- absint handles sanitization.
305 $existing_term_ids = array_map( 'absint', $_POST['blocks_category'] );
306 $term_ids = array_merge( $term_ids, $existing_term_ids );
307 }
308
309 wp_set_post_terms( $post_id, array_unique( $term_ids ), 'blocks_category' );
310
311 if ( isset( $_POST['blocks_tags'] ) ) {
312 $tags_input = sanitize_text_field( wp_unslash( $_POST['blocks_tags'] ) );
313 $tags_array = array_map( 'trim', explode( ',', $tags_input ) );
314 $tags_array = array_filter( $tags_array );
315 wp_set_post_terms( $post_id, $tags_array, 'blocks_tag' );
316 } else {
317 wp_set_post_terms( $post_id, array(), 'blocks_tag' );
318 }
319 }
320 // phpcs:enable WordPress.Security.NonceVerification.Missing
321
322 /**
323 * Save a block from POST data.
324 *
325 * @param int $post_id Post ID (-1 for new block).
326 * @return int|false Saved post ID or false on failure.
327 */
328 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in blocks_handle_save_action before calling this.
329 function blocks_save( $post_id = -1 ) {
330 $cms_block = null;
331
332 if ( -1 !== $post_id ) {
333 $cms_block = Blocks::get_instance( $post_id );
334 }
335
336 if ( ! $cms_block ) {
337 $cms_block = Blocks::get_template();
338 }
339
340 if ( isset( $_POST['post_title'] ) ) {
341 $cms_block->set_title( sanitize_text_field( wp_unslash( $_POST['post_title'] ) ) );
342 }
343
344 if ( isset( $_POST['blocks-locale'] ) ) {
345 $locale = sanitize_text_field( wp_unslash( $_POST['blocks-locale'] ) );
346 if ( blocks_is_valid_locale( $locale ) ) {
347 $cms_block->locale = $locale;
348 }
349 }
350
351 if ( isset( $_POST['post_status'] ) ) {
352 $cms_block->post_status = sanitize_key( wp_unslash( $_POST['post_status'] ) );
353 }
354
355 $properties = blocks_process_properties( $cms_block->get_properties() );
356 $cms_block->set_properties( $properties );
357
358 do_action( 'blocks_save', $cms_block );
359
360 $saved_id = $cms_block->save();
361
362 if ( $saved_id ) {
363 blocks_save_taxonomies( $saved_id );
364
365 $popup_enabled = isset( $properties['popup_enabled'] ) ? absint( $properties['popup_enabled'] ) : 0;
366 update_post_meta( $saved_id, '_blocks_popup_enabled', $popup_enabled );
367
368 $banner_enabled = isset( $properties['banner_enabled'] ) ? absint( $properties['banner_enabled'] ) : 0;
369 update_post_meta( $saved_id, '_blocks_banner_enabled', $banner_enabled );
370 }
371
372 return $saved_id;
373 }
374 // phpcs:enable WordPress.Security.NonceVerification.Missing
375