PluginProbe
Booking Calendar / 11.2
Booking Calendar v11.2
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 10.11.2 All 203 releases
booking / includes / page-form-builder / bfb-schemas.php

bfb-schemas.php in Booking Calendar 11.2, at includes/page-form-builder/bfb-schemas.php

176 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Hybrid++ Schemas utilities: normalize/validate/merge/extract.
4 *
5 * @package Booking Calendar.
6 * @author wpdevelop, oplugins
7 * @web-site https://wpbookingcalendar.com/
8 * @email info@wpbookingcalendar.com
9 *
10 * @since 11.0.0
11 * @modified 2025-08-29
12 * @version 1.0
13 */
14
15 // ---------------------------------------------------------------------------------------------------------------------
16 // == File bfb-schemas.php == Time point: 2025-08-29 12:25
17 // ---------------------------------------------------------------------------------------------------------------------
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 /**
23 * Utilities for working with field/section/component packs.
24 */
25 class WPBC_BFB_Schemas_Util {
26
27 /**
28 * Normalize a single pack to a safe, known shape.
29 *
30 * @param array $pack Raw pack from a filter callback.
31 *
32 * @return array Normalized pack.
33 */
34 public static function normalize_pack( $pack ) {
35 $pack = is_array( $pack ) ? $pack : array();
36
37 $pack['kind'] = isset( $pack['kind'] ) ? sanitize_key( $pack['kind'] ) : 'field';
38 $pack['type'] = isset( $pack['type'] ) ? sanitize_key( $pack['type'] ) : '';
39 $pack['schema'] = ( isset( $pack['schema'] ) && is_array( $pack['schema'] ) ) ? $pack['schema'] : array();
40 if ( ! isset( $pack['schema']['props'] ) || ! is_array( $pack['schema']['props'] ) ) {
41 $pack['schema']['props'] = array();
42 }
43
44 $pack['inspector_ui'] = ( isset( $pack['inspector_ui'] ) && is_array( $pack['inspector_ui'] ) ) ? $pack['inspector_ui'] : array();
45
46 if ( ! isset( $pack['inspector_ui']['groups'] ) || ! is_array( $pack['inspector_ui']['groups'] ) ) {
47 $pack['inspector_ui']['groups'] = array();
48 }
49
50 $pack['header_actions'] = ( isset( $pack['header_actions'] ) && is_array( $pack['header_actions'] ) ) ? array_values( $pack['header_actions'] ) : array();
51
52 $pack['templates_printer'] = ( isset( $pack['templates_printer'] ) && is_callable( $pack['templates_printer'] ) ) ? $pack['templates_printer'] : null;
53
54 return $pack;
55 }
56
57 /**
58 * Basic validation: keep only supported prop/control types and JSON-serializable data.
59 *
60 * @param array $pack Normalized pack.
61 *
62 * @return array Validated pack (unsafe bits removed).
63 */
64 public static function validate_pack( $pack ) {
65
66 // Allow extra prop/control types used by the Inspector Factory.
67 $allowed_prop_types = array( 'string', 'number', 'boolean', 'array', 'int', 'float', 'enum', 'color' );
68 // Expanded to support Factory extras and color control.
69 $allowed_control_types = array( 'text', 'number', 'checkbox', 'textarea', 'select', 'range_number', 'len', 'color' );
70
71 // Validate prop meta.
72 foreach ( $pack['schema']['props'] as $prop_key => $meta ) {
73
74 if ( ! is_array( $meta ) ) {
75 unset( $pack['schema']['props'][ $prop_key ] );
76 continue;
77 }
78 $meta['type'] = isset( $meta['type'] ) ? $meta['type'] : 'string';
79 if ( ! in_array( $meta['type'], $allowed_prop_types, true ) ) {
80 unset( $pack['schema']['props'][ $prop_key ] );
81 continue;
82 }
83 // Drop non-serializable values.
84 foreach ( $meta as $k => $v ) {
85 if ( is_object( $v ) && ! ( $v instanceof JsonSerializable ) ) {
86 unset( $meta[ $k ] );
87 }
88 }
89 $pack['schema']['props'][ $prop_key ] = $meta;
90 }
91
92 // Validate inspector groups/controls.
93 if ( ! empty( $pack['inspector_ui']['groups'] ) ) {
94 foreach ( $pack['inspector_ui']['groups'] as $g_i => $group ) {
95 if ( ! is_array( $group ) ) {
96 unset( $pack['inspector_ui']['groups'][ $g_i ] );
97 continue;
98 }
99 $group['controls'] = ( isset( $group['controls'] ) && is_array( $group['controls'] ) ) ? $group['controls'] : array();
100
101 foreach ( $group['controls'] as $c_i => $control ) {
102 if ( ! is_array( $control ) ) {
103 unset( $group['controls'][ $c_i ] );
104 continue;
105 }
106 if ( empty( $control['key'] ) || empty( $control['type'] ) || ! in_array( $control['type'], $allowed_control_types, true ) ) {
107 unset( $group['controls'][ $c_i ] );
108 continue;
109 }
110 // Remove objects in control meta.
111 foreach ( $control as $k => $v ) {
112 if ( is_object( $v ) && ! ( $v instanceof JsonSerializable ) ) {
113 unset( $control[ $k ] );
114 }
115 }
116 $group['controls'][ $c_i ] = $control;
117 }
118 $pack['inspector_ui']['groups'][ $g_i ] = $group;
119 }
120 }
121
122 // Sanitize header action keys.
123 if ( ! empty( $pack['header_actions'] ) ) {
124 $san = array();
125 foreach ( $pack['header_actions'] as $act ) {
126 $san[] = sanitize_key( $act );
127 }
128 $pack['header_actions'] = array_values( array_unique( $san ) );
129 }
130
131 return $pack;
132 }
133
134 /**
135 * Merge a list of packs keyed by type. Later packs win on conflicts.
136 *
137 * @param array $packs Packs list.
138 *
139 * @return array Merged packs keyed by type.
140 */
141 public static function merge_packs( $packs ) {
142 $merged = array();
143 foreach ( (array) $packs as $pack ) {
144 $pack = self::normalize_pack( $pack );
145 $pack = self::validate_pack( $pack );
146 if ( empty( $pack['type'] ) ) {
147 continue;
148 }
149 $merged[ $pack['type'] ] = $pack; // last writer wins.
150 }
151
152 return $merged;
153 }
154
155 /**
156 * Extract only the JS-safe schema bits for localization.
157 *
158 * @param array $packs_by_type Merged packs keyed by type.
159 *
160 * @return array Array keyed by type for JS (small payload).
161 */
162 public static function extract_schemas_for_js( $packs_by_type ) {
163 $out = array();
164 foreach ( (array) $packs_by_type as $type => $pack ) {
165 $out[ $type ] = array(
166 'kind' => isset( $pack['kind'] ) ? $pack['kind'] : 'field',
167 'schema' => isset( $pack['schema'] ) ? $pack['schema'] : array( 'props' => array() ),
168 'inspector_ui' => isset( $pack['inspector_ui'] ) ? $pack['inspector_ui'] : array( 'groups' => array() ),
169 'header_actions' => isset( $pack['header_actions'] ) ? array_values( $pack['header_actions'] ) : array(),
170 );
171 }
172
173 return $out;
174 }
175 }
176