'number', 'label' => 'Price']); * echo Form::render('email', '', ['type' => 'email', 'required' => true]); */ class Form { /** * Render a form field based on type */ public static function render(string $name, mixed $value, array $config = []): string { if ($value === null) { $value = ''; } if (!empty($config['hidden'])) { return ''; } $type = $config['type'] ?? 'text'; $method = 'render' . str_replace('_', '', ucwords($type, '_')); $output = method_exists(static::class, $method) ? static::$method($name, $value, $config) : static::renderText($name, $value, $config); return apply_filters('jvbRenderFormMeta', $output, $name, $config, $value, null); } /** * Render with Meta instance (convenience method) */ public static function renderFrom(Meta $meta, string $name): string { $value = $meta->get($name); $config = $meta->config($name) ?? ['type' => 'text']; return static::render($name, $value, $config); } /** * Render complete form from Meta instance */ public static function renderFormFrom(Meta $meta, string $endpoint, array $options = []): string { $id = $options['form-id'] ?? $endpoint; $classes = isset($options['classes']) ? ' class="' . implode(' ', $options['classes']) . '"' : ''; $output = '
'; return $output; } // ───────────────────────────────────────────────────────────── // Helper Methods // ───────────────────────────────────────────────────────────── public static function fieldWrap(string $name, string $content, array $config, bool $col = false): string { if (!array_key_exists('type', $config)) { jvbDump('No type set for '.$name.' with config: '.print_r($config, true)); } $classes = static::buildClasses($config); $datasets = static::buildDatasets($config); if (!array_key_exists('type', $config)) { error_log('Config without type: '.print_r($config, true)); } $output = sprintf( '%s
', esc_attr($name), esc_html($config['description']) ); } return ''; } protected static function inputAttrs(string $name, array $config): string { $attrs = [ 'id' => $name, 'name' => $name, ]; if (!empty($config['placeholder'])) { $attrs['placeholder'] = $config['placeholder']; } if (!empty($config['autocomplete'])) { $attrs['autocomplete'] = $config['autocomplete']; } if (isset($config['min'])) { $attrs['min'] = $config['min']; } if (isset($config['max'])) { $attrs['max'] = $config['max']; } if (isset($config['step'])) { $attrs['step'] = $config['step']; } $html = ''; //Add the attributes that stand on their own $standalones = ['required', 'disabled', 'readonly','multiple']; foreach($standalones as $s) { if (array_key_exists($s, $config) && $config[$s] === true) { $html .= ' '.$s; } } foreach ($attrs as $key => $val) { $html .= sprintf(' %s="%s"', $key, esc_attr($val)); } return $html; } // ───────────────────────────────────────────────────────────── // Type Renderers // ───────────────────────────────────────────────────────────── protected static function renderText(string $name, mixed $value, array $config): string { $value = ($value !== '') ? ' value="'.esc_attr($value).'"' : ''; $input = sprintf( '', $config['subtype']??'text', $value, static::inputAttrs($name, $config) ); return static::fieldWrap($name, $input, $config); } protected static function renderTextarea(string $name, mixed $value, array $config): string { $rows = $config['rows'] ?? 5; $quill = (array_key_exists('quill', $config) && $config['quill'] === true) ? ' data-editor="true"' : ''; if ($quill !== '') { $allowImages = array_key_exists('allowImage', $config); $quill .= ($allowImages) ? ' data-allowimage="true"' : ' data-allowimage="false"'; } $textarea = sprintf( '', $rows, static::inputAttrs($name, $config), $quill, esc_textarea($value) ); return static::fieldWrap($name, $textarea, $config); } protected static function renderNumber(string $name, mixed $value, array $config): string { $attrs = static::inputAttrs($name, $config); $value = ($value !== '') ? ' value="'.esc_attr($value).'"' : ''; $input = sprintf( '', $value, $attrs ); return static::fieldWrap($name, $input, $config); } protected static function renderQuantity(string $name, mixed $value, array $config): string { if (!array_key_exists('class', $config)) { $config['class']=[]; } $config['class'][] ='quantity-input'; $attrs = static::inputAttrs($name, $config); $value = ($value !== '') ? ' value="'.esc_attr($value).'"' : ''; $input = sprintf( '
Click to upload or drag and drop
%s
(max. %s)
You can group images to create separate %s.
If a %s has multiple images, you can select the %s to set an image as the main one.
', $plural, $singular, jvbIcon('star') ); } if (array_key_exists('upload_description', $config) && $config['upload_description']!==''){ $input .= sprintf('%s
', esc_html($config['upload_description'])); } $input .= ''; $input .= jvbRenderProgressBar('', false, true, true); $input .= '%s These will become individual %s %s
Google Maps not configured. Please configure in Integrations settings.
Current location: %s
Search below to change:
', esc_html($value['address']) ); } $links = (!empty($value)) ? jvbLocationLinks($value) : ''; $input .= sprintf( '{ loading items }
{ nothing found }