PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / page-form-builder / field-packs / custom-shortcode / field-custom-shortcode.php

field-custom-shortcode.php in Booking Calendar 11.8.4, at includes/page-form-builder/field-packs/custom-shortcode/field-custom-shortcode.php

235 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPBC BFB Pack: Custom Shortcode.
4 *
5 * Adds one validated shortcode token to the Advanced Booking Form. The token
6 * may include Booking Calendar options and quoted values, such as
7 * `[coupon discount ""]`, while the field pack remains independent of the
8 * runtime service that interprets the selected shortcode.
9 *
10 * @package Booking Calendar
11 * @since 11.8.2
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /**
19 * Normalize one Custom Shortcode value for persistence.
20 *
21 * This mirrors the browser-side syntax boundary so a direct or modified save
22 * request cannot persist nested tokens, HTML delimiters, control characters,
23 * unbalanced quotes, or an excessively long shortcode through this field pack.
24 * Runtime shortcode support remains the responsibility of the public form
25 * parser and edition-specific token producers.
26 *
27 * @since 11.8.4
28 *
29 * @param mixed $shortcode_value Candidate Custom Shortcode value.
30 *
31 * @return string Normalized shortcode, or an empty string when invalid.
32 */
33 function wpbc_bfb_normalize_custom_shortcode( $shortcode_value ) {
34 $shortcode = trim( (string) $shortcode_value );
35
36 if ( strlen( $shortcode ) > 4000 ) {
37 return '';
38 }
39
40 $shortcode_characters = array();
41 $shortcode_length = preg_match_all( '/./us', $shortcode, $shortcode_characters );
42
43 if (
44 false === $shortcode_length ||
45 $shortcode_length < 3 ||
46 $shortcode_length > 1000 ||
47 '[' !== substr( $shortcode, 0, 1 ) ||
48 ']' !== substr( $shortcode, -1 )
49 ) {
50 return '';
51 }
52
53 $shortcode_body = trim( substr( $shortcode, 1, -1 ) );
54
55 if ( '' === $shortcode_body || preg_match( '/[\x00-\x1F\x7F<>\[\]]/', $shortcode_body ) ) {
56 return '';
57 }
58
59 $shortcode_name_end = strpos( $shortcode_body, ' ' );
60 $shortcode_name = false === $shortcode_name_end
61 ? $shortcode_body
62 : substr( $shortcode_body, 0, $shortcode_name_end );
63
64 if ( ! preg_match( '/^[A-Za-z0-9_.*-]+$/D', $shortcode_name ) ) {
65 return '';
66 }
67
68 $active_quote = '';
69 $body_length = strlen( $shortcode_body );
70
71 for ( $index = strlen( $shortcode_name ); $index < $body_length; $index++ ) {
72 $character = $shortcode_body[ $index ];
73
74 if ( '' !== $active_quote ) {
75 if ( $character === $active_quote ) {
76 $active_quote = '';
77 }
78 continue;
79 }
80
81 if ( '"' === $character || "'" === $character ) {
82 $active_quote = $character;
83 }
84 }
85
86 return '' === $active_quote ? '[' . $shortcode_body . ']' : '';
87 }
88
89 /**
90 * Sanitize Custom Shortcode values inside a Form Builder structure.
91 *
92 * The recursive traversal understands only the standard field-node envelope
93 * and leaves every unrelated field, section, page, and unknown extension value
94 * untouched.
95 *
96 * @since 11.8.4
97 *
98 * @param array $structure Form Builder structure about to be persisted.
99 *
100 * @return array Structure with Custom Shortcode values normalized.
101 */
102 function wpbc_bfb_sanitize_structure__custom_shortcode( $structure ) {
103 if (
104 'field' === ( isset( $structure['type'] ) ? $structure['type'] : '' ) &&
105 isset( $structure['data'] ) &&
106 is_array( $structure['data'] ) &&
107 'custom_shortcode' === ( isset( $structure['data']['type'] ) ? $structure['data']['type'] : '' )
108 ) {
109 $structure['data']['shortcode'] = wpbc_bfb_normalize_custom_shortcode(
110 isset( $structure['data']['shortcode'] ) ? $structure['data']['shortcode'] : ''
111 );
112 }
113
114 foreach ( $structure as $structure_key => $structure_value ) {
115 if ( is_array( $structure_value ) ) {
116 $structure[ $structure_key ] = wpbc_bfb_sanitize_structure__custom_shortcode( $structure_value );
117 }
118 }
119
120 return $structure;
121 }
122 add_filter( 'wpbc_bfb_sanitize_structure_before_save', 'wpbc_bfb_sanitize_structure__custom_shortcode', 10, 1 );
123
124 /**
125 * Register the Custom Shortcode field schema and Inspector control.
126 *
127 * The field stores one string. The browser pack applies a bounded allow-list
128 * before exporting it, and the existing save endpoint applies WordPress KSES
129 * to the complete generated Advanced Booking Form.
130 *
131 * @param array $packs Registered Builder field packs.
132 *
133 * @return array Updated field packs.
134 */
135 function wpbc_bfb_register_field_packs__custom_shortcode( $packs ) {
136 $packs['custom_shortcode'] = array(
137 'kind' => 'field',
138 'type' => 'custom_shortcode',
139 'label' => __( 'Custom Shortcode', 'booking' ),
140 'icon' => 'wpbc-bi-code',
141 'usage_key' => 'custom_shortcode',
142 'schema' => array(
143 'props' => array(
144 'shortcode' => array(
145 'type' => 'string',
146 'default' => '[field_name_hint]',
147 ),
148 ),
149 ),
150 'inspector_ui' => array(
151 'title' => __( 'Custom Shortcode', 'booking' ),
152 'description' => __( 'Add one supported Booking Calendar shortcode. Options and quoted values are allowed, for example [coupon discount ""]. For a Form Options Cost hint, use its field name followed by _hint.', 'booking' ),
153 'header_variant' => 'toolbar',
154 'header_actions' => array( 'deselect', 'scrollto', 'move-up', 'move-down', 'duplicate', 'delete' ),
155 'groups' => array(
156 array(
157 'key' => 'basic',
158 'label' => __( 'Shortcode', 'booking' ),
159 'open' => true,
160 'controls' => array(
161 array(
162 'type' => 'text',
163 'key' => 'shortcode',
164 'label' => __( 'Shortcode', 'booking' ),
165 'placeholder' => '[field_name_hint]',
166 ),
167 ),
168 ),
169 ),
170 ),
171 );
172
173 return $packs;
174 }
175 add_filter( 'wpbc_bfb_register_field_packs', 'wpbc_bfb_register_field_packs__custom_shortcode' );
176
177 /**
178 * Enqueue the Custom Shortcode renderer and exporters in Form Builder.
179 *
180 * WordPress calls this hook only while loading the Builder page. The runtime
181 * asset is deliberately loaded from `_out`, matching the project contract.
182 *
183 * @param string $page Current administration page slug.
184 *
185 * @return void
186 */
187 function wpbc_bfb_enqueue__custom_shortcode_js( $page ) {
188 wp_enqueue_script(
189 'wpbc-bfb_field_custom_shortcode',
190 wpbc_plugin_url( '/includes/page-form-builder/field-packs/custom-shortcode/_out/custom-shortcode.js' ),
191 array( 'wpbc-bfb' ),
192 WP_BK_VERSION_NUM,
193 true
194 );
195
196 wp_localize_script(
197 'wpbc-bfb_field_custom_shortcode',
198 'WPBC_BFB_Custom_Shortcode_Boot',
199 array(
200 'example_shortcode' => '[field_name_hint]',
201 'invalid_message' => __( 'Enter one complete shortcode, for example [field_name_hint] or [coupon discount ""].', 'booking' ),
202 )
203 );
204 }
205 add_action( 'wpbc_enqueue_js_field_pack', 'wpbc_bfb_enqueue__custom_shortcode_js', 10, 1 );
206
207 /**
208 * Add Custom Shortcode to the Cost Hints palette group.
209 *
210 * The palette placement reflects the primary Form Options Costs use case, but
211 * the field itself remains a generic single-token exporter.
212 *
213 * @param string $group Palette group.
214 * @param string $position Position inside the group.
215 *
216 * @return void
217 */
218 function wpbc_bfb_palette_register_items__custom_shortcode( $group, $position ) {
219 if ( 'hints' !== $group || 'bottom' !== $position ) {
220 return;
221 }
222 ?>
223 <li class="wpbc_bfb__field"
224 data-id="custom_shortcode"
225 data-type="custom_shortcode"
226 data-usage_key="custom_shortcode"
227 data-shortcode="[field_name_hint]">
228 <i class="menu_icon icon-1x wpbc-bi-code"></i>
229 <span class="wpbc_bfb__field-label"><?php echo esc_html__( 'Custom Shortcode', 'booking' ); ?></span>
230 <span class="wpbc_bfb__field-type">[field_name_hint]</span>
231 </li>
232 <?php
233 }
234 add_action( 'wpbc_bfb_palette_register_items', 'wpbc_bfb_palette_register_items__custom_shortcode', 10, 2 );
235