depage-forms v1.4.1
html forms made easy
Loading...
Searching...
No Matches
HtmlForm.php
Go to the documentation of this file.
1<?php
2
14
64
65namespace Depage\HtmlForm;
66
67
73function autoload($class)
74{
75 $class = str_replace('\\', '/', str_replace(__NAMESPACE__ . '\\', '', $class));
76 $filePath = __DIR__ . '/' . $class . '.php';
77 $filePath = str_replace('..', '', $filePath);
78
79 $resolved = realpath($filePath);
80 if ($resolved !== false && file_exists($resolved)) {
81 require_once($resolved);
82 }
83}
84
85spl_autoload_register(__NAMESPACE__ . '\autoload');
86
132{
133 public const priorityCountries = [
134 'en' => ['us','gb','ie','au','nz'],
135 'de' => ['de','at','ch'],
136 'fr' => ['fr','ch','be','lu','ca'],
137 'it' => ['it','ch'],
138 ];
142 protected $method;
143
147 protected $url;
148
152 protected $submitURL;
153
157 protected $successURL;
158
162 protected $cancelURL;
163
167 protected $label;
168
172 protected $backLabel;
173
177 protected $cancelLabel;
178
182 protected $class;
183
187 protected $validator;
188
192 protected $jsValidation;
193
197 protected $jsAutosave;
198
203
207 protected $sessionSlot;
208
212 private $currentStepId;
213
217 private $steps = [];
218
222 protected $ttl;
223
227 public $valid;
228
232 public $isAutoSaveRequest = false;
233
237 protected $internalFields = [
238 'formIsValid',
239 'formIsAutosaved',
240 'formName',
241 'formTimestamp',
242 'formStep',
243 'formFinalPost',
244 'formCsrfToken',
245 'formCaptcha',
246 ];
247
251 protected $namespaces = ['\\Depage\\HtmlForm\\Elements'];
260 public function __construct(string $name, array $parameters = [], HtmlForm|null $form = null)
261 {
262 // workaround for crash with gettext when LANG is not set in the environment
263 // gettext is used in default settings of some input elements (e,g, error messages)
264 if (empty(getenv('LANG'))) {
265 $fallback = getenv('LANGUAGE') ?: 'en_US.UTF-8';
266 putenv('LANG=' . $fallback);
267 }
268 $this->isAutoSaveRequest = isset($_POST['formAutosave']) && $_POST['formAutosave'] === "true";
269
270 parent::__construct($name, $parameters, $this);
271
272 $this->url = parse_url($this->submitURL);
273 if (!empty($this->successURL)) {
274 $this->validateRedirectUrl($this->successURL, true);
275 }
276 if (!empty($this->cancelURL)) {
277 $this->validateRedirectUrl($this->cancelURL, true);
278 }
279 if (empty($this->successURL)) {
280 $this->successURL = $this->submitURL;
281 }
282 if (empty($this->cancelURL)) {
283 $this->cancelURL = $this->submitURL;
284 }
285
286 $this->currentStepId = isset($_GET['step']) ? $_GET['step'] : 0;
287
288 $this->startSession();
289
290 $this->valid = (isset($this->sessionSlot['formIsValid'])) ? $this->sessionSlot['formIsValid'] : null;
291
292 // set CSRF Token
293 if (!isset($this->sessionSlot['formCsrfToken'])) {
294 $this->sessionSlot['formCsrfToken'] = $this->getNewCsrfToken();
295 }
296
297 if (!isset($this->sessionSlot['formFinalPost'])) {
298 $this->sessionSlot['formFinalPost'] = false;
299 }
300
301 // create a hidden input to tell forms apart
302 $this->addHidden('formName')->setValue($this->name);
303
304 // create hidden input for submitted step
305 $this->addHidden('formStep')->setValue($this->currentStepId);
306
307 // create hidden input for CSRF token
308 $this->addHidden('formCsrfToken')->setValue($this->sessionSlot['formCsrfToken']);
309
310 $this->addChildElements();
311 }
312
321 protected function setDefaults(): void
322 {
323 parent::setDefaults();
324
325 $this->defaults['label'] = 'submit';
326 $this->defaults['cancelLabel'] = '';
327 $this->defaults['backLabel'] = '';
328 $this->defaults['class'] = '';
329 $this->defaults['method'] = 'post';
330 // @todo adjust submit url for steps when used
331 $this->defaults['submitURL'] = $_SERVER['REQUEST_URI'];
332 $this->defaults['successURL'] = null;
333 $this->defaults['cancelURL'] = null;
334 $this->defaults['validator'] = null;
335 $this->defaults['ttl'] = 60 * 60; // 60 minutes
336 $this->defaults['jsValidation'] = 'blur';
337 $this->defaults['jsAutosave'] = 'false';
338 }
339
348 private function startSession(): void
349 {
350 // check if there's an open session
351 if (!session_id()) {
352 $params = session_get_cookie_params();
353 $sessionName = session_name();
354
355 session_set_cookie_params([
356 'lifetime' => $this->ttl,
357 'path' => $params['path'],
358 'domain' => $params['domain'],
359 'secure' => $params['secure'],
360 'httponly' => $params['httponly'],
361 'samesite' => 'Lax',
362 ]);
363 session_start();
364
365 // Extend the expiration time upon page load
366 if (isset($_COOKIE[$sessionName])) {
367 setcookie(
368 $sessionName,
369 $_COOKIE[$sessionName],
370 time() + $this->ttl,
371 $params['path'],
372 $params['domain'],
373 $params['secure'],
374 $params['httponly'],
375 );
376 }
377 }
378 $this->sessionSlotName = 'htmlform-' . $this->name . '-data';
379 $this->sessionSlot = & $_SESSION[$this->sessionSlotName];
380
381 $this->sessionExpiry();
382 }
391 private function sessionExpiry(): void
392 {
393 if (isset($this->ttl) && is_numeric($this->ttl)) {
394 $timestamp = time();
395
396 if (
397 isset($this->sessionSlot['formTimestamp'])
398 && ($timestamp - $this->sessionSlot['formTimestamp'] > $this->ttl)
399 ) {
400 $this->clearSession();
401 $this->sessionSlot = & $_SESSION[$this->sessionSlotName];
402 }
403
404 $this->sessionSlot['formTimestamp'] = $timestamp;
405 }
406 }
412 public function isEmpty()
413 {
414 return !isset($this->sessionSlot['formName']);
415 }
416
422 protected function getNewCsrfToken(): string
423 {
424 return base64_encode(openssl_random_pseudo_bytes(16));
425 }
426
438 protected function addElement(string $type, string $name, array $parameters): Abstracts\Element
439 {
440 $this->checkElementName($name);
441
442 $newElement = parent::addElement($type, $name, $parameters);
443
444 if ($newElement instanceof Elements\Step) {
445 $this->steps[] = $newElement;
446 }
447 if ($newElement instanceof Abstracts\Input) {
448 $this->updateInputValue($name);
449 }
450
451 return $newElement;
452 }
453
462 public function checkElementName(string $name): void
463 {
464 foreach ($this->getElements(true) as $element) {
465 if ($element->getName() === $name) {
466 throw new Exceptions\DuplicateElementNameException("Element name \"{$name}\" already in use.");
467 }
468 }
469 }
470
475 private function getCurrentElements(): array
476 {
477 $currentElements = [];
478
479 foreach ($this->elements as $element) {
480 if ($element instanceof Abstracts\Container) {
481 if (
482 !($element instanceof Elements\Step)
483 || (isset($this->steps[$this->currentStepId]) && ($element == $this->steps[$this->currentStepId]))
484 ) {
485 $currentElements = array_merge($currentElements, $element->getElements());
486 }
487 } else {
488 $currentElements[] = $element;
489 }
490 }
491
492 return $currentElements;
493 }
500 public function registerNamespace(string $namespace): void
501 {
502 $this->namespaces[] = $namespace;
503 }
504
509 public function getNamespaces(): array
510 {
511 return $this->namespaces;
512 }
513
520 private function inCurrentStep(string $name): bool
521 {
522 return in_array($this->getElement($name), $this->getCurrentElements());
523 }
534 public function setCurrentStep(int|null $step = null): void
535 {
536 if (!is_null($step)) {
537 $this->currentStepId = $step;
538 }
539 if (!is_numeric($this->currentStepId)
540 || ($this->currentStepId > count($this->steps) - 1)
541 || ($this->currentStepId < 0)
542 ) {
543 $this->currentStepId = $this->getFirstInvalidStep();
544 }
545 }
546 public function getUrl(): array
547 {
548 return $this->url;
549 }
550
555 public function getSteps(): array
556 {
557 return $this->steps;
558 }
559
564 public function getCurrentStepId(): int
565 {
566 return $this->currentStepId;
567 }
568
577 public function getFirstInvalidStep(): int
578 {
579 if (count($this->steps) > 0) {
580 foreach ($this->steps as $stepNumber => $step) {
581 if (!$step->validate()) {
582 return $stepNumber;
583 }
584 }
591 return count($this->steps) - 1;
592 } else {
593 return 0;
594 }
595 }
596
603 public function buildUrl(array $args = []): string
604 {
605 $url = isset($this->url['scheme']) ? $this->url['scheme'] . '://' : '';
606 $url .= $this->url['host'] ?? '';
607 $url .= isset($this->url['port']) ? ':' . $this->url['port'] : '';
608 $url .= $this->url['path'] ?? '';
609 $url .= $this->buildUrlQuery($args);
610
611 return $url;
612 }
613
619 public function buildUrlQuery(array $args = []): string
620 {
621 $query = '';
622 $queryParts = [];
623
624 if (isset($this->url['query']) && $this->url['query'] != "") {
625 //decoding query string
626 $query = html_entity_decode($this->url['query']);
627
628 //parsing the query into an array
629 parse_str($query, $queryParts);
630 }
631
632 foreach ($args as $name => $value) {
633 if ($value != "") {
634 $queryParts[$name] = $value;
635 } elseif (isset($queryParts[$name])) {
636 unset($queryParts[$name]);
637 }
638 }
639
640 // build the query again
641 $query = http_build_query($queryParts);
642
643 if ($query == "") {
644 return "";
645 }
646
647 return "?" . $query;
648 }
649
661 public function updateInputValue(string $name): void
662 {
663 $element = $this->getElement($name);
664
665 // handle captcha phrase
666 if ($this->getElement($name) instanceof Elements\Captcha) {
667 $element->setSessionSlot($this->sessionSlot);
668 }
669
670 // if it's a post, take the value from there and save it to the session
671 if (
672 isset($_POST['formName']) && ($_POST['formName'] === $this->name)
673 && $this->inCurrentStep($name)
674 && isset($_POST['formCsrfToken']) && $_POST['formCsrfToken'] === $this->sessionSlot['formCsrfToken']
675 ) {
676 if ($this->getElement($name) instanceof Elements\File) {
677 // handle uploaded file
678 $oldValue = isset($this->sessionSlot[$name]) ? $this->sessionSlot[$name] : null;
679 $this->sessionSlot[$name] = $element->handleUploadedFiles($oldValue);
680 } elseif (!$element->getDisabled()) {
681 // save value
682 $value = isset($_POST[$name]) ? $_POST[$name] : null;
683 $this->sessionSlot[$name] = $element->setValue($value);
684 } elseif (!isset($this->sessionSlot[$name])) {
685 // set default value for disabled elements
686 $this->sessionSlot[$name] = $element->setValue($element->getDefaultValue());
687 }
688 }
689 // if it's not a post, try to get the value from the session
690 elseif (isset($this->sessionSlot[$name])) {
691 $element->setValue($this->sessionSlot[$name]);
692 }
693 }
694
700 public function clearInputValue(string $name): void
701 {
702 $element = $this->getElement($name);
703
704 $this->sessionSlot[$name] = $element->clearValue();
705 }
706
716 public function populate(array|object $data = []): void
717 {
718 foreach ($this->getElements() as $element) {
719 $name = $element->name;
720 if (!in_array($name, $this->internalFields)) {
721 if (is_array($data) && isset($data[$name])) {
722 $value = $data[$name];
723 } elseif (is_object($data) && isset($data->$name)) {
724 $value = $data->$name;
725 }
726
727 if (isset($value)) {
728 $element->setDefaultValue($value);
729 if ($element->getDisabled() && !isset($this->sessionSlot[$name])) {
730 $this->sessionSlot[$name] = $value;
731 }
732 }
733
734 unset($value);
735 }
736 }
737 }
738
749 public function process(): void
750 {
751 $this->setCurrentStep();
752 // if there's post-data from this form
753 if (isset($_POST['formName']) && ($_POST['formName'] === $this->name)) {
754 // save in session if submission was from last step
755 $this->sessionSlot['formFinalPost'] = count($this->steps) == 0 || $_POST['formStep'] + 1 == count($this->steps)
757
758 if (!empty($this->cancelLabel) && isset($_POST['formSubmit']) && $_POST['formSubmit'] === $this->cancelLabel) {
759 // cancel button was pressed
760 $this->clearSession();
761 $this->redirect($this->cancelURL);
762 } elseif ($this->isAutoSaveRequest) {
763 // do not redirect -> is autosave
764 $this->onPost();
765 } elseif (!empty($this->backLabel) && isset($_POST['formSubmit']) && $_POST['formSubmit'] === $this->backLabel) {
766 // back button was pressed
767 $this->onPost();
768
769 $this->sessionSlot['formFinalPost'] = false;
770 $prevStep = $this->currentStepId - 1;
771 if ($prevStep < 0) {
772 $prevStep = 0;
773 }
774 $this->redirect($this->buildUrl(['step' => ($prevStep <= 0) ? '' : $prevStep]));
775 } elseif ($this->validate()) {
776 // form was successfully submitted
777 $this->onPost();
778
779 $this->redirect($this->successURL);
780 } else {
781 // goto to next step or display first invalid step
782 $this->onPost();
783
784 $nextStep = $this->currentStepId + 1;
785 $firstInvalidStep = $this->getFirstInvalidStep();
786 if ($nextStep > $firstInvalidStep) {
787 $nextStep = $firstInvalidStep;
788 }
789 if ($nextStep > count($this->steps)) {
790 $nextStep = count($this->steps) - 1;
791 }
792 $this->redirect($this->buildUrl(['step' => ($nextStep == 0) ? '' : $nextStep]));
793 }
794 }
795 }
796
806 public function validate(): bool
807 {
808 // onValidate hook for custom required/validation rules
809 $this->valid = $this->onValidate();
810
811 $this->valid = $this->valid && $this->validateAutosave();
812
813 if ($this->valid && !is_null($this->validator)) {
814 if (is_callable($this->validator)) {
815 $this->valid = call_user_func($this->validator, $this, $this->getValues());
816 } else {
817 throw new Exceptions\ValidatorNotCallable("The validator paramater must be callable");
818 }
819 }
820 $this->valid = $this->valid && $this->sessionSlot['formFinalPost'];
821
822 // save validation-state in session
823 $this->sessionSlot['formIsValid'] = $this->valid;
824
825 return $this->valid;
826 }
827
836 protected function onPost(): bool
837 {
838 return true;
839 }
840
849 protected function onValidate(): bool
850 {
851 return true;
852 }
853
862 public function validateAutosave(): bool
863 {
864 parent::validate();
865
866 if (isset($_POST['formCsrfToken'])) {
867 $hasCorrectToken = $_POST['formCsrfToken'] === $this->sessionSlot['formCsrfToken'];
868 $this->valid = $this->valid && $hasCorrectToken;
869
870 if (!$hasCorrectToken) {
871 $this->httpResponseCode(400);
872 $this->log("HtmlForm: Requst invalid because of incorrect CsrfToken");
873 }
874 }
875
876 $partValid = $this->valid;
877
878 // save data in session when autosaving but don't validate successfully
879 if ($this->isAutoSaveRequest
880 || (isset($this->sessionSlot['formIsAutosaved'])
881 && $this->sessionSlot['formIsAutosaved'] === true)
882 ) {
883 $this->valid = false;
884 }
885
886 // save whether form was autosaved the last time
887 $this->sessionSlot['formIsAutosaved'] = $this->isAutoSaveRequest;
888
889 return $partValid;
890 }
891
896 public function getValues(): ?array
897 {
898 if (isset($this->sessionSlot)) {
899 // remove internal attributes from values
900 return array_diff_key($this->sessionSlot, array_fill_keys($this->internalFields, ''));
901 } else {
902 return null;
903 }
904 }
905
910 public function getValuesWithLabel(): ?array
911 {
912 //get values first
913 $values = $this->getValues();
914 $valuesWithLabel = [];
915 if (isset($values)) {
916 foreach ($values as $element => $value) {
917 $elem = $this->getElement($element);
918
919 if ($elem) {
920 $valuesWithLabel[$element] = [
921 "value" => $value,
922 "label" => $elem->getLabel(),
923 ];
924 }
925 }
926
927 return $valuesWithLabel;
928 } else {
929 return null;
930 }
931 }
932
940 private function validateRedirectUrl(string $url, $allowExternal = false): void
941 {
942 if (empty($url)) {
943 return;
944 }
945
946 $parsed = parse_url($url);
947
948 if ($parsed === false) {
949 throw new \InvalidArgumentException("Invalid redirect URL.");
950 }
951
952 if (isset($parsed['scheme']) && $parsed['scheme'] !== 'https') {
953 //throw new \InvalidArgumentException("Only HTTPS redirects are allowed.");
954 }
955
956 if (!isset($parsed['host'])) {
957 return;
958 }
959
960 if (!$allowExternal) {
961 $allowedHosts = $_SERVER['HTTP_HOST'] ?? '';
962 $allowedHosts = array_map('trim', explode(',', $allowedHosts));
963 if (!in_array($parsed['host'], $allowedHosts, true)) {
964 throw new \InvalidArgumentException("Redirect to external host not allowed.");
965 }
966 }
967 }
975 private function validateRedirect(string $url): void
976 {
977 if (empty($url)) {
978 throw new \InvalidArgumentException("Empty URL.");
979 }
980
981 if (preg_match('/[\r\n]/', $url)) {
982 throw new \InvalidArgumentException("Invalid URL: newline characters detected.");
983 }
984
985 $parsed = parse_url($url);
986 if ($parsed === false) {
987 throw new \InvalidArgumentException("Invalid URL format.");
988 }
989
990 if (isset($parsed['scheme'])) {
991 $allowedSchemes = ['http', 'https'];
992 if (!in_array(strtolower($parsed['scheme']), $allowedSchemes, true)) {
993 throw new \InvalidArgumentException("Invalid URL scheme.");
994 }
995 }
996 }
1002 public function redirect(string $url): void
1003 {
1004 $this->validateRedirect($url);
1005 $safeUrl = htmlspecialchars($url, ENT_QUOTES | FILTER_FLAG_NO_ENCODE_QUOTES, 'UTF-8');
1006 header('Location: ' . $safeUrl);
1007 exit;
1008 }
1009
1014 public function httpResponseCode(int $code): void
1015 {
1016 http_response_code($code);
1017 }
1018
1025 public function clearSession(bool $clearCsrfToken = true): void
1026 {
1027 if ($clearCsrfToken) {
1028 // clear everything
1029 $this->clearValue();
1030
1031 unset($_SESSION[$this->sessionSlotName]);
1032 unset($this->sessionSlot);
1033 } else {
1034 // clear everything except internal fields
1035 foreach ($this->getElements(false) as $element) {
1036 if (!$element->getDisabled() && !in_array($element->name, $this->internalFields)) {
1037 unset($this->sessionSlot[$element->name]);
1038 }
1039 }
1040 }
1041 }
1042
1048 public static function clearOldSessions(int $ttl = 3600, string $pattern = "/^htmlform-.*/"): void
1049 {
1050 $timestamp = time();
1051
1052 if (empty($_SESSION)) {
1053 return;
1054 }
1055 foreach ($_SESSION as $key => &$val) {
1056 if (preg_match($pattern, $key)
1057 && isset($val['formTimestamp'])
1058 && ($timestamp - $val['formTimestamp'] > $ttl)
1059 ) {
1060 unset($_SESSION[$key]);
1061 }
1062 }
1063 }
1064
1068 protected function htmlDataAttributes(): string
1069 {
1070 $this->dataAttr['jsvalidation'] = $this->jsValidation;
1071 $this->dataAttr['jsautosave'] = $this->jsAutosave === true ? "true" : $this->jsAutosave;
1072
1073 return parent::htmlDataAttributes();
1074 }
1075
1078 protected function htmlSubmitURL(): string
1079 {
1080 $step = $this->currentStepId != 0 ? $this->currentStepId : '';
1081
1082 return $this->htmlEscape($this->buildUrl(['step' => $step]));
1083 }
1084
1092 public function __toString(): string
1093 {
1094 $renderedElements = '';
1095 $submit = '';
1096 $cancel = '';
1097 $back = '';
1098 $label = $this->htmlLabel();
1099 $cancellabel = $this->htmlCancelLabel();
1100 $backlabel = $this->htmlBackLabel();
1101 $class = $this->htmlClass();
1102 $method = $this->htmlMethod();
1103 $submitURL = $this->htmlSubmitURL();
1104 $dataAttr = $this->htmlDataAttributes();
1105 $disabledAttr = $this->disabled ? " disabled=\"disabled\"" : "";
1106
1107 foreach ($this->elementsAndHtml as $element) {
1108 // leave out inactive step elements
1109 if (!($element instanceof Elements\Step)
1110 || (isset($this->steps[$this->currentStepId]) && $this->steps[$this->currentStepId] == $element)
1111 ) {
1112 $renderedElements .= $element;
1113 }
1114 }
1115
1116 if (!empty($this->cancelLabel)) {
1117 $cancel = "<p id=\"{$this->name}-cancel\" class=\"cancel\"><input type=\"submit\" name=\"formSubmit\" value=\"{$cancellabel}\"$disabledAttr></p>\n";
1118 }
1119 if (!empty($this->backLabel) && $this->currentStepId > 0) {
1120 $back = "<p id=\"{$this->name}-back\" class=\"back\"><input type=\"submit\" name=\"formSubmit\" value=\"{$backlabel}\"$disabledAttr></p>\n";
1121 }
1122 if (!empty($this->label)) {
1123 $submit = "<p id=\"{$this->name}-submit\" class=\"submit\"><input type=\"submit\" name=\"formSubmit\" value=\"{$label}\"$disabledAttr></p>\n";
1124 }
1125
1126
1127 return "<form id=\"{$this->name}\" name=\"{$this->name}\" class=\"depage-form {$class}\" method=\"{$method}\" action=\"{$submitURL}\"{$dataAttr} enctype=\"multipart/form-data\">" . "\n" .
1128 $renderedElements .
1129 $submit .
1130 $cancel .
1131 $back .
1132 "</form>";
1133 }
1134}
1135
1163
1173
1184
1194
1205
1215
1227
1238
1249
1262
1271
1282
1283/* vim:set ft=php sw=4 sts=4 fdm=marker et : */
container element base class
Definition Container.php:60
addChildElements()
Sub-element generator hook.
$form
Parent form object reference.
Definition Container.php:72
clearValue()
Deletes values of all child elements.
getElement(string $name, bool $includeFieldsets=false)
Gets subelement by name.
getElements(bool $includeFieldsets=false)
Returns containers subelements.
log(string $argument, ?string $type=null)
error & warning logger
Definition Element.php:238
$dataAttr
Extra information about the data that is saved inside the element.
Definition Element.php:79
htmlEscape(array|string $options=[])
Escapes HTML in strings and arrays of strings.
Definition Element.php:263
main interface to users
Definition HtmlForm.php:132
$valid
Form validation result/status.
Definition HtmlForm.php:227
$isAutoSaveRequest
true if form request is from autosave call
Definition HtmlForm.php:232
registerNamespace(string $namespace)
Stores element namespaces for adding.
Definition HtmlForm.php:500
clearInputValue(string $name)
clearInputValue
Definition HtmlForm.php:700
$method
HTML form method attribute.
Definition HtmlForm.php:142
getCurrentStepId()
Returns the current step id.
Definition HtmlForm.php:564
$label
Contains the submit button label of the form.
Definition HtmlForm.php:167
validate()
Validates the forms subelements.
Definition HtmlForm.php:806
httpResponseCode(int $code)
Sets the HTTP response code.
$jsAutosave
Contains the javascript autosave type of the form.
Definition HtmlForm.php:197
$class
Contains the additional class value of the form.
Definition HtmlForm.php:182
$cancelURL
Specifies where the user is redirected to, once the form-data is cancelled.
Definition HtmlForm.php:162
getSteps()
Returns an array of steps.
Definition HtmlForm.php:555
__construct(string $name, array $parameters=[], HtmlForm|null $form=null)
HtmlForm class constructor.
Definition HtmlForm.php:260
$jsValidation
Contains the javascript validation type of the form.
Definition HtmlForm.php:192
getFirstInvalidStep()
Returns first step that didn't pass validation.
Definition HtmlForm.php:577
htmlDataAttributes()
Returns dataAttr escaped as attribute string.
$namespaces
Namespace strings for addible element classes.
Definition HtmlForm.php:251
onValidate()
Validation hook.
Definition HtmlForm.php:849
validateAutosave()
If the form is autosaving the validation property is defaulted to false.
Definition HtmlForm.php:862
$ttl
Time until session expiry (seconds)
Definition HtmlForm.php:222
getValues()
Gets form-data from current PHP session.
Definition HtmlForm.php:896
static clearOldSessions(int $ttl=3600, string $pattern="/^htmlform-.*/")
clearOldSessions
__toString()
Renders form to HTML.
process()
Calls form validation and handles redirects.
Definition HtmlForm.php:749
$submitURL
HTML form action attribute.
Definition HtmlForm.php:152
redirect(string $url)
Redirects Browser to a different URL.
checkElementName(string $name)
Checks for duplicate subelement names.
Definition HtmlForm.php:462
buildUrlQuery(array $args=[])
Adding step parameter to already existing query.
Definition HtmlForm.php:619
$successURL
Specifies where the user is redirected to, once the form-data is valid.
Definition HtmlForm.php:157
updateInputValue(string $name)
Updates the value of an associated input element.
Definition HtmlForm.php:661
$sessionSlot
PHP session handle.
Definition HtmlForm.php:207
clearSession(bool $clearCsrfToken=true)
Deletes the current forms' PHP session data.
$internalFields
List of internal fieldnames that are not part of the results.
Definition HtmlForm.php:237
$validator
Contains the validator function of the form.
Definition HtmlForm.php:187
$cancelLabel
Contains the cancel button label of the form.
Definition HtmlForm.php:177
populate(array|object $data=[])
Fills subelement values.
Definition HtmlForm.php:716
setCurrentStep(int|null $step=null)
Validates step number of GET request.
Definition HtmlForm.php:534
htmlSubmitURL()
Returns form url escaped as attribute string.
getValuesWithLabel()
Gets form-data from current PHP session but also contain elemnt labels.
Definition HtmlForm.php:910
setDefaults()
Collects initial values across subclasses.
Definition HtmlForm.php:321
$sessionSlotName
Contains the name of the array in the PHP session, holding the form-data.
Definition HtmlForm.php:202
$url
url of the current page
Definition HtmlForm.php:147
$backLabel
Contains the back button label of the form.
Definition HtmlForm.php:172
getNamespaces()
Returns list of registered namespaces.
Definition HtmlForm.php:509
isEmpty()
Returns wether form has been submitted before or not.
Definition HtmlForm.php:412
buildUrl(array $args=[])
Builds URL from parts.
Definition HtmlForm.php:603
getNewCsrfToken()
Returns new XSRF token.
Definition HtmlForm.php:422
addElement(string $type, string $name, array $parameters)
Adds input or fieldset elements to htmlform.
Definition HtmlForm.php:438
Abstract element classes.
Definition Container.php:11
Classes for HTML input-elements.
Definition Address.php:10
htmlform class and autoloader
autoload($class)
PHP autoloader.
Definition HtmlForm.php:73