Personal Website
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
3.6 KiB

<?php
namespace App\Classes;
use \Klein\Klein;
class Form {
private $router;
private $data = [];
private $resetLabel = '';
private $submitLabel = 'Submit';
private $errorKey = '';
public function __construct(Klein $router)
{
$this->router = $router;
$this->router->service()->csrfToken = Session::token();
$this->router->service()->form = $this;
$this->router->service()->injectView = '../app/views/form.php';
}
//-------------------------------------//
public function addField(string $name, array $field): void
{
// "name" => [
// "label",
// "type", text, email, tel, password, radio, textarea, checkbox(?), comment
// "data", (for radio fields) [ 'value' => 'Label', 'value' => 'Label']
// "rules", (server side rules)
// "message", (server side error message)
// "pattern", (client sided rule)
// "title",
// ],
$this->data[$name] = [
$field[0] ?? '',
$field[1] ?? '',
$field[2] ?? '',
$field[3] ?? '',
$field[4] ?? '',
$field[5] ?? '',
$field[6] ?? '',
];
}
public function validated(array $submit = []): bool
{
$result = false;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$result = true;
if (empty($submit)) {
$submit = $_POST;
}
if (!Session::validateToken($submit)) {
$result = false;
}
// Only check fields if CSRF token is valid
if ($result) {
// Check field rules
foreach ($this->data as $ruleName => $ruleValue) {
$found = false;
$value = '';
foreach ($submit as $submitName => $submitValue) {
if ($ruleName == $submitName) {
$found = true;
$value = $submitValue;
break;
}
if ($ruleValue[1] == 'comment') {
$found = true;
break;
}
}
if (!$found || !$this->matchRule($ruleName, $value)) {
$this->errorKey = $ruleName;
$result = false;
break;
}
}
}
// If unsuccessful, remember the form fields
if (!$result) {
foreach (array_keys($this->data) as $name) {
if ($name == 'captcha') {
continue;
}
$this->router->service()->{$name} = $submit[$name] ?? '';
}
}
}
Session::delete('captcha');
return $result;
}
public function matchRule(string $key, string $value): bool
{
// Get the rule(s)
$rule = $this->data[$key];
$rules = explode('|', $rule[3]);
if (array_search('required', $rules) !== false) {
if (empty($value)) {
return false;
}
}
if (array_search('email', $rules) !== false) {
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
return false;
}
}
if (array_search('tel', $rules) !== false) {
if (!filter_var($value, FILTER_VALIDATE_REGEXP, [
'options' => [
'regexp' => '/^([0-9]{2}-?[0-9]{8})|([0-9]{3}-?[0-9]{7})$/',
]
])) {
return false;
}
}
if (array_search('captcha', $rules) !== false) {
if (!Session::exists('captcha')) {
return false;
}
else if ($value != Session::get('captcha')) {
return false;
}
}
return true;
}
public function errorMessage(): string
{
return $this->errorKey != '' ? $this->data[$this->errorKey][4] : '';
}
//-------------------------------------//
public function getFields(): array
{
return $this->data;
}
public function getReset(): string
{
return $this->resetLabel;
}
public function getSubmit(): string
{
return $this->submitLabel;
}
public function setData(array $data): void
{
$this->data = $data;
}
public function setReset(string $resetLabel): void
{
$this->resetLabel = $resetLabel;
}
public function setSubmit(string $submitLabel): void
{
$this->submitLabel = $submitLabel;
}
}