<?php /***************************************************************************** * FormView.php * Contains the form template. * * Kabuki CMS (C) 2013-2023, Aaron van Geffen *****************************************************************************/ class FormView extends SubTemplate { private $form; private array $data; private array $missing; private $title; public function __construct(Form $form, $title = '') { $this->form = $form; $this->title = $title; } protected function html_content($exclude = [], $include = []) { if (!empty($this->title)) echo ' <h1>', $this->title, '</h1>'; foreach ($this->_subtemplates as $template) $template->html_main(); echo ' <form action="', $this->form->request_url, '" method="', $this->form->request_method, '" enctype="multipart/form-data">'; if (isset($this->form->content_above)) echo $this->form->content_above; $this->missing = $this->form->getMissing(); $this->data = $this->form->getData(); foreach ($this->form->getFields() as $field_id => $field) { // Either we have a blacklist if (!empty($exclude) && in_array($field_id, $exclude)) continue; // ... or a whitelist elseif (!empty($include) && !in_array($field_id, $include)) continue; // ... or neither (ha) $this->renderField($field_id, $field); } echo ' <input type="hidden" name="', Session::getSessionTokenKey(), '" value="', Session::getSessionToken(), '"> <div class="form-group"> <div class="offset-sm-2 col-sm-10"> <button type="submit" name="submit" class="btn btn-primary">', $this->form->getSubmitButtonCaption(), '</button>'; if (isset($this->form->content_below)) echo ' ', $this->form->content_below; echo ' </div> </div> </form>'; } protected function renderField($field_id, array $field) { if (isset($field['before_html'])) echo ' ', $field['before_html']; echo ' <div class="row mb-2">'; if (isset($field['before'])) echo $field['before']; if ($field['type'] !== 'checkbox') if (isset($field['label'])) echo ' <label class="col-sm-2 col-form-label" for="', $field_id, '"', in_array($field_id, $this->missing) ? ' style="color: red"' : '', '>', $field['label'], ':</label> <div class="', isset($field['class']) ? $field['class'] : 'col-sm-6', '">'; else echo ' <div class="offset-sm-2 ', isset($field['class']) ? $field['class'] : 'col-sm-6', '">'; switch ($field['type']) { case 'select': $this->renderSelect($field_id, $field); break; case 'radio': $this->renderRadio($field_id, $field); break; case 'checkbox': $this->renderCheckbox($field_id, $field); break; case 'textarea': $this->renderTextArea($field_id, $field); break; case 'color': $this->renderColor($field_id, $field); break; case 'numeric': $this->renderNumeric($field_id, $field); break; case 'file': $this->renderFile($field_id, $field); break; case 'captcha': $this->renderCaptcha($field_id, $field); break; case 'text': case 'password': default: $this->renderText($field_id, $field); } if (isset($field['after'])) echo ' ', $field['after']; if ($field['type'] !== 'checkbox') echo ' </div>'; echo ' </div>'; } private function renderCaptcha($field_id, array $field) { echo ' <div class="g-recaptcha" data-sitekey="', RECAPTCHA_API_KEY, '"></div> <script src="https://www.google.com/recaptcha/api.js"></script>'; } private function renderCheckbox($field_id, array $field) { echo ' <div class="offset-sm-2 col-sm-10"> <div class="form-check"> <input class="form-check-input" type="checkbox"', $this->data[$field_id] ? ' checked' : '', !empty($field['disabled']) ? ' disabled' : '', ' name="', $field_id, '" id="check-', $field_id, '"> <label class="form-check-label" for="check-', $field_id, '"> ', $field['label'], ' </label> </div> </div>'; } private function renderColor($field_id, array $field) { echo ' <input class="form-control" type="color" name="', $field_id, '" id="', $field_id, '" value="', htmlspecialchars($this->data[$field_id]), '"', !empty($field['disabled']) ? ' disabled' : '', '>'; } private function renderFile($field_id, array $field) { if (!empty($this->data[$field_id])) echo 'Currently using asset <tt>', $this->data[$field_id], '</tt>. Upload to overwrite.<br>'; echo ' <input class="form-control" type="file" name="', $field_id, '" id="', $field_id, '"', !empty($field['disabled']) ? ' disabled' : '', '>'; } private function renderNumeric($field_id, array $field) { echo ' <input class="form-control" type="number"', isset($field['step']) ? ' step="' . $field['step'] . '"' : '', ' min="', isset($field['min_value']) ? $field['min_value'] : '0', '"', ' max="', isset($field['max_value']) ? $field['max_value'] : '9999', '"', ' name="', $field_id, '" id="', $field_id, '"', isset($field['size']) ? ' size="' . $field['size'] . '"' : '', isset($field['maxlength']) ? ' maxlength="' . $field['maxlength'] . '"' : '', ' value="', htmlspecialchars($this->data[$field_id]), '"', !empty($field['disabled']) ? ' disabled' : '', '>'; } private function renderRadio($field_id, array $field) { foreach ($field['options'] as $value => $option) echo ' <div class="form-check"> <input class="form-check-input" type="radio" name="', $field_id, '" id="radio-', $field_id, '-', $value, '" value="', $value, '"', $this->data[$field_id] == $value ? ' checked' : '', !empty($field['disabled']) ? ' disabled' : '', '> <label class="form-check-label" for="radio-', $field_id, '-', $value, '"> ', htmlspecialchars($option), ' </label> </div>'; } private function renderSelect($field_id, array $field) { echo ' <select class="form-select" name="', $field_id, !empty($field['multiple']) ? '[]' : '', '" id="', $field_id, '"', !empty($field['disabled']) ? ' disabled' : '', !empty($field['multiple']) ? ' multiple' : '', !empty($field['size']) ? ' size="' . $field['size'] . '"' : '', '>'; if (isset($field['placeholder'])) echo ' <option value="">', $field['placeholder'], '</option>'; foreach ($field['options'] as $key => $value) { if (is_array($value)) { assert(empty($field['multiple'])); $this->renderSelectOptionGroup($field_id, $key, $value); } else $this->renderSelectOption($field_id, $value, $key, !empty($field['multiple'])); } echo ' </select>'; } private function renderSelectOption($field_id, $label, $value, $multiple = false) { echo ' <option value="', $value, '"', !$multiple && $this->data[$field_id] == $value ? ' selected' : '', $multiple && in_array($value, $this->data[$field_id]) ? ' selected' : '', '>', htmlspecialchars($label), '</option>'; } private function renderSelectOptionGroup($field_id, $label, $options) { echo ' <optgroup label="', $label, '">'; foreach ($options as $value => $option) $this->renderSelectOption($field_id, $option, $value); echo ' </optgroup>'; } private function renderText($field_id, array $field) { echo ' <input class="form-control" ', 'type="', $field['type'], '" ', 'name="', $field_id, '" ', 'id="', $field_id, '"', isset($field['size']) ? ' size="' . $field['size'] . '"' : '', isset($field['maxlength']) ? ' maxlength="' . $field['maxlength'] . '"' : '', isset($this->data[$field_id]) ? ' value="' . htmlspecialchars($this->data[$field_id]) . '"' : '', isset($field['placeholder']) ? ' placeholder="' . $field['placeholder'] . '"' : '', !empty($field['disabled']) ? ' disabled' : '', isset($field['trigger']) ? ' class="trigger-' . $field['trigger'] . '"' : '', '>'; } private function renderTextArea($field_id, array $field) { echo ' <textarea class="form-control' . '" name="', $field_id, '" id="', $field_id, '" cols="', isset($field['columns']) ? $field['columns'] : 40, '" rows="', isset($field['rows']) ? $field['rows'] : 4, '"', isset($field['placeholder']) ? ' placeholder="' . $field['placeholder'] . '"' : '', '"', !empty($field['disabled']) ? ' disabled' : '', '>', $this->data[$field_id], '</textarea>'; } }