| 
<?php
/**
 * User: delboy1978uk
 * Date: 19/11/2016
 * Time: 21:41
 */
 
 namespace Del\Form\Field;
 
 use Del\Form\Collection\FilterCollection;
 use Del\Form\Collection\ValidatorCollection;
 use Del\Form\Filter\FilterInterface;
 use Del\Form\FormInterface;
 use Del\Form\Renderer\Field\FieldRendererInterface;
 use Del\Form\Renderer\Field\TextRender;
 use Del\Form\Traits\HasAttributesTrait;
 use Del\Form\Validator\NotEmpty;
 use Del\Form\Validator\ValidatorInterface;
 use Exception;
 
 abstract class FieldAbstract implements FieldInterface
 {
 
 /**  @var FormInterface[] $dynamicFormCollection */
 private $dynamicFormCollection;
 
 /**  @var FilterCollection $filterCollection */
 private $filterCollection;
 
 /**  @var ValidatorCollection $validatorCollection */
 private $validatorCollection;
 
 /** @var FieldRendererInterface $renderer  */
 private $renderer;
 
 /** @var array $errorMessages */
 private $errorMessages;
 
 /** @var string $customErrorMessage */
 private $customErrorMessage;
 
 /** @var string $label */
 private $label;
 
 /** @var bool $required */
 private $required;
 
 use HasAttributesTrait;
 
 /**
 * @return string
 */
 abstract public function getTag();
 
 abstract public function init();
 
 public function __construct($name, $value = null)
 {
 $this->required = false;
 $this->dynamicFormCollection = [];
 $this->filterCollection = new FilterCollection();
 $this->validatorCollection = new ValidatorCollection();
 $this->renderer = new TextRender();
 $this->setName($name);
 is_null($value) ? null : $this->setValue($value);
 $this->init();
 }
 
 /**
 * @return string
 */
 public function getName()
 {
 return $this->getAttribute('name');
 }
 
 /**
 * @param string $name
 * @return FieldAbstract
 */
 public function setName($name)
 {
 $this->setAttribute('name', $name);
 return $this;
 }
 
 /**
 * @return string
 */
 public function getId()
 {
 return $this->getAttribute('id');
 }
 
 /**
 * @param string $id
 * @return FieldAbstract
 */
 public function setId($id)
 {
 $this->setAttribute('id', $id);
 return $this;
 }
 
 /**
 * @return string
 */
 public function getClass()
 {
 return $this->getAttribute('class') ?: 'form-control';
 }
 
 /**
 * @param string $class
 * @return FieldAbstract
 */
 public function setClass($class)
 {
 $this->setAttribute('class', $class);
 return $this;
 }
 
 /**
 * @return mixed
 */
 public function getValue()
 {
 return $this->getAttribute('value');
 }
 
 /**
 * @param mixed $value
 * @return FieldAbstract
 */
 public function setValue($value)
 {
 $this->setAttribute('value', $value);
 $this->filterValue();
 return $this;
 }
 
 /**
 * @param ValidatorInterface $validator
 * @return $this
 */
 public function addValidator(ValidatorInterface $validator)
 {
 $this->validatorCollection->append($validator);
 return $this;
 }
 
 /**
 * @return ValidatorCollection
 */
 public function getValidators()
 {
 return $this->validatorCollection;
 }
 
 /**
 * @param FilterInterface $filter
 * @return $this
 */
 public function addFilter(FilterInterface $filter)
 {
 $this->filterCollection->append($filter);
 return $this;
 }
 
 /**
 * @return FilterCollection
 */
 public function getFilters()
 {
 return $this->filterCollection;
 }
 
 /**
 *  Runs the checkForErrors method for each field, which adds to errorMessages if invalid
 *
 * @return bool
 * @throws Exception If validation of $value is impossible
 */
 public function isValid()
 {
 $this->errorMessages = [];
 $this->validatorCollection->rewind();
 while ($this->validatorCollection->valid()) {
 $this->checkForErrors($this->validatorCollection->current());
 $this->validatorCollection->next();
 }
 $count = count($this->errorMessages);
 return $count == 0;
 }
 
 /**
 * @param ValidatorInterface $validator
 */
 private function checkForErrors(ValidatorInterface $validator)
 {
 $value = $this->getValue();
 
 if ((!$validator->isValid($value)) && $this->isRequired()) {
 $this->errorMessages = array_merge($this->errorMessages, $validator->getMessages());
 }
 }
 
 private function filterValue()
 {
 $value = $this->getAttribute('value');
 $this->filterCollection->rewind();
 while ($this->filterCollection->valid()) {
 $value = $this->filterCollection->current()->filter($value);
 $this->filterCollection->next();
 }
 $this->filterCollection->rewind();
 $this->setAttribute('value', $value);
 }
 
 /**
 * @return array
 */
 public function getMessages()
 {
 return array_values($this->errorMessages);
 }
 
 /**
 * @return string
 */
 public function getLabel()
 {
 return $this->label;
 }
 
 /**
 * @param string $label
 * @return $this
 */
 public function setLabel($label)
 {
 $this->label = $label;
 return $this;
 }
 
 /**
 * @param string $message
 * @return $this
 */
 public function setCustomErrorMessage($message)
 {
 $this->customErrorMessage = $message;
 return $this;
 }
 
 /**
 * @return bool
 */
 public function hasCustomErrorMessage()
 {
 return $this->customErrorMessage != null;
 }
 
 /**
 * @return string
 */
 public function getCustomErrorMessage()
 {
 return $this->customErrorMessage;
 }
 
 /**
 * @return FieldRendererInterface
 */
 public function getRenderer()
 {
 return $this->renderer;
 }
 
 /**
 * @param FieldRendererInterface $renderer
 * @return $this
 */
 public function setRenderer(FieldRendererInterface $renderer)
 {
 $this->renderer = $renderer;
 return $this;
 }
 
 /**
 * If a field is required then it must have a value
 * We add a not empty validator
 *
 * @return boolean
 */
 public function isRequired()
 {
 return $this->required;
 }
 
 /**
 * @param boolean $required
 * @return FieldAbstract
 */
 public function setRequired($required)
 {
 $required ? $this->addNotEmptyValidator() : $this->removeNotEmptyValidator();
 $this->required = $required;
 return $this;
 }
 
 private function addNotEmptyValidator()
 {
 $notEmpty = new NotEmpty();
 $this->addValidator($notEmpty);
 }
 
 private function removeNotEmptyValidator()
 {
 $this->validatorCollection->rewind();
 while ($this->validatorCollection->valid()) {
 $validator = $this->validatorCollection->current();
 $validator instanceof NotEmpty
 ? $this->validatorCollection->offsetUnset($this->validatorCollection->key())
 : null;
 $this->validatorCollection->next();
 }
 }
 
 /**
 * @param FormInterface $form
 * @param $triggerValue
 * @return $this
 */
 public function addDynamicForm(FormInterface $form, $triggerValue)
 {
 $this->dynamicFormCollection[$triggerValue] = $form;
 return $this;
 }
 
 /**
 * @return bool
 */
 public function hasDynamicForms()
 {
 return count($this->dynamicFormCollection) > 0;
 }
 
 /**
 * @return FormInterface[]
 * @throws Exception
 */
 public function getDynamicForms()
 {
 if (!$this->hasDynamicForms()) {
 throw new Exception('No dynamic form for this value - Did you check hasDynamicForm() ?');
 }
 return $this->dynamicFormCollection;
 }
 }
 |