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