+Базовая версия пакета форм
commit
35cc11bc59
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "artmark/forms",
|
||||
"description": "Form Manager",
|
||||
"type": "library",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andrey Pokidov",
|
||||
"email": "pokidov@e-traffic.ru"
|
||||
}
|
||||
],
|
||||
"require": {}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Artmark\Forms\Attributes\DisabledAttribute;
|
||||
|
||||
/**
|
||||
* Description of AbstractChoiceOption
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractChoiceOption extends AbstractVisibleHtml
|
||||
{
|
||||
use DisabledAttribute;
|
||||
|
||||
/**
|
||||
* The value of the option
|
||||
* @var string|int|float
|
||||
*/
|
||||
private $value = '';
|
||||
|
||||
/**
|
||||
* The label of the option
|
||||
* @var string
|
||||
*/
|
||||
private $text = '';
|
||||
|
||||
public function __construct($value, $text)
|
||||
{
|
||||
$this->value = self::correctValue($value);
|
||||
$this->text = strval($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает поле типа AbstractChoiceField
|
||||
* @return AbstractChoiceField
|
||||
*/
|
||||
public abstract function field();
|
||||
|
||||
/**
|
||||
* Возвращает значение опции
|
||||
* @return string|int|float
|
||||
*/
|
||||
public function value()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текст опции
|
||||
* @return string
|
||||
*/
|
||||
public function text()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Задёт новый текст для опции
|
||||
* @param string $newText
|
||||
* @return $this
|
||||
*/
|
||||
public function setText($newText)
|
||||
{
|
||||
$this->text = self::correctValue($newText);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The methods allows to determine is the option selected or not
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSelected()
|
||||
{
|
||||
return $this->field()->isSelected($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отмечает опцию как выбранную
|
||||
* @return $this
|
||||
*/
|
||||
public function select()
|
||||
{
|
||||
$this->field()->select($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$attributes['value'] = $this->value;
|
||||
|
||||
$this->appendVisibleAttributes($attributes);
|
||||
$this->appendDisabledAttribute($attributes);
|
||||
|
||||
$this->field()->appendAttributesToOption($this, $attributes);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
private static function correctValue($value)
|
||||
{
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_null($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return strval($value);
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of AbstractField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractField extends AbstractHtml
|
||||
{
|
||||
/**
|
||||
* Форма, к которой относится поле
|
||||
* @var Form or null
|
||||
*/
|
||||
private $form;
|
||||
|
||||
/**
|
||||
* Текстовая метка поля
|
||||
* @var Label
|
||||
*/
|
||||
private $label;
|
||||
|
||||
/**
|
||||
* Тип поля
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* Название поля
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
protected function __construct($form, $type, $name)
|
||||
{
|
||||
self::checkName($name);
|
||||
self::checkType($type);
|
||||
self::checkForm($form);
|
||||
|
||||
$this->label = new Label($this);
|
||||
|
||||
$this->form = $form;
|
||||
$this->type = $type;
|
||||
$this->name = Utils::cleanString($name);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Form or null
|
||||
*/
|
||||
public function form()
|
||||
{
|
||||
return $this->form;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function type()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function nameWithFormPrefix()
|
||||
{
|
||||
if (!is_null($this->form) && $this->form->hasNamePrefix()) {
|
||||
return $this->form->namePrefix() . $this->name;
|
||||
}
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function idWithFormPrefix()
|
||||
{
|
||||
if (!$this->hasId()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!is_null($this->form) && $this->form->hasIdPrefix()) {
|
||||
return $this->form->idPrefix() . $this->id();
|
||||
}
|
||||
|
||||
return $this->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ранее заданное значение поля
|
||||
* @return mixed
|
||||
*/
|
||||
public abstract function value();
|
||||
|
||||
/**
|
||||
* Устанавливает новое значение для поля
|
||||
* @param mixed $newValue новое значение
|
||||
* @return $this
|
||||
*/
|
||||
public abstract function setValue($newValue);
|
||||
|
||||
/**
|
||||
* Возвращает текстовую метку поля
|
||||
* @return Label
|
||||
*/
|
||||
public function label()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает текст для метки поля
|
||||
* @param string $text
|
||||
* @return $this
|
||||
*/
|
||||
public function setLabelText($text)
|
||||
{
|
||||
$this->label->setText($text);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$attributes['name'] = $this->nameWithFormPrefix();
|
||||
|
||||
if ($this->hasId()) {
|
||||
$attributes['id'] = $this->idWithFormPrefix();
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
public static function checkForm($form)
|
||||
{
|
||||
if (is_null($form) || $form instanceof Form) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AttributeException('The name of a field must be a non-empty string');
|
||||
}
|
||||
|
||||
public static function checkName($name)
|
||||
{
|
||||
if (!self::isCorrectName($name)) {
|
||||
throw new AttributeException('The name of a field must be a non-empty string');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectName($name)
|
||||
{
|
||||
return is_numeric($name) || Utils::isNonEmptyString($name);
|
||||
}
|
||||
|
||||
public static function checkType($type)
|
||||
{
|
||||
if (!self::isCorrectType($type)) {
|
||||
throw new AttributeException('The type of a field must be a non-empty string with of english letters, numbers, underline and dash symbols');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectType($type)
|
||||
{
|
||||
return is_string($type) && preg_match('/^[0-9a-z_\-]+$/ui', trim($type));
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Artmark\Forms\Attributes\IdAttribute;
|
||||
|
||||
/**
|
||||
* Description of AbstractHtml
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractHtml implements Html
|
||||
{
|
||||
use IdAttribute;
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = [];
|
||||
|
||||
$this->appendIdAttribute($attributes);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Artmark\Forms\Attributes\SizeAttribute;
|
||||
use Artmark\Forms\Attributes\MaxLengthAttribute;
|
||||
|
||||
/**
|
||||
* Description of AbstractTextField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractTextField extends AbstractVisibleField
|
||||
{
|
||||
use SizeAttribute, MaxLengthAttribute;
|
||||
|
||||
private $value = '';
|
||||
|
||||
protected function __construct($form, $type, $name, $value = '')
|
||||
{
|
||||
parent::__construct($form, $type, $name);
|
||||
|
||||
$this->setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение поля
|
||||
* @return string
|
||||
*/
|
||||
public function value()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Задаёт новое значение для текстового поля
|
||||
* @param string|int|float $newValue
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($newValue)
|
||||
{
|
||||
if (is_string($newValue) || is_numeric($newValue)) {
|
||||
$this->value = strval($newValue);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ассоциативный массив аттрибутов текстового поля
|
||||
* @return array
|
||||
*/
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$this->appendSizeAttribute($attributes);
|
||||
|
||||
$this->appendMaxLengthAttribute($attributes);
|
||||
|
||||
$attributes['value'] = $this->value;
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Artmark\Forms\Attributes\VisibleAttributes;
|
||||
use Artmark\Forms\Attributes\RequiredAttribute;
|
||||
use Artmark\Forms\Attributes\ReadOnlyAttribute;
|
||||
use Artmark\Forms\Attributes\DisabledAttribute;
|
||||
|
||||
/**
|
||||
* Description of AbstractVisibleField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractVisibleField extends AbstractField
|
||||
{
|
||||
use VisibleAttributes, RequiredAttribute, ReadOnlyAttribute, DisabledAttribute;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$this->appendVisibleAttributes($attributes);
|
||||
|
||||
$this->appendRequiredAttribute($attributes);
|
||||
|
||||
$this->appendReadOnlyAttribute($attributes);
|
||||
|
||||
$this->appendDisabledAttribute($attributes);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Artmark\Forms\Attributes\VisibleAttributes;
|
||||
|
||||
/**
|
||||
* Description of AbstractVisibleHtml
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
abstract class AbstractVisibleHtml extends AbstractHtml
|
||||
{
|
||||
use VisibleAttributes;
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$this->appendVisibleAttributes($attributes);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of ActionAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait ActionAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $action = '';
|
||||
|
||||
/**
|
||||
* HTML action attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasAction()
|
||||
{
|
||||
return $this->action !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newAction
|
||||
* @return $this
|
||||
*/
|
||||
public function setAction($newAction)
|
||||
{
|
||||
self::checkAction($newAction);
|
||||
|
||||
$this->action = trim($newAction);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeAction()
|
||||
{
|
||||
$this->action = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendActionAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasAction())
|
||||
{
|
||||
$attributes['action'] = $this->action;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
public static function checkAction($action)
|
||||
{
|
||||
if (!self::isCorrectAction($action)) {
|
||||
throw new AttributeException('Incorrect action value: `' . strval($action) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectAction($action)
|
||||
{
|
||||
return is_string($action);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of AttributeException
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class AttributeException extends \Exception
|
||||
{
|
||||
public function __construct(string $message = "", int $code = 0, \Throwable $previous = NULL)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of CssClassAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait CssClassAttribute
|
||||
{
|
||||
private $classes = [];
|
||||
|
||||
/**
|
||||
* Массив названий CSS классов
|
||||
* @return string[]
|
||||
*/
|
||||
public function cssClasses()
|
||||
{
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, что список CSS классов не пуст
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasCssClasses()
|
||||
{
|
||||
return count($this->classes) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, имеется ли такой класс
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasCssClass($className)
|
||||
{
|
||||
if (!is_string($className)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cleaned = trim($className);
|
||||
|
||||
return $cleaned !== '' && in_array($cleaned, $this->classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет все CSS классы
|
||||
* @return $this
|
||||
*/
|
||||
public function clearCssClasses()
|
||||
{
|
||||
$this->classes = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет CSS классы в начало списка
|
||||
* @param string|array $classes
|
||||
* @return $this
|
||||
*/
|
||||
public function prependCssClasses($classes)
|
||||
{
|
||||
if (!is_array($classes) && !is_string($classes)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$classList = self::filterClasseserClasses(self::parseClasses($classes));
|
||||
|
||||
foreach ($this->classes as $className) {
|
||||
if (!in_array($className, $classList)) {
|
||||
$className[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
$this->classes = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет CSS классы в конец списка
|
||||
* @param string|array $classes
|
||||
* @return $this
|
||||
*/
|
||||
public function appendCssClasses($classes)
|
||||
{
|
||||
if (!is_array($classes) && !is_string($classes)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
foreach (self::filterClasseserClasses(self::parseClasses($classes)) as $className) {
|
||||
if (!in_array($className, $this->classes)) {
|
||||
$this->classes[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет CSS классы из списка
|
||||
* @param string|array $classes
|
||||
* @return $this
|
||||
*/
|
||||
public function removeCssClasses($classes)
|
||||
{
|
||||
if (!is_array($classes) && !is_string($classes)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach (self::filterClasseserClasses(self::parseClasses($classes)) as $className) {
|
||||
$keys = array_keys($this->classes, $className);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
unset($this->classes[$key]);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i > 0) {
|
||||
$this->classes = array_values($this->classes);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendCssClassAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasCssClasses()) {
|
||||
$attributes['class'] = implode(' ', $this->classes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static function filterClasseserClasses(array $classList)
|
||||
{
|
||||
$filteredClasses = [];
|
||||
|
||||
foreach ($classList as $className) {
|
||||
if (self::isCorretClassName($className) && !in_array($className, $filteredClasses)) {
|
||||
$filteredClasses[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredClasses;
|
||||
}
|
||||
|
||||
|
||||
private static function parseClasses($classes) {
|
||||
if (is_array($classes)) {
|
||||
return $classes;
|
||||
}
|
||||
|
||||
return preg_split('/[ \r\n\t\b]+/', $classes);
|
||||
}
|
||||
|
||||
public static function checkClassName($className)
|
||||
{
|
||||
if (!self::isCorretClassName($className)) {
|
||||
throw new FieldException('Incorrect class name: `' . strval($className) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorretClassName($className)
|
||||
{
|
||||
return is_string($className) && preg_match('/^[a-z0-9_]+(-[a-z0-9_]+)*$/i', trim($className));
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of DirectionAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait DirectionAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $direction = '';
|
||||
|
||||
/**
|
||||
* HTML dir attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function direction()
|
||||
{
|
||||
return $this->direction;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasDirection()
|
||||
{
|
||||
return $this->direction !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newDirection
|
||||
* @return $this
|
||||
*/
|
||||
public function setDirection($newDirection)
|
||||
{
|
||||
self::checkDirection($newDirection);
|
||||
|
||||
$this->direction = self::normalizeString($newDirection);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeDirection()
|
||||
{
|
||||
$this->direction = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendDirectionAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasDirection())
|
||||
{
|
||||
$attributes['dir'] = $this->direction;
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkDirection($direction)
|
||||
{
|
||||
if (!self::isCorrectDirection($direction)) {
|
||||
throw new AttributeException('Incorrect direction value: `' . strval($direction) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectDirection($direction)
|
||||
{
|
||||
if (!is_string($direction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$corrected = self::normalizeString($direction);
|
||||
|
||||
return $corrected === '' || $corrected === 'ltr' || $corrected === 'rtl';
|
||||
}
|
||||
|
||||
private static function normalizeString($value)
|
||||
{
|
||||
return strtolower(trim($value));
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of DisabledAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait DisabledAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $disabled = false;
|
||||
|
||||
/**
|
||||
* Выключено ли поле
|
||||
* @return boolean
|
||||
*/
|
||||
public function isDisabled()
|
||||
{
|
||||
return $this->disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Включено ли поле
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return !$this->disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выключает поле
|
||||
* @return $this
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$this->disabled = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Включает поле
|
||||
* @return $this
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$this->disabled = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendDisabledAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->disabled) {
|
||||
$attributes['disabled'] = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
use Artmark\Forms\Utils;
|
||||
|
||||
/**
|
||||
* Description of IdAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait IdAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id = '';
|
||||
|
||||
/**
|
||||
* HTML Id attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function id()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasId()
|
||||
{
|
||||
return $this->id !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newId
|
||||
* @return $this
|
||||
*/
|
||||
public function setId($newId)
|
||||
{
|
||||
self::checkId($newId);
|
||||
|
||||
$this->id = Utils::cleanString($newId);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeId()
|
||||
{
|
||||
$this->id = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendIdAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasId())
|
||||
{
|
||||
$attributes['id'] = $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkId($id)
|
||||
{
|
||||
if (!self::isCorrectId($id)) {
|
||||
throw new AttributeException('Incorrect id value: `' . strval($id) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectId($id)
|
||||
{
|
||||
return is_numeric($id) || (is_string($id) && !preg_match('/[ \r\n\t\b]+/', trim($id)));
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of LanguageAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait LanguageAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $language = '';
|
||||
|
||||
/**
|
||||
* HTML lang attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function language()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasLanguage()
|
||||
{
|
||||
return $this->language !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newLanguage
|
||||
* @return $this
|
||||
*/
|
||||
public function setLanguage($newLanguage)
|
||||
{
|
||||
self::checkLanguage($newLanguage);
|
||||
|
||||
$this->language = trim($newLanguage);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeLanguage()
|
||||
{
|
||||
$this->language = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendLanguageAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasLanguage())
|
||||
{
|
||||
$attributes['lang'] = $this->language;
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkLanguage($language)
|
||||
{
|
||||
if (!self::isCorrectLanguage($language)) {
|
||||
throw new AttributeException('Incorrect language value: `' . strval($language) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectLanguage($language)
|
||||
{
|
||||
if (!is_string($language)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cleaned = trim($language);
|
||||
|
||||
return $cleaned === '' || preg_match('/^[A-Za-z]{2}([_\-][A-Za-z]{2}){0,1}$/', $cleaned);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of MaxLengthAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait MaxLengthAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxlength = 0;
|
||||
|
||||
/**
|
||||
* HTML site attribute of the input tag
|
||||
* @return int
|
||||
*/
|
||||
public function maxLength()
|
||||
{
|
||||
return $this->maxlength;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasMaxLength()
|
||||
{
|
||||
return $this->maxlength > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $newMaxLength
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxLength($newMaxLength)
|
||||
{
|
||||
$this->maxlength = intval($newMaxLength);
|
||||
|
||||
if ($this->maxlength < 0) {
|
||||
$this->maxlength = 0;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeMaxLength()
|
||||
{
|
||||
$this->maxlength = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendMaxLengthAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasMaxLength())
|
||||
{
|
||||
$attributes['maxlength'] = $this->maxlength;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of MethodAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait MethodAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $method = 'POST';
|
||||
|
||||
/**
|
||||
* HTML method attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function method()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isPost()
|
||||
{
|
||||
return $this->method === 'POST';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isGet()
|
||||
{
|
||||
return $this->method === 'GET';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newMethod
|
||||
* @return $this
|
||||
*/
|
||||
public function setMethod($newMethod)
|
||||
{
|
||||
self::checkMethod($newMethod);
|
||||
|
||||
$this->method = self::normalizeMethod($newMethod);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendMethodAttribute(array & $attributes)
|
||||
{
|
||||
$attributes['method'] = $this->method;
|
||||
}
|
||||
|
||||
public static function checkMethod($method)
|
||||
{
|
||||
if (!self::isCorrectMethod($method)) {
|
||||
throw new AttributeException('Incorrect method value: `' . strval($method) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectMethod($method)
|
||||
{
|
||||
if (!is_string($method)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$corrected = self::normalizeMethod($method);
|
||||
|
||||
return $corrected === 'POST' || $corrected === 'GET';
|
||||
}
|
||||
|
||||
private static function normalizeMethod($method)
|
||||
{
|
||||
return strtoupper(trim($method));
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of ReadOnlyAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait ReadOnlyAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $readonly = false;
|
||||
|
||||
/**
|
||||
* Закрыто ли изменение поля
|
||||
* @return boolean
|
||||
*/
|
||||
public function isReadOnly()
|
||||
{
|
||||
return $this->readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Доступно ли поле для изменения
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEditable()
|
||||
{
|
||||
return !$this->readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Помечает поле недоступным для изменения
|
||||
* @return $this
|
||||
*/
|
||||
public function setReadOnly()
|
||||
{
|
||||
$this->readonly = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Помечает поле доступным для изменения
|
||||
* @return $this
|
||||
*/
|
||||
public function setEditable()
|
||||
{
|
||||
$this->readonly = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendReadOnlyAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->readonly) {
|
||||
$attributes['readonly'] = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of RequiredAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait RequiredAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $required = false;
|
||||
|
||||
/**
|
||||
* Is the field required
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRequired()
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the field required
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOptional()
|
||||
{
|
||||
return !$this->required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Помечает поле обязательным для заполнения
|
||||
* @return $this
|
||||
*/
|
||||
public function setRequired()
|
||||
{
|
||||
$this->required = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Помечает поле необязательным для заполнения
|
||||
* @return $this
|
||||
*/
|
||||
public function setOptional()
|
||||
{
|
||||
$this->required = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendRequiredAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->required) {
|
||||
$attributes['required'] = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of SizeAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait SizeAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $size = 0;
|
||||
|
||||
/**
|
||||
* HTML site attribute of the input tag
|
||||
* @return int
|
||||
*/
|
||||
public function size()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasSize()
|
||||
{
|
||||
return $this->size > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $newSize
|
||||
* @return $this
|
||||
*/
|
||||
public function setSize($newSize)
|
||||
{
|
||||
$this->size = intval($newSize);
|
||||
|
||||
if ($this->size < 0) {
|
||||
$this->size = 0;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeSize()
|
||||
{
|
||||
$this->size = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendSizeAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasSize())
|
||||
{
|
||||
$attributes['size'] = $this->size;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
use Artmark\Forms\Utils;
|
||||
|
||||
/**
|
||||
* Description of StyleAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait StyleAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $style = '';
|
||||
|
||||
/**
|
||||
* HTML style attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function style()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasStyle()
|
||||
{
|
||||
return $this->style !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setStyle($newStyle)
|
||||
{
|
||||
self::checkStyle($newStyle);
|
||||
|
||||
$this->style = Utils::cleanString($newStyle);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeStyle()
|
||||
{
|
||||
$this->style = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendStyleAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasStyle())
|
||||
{
|
||||
$attributes['style'] = $this->style;
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkStyle($style)
|
||||
{
|
||||
if (!self::isCorrectStyle($style)) {
|
||||
throw new AttributeException('Incorrect style value: `' . strval($style) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectStyle($style)
|
||||
{
|
||||
return is_string($style);
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of TargetAttribute
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait TargetAttribute
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $target = '';
|
||||
|
||||
/**
|
||||
* HTML target attribute of the tag
|
||||
* @return string
|
||||
*/
|
||||
public function target()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasTarget()
|
||||
{
|
||||
return $this->target !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $newTarget
|
||||
* @return $this
|
||||
*/
|
||||
public function setTarget($newTarget)
|
||||
{
|
||||
self::checkTarget($newTarget);
|
||||
|
||||
$this->target = trim($newTarget);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeTarget()
|
||||
{
|
||||
$this->target = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function appendTargetAttribute(array & $attributes)
|
||||
{
|
||||
if ($this->hasTarget())
|
||||
{
|
||||
$attributes['target'] = $this->target;
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkTarget($target)
|
||||
{
|
||||
if (!self::isCorrectTarget($target)) {
|
||||
throw new AttributeException('Incorrect target value: `' . strval($target) . '`');
|
||||
}
|
||||
}
|
||||
|
||||
public static function isCorrectTarget($target)
|
||||
{
|
||||
return is_string($target);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Attributes;
|
||||
|
||||
/**
|
||||
* Description of VisibleAttributes
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
trait VisibleAttributes
|
||||
{
|
||||
use DirectionAttribute, LanguageAttribute, StyleAttribute, CssClassAttribute;
|
||||
|
||||
protected function appendVisibleAttributes(array & $attributes)
|
||||
{
|
||||
$this->appendDirectionAttribute($attributes);
|
||||
$this->appendLanguageAttribute($attributes);
|
||||
$this->appendCssClassAttribute($attributes);
|
||||
$this->appendStyleAttribute($attributes);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of FieldException
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class FieldException extends FormException
|
||||
{
|
||||
public function __construct(string $message = "", int $code = 0, \Throwable $previous = NULL)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractVisibleField;
|
||||
|
||||
/**
|
||||
* Description of TextField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class CheckboxField extends AbstractVisibleField
|
||||
{
|
||||
private $checked = false;
|
||||
|
||||
public function __construct($form, $name)
|
||||
{
|
||||
parent::__construct($form, 'checkbox', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ранее заданное значение поля
|
||||
* @return boolean Метод возвращает true, если поле отмечено флагом, иначе - false
|
||||
*/
|
||||
public function value()
|
||||
{
|
||||
return $this->checked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает новое значение для поля
|
||||
* @param boolean $newValue Необходимо передать true, если необходимо установить флаг, false, чтобы убрать флаг
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($newValue)
|
||||
{
|
||||
$this->checked = !empty($newValue);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$attributes['value'] = 1;
|
||||
|
||||
if ($this->checked) {
|
||||
$attributes['checked'] = null;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractTextField;
|
||||
|
||||
/**
|
||||
* Description of EmailField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class EmailField extends AbstractTextField
|
||||
{
|
||||
public function __construct($form, $name, $value = '')
|
||||
{
|
||||
parent::__construct($form, 'email', $name, $value);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractField;
|
||||
|
||||
/**
|
||||
* Description of HiddenField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class HiddenField extends AbstractField
|
||||
{
|
||||
private $value;
|
||||
|
||||
public function __construct($form, $name, $value = '')
|
||||
{
|
||||
parent::__construct($form, 'hidden', $name);
|
||||
|
||||
$this->setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение поля
|
||||
* @return string
|
||||
*/
|
||||
public function value()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Задаёт новое значение для поля типа hidden
|
||||
* @param string|int|float $newValue
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($newValue)
|
||||
{
|
||||
if (is_string($newValue) || is_numeric($newValue)) {
|
||||
$this->value = strval($newValue);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$attributes['value'] = $this->value;
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractTextField;
|
||||
|
||||
/**
|
||||
* Description of PasswordField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class PasswordField extends AbstractTextField
|
||||
{
|
||||
public function __construct($form, $name)
|
||||
{
|
||||
parent::__construct($form, 'password', $name, '');
|
||||
}
|
||||
|
||||
public function setValue($newValue)
|
||||
{
|
||||
//No value need to be written
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractChoiceField;
|
||||
use Artmark\Forms\AbstractChoiceOption;
|
||||
|
||||
/**
|
||||
* Description of RadioField
|
||||
*
|
||||
* @author Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*/
|
||||
class RadioField extends AbstractChoiceField
|
||||
{
|
||||
public function __construct($form, $name)
|
||||
{
|
||||
parent::__construct($form, 'radio', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Создаёт новый экземпляр опции
|
||||
* @return RadioOption
|
||||
*/
|
||||
protected function createOption($value, $text)
|
||||
{
|
||||
return new RadioOption($this, $value, $text);
|
||||
}
|
||||
|
||||
public function appendAttributesToOption(AbstractChoiceOption $option, array & $attributes)
|
||||
{
|
||||
if ($this->isSelected($option)) {
|
||||
$attributes['checked'] = null;
|
||||
}
|
||||
|
||||
if (!$option->hasCssClasses()) {
|
||||
$this->appendCssClassAttribute($attributes);
|
||||
}
|
||||
|
||||
if (!$option->hasStyle()) {
|
||||
$this->appendStyleAttribute($attributes);
|
||||
}
|
||||
|
||||
if ($this->isDisabled()) {
|
||||
$this->appendDisabledAttribute($attributes);
|
||||
}
|
||||
|
||||
$attributes['name'] = $this->name();
|
||||
|
||||
if (!$option->hasId()) {
|
||||
$option->setId($this->name() . '_' . $option->value());
|
||||
$attributes['id'] = $option->id();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractChoiceOption;
|
||||
|
||||
/**
|
||||
* Description of RadioOption
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class RadioOption extends AbstractChoiceOption
|
||||
{
|
||||
/**
|
||||
* The field which is the owner of the option
|
||||
* @var RadioField
|
||||
*/
|
||||
private $field;
|
||||
|
||||
public function __construct(RadioField $field, $value, $text)
|
||||
{
|
||||
parent::__construct($value, $text);
|
||||
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает поле типа RadioField
|
||||
* @return RadioField
|
||||
*/
|
||||
public function field()
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractChoiceField;
|
||||
use Artmark\Forms\AbstractChoiceOption;
|
||||
|
||||
use Artmark\Forms\Attributes\SizeAttribute;
|
||||
|
||||
/**
|
||||
* Description of TextField
|
||||
*
|
||||
* @author Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*/
|
||||
class SelectField extends AbstractChoiceField
|
||||
{
|
||||
use SizeAttribute;
|
||||
|
||||
public function __construct($form, $name)
|
||||
{
|
||||
parent::__construct($form, 'select', $name);
|
||||
}
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
$this->appendSizeAttribute($attributes);
|
||||
|
||||
if ($this->isMultiSelect()) {
|
||||
$attributes['multiple'] = null;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создаёт новый экземпляр опции
|
||||
* @return SelectOption
|
||||
*/
|
||||
protected function createOption($value, $text)
|
||||
{
|
||||
return new SelectOption($this, $value, $text);
|
||||
}
|
||||
|
||||
public function appendAttributesToOption(AbstractChoiceOption $option, array & $attributes)
|
||||
{
|
||||
if ($this->isSelected($option)) {
|
||||
$attributes['selected'] = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractChoiceOption;
|
||||
|
||||
/**
|
||||
* Description of SelectionOption
|
||||
*
|
||||
* @author Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*/
|
||||
class SelectOption extends AbstractChoiceOption
|
||||
{
|
||||
/**
|
||||
* The field which is the owner of the option
|
||||
* @var SelectField
|
||||
*/
|
||||
private $field;
|
||||
|
||||
public function __construct(SelectField $field, $value, $text)
|
||||
{
|
||||
parent::__construct($value, $text);
|
||||
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает поле типа SelectField
|
||||
* @return SelectField
|
||||
*/
|
||||
public function field()
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms\Fields;
|
||||
|
||||
use Artmark\Forms\AbstractTextField;
|
||||
|
||||
/**
|
||||
* Description of TextField
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class TextField extends AbstractTextField
|
||||
{
|
||||
public function __construct($form, $name, $value = '')
|
||||
{
|
||||
parent::__construct($form, 'text', $name, $value);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of FormException
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class FormException extends \Exception
|
||||
{
|
||||
public function __construct(string $message = "", int $code = 0, \Throwable $previous = NULL)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
/**
|
||||
* Description of FormRenderer
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class FormRenderer
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var FormRenderer
|
||||
*/
|
||||
private static $renderer = null;
|
||||
|
||||
private static $registered = false;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return FormRenderer
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (is_null(self::$renderer)) {
|
||||
self::$renderer = new FormRenderer();
|
||||
}
|
||||
|
||||
return self::$renderer;
|
||||
}
|
||||
|
||||
public static function register()
|
||||
{
|
||||
if (self::$registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$registered = true;
|
||||
|
||||
Blade::directive('form_begin', function ($expression) { return '<?php echo \Artmark\Forms\FormRenderer::instance()->beginForm(' . $expression . '); ?>'; });
|
||||
Blade::directive('form_end', function ($expression) { return '<?php echo \Artmark\Forms\FormRenderer::instance()->endForm(' . $expression . '); ?>'; });
|
||||
|
||||
Blade::directive('form_label', function ($expression) { return '<?php echo \Artmark\Forms\FormRenderer::instance()->renderLabel(' . $expression . '); ?>'; });
|
||||
Blade::directive('form_field', function ($expression) { return '<?php echo \Artmark\Forms\FormRenderer::instance()->renderField(' . $expression . '); ?>'; });
|
||||
}
|
||||
|
||||
public function beginForm(Form $form)
|
||||
{
|
||||
return '<form' . $this->encodeHtmlAttributes($form->getAssociativeAttributes()) . ">\n";
|
||||
}
|
||||
|
||||
public function renderLabel(AbstractField $field, $suffix = ':')
|
||||
{
|
||||
return '<label' . $this->encodeHtmlAttributes($field->label()->getAssociativeAttributes()) . '>' . e($field->label()->text()) . $suffix . '</label>';
|
||||
}
|
||||
|
||||
public function renderField(AbstractField $field)
|
||||
{
|
||||
return view('accessories.forms.' . $field->type(), [
|
||||
'renderer' => $this,
|
||||
'field' => $field,
|
||||
]);
|
||||
}
|
||||
|
||||
public function endForm()
|
||||
{
|
||||
return "</form>\n";
|
||||
}
|
||||
|
||||
public function encodeHtmlAttributes(array $attributes)
|
||||
{
|
||||
$html = '';
|
||||
|
||||
foreach ($attributes as $name => $value)
|
||||
{
|
||||
$html .= ' ' . e($name);
|
||||
|
||||
if (!is_null($value)) {
|
||||
$html .= '="' . e($value) . '"';
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of BasicHtml
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
interface Html
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAssociativeAttributes();
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of Label
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class Label extends AbstractVisibleHtml
|
||||
{
|
||||
/**
|
||||
* Поле, к которому привязана текстовая метка
|
||||
* @var AbstractField
|
||||
*/
|
||||
private $field = null;
|
||||
|
||||
private $text = '';
|
||||
|
||||
public function __construct(AbstractField $field)
|
||||
{
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Текст метки поля
|
||||
* @return string
|
||||
*/
|
||||
public function text()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает новый текст для метки поля
|
||||
* @param string $newText
|
||||
* @throws FieldException
|
||||
*/
|
||||
public function setText($newText)
|
||||
{
|
||||
if (!is_string($newText) && !is_numeric($newText)) {
|
||||
throw new FieldException('Incorrect field label text: `' . strval($newText) . '`');
|
||||
}
|
||||
|
||||
$this->text = Utils::cleanString($newText);
|
||||
}
|
||||
|
||||
public function getAssociativeAttributes()
|
||||
{
|
||||
$attributes = parent::getAssociativeAttributes();
|
||||
|
||||
if ($this->field->hasId()) {
|
||||
$attributes['for'] = $this->field->idWithFormPrefix();
|
||||
}
|
||||
else {
|
||||
$attributes['for'] = $this->field->nameWithFormPrefix();
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Artmark\Forms;
|
||||
|
||||
/**
|
||||
* Description of Utils
|
||||
*
|
||||
* @author Andrey Pokidov <pokidov@e-traffic.ru>
|
||||
*/
|
||||
class Utils
|
||||
{
|
||||
public static function isEmptyString($value)
|
||||
{
|
||||
return $value === '';
|
||||
}
|
||||
|
||||
public static function isNonEmptyString($value)
|
||||
{
|
||||
return is_string($value) && $value !== '';
|
||||
}
|
||||
|
||||
public static function cleanString($value)
|
||||
{
|
||||
return trim(strval($value));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue