PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.3
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.3
5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / helpers / form_helper.php
latepoint / lib / helpers Last commit date
activities_helper.php 1 year ago agent_helper.php 1 year ago auth_helper.php 1 year ago blocks_helper.php 1 year ago booking_helper.php 1 year ago bricks_helper.php 1 year ago bundles_helper.php 1 year ago calendar_helper.php 1 year ago carts_helper.php 1 year ago connector_helper.php 1 year ago csv_helper.php 1 year ago customer_helper.php 1 year ago database_helper.php 1 year ago debug_helper.php 1 year ago defaults_helper.php 1 year ago elementor_helper.php 1 year ago email_helper.php 1 year ago encrypt_helper.php 1 year ago events_helper.php 1 year ago form_helper.php 1 year ago icalendar_helper.php 1 year ago image_helper.php 1 year ago invoices_helper.php 1 year ago license_helper.php 1 year ago location_helper.php 1 year ago marketing_systems_helper.php 1 year ago meeting_systems_helper.php 1 year ago menu_helper.php 1 year ago meta_helper.php 1 year ago migrations_helper.php 1 year ago money_helper.php 1 year ago notifications_helper.php 1 year ago order_intent_helper.php 1 year ago orders_helper.php 1 year ago pages_helper.php 1 year ago params_helper.php 1 year ago payments_helper.php 1 year ago price_breakdown_helper.php 1 year ago process_jobs_helper.php 1 year ago processes_helper.php 1 year ago replacer_helper.php 1 year ago resource_helper.php 1 year ago roles_helper.php 1 year ago router_helper.php 1 year ago service_helper.php 1 year ago sessions_helper.php 1 year ago settings_helper.php 1 year ago shortcodes_helper.php 1 year ago sms_helper.php 1 year ago steps_helper.php 1 year ago stripe_connect_helper.php 1 year ago styles_helper.php 1 year ago support_topics_helper.php 1 year ago time_helper.php 1 year ago timeline_helper.php 1 year ago transaction_intent_helper.php 1 year ago util_helper.php 1 year ago version_specific_updates_helper.php 1 year ago whatsapp_helper.php 1 year ago work_periods_helper.php 1 year ago wp_datetime.php 1 year ago wp_user_helper.php 1 year ago
form_helper.php
913 lines
1 <?php
2
3 class OsFormHelper {
4
5
6 public static function get_hidden_fields_for_array( array $array, string $prefix = '' ): string {
7 $inputs = '';
8 foreach ( $array as $key => $value ) {
9 $fieldName = $prefix ? $prefix . "[" . $key . "]" : $key;
10
11 if ( is_array( $value ) ) {
12 $inputs .= self::get_hidden_fields_for_array( $value, $fieldName );
13 } else {
14 $inputs .= OsFormHelper::hidden_field( $fieldName, $value );
15 }
16 }
17
18 return $inputs;
19 }
20
21 public static function atts_string_from_array( $atts = array(), $join_atts = array() ) {
22 $atts_str = '';
23 if ( ! empty( $atts ) ) {
24 if ( isset( $atts['add_string_to_id'] ) ) {
25 unset( $atts['add_string_to_id'] );
26 }
27 if ( isset( $atts['skip_id'] ) ) {
28 unset( $atts['skip_id'] );
29 }
30 foreach ( $atts as $key => $value ) {
31 if ( isset( $join_atts[ $key ] ) ) {
32 $value .= ' ' . $join_atts[ $key ];
33 unset( $join_atts[ $key ] );
34 }
35 if ( ! is_array( $value ) ) {
36 $atts_str .= esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
37 }
38 }
39 }
40 if ( ! empty( $join_atts ) ) {
41 foreach ( $join_atts as $key => $value ) {
42 $atts_str .= esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
43 }
44 }
45
46 return $atts_str;
47 }
48
49
50 /**
51 * @param string $name
52 * @param string $label
53 * @param bool $is_active
54 * @param $controlledToggleId
55 * @param $size
56 *
57 * @return string
58 */
59 public static function toggler_radio_field( string $name, string $label, string $value, bool $is_active, $controlledToggleId = false, $size = false, $atts = [] ): string {
60 if ( ! $size ) {
61 $size = 'normal';
62 }
63 $status = $is_active ? 'on' : 'off';
64 $controlledToggleHtml = $controlledToggleId ? 'data-controlled-toggle-id="' . $controlledToggleId . '"' : '';
65 $html = '';
66 $id = self::name_to_id( $name . '_' . $value );
67 $extra = ( empty( $atts['sub_label'] ) ) ? '' : ' with-sub-label';
68 if ( $label ) {
69 $html .= '<div class="os-form-group os-form-toggler-group ' . $extra . ' size-' . $size . '">';
70 }
71 $html .= OsFormHelper::radio_field( $name, $value, $is_active, [ 'id' => $id ] );
72 $html .= '<div ' . $controlledToggleHtml . ' class="os-toggler os-toggler-radio ' . $status . ' size-' . $size . '" data-is-string-value="true" data-for="' . $id . '"><div class="toggler-rail"><div class="toggler-pill"></div></div></div>';
73 if ( $label ) {
74 $html .= '<div class="os-toggler-label-w">';
75 $html .= '<label>' . esc_html( $label ) . '</label>';
76 if ( ! empty( $atts['sub_label'] ) ) {
77 $html .= '<span>' . esc_html( $atts['sub_label'] ) . '</span>';
78 }
79 $html .= '</div>';
80 }
81 if ( $label ) {
82 $html .= '</div>';
83 }
84
85 return $html;
86 }
87
88 /**
89 * @param string $name
90 * @param string $label
91 * @param bool $is_active
92 * @param $controlledToggleId
93 * @param $size
94 *
95 * @return string
96 */
97 public static function toggler_field( string $name, string $label, bool $is_active, $controlledToggleId = false, $size = false, $atts = [] ): string {
98 if ( ! $size ) {
99 $size = 'normal';
100 }
101 $status = $is_active ? 'on' : 'off';
102 $value = $is_active ? 'on' : 'off';
103 $controlledToggleHtml = $controlledToggleId ? 'data-controlled-toggle-id="' . $controlledToggleId . '"' : '';
104 $html = '';
105 $id = self::name_to_id( $name );
106 $extra = ( empty( $atts['sub_label'] ) ) ? '' : ' with-sub-label';
107 if ( $label ) {
108 $html .= '<div class="os-form-group os-form-toggler-group ' . $extra . ' size-' . $size . '">';
109 }
110 $html .= OsFormHelper::hidden_field( $name, $value, [ 'id' => $id ] );
111 $instant_update = ! empty( $atts['instant_update_route'] ) ? 'data-os-instant-update="' . esc_attr( $atts['instant_update_route'] ) . '"' : '';
112 $instant_update .= empty( $atts['nonce'] ) ? '' : ' data-nonce="' . esc_attr( $atts['nonce'] ) . '"';
113 $html .= '<div ' . $controlledToggleHtml . ' class="os-toggler ' . $status . ' size-' . $size . '" data-is-string-value="true" data-for="' . $id . '" ' . $instant_update . '><div class="toggler-rail"><div class="toggler-pill"></div></div></div>';
114 if ( $label ) {
115 $html .= '<div class="os-toggler-label-w">';
116 $html .= '<label>' . esc_html( $label ) . '</label>';
117 if ( ! empty( $atts['sub_label'] ) ) {
118 $html .= '<span>' . esc_html( $atts['sub_label'] ) . '</span>';
119 }
120 $html .= '</div>';
121 }
122 if ( $label ) {
123 $html .= '</div>';
124 }
125
126 return $html;
127 }
128
129
130 public static function media_uploader_field( $name, $post_id = 0, $label_set_str = '', $label_remove_str = '', $value_image_id = false, $atts = array(), $wrapper_atts = array(), $is_avatar = false, $is_compact = false, $default_image_html = '' ) {
131 $upload_link = esc_url( get_upload_iframe_src( 'image', $post_id ) );
132 $img_html = '';
133 $has_image_class = '';
134 $label_str = $label_set_str;
135
136 // Image is set
137 if ( $value_image_id ) {
138 $image_url = esc_url( OsImageHelper::get_image_url_by_id( $value_image_id ) );
139 $img_html = $is_avatar ? '<div class="image-self" style="background-image: url(' . $image_url . ')"></div>' : '<img src="' . $image_url . '"/>';
140 $has_image_class = 'has-image';
141 $label_str = $label_remove_str;
142 } else {
143 $img_html = '<div class="os-placeholder"></div>';
144 }
145
146 $is_avatar_class = $is_avatar ? ' is-avatar ' : '';
147 $is_compact_class = $is_compact ? ' is-compact ' : '';
148 $html = '';
149 $html .= '<div class="os-image-selector-w ' . $is_avatar_class . ' ' . $is_compact_class . ' ' . $has_image_class . '">';
150 $html .= '<a href="' . $upload_link . '" data-label-remove-str="' . esc_attr( $label_remove_str ) . '" data-label-set-str="' . esc_attr( $label_set_str ) . '"' . self::atts_string_from_array( $wrapper_atts, [ 'class' => "os-image-selector-trigger" ] ) . '>';
151 $html .= '<div class="os-image-container">' . $img_html . '</div>';
152 if ( $default_image_html ) {
153 $html .= '<div class="os-default-image-wrapper">' . $default_image_html . '</div>';
154 }
155 $html .= '<div class="os-image-selector-text"><span class="os-text-holder">' . esc_html( $label_str ) . '</span></div>';
156 $html .= '</a>';
157 $html .= '<input type="hidden" name="' . $name . '" value="' . esc_attr( $value_image_id ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-image-id-holder' ] ) . '/>';
158 $html .= '</div>';
159
160 return $html;
161 }
162
163 public static function file_upload_field( $name, $label, $value = '', $atts = [], $wrapper_atts = [] ) {
164 $accepted_formats = '.jpg,.jpeg,.png,.gif,.ico,.pdf,.doc,.docx,.ppt,.pptx,.pps,.ppsx,.odt,.xls,.xlsx,.PSD,.mp3,.m4a,.ogg,.wav,.mp4,.m4v,.mov,.wmv,.avi,.mpg,.ogv,.3gp,.3g2,.json';
165 // generate id if not set
166 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
167 $atts['id'] = self::name_to_id( $name, $atts );
168 }
169 $html = '';
170 if ( ! empty( $wrapper_atts ) ) {
171 $html .= '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
172 }
173 $html .= '<div class="os-form-group os-form-file-upload-group">';
174 if ( $label ) {
175 $html .= '<label for="' . esc_attr( $name ) . '">' . $label . '</label>';
176 }
177 $html .= '<a target="_blank" href="' . esc_url( $value ) . '" class="os-uploaded-file-info ' . ( ! empty( $value ) ? 'is-uploaded' : '' ) . '" style="' . ( empty( $value ) ? 'display: none' : '' ) . '">
178 <div class="uf-icon"><i class="latepoint-icon latepoint-icon-file-text"></i></div>
179 <div class="uf-data">
180 <div class="uf-name">' . ( ! empty( $value ) ? basename( $value ) : '' ) . '</div>
181 </div>
182 <div class="uf-remove"><i class="latepoint-icon latepoint-icon-cross"></i></div>
183 </a>';
184 $html .= '<div class="os-upload-file-input-w" style="' . ( $value ? 'display: none' : '' ) . '">';
185 $html .= '<input type="file" accept="' . $accepted_formats . '" name="' . esc_attr( $name ) . '" multiple="false" ' . self::atts_string_from_array( $atts ) . '/>';
186 if ( $value ) {
187 $html .= self::hidden_field( $name, $value );
188 }
189 $html .= '</div>';
190 $html .= '</div>';
191 if ( ! empty( $wrapper_atts ) ) {
192 $html .= '</div>';
193 }
194
195 return $html;
196 }
197
198 public static function generate_select_options_from_custom_field( $options ) {
199 if ( ! empty( $options ) ) {
200 return preg_split( '/\r\n|\r|\n/', $options );
201 } else {
202 return [];
203 }
204 }
205
206 /**
207 * @param $name
208 * @param $id
209 * @param $label
210 * @param $content
211 * @param $atts
212 *
213 * @return string
214 *
215 * Same as wp_editor_field but returns the html instead of echoing it
216 */
217 public static function wp_editor_field_return( $name, $id, $label, $content, $atts = array() ) {
218 ob_start();
219
220 self::wp_editor_field( $name, $id, $label, $content, $atts );
221
222 $html = ob_get_clean();
223
224 return $html;
225 }
226
227 public static function wp_editor_field( $name, $id, $label, $content, $atts = array() ) {
228 $editor_height = isset( $atts['editor_height'] ) ? $atts['editor_height'] : 300;
229 echo '<div class="os-form-group os-form-control-wp-editor-group">';
230 echo '<label for="' . esc_attr( $name ) . '">' . esc_html( $label ) . '</label>';
231 wp_editor( $content, $id, [
232 'textarea_name' => $name,
233 'media_buttons' => false,
234 'editor_height' => $editor_height
235 ] );
236 echo '</div>';
237 }
238
239
240 public static function textarea_field( $name, $label, $value = '', $atts = array(), $wrapper_atts = array() ) {
241 $extra_class = ' os-form-group-transparent';
242 if ( isset( $atts['theme'] ) ) {
243 switch ( $atts['theme'] ) {
244 case 'bordered':
245 $extra_class = ' os-form-group-bordered';
246 break;
247 case 'right-aligned':
248 $extra_class = ' os-form-group-right-aligned';
249 break;
250 case 'simple':
251 $extra_class = ' os-form-group-simple';
252 unset( $atts['theme'] );
253 break;
254 }
255 }
256 // generate id if not set
257 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
258 $atts['id'] = self::name_to_id( $name, $atts );
259 }
260 if ( $value ) {
261 $extra_class .= ' has-value';
262 }
263 if ( empty( $label ) ) {
264 $extra_class .= ' no-label';
265 }
266
267 // validations
268 if ( ! empty( $atts['validate'] ) ) {
269 $validate_html = 'data-os-validate="' . esc_attr( implode( ' ', $atts['validate'] ) ) . '"';
270 } else {
271 $validate_html = '';
272 }
273 unset( $atts['validate'] );
274 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
275 $html .= '<div ' . self::atts_string_from_array( array( 'class' => 'os-form-group os-form-textfield-group os-form-textarea-group' . $extra_class ) ) . '>';
276 if ( $label ) {
277 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">' . $label . '</label>';
278 }
279 $placeholder = ( ! empty( $atts['placeholder'] ) ) ? $atts['placeholder'] : $label;
280 $html .= '<textarea ' . $validate_html . ' type="text" placeholder="' . esc_attr( $placeholder ) . '" name="' . esc_attr( $name ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . '>' . esc_textarea( $value ?? '' ) . '</textarea>';
281 $html .= '</div>';
282 $html .= '</div>';
283
284 return $html;
285 }
286
287 public static function service_selector_adder_field( $name, $label, $add_label, $options = array(), $value = '', $atts = array(), $wrapper_atts = array() ) {
288 $html = '<div ' . self::atts_string_from_array( $wrapper_atts, [ 'class' => 'os-form-group os-form-select-group os-form-group-transparent service-selector-adder-field-w' ] ) . '>';
289 if ( $label ) {
290 $html .= '<label for="' . $name . '">' . $label . '</label>';
291 }
292 $html .= '<div class="selector-adder-w">';
293 $html .= '<select name="' . $name . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . ' data-select-source="' . esc_attr( OsRouterHelper::build_route_name( 'service_categories', 'list_for_select' ) ) . '">';
294 foreach ( $options as $option ) {
295 if ( isset( $option['value'] ) && isset( $option['label'] ) ) {
296 $selected = ( $value == $option['value'] ) ? 'selected' : '';
297 $html .= '<option value="' . esc_attr( $option['value'] ) . '" ' . $selected . '>' . esc_html( $option['label'] ) . '</option>';
298 }
299 }
300 $html .= '</select>';
301 $html .= '<button class="latepoint-btn latepoint-btn-primary" data-os-action="' . esc_attr( OsRouterHelper::build_route_name( 'service_categories', 'new_form' ) ) . '" data-os-output-target="lightbox"><i class="latepoint-icon latepoint-icon-plus"></i> <span>' . esc_html( $add_label ) . '</span></button>';
302 $html .= '</div>';
303 $html .= '</div>';
304
305 return $html;
306 }
307
308 public static function location_selector_adder_field( $name, $label, $add_label, $options = array(), $value = '', $atts = array(), $wrapper_atts = array() ) {
309 $html = '<div ' . self::atts_string_from_array( $wrapper_atts, [ 'class' => 'os-form-group os-form-select-group os-form-group-transparent location-selector-adder-field-w' ] ) . '>';
310 if ( $label ) {
311 $html .= '<label for="' . $name . '">' . $label . '</label>';
312 }
313 $html .= '<div class="selector-adder-w">';
314 $html .= '<select name="' . $name . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . ' data-select-source="' . esc_attr( OsRouterHelper::build_route_name( 'location_categories', 'list_for_select' ) ) . '">';
315 foreach ( $options as $option ) {
316 if ( isset( $option['value'] ) && isset( $option['label'] ) ) {
317 $selected = ( $value == $option['value'] ) ? 'selected' : '';
318 $html .= '<option value="' . esc_attr( $option['value'] ) . '" ' . $selected . '>' . esc_html( $option['label'] ) . '</option>';
319 }
320 }
321 $html .= '</select>';
322 $html .= '<button class="latepoint-btn latepoint-btn-primary" data-os-action="' . esc_attr( OsRouterHelper::build_route_name( 'location_categories', 'new_form' ) ) . '" data-os-output-target="lightbox"><i class="latepoint-icon latepoint-icon-plus"></i> <span>' . esc_html( $add_label ) . '</span></button>';
323 $html .= '</div>';
324 $html .= '</div>';
325
326 return $html;
327 }
328
329 public static function model_options_for_multi_select( $model_name ) {
330 $options = [];
331 switch ( $model_name ) {
332 case 'service':
333 case 'OsServiceModel':
334 $service = new OsServiceModel;
335 $services = $service->get_results_as_models();
336 if ( $services ) {
337 foreach ( $services as $service ) {
338 $options[] = [ 'value' => $service->id, 'label' => $service->name ];
339 }
340 }
341 break;
342 case 'agent':
343 case 'OsAgentModel':
344 $agent = new OsAgentModel;
345 $agents = $agent->get_results_as_models();
346 if ( $agents ) {
347 foreach ( $agents as $agent ) {
348 $options[] = [ 'value' => $agent->id, 'label' => $agent->full_name ];
349 }
350 }
351 break;
352 case 'customer':
353 case 'OsCustomerModel':
354 $customer = new OsCustomerModel;
355 $customers = $customer->get_results_as_models();
356 if ( $customers ) {
357 foreach ( $customers as $customer ) {
358 $options[] = [ 'value' => $customer->id, 'label' => $customer->full_name ];
359 }
360 }
361 break;
362
363 case 'bundle':
364 case 'OsBundleModel':
365 if ( $bundles = ( new OsBundleModel() )->get_results_as_models() ) {
366 foreach ( $bundles as $bundle ) {
367 $options[] = [ 'value' => $bundle->id, 'label' => $bundle->name ];
368 }
369 }
370
371 break;
372 }
373
374 /**
375 * Returns an array of options based on model name/mnemonic, formatted for multi-select fields
376 *
377 * @param {array} $options Array of model options to filter
378 * @param {string} $model_name Class name or mnemonic used to determine resultant options
379 *
380 * @returns {array} Filtered array of model options
381 * @since 4.4.0
382 * @hook latepoint_model_options_for_multi_select
383 *
384 */
385 return apply_filters( 'latepoint_model_options_for_multi_select', $options, $model_name );
386 }
387
388 public static function date_picker_field( string $name, string $formatted_value = '', string $raw_value = '', array $atts = [] ): string {
389 $html = '<div data-single-date="yes" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-date-range-picker' ] ) . '>
390 <span class="range-picker-value">' . esc_html( $formatted_value ) . '</span>
391 <i class="latepoint-icon latepoint-icon-chevron-down"></i>
392 <input class="os-datepicker-date-from" type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $raw_value ) . '"/>
393 </div>';
394
395 return $html;
396 }
397
398 public static function multi_select_field( $name, $label = false, $options = [], $selected_values = [], $atts = [], $wrapper_atts = [] ) {
399 $html = '';
400 if ( ! $selected_values ) {
401 $selected_values = [];
402 }
403 // generate id if not set
404 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
405 $atts['id'] = self::name_to_id( $name, $atts );
406 }
407 if ( ! empty( $wrapper_atts ) ) {
408 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
409 }
410 $html .= '<div class="os-form-group os-form-select-group os-form-group-transparent">';
411 if ( $label ) {
412 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">' . esc_html( $label ) . '</label>';
413 }
414 $html .= '<select " ' . self::atts_string_from_array( $atts, [ 'class' => 'os-late-select' ] ) . ' data-placeholder="' . esc_attr__( 'Click to select...', 'latepoint' ) . '" multiple>';
415 foreach ( $options as $key => $option ) {
416 if ( isset( $option['value'] ) && isset( $option['label'] ) ) {
417 $selected = ( $selected_values && is_array( $selected_values ) && in_array( $option['value'], $selected_values ) ) ? 'selected="selected"' : '';
418 $html .= '<option value="' . esc_attr( $option['value'] ) . '" ' . $selected . '>' . esc_html( $option['label'] ) . '</option>';
419 } else {
420 $value = ( is_string( $key ) ) ? $key : $option;
421 $selected = ( $selected_values && in_array( $value, $selected_values ) ) ? 'selected' : '';
422 $html .= '<option value="' . esc_attr( $value ) . '" ' . $selected . '>' . esc_html( $option ) . '</option>';
423 }
424 }
425 $html .= '</select>';
426 $html .= OsFormHelper::hidden_field( $name, is_array( $selected_values ) ? implode( ',', $selected_values ) : $selected_values, [ 'skip_id' => true ] );
427 $html .= '</div>';
428 if ( ! empty( $wrapper_atts ) ) {
429 $html .= '</div>';
430 }
431
432 return $html;
433 }
434
435
436 public static function multi_checkbox_field( $name, $label = false, $options = [], $selected_values = [], $atts = [], $wrapper_atts = [] ) {
437 $html = '';
438
439 if ( ! empty( $wrapper_atts ) ) {
440 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
441 }
442
443 $html .= '<div class="os-form-group os-form-multiselect-group os-form-group-transparent">';
444
445 if ( $label ) {
446 $html .= '<label>' . esc_html( $label ) . '</label>';
447 }
448
449 foreach ( $options as $key => $option ) {
450 if ( isset( $option['value'] ) && isset( $option['label'] ) ) {
451 $value = $option['value'];
452 $option_label = $option['label'];
453 } else {
454 $value = ( is_string( $key ) ) ? $key : $option;
455 $option_label = $option;
456 }
457
458 $checkbox_id = self::name_to_id( $name . '_' . $value );
459 $is_checked = in_array( $value, $selected_values );
460
461 $html .= self::checkbox_field(
462 $name . '[]',
463 $option_label,
464 $value,
465 $is_checked,
466 [ 'id' => $checkbox_id ] + $atts,
467 [ 'class' => 'checkbox-option-wrapper' ],
468 ''
469 );
470 }
471
472 $html .= '</div>';
473
474 if ( ! empty( $wrapper_atts ) ) {
475 $html .= '</div>';
476 }
477
478 return $html;
479 }
480
481 public static function select_field( $name, $label, $options = array(), $selected_value = '', $atts = array(), $wrapper_atts = array(), $add_value_if_not_present = false ) {
482 $extra_class = ' os-form-group-transparent';
483 if ( isset( $atts['theme'] ) ) {
484 switch ( $atts['theme'] ) {
485 case 'bordered':
486 $extra_class = ' os-form-group-bordered';
487 break;
488 case 'right-aligned':
489 $extra_class = ' os-form-group-right-aligned';
490 break;
491 case 'simple':
492 $extra_class = ' os-form-group-simple';
493 unset( $atts['theme'] );
494 break;
495 }
496 }
497 $html = '';
498 // generate id if not set
499 if ( ! $atts ) {
500 $atts = [];
501 }
502 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
503 $atts['id'] = self::name_to_id( $name, $atts );
504 }
505
506 // validations
507 if ( ! empty( $atts['validate'] ) ) {
508 $validate_html = 'data-os-validate="' . esc_attr( implode( ' ', $atts['validate'] ) ) . '"';
509 } else {
510 $validate_html = '';
511 }
512
513 if ( ! empty( $wrapper_atts ) ) {
514 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
515 }
516 $html .= '<div class="os-form-group os-form-select-group ' . esc_attr( $extra_class ) . '">';
517 if ( $label ) {
518 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">' . esc_html( $label ) . '</label>';
519 }
520 $html .= '<select ' . $validate_html . ' name="' . esc_attr( $name ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . '>';
521 if ( isset( $atts['placeholder'] ) && ! empty( $atts['placeholder'] ) ) {
522 $html .= '<option value="">' . esc_html( $atts['placeholder'] ) . '</option>';
523 }
524 if ( is_array( $options ) ) {
525 foreach ( $options as $key => $option ) {
526 if ( isset( $option['value'] ) && isset( $option['label'] ) ) {
527 $selected = ( $selected_value == $option['value'] ) ? 'selected' : '';
528 $html .= '<option value="' . esc_attr( $option['value'] ) . '" ' . $selected . '>' . esc_html( $option['label'] ) . '</option>';
529 } else {
530 $value = ( is_string( $key ) ) ? $key : $option;
531 $selected = ( $selected_value == $value ) ? 'selected' : '';
532 $html .= '<option value="' . esc_attr( $value ) . '" ' . $selected . '>' . esc_html( $option ) . '</option>';
533 }
534 }
535 } else {
536 $html .= $options;
537 }
538 if ( $add_value_if_not_present && ! isset( $options[ $selected_value ] ) ) {
539 $html .= '<option value="' . esc_attr( $selected_value ) . '">' . esc_html( $selected_value ) . '</option>';
540 }
541 $html .= '</select>';
542 $html .= '</div>';
543 if ( ! empty( $wrapper_atts ) ) {
544 $html .= '</div>';
545 }
546
547 return $html;
548 }
549
550 public static function time_field( $name, $label, $value = '', $as_period = false ) {
551 if ( strpos( $value, ':' ) === false ) {
552 $formatted_value = OsTimeHelper::minutes_to_hours_and_minutes( $value, false, false );
553 }
554
555 $extra_class = '';
556 if ( $as_period ) {
557 $extra_class = 'as-period';
558 }
559
560 $html = '<div class="os-time-group os-time-input-w ' . $extra_class . '">';
561 if ( $label ) {
562 $html .= '<label for="' . esc_attr( $name ) . '[formatted_value]">' . esc_html( $label ) . '</label>';
563 }
564 $html .= '<div class="os-time-input-fields">';
565 $html .= '<input type="text" placeholder="HH:MM" name="' . esc_attr( $name ) . '[formatted_value]" value="' . esc_attr( $formatted_value ) . '" class="os-form-control os-mask-time"/>';
566
567 // am-pm toggler switch
568 if ( ! OsTimeHelper::is_army_clock() ) {
569 $is_am = ( OsTimeHelper::am_or_pm( $value ) == 'am' );
570 $am_active = ( $is_am ) ? 'active' : '';
571 $pm_active = ( ! $is_am ) ? 'active' : '';
572 $html .= '<input type="hidden" name="' . esc_attr( $name ) . '[ampm]" value="' . esc_attr( OsTimeHelper::am_or_pm( $value ) ) . '" class="ampm-value-hidden-holder"/>';
573 $html .= '<div class="time-ampm-w"><div class="time-ampm-select time-am ' . $am_active . '" data-ampm-value="am">' . esc_html__( 'am', 'latepoint' ) . '</div><div class="time-ampm-select time-pm ' . $pm_active . '" data-ampm-value="pm">' . esc_html__( 'pm', 'latepoint' ) . '</div></div>';
574 }
575
576 $html .= '</div>';
577 $html .= '</div>';
578
579 return $html;
580 }
581
582
583 public static function color_picker( $name, $label, $value = '', $atts = array(), $wrapper_atts = array() ) {
584 $extra_class = '';
585 if ( $value != '' ) {
586 $extra_class = ' has-value';
587 }
588 $html = '';
589 if ( ! empty( $wrapper_atts ) ) {
590 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
591 }
592 $html .= '<div ' . self::atts_string_from_array( array( 'class' => 'os-form-group os-form-group-transparent os-form-color-picker-group' . $extra_class ) ) . '>';
593 if ( $label ) {
594 $html .= '<label for="' . esc_attr( $name ) . '">' . esc_html( $label ) . '</label>';
595 }
596 $html .= '<div class="latepoint-color-picker-w">';
597 $html .= '<div class="latepoint-color-picker" data-color="' . esc_attr( $value ) . '"></div>';
598 $html .= '<input maxlength="7" type="text" name="' . esc_attr( $name ) . '" placeholder="' . esc_attr__( 'Pick a color', 'latepoint' ) . '" value="' . esc_attr( $value ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . '/>';
599 $html .= '</div>';
600 $html .= '</div>';
601 if ( ! empty( $wrapper_atts ) ) {
602 $html .= '</div>';
603 }
604
605 return $html;
606 }
607
608 public static function name_to_id( $name, $atts = [] ) {
609 $name = strtolower( preg_replace( '/[^0-9a-zA-Z_]/', '_', $name ) );
610 $name = preg_replace( '/__+/', '_', $name );
611 $name = rtrim( $name, '_' );
612 if ( isset( $atts['add_unique_id'] ) && $atts['add_unique_id'] ) {
613 $name .= '_' . OsUtilHelper::random_text( 'hexdec', 8 );
614 }
615 if ( isset( $atts['add_string_to_id'] ) && $atts['add_string_to_id'] ) {
616 $name .= $atts['add_string_to_id'];
617 }
618
619 return $name;
620 }
621
622
623 // Value: on
624 public static function checkbox_field( $name, $label, $value = '', $is_checked = false, $atts = array(), $wrapper_atts = array(), $off_value = 'off' ) {
625 $html = '';
626 // generate id if not set
627 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
628 $atts['id'] = self::name_to_id( $name, $atts );
629 }
630 if ( ! empty( $wrapper_atts ) ) {
631 $html .= '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
632 }
633 $checked_class = $is_checked ? 'is-checked' : '';
634 if ( isset( $atts['data-toggle-element'] ) ) {
635 $checked_class .= ' has-toggle-element';
636 }
637 if ( isset( $atts['data-inverse-toggle'] ) ) {
638 $checked_class .= ' inverse-toggle';
639 }
640
641 // validations
642 if ( ! empty( $atts['validate'] ) ) {
643 $validate_html = 'data-os-validate="' . esc_attr( implode( ' ', $atts['validate'] ) ) . '"';
644 } else {
645 $validate_html = '';
646 }
647 unset( $atts['validate'] );
648
649 $checked_attr = $is_checked ? 'checked' : '';
650 $html .= '<div ' . self::atts_string_from_array( array( 'class' => 'os-form-group os-form-checkbox-group ' . $checked_class ) ) . '>';
651 if ( $label ) {
652 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">';
653 }
654 if ( $off_value !== false ) {
655 $html .= '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $off_value ) . '"/>';
656 }
657 $html .= '<input type="checkbox" ' . $validate_html . ' name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" ' . $checked_attr . ' ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-checkbox' ] ) . '/>';
658 if ( $label ) {
659 $html .= '<div>' . wp_kses_post( $label ) . '</div>' . '</label>';
660 }
661 $html .= '</div>';
662 if ( ! empty( $wrapper_atts ) ) {
663 $html .= '</div>';
664 }
665
666 return $html;
667 }
668
669 /**
670 * @param string $name
671 * @param string $label
672 * @param string $value
673 * @param array $atts
674 * @param array $wrapper_atts
675 * @param array $form_group_atts
676 *
677 * @return string
678 */
679 public static function money_field( $name, $label, $value = '', $atts = [], $wrapper_atts = [], $form_group_atts = [] ) {
680 $input_class = 'os-mask-money';
681 if ( isset( $atts['class'] ) ) {
682 $input_class .= ' ' . $atts['class'];
683 }
684 $atts = array_merge( $atts, [ 'class' => $input_class, 'inputmode' => 'decimal' ] );
685 $value = OsMoneyHelper::to_money_field_format( $value );
686
687 return self::text_field( $name, $label, $value, $atts, $wrapper_atts, $form_group_atts );
688 }
689
690 /**
691 * @param string $name
692 * @param string $label
693 * @param string $value
694 * @param array $atts
695 * @param array $wrapper_atts
696 *
697 * @return string
698 *
699 * Generates a text input field
700 */
701 public static function text_field( $name, $label, $value = '', $atts = [], $wrapper_atts = [], $form_group_atts = [] ) {
702 $extra_class = ' os-form-group-transparent';
703 if ( isset( $atts['theme'] ) ) {
704 switch ( $atts['theme'] ) {
705 case 'bordered':
706 $extra_class = ' os-form-group-bordered';
707 break;
708 case 'right-aligned':
709 $extra_class = ' os-form-group-right-aligned';
710 break;
711 case 'simple':
712 $extra_class = ' os-form-group-simple';
713 unset( $atts['theme'] );
714 break;
715 }
716 }
717 if ( isset( $form_group_atts['class'] ) ) {
718 $extra_class .= ' ' . $form_group_atts['class'] . ' ';
719 unset( $form_group_atts['class'] );
720 }
721 // generate id if not set
722 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
723 $atts['id'] = self::name_to_id( $name, $atts );
724 }
725 if ( $value != '' ) {
726 $extra_class .= ' has-value';
727 }
728 if ( empty( $label ) ) {
729 $extra_class .= ' no-label';
730 }
731
732 // validations
733 if ( ! empty( $atts['validate'] ) ) {
734 $validate_html = 'data-os-validate="' . esc_attr( implode( ' ', $atts['validate'] ) ) . '"';
735 } else {
736 $validate_html = '';
737 }
738 unset( $atts['validate'] );
739 $html = '';
740 if ( ! empty( $wrapper_atts ) ) {
741 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
742 }
743 $html .= '<div class ="os-form-group os-form-textfield-group' . esc_attr( $extra_class ) . '" ' . self::atts_string_from_array( $form_group_atts ) . '>';
744 $placeholder = ( ! empty( $atts['placeholder'] ) ) ? $atts['placeholder'] : $label;
745 if ( $label ) {
746 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">' . esc_html( $label ) . '</label>';
747 }
748 $input_class = 'os-form-control';
749 $html .= '<input ' . $validate_html . ' type="' . esc_attr( ( $atts['type'] ?? 'text' ) ) . '" placeholder="' . esc_attr( $placeholder ) . '" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => $input_class ] ) . '/>';
750 $html .= '</div>';
751 if ( ! empty( $wrapper_atts ) ) {
752 $html .= '</div>';
753 }
754
755 return $html;
756 }
757
758 /**
759 * @param string $name
760 * @param string $label
761 * @param string $value
762 * @param array $atts
763 * @param array $wrapper_atts
764 *
765 * @return string
766 *
767 * Generates a telephone text input field
768 */
769 public static function phone_number_field( $name, $label, $value = '', $atts = [], $wrapper_atts = [], $form_group_atts = [] ) {
770 // Remain standards compliant
771 $atts['type'] = 'tel';
772 $atts['format'] = '[0-9]*';
773
774 $atts['class'] = $atts['class'] ?? '';
775 if ( strpos( $atts['class'], 'os-mask-phone' ) === false ) {
776 $atts['class'] .= ' os-mask-phone';
777 }
778 $form_group_atts['class'] = ( $form_group_atts['class'] ?? '' ) . ' os-form-phonefield-group';
779
780 $atts['validate'] = empty( $atts['validate'] ) ? [] : $atts['validate'];
781 if ( OsSettingsHelper::is_on( 'validate_phone_number' ) && in_array( 'presence', $atts['validate'] ) ) {
782 // validate phone if the field is required
783 $atts['validate'][] = 'phone';
784 }
785
786 return self::text_field( $name, $label, $value, $atts, $wrapper_atts, $form_group_atts );
787 }
788
789
790 /**
791 * @param string $name
792 * @param string $placeholder
793 * @param string $value
794 *
795 * @return string
796 *
797 * Generates quantity input field
798 */
799 public static function quantity_field( $name, $placeholder, $value = '' ): string {
800 return '<div class="item-quantity-selector-w">
801 <div class="item-quantity-selector item-quantity-selector-minus" data-sign="minus"></div>
802 <input type="text" name="' . esc_attr( $name ) . '" class="item-quantity-selector-input" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $placeholder ) . '">
803 <div class="item-quantity-selector item-quantity-selector-plus" data-sign="plus"></div>
804 </div>';
805 }
806
807 /**
808 * @param string $name
809 * @param string $label
810 * @param string $value
811 * @param int|float|null $min
812 * @param int|float|null $max
813 * @param array $atts
814 * @param array $wrapper_atts
815 *
816 * @return string
817 *
818 * Generates a numeric text input field
819 */
820 public static function number_field( $name, $label, $value = '', $min = null, $max = null, $atts = [], $wrapper_atts = [], $form_group_atts = [] ): string {
821 $atts['type'] = 'number';
822 if ( is_numeric( $min ) ) {
823 $atts['min'] = $min;
824 }
825 if ( is_numeric( $max ) && ( ! is_numeric( $min ) || $max >= $min ) ) {
826 $atts['max'] = $max;
827 }
828
829 return self::text_field( $name, $label, $value, $atts, $wrapper_atts, $form_group_atts );
830 }
831
832 public static function password_field( $name, $label, $value = '', $atts = array(), $wrapper_atts = array() ) {
833 $extra_class = ' os-form-group-transparent';
834 if ( isset( $atts['theme'] ) ) {
835 switch ( $atts['theme'] ) {
836 case 'bordered':
837 $extra_class = ' os-form-group-bordered';
838 break;
839 case 'right-aligned':
840 $extra_class = ' os-form-group-right-aligned';
841 break;
842 case 'simple':
843 $extra_class = ' os-form-group-simple';
844 unset( $atts['theme'] );
845 break;
846 }
847 }
848 // generate id if not set
849 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
850 $atts['id'] = self::name_to_id( $name, $atts );
851 }
852 if ( $value != '' ) {
853 $extra_class .= ' has-value';
854 }
855 if ( empty( $label ) ) {
856 $extra_class .= ' no-label';
857 }
858 $html = '';
859 if ( ! empty( $wrapper_atts ) ) {
860 $html = '<div ' . self::atts_string_from_array( $wrapper_atts ) . '>';
861 }
862 $html .= '<div ' . self::atts_string_from_array( array( 'class' => 'os-form-group os-form-textfield-group' . $extra_class ) ) . '>';
863 $placeholder = ( isset( $atts['placeholder'] ) && ! empty( $atts['placeholder'] ) ) ? $atts['placeholder'] : $label;
864 if ( $label ) {
865 $html .= '<label for="' . esc_attr( $atts['id'] ) . '">' . esc_html( $label ) . '</label>';
866 }
867 $html .= '<input type="password" placeholder="' . esc_attr( $placeholder ) . '" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" ' . self::atts_string_from_array( $atts, [ 'class' => 'os-form-control' ] ) . '/>';
868 $html .= '</div>';
869 if ( ! empty( $wrapper_atts ) ) {
870 $html .= '</div>';
871 }
872
873 return $html;
874 }
875
876 public static function hidden_field( $name, $value, $atts = array() ) {
877 // generate id if not set
878 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
879 $atts['id'] = self::name_to_id( $name, $atts );
880 }
881 $html = '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" ' . self::atts_string_from_array( $atts ) . '/>';
882
883 return $html;
884 }
885
886
887 public static function radio_field( $name, $value, $checked = false, $atts = array() ) {
888 // generate id if not set
889 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
890 $atts['id'] = self::name_to_id( $name, $atts );
891 }
892 $checked_html = $checked ? 'checked' : '';
893 $html = '<input ' . $checked_html . ' type="radio" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" ' . self::atts_string_from_array( $atts ) . '/>';
894
895 return $html;
896 }
897
898
899 public static function button( $name, $label, $type = 'button', $atts = array(), $icon = false ) {
900 // generate id if not set
901 if ( ! isset( $atts['id'] ) && ! isset( $atts['skip_id'] ) ) {
902 $atts['id'] = self::name_to_id( $name, $atts );
903 }
904 $html = '<div class="os-form-group">';
905 if ( $icon ) {
906 $label = '<i class="latepoint-icon ' . esc_attr( $icon ) . '"></i><span>' . $label . '</span>';
907 }
908 $html .= '<button type="' . esc_attr( $type ) . '" name="' . esc_attr( $name ) . '" ' . self::atts_string_from_array( $atts ) . '>' . esc_html( $label ) . '</button>';
909 $html .= '</div>';
910
911 return $html;
912 }
913 }