Forms/src/FuzeWorks/Forms/Field.php

393 lines
10 KiB
PHP
Executable File

<?php
/**
* FuzeWorks Forms Library
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-${YEAR} i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - ${YEAR}, i15. (http://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @link https://i15.nl
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
namespace FuzeWorks\Forms;
abstract class Field
{
protected string $name;
protected string $formName = '';
protected ?string $identifier = null;
protected ?string $label = null;
protected ?string $note = null;
protected mixed $value = null;
protected array $errors = [];
protected bool $lock = false;
protected bool $optional = false;
protected bool $validated = false;
protected bool $valid = false;
protected array $classNames = [];
protected ?string $emptyErrorString = null;
/**
* @var callable[]
*/
protected array $conditions = [];
public function __construct(string $name)
{
$this->name = $name;
}
/**
* Validates this field against its internal and added conditions.
*
* Returns true if all conditions are met, or false if there are errors.
* If the result is false, a list of errors can be retrieved using the getErrors() method.
* @see getErrors
*
* @return bool
*/
public function validate(): bool
{
// Prepare output variables
$this->errors = [];
$this->validated = true;
$this->valid = true;
// Check if empty or null
if (empty($this->value)) {
// If the value is empty and not optional, turn it into an error
if (!$this->optional) {
$this->valid = false;
if (!is_null($this->emptyErrorString))
$this->errors[] = $this->emptyErrorString;
else
$this->errors[] = $this->getLabel() . " may not be empty.";
return false;
}
// If the value is empty but also optional, that's perfectly fine. Immediately accept without any further tests.
return true;
}
// Check validateField
if (!$this->validateField())
$this->valid = false;
// Check for conditions
foreach ($this->conditions as $condition)
if (!call_user_func($condition, $this))
$this->valid = false;
return $this->valid;
}
/**
* Whether the field has been validated.
*
* @see validate
* @return bool
*/
public function isValidated(): bool
{
return $this->validated;
}
/**
* Whether the field has met all conditions during validation
*
* @return bool
*/
public function isValid(): bool
{
return $this->valid;
}
/**
* Change the valid status of the field to false, if so required by post-checks.
*
* @return void
*/
public function invalidate(): void
{
$this->valid = false;
}
/**
* Returns the name of the field, as was added with the construction of the field.
*
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* Returns the currently set value of the field.
*
* @return mixed
*/
public function getValue(): mixed
{
return $this->value;
}
/**
* Returns the unique identifier of the field.
*
* If an identifier has been set, it shall return 'formName_fieldIdentifier'
* If no identifier has been set, it shall return 'formName_fieldName'
*
* @return string
*/
public function getId(): string
{
if (is_null($this->identifier))
return $this->formName . "_" . $this->name;
return $this->formName . "_" . $this->identifier;
}
/**
* Returns the label of this field, which is the most human-readable.
*
* If a label has been set, returns that label.
* If no label has been set, returns ucfirst(fieldName).
*
* @return string
*/
public function getLabel(): string
{
return is_null($this->label) ? ucfirst($this->name) : $this->label;
}
/**
* Returns the note of this field.
*
* Notes are there for the developer to categorize fields, if this is required.
*
* @return string|null
*/
public function getNote(): ?string
{
return $this->note;
}
/**
* Returns an array of strings with all errors found during validation.
*
* @return string[]
*/
public function getErrors(): array
{
return $this->errors;
}
/**
* Set the current value of this field, which it may be validated against.
* ALWAYS VERIFY AGAINST XSS ATTACKS!!!!!!!!!!
*
* If field is locked the value will not be updated.
* @see lock
*
* @param mixed $value
* @return $this
*/
public function setValue(mixed $value): static
{
if (!$this->lock)
$this->value = $value;
return $this;
}
/**
* Sets the identifier of the field.
*
* @param string $identifier
* @return $this
*/
public function setId(string $identifier): static
{
$this->identifier = $identifier;
return $this;
}
/**
* Sets the label of the field.
*
* @param string $label
* @return $this
*/
public function setLabel(string $label): static
{
$this->label = $label;
return $this;
}
/**
* Sets the note of the field.
*
* @param string $note
* @return $this
*/
public function setNote(string $note): static
{
$this->note = $note;
return $this;
}
/**
* When enabled, locks the field, so it may not be edited anymore.
*
* @param bool $lock
* @return $this
*/
public function lock(bool $lock = true): static
{
$this->lock = $lock;
return $this;
}
/**
* When enabled, marks the field as optional, so that it may be left empty during validation.
*
* @param bool $opt
* @return $this
*/
public function optional(bool $opt = true): static
{
$this->optional = $opt;
return $this;
}
/**
* Adds a manual condition to the field that it will be validated against.
*
* @param callable $condition
* @return $this
*/
public function condition(callable $condition): static
{
$this->conditions[] = $condition;
return $this;
}
/**
* Set the string to be displayed when a value is not set and isn't optional.
*
* @param string $errorString
* @return $this
*/
public function emptyErrorString(string $errorString): static
{
$this->emptyErrorString = $errorString;
return $this;
}
/**
* Add an error to be displayed on this field.
*
* @param string $errorString
* @return $this
*/
public function addError(string $errorString): static
{
$this->errors[] = $errorString;
return $this;
}
/**
* Adds the CSS classnames to be printed inside the element.
*
* @param array $classNames
* @return $this
*/
public function class(array $classNames): static
{
foreach ($classNames as $className)
$this->classNames[] = $className;
return $this;
}
/**
* Add one CSS classname to be printed inside the element
*
* @param string $class
* @return $this
*/
public function addClass(string $class): static
{
$this->classNames[] = $class;
return $this;
}
/**
* Sets the CSS classnames to be printed inside the element
*
* @param array $classNames
* @return $this
*/
public function setClasses(array $classNames): static
{
$this->classNames = $classNames;
return $this;
}
/**
* @internal
*/
public function setFormName(string $formName): void
{
$this->formName = $formName;
}
/**
* Run a validation test against internal conditions.
*
* Gets called by validate() method
* @see validate
*
* @return bool
*/
protected abstract function validateField(): bool;
/**
* Generates a html string that will be added to the form.
*
* @return string
*/
public abstract function generateHtml(): string;
public function __toString()
{
return $this->generateHtml();
}
}