PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 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 All 205 releases
booking / includes / page-catalog-booking-resources / class-wpbc-catalog-inline-fields.php

class-wpbc-catalog-inline-fields.php in Booking Calendar 11.9, at includes/page-catalog-booking-resources/class-wpbc-catalog-inline-fields.php

188 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking Resources inline and bulk field definitions.
4 *
5 * @package Booking Calendar
6 * @since 11.6.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Produce current Resource field contracts from the domain inspector schema.
15 *
16 * The provider selects presentation-safe fields only. Resource mutation
17 * services remain responsible for request-time authorization and validation.
18 *
19 * @since 11.6.0
20 */
21 final class WPBC_Catalog_Booking_Resources_Inline_Fields implements WPBC_UI_Catalog_Inline_Fields {
22
23 /** @var WPBC_Catalog_Booking_Resource_Inspector_Schema Resource schema service. */
24 private $schema;
25
26 /** @var array<int,array<string,array<string,mixed>>> Request-local field cache. */
27 private $field_cache = array();
28
29 /**
30 * Construct the provider with an optional schema service for tests.
31 *
32 * @param WPBC_Catalog_Booking_Resource_Inspector_Schema|null $schema Resource schema service.
33 */
34 public function __construct( $schema = null ) {
35 $this->schema = $schema instanceof WPBC_Catalog_Booking_Resource_Inspector_Schema ? $schema : new WPBC_Catalog_Booking_Resource_Inspector_Schema();
36 }
37
38 /**
39 * Return inline-safe fields for one authorized Resource.
40 *
41 * @param array<string,mixed> $record Current authorized Resource.
42 * @return array<int,array<string,mixed>> Browser-safe field definitions.
43 */
44 public function get_inline_fields( $record ) {
45 $column_map = array(
46 'title' => 'resource',
47 'description' => 'resource',
48 'base_cost' => 'price',
49 'default_form' => 'default_form',
50 'priority' => 'priority',
51 );
52 $inline_fields = array();
53
54 foreach ( $this->get_indexed_fields( $record ) as $field_key => $field ) {
55 if ( empty( $field['editable'] ) || ! isset( $column_map[ $field_key ] ) || ! in_array( $field['type'], WPBC_UI_Catalog_Inline_Field_Schema::CONTROL_TYPES, true ) ) {
56 continue;
57 }
58 $field['column'] = $column_map[ $field_key ];
59 $inline_fields[] = $field;
60 }
61
62 return WPBC_UI_Catalog_Inline_Field_Schema::normalize_fields( $inline_fields );
63 }
64
65 /**
66 * Return fields safely shared by every authorized Resource.
67 *
68 * @param array<int,array<string,mixed>> $records Authorized Resources.
69 * @return array<int,array<string,mixed>> Common browser-safe fields.
70 */
71 public function get_bulk_fields( $records ) {
72 $allowed_keys = array( 'searchable_status', 'availability_mode', 'base_cost', 'default_form', 'priority', 'owner_user_id' );
73 $fields_by_resource = array();
74
75 foreach ( $records as $record ) {
76 $resource_fields = $this->get_indexed_fields( $record );
77 foreach ( $resource_fields as $field_key => $field ) {
78 if ( ! in_array( $field_key, $allowed_keys, true ) || empty( $field['editable'] ) ) {
79 unset( $resource_fields[ $field_key ] );
80 }
81 }
82 $fields_by_resource[] = $resource_fields;
83 }
84
85 $common_fields = array();
86 foreach ( $allowed_keys as $field_key ) {
87 $field_definitions = array();
88 foreach ( $fields_by_resource as $resource_fields ) {
89 if ( ! isset( $resource_fields[ $field_key ] ) ) {
90 $field_definitions = array();
91 break;
92 }
93 $field_definitions[] = $resource_fields[ $field_key ];
94 }
95 if ( empty( $field_definitions ) || ( 'owner_user_id' === $field_key && $this->selection_has_hierarchy( $records ) ) ) {
96 continue;
97 }
98 $field_definition = $field_definitions[0];
99 if ( in_array( $field_key, array( 'searchable_status', 'availability_mode', 'default_form', 'owner_user_id' ), true ) ) {
100 $field_definition['options'] = $this->intersect_options( $field_definitions, 'owner_user_id' === $field_key );
101 if ( empty( $field_definition['options'] ) ) {
102 continue;
103 }
104 }
105 $common_fields[] = $field_definition;
106 }
107
108 return WPBC_UI_Catalog_Inline_Field_Schema::normalize_fields( $common_fields );
109 }
110
111 /**
112 * Return current inspector fields indexed by stable key.
113 *
114 * @param array<string,mixed> $resource Authorized Resource.
115 * @return array<string,array<string,mixed>> Current Resource fields.
116 */
117 public function get_indexed_fields( $resource ) {
118 $resource_id = isset( $resource['id'] ) ? absint( $resource['id'] ) : 0;
119 if ( $resource_id && isset( $this->field_cache[ $resource_id ] ) ) {
120 return $this->field_cache[ $resource_id ];
121 }
122 $contract = $this->schema->get_edit_schema( $resource );
123 $fields = array();
124 if ( ! is_wp_error( $contract ) ) {
125 foreach ( isset( $contract['sections'] ) ? (array) $contract['sections'] : array() as $section ) {
126 foreach ( isset( $section['fields'] ) ? (array) $section['fields'] : array() as $field ) {
127 if ( ! empty( $field['key'] ) ) {
128 $fields[ sanitize_key( $field['key'] ) ] = $field;
129 }
130 }
131 }
132 }
133 if ( $resource_id ) {
134 $this->field_cache[ $resource_id ] = $fields;
135 }
136
137 return $fields;
138 }
139
140 /**
141 * Intersect select choices across current Resource schemas.
142 *
143 * @param array<int,array<string,mixed>> $definitions Field definitions.
144 * @param bool $exclude_zero Whether zero cannot be assigned.
145 * @return array<int,array{value:string,label:string}> Common choices.
146 */
147 private function intersect_options( $definitions, $exclude_zero ) {
148 $options = array();
149 foreach ( isset( $definitions[0]['options'] ) ? (array) $definitions[0]['options'] : array() as $option ) {
150 $option_value = isset( $option['value'] ) ? (string) $option['value'] : '';
151 if ( $exclude_zero && '0' === $option_value ) {
152 continue;
153 }
154 $is_common = true;
155 foreach ( array_slice( $definitions, 1 ) as $definition ) {
156 if ( ! in_array( $option_value, array_map( 'strval', wp_list_pluck( isset( $definition['options'] ) ? $definition['options'] : array(), 'value' ) ), true ) ) {
157 $is_common = false;
158 break;
159 }
160 }
161 if ( $is_common ) {
162 $options[] = array(
163 'value' => $option_value,
164 'label' => isset( $option['label'] ) ? wp_strip_all_tags( (string) $option['label'] ) : $option_value,
165 );
166 }
167 }
168
169 return $options;
170 }
171
172 /**
173 * Determine whether ownership editing could split a Resource hierarchy.
174 *
175 * @param array<int,array<string,mixed>> $resources Authorized Resources.
176 * @return bool True when a parent or child is present.
177 */
178 private function selection_has_hierarchy( $resources ) {
179 foreach ( $resources as $resource ) {
180 if ( ! empty( $resource['parent_id'] ) || ! empty( $resource['child_count'] ) ) {
181 return true;
182 }
183 }
184
185 return false;
186 }
187 }
188