<?php
/**
* User: delboy1978uk
* Date: 19/11/2016
* Time: 12:13
*/
namespace Del\Form;
use Del\Form\Collection\FieldCollection;
use Del\Form\Field\FieldInterface;
use Del\Form\Field\FileUpload;
use Del\Form\Renderer\FormRenderer;
use Del\Form\Renderer\FormRendererInterface;
use Del\Form\Traits\HasAttributesTrait;
abstract class AbstractForm implements FormInterface
{
const ENC_TYPE_MULTIPART_FORM_DATA = 'multipart/form-data';
const ENC_TYPE_URL_ENCODED = 'application/x-www-form-urlencoded';
const ENC_TYPE_TEXT_PLAIN = 'text/plain';
const METHOD_POST = 'post';
const METHOD_GET = 'get';
/** @var FieldCollection $fieldCollection */
private $fieldCollection;
/** @var FormRendererInterface */
private $formRenderer;
/** @var array $errorMessages */
private $errorMessages;
/** @var bool $displayErrors */
private $displayErrors;
use HasAttributesTrait;
/**
* AbstractForm constructor.
* @param $name
*/
public function __construct($name)
{
$this->fieldCollection = new FieldCollection();
$this->formRenderer = new FormRenderer();
$this->attributes = [
'name' => $name,
'method' => self::METHOD_POST,
];
$this->displayErrors = false;
$this->init();
}
abstract public function init();
/**
* @return bool
*/
public function isValid()
{
$this->errorMessages = [];
$fields = $this->fieldCollection;
$this->validateFields($fields);
$count = count($this->errorMessages);
$valid = ($count == 0);
if ($valid) {
$this->moveUploadedFiles();
}
return $valid;
}
/**
* @param FieldCollection $fields
*/
private function validateFields(FieldCollection $fields)
{
$fields->rewind();
while ($fields->valid()) {
$this->checkFieldForErrors($fields->current());
$this->checkDynamicFormsForErrors($fields->current());
$fields->next();
}
$fields->rewind();
}
/**
* @param FieldInterface $field
*/
private function checkFieldForErrors(FieldInterface $field)
{
if (!$field->isValid()) {
$this->errorMessages[$field->getName()] = $field->getMessages();
}
}
public function checkDynamicFormsForErrors(FieldInterface $field)
{
if ($field->hasDynamicForms()) {
$forms = $field->getDynamicForms();
$value = $field->getValue();
if (isset($forms[$value])) {
$form = $forms[$value];
$fields = $form->getFields();
$this->validateFields($fields);
}
}
}
/**
* @return array
*/
public function getValues()
{
$values = [];
$fields = $this->fieldCollection;
$values = $this->getFieldValues($fields, $values);
return $values;
}
/**
* @param FieldCollection $fields
* @param array $values
* @return array
*/
private function getFieldValues(FieldCollection $fields, array $values)
{
$fields->rewind();
while ($fields->valid()) {
/** @var FieldInterface $field */
$field = $fields->current();
$value = $field->getValue();
$values[$field->getName()] = $value;
if ($field->hasDynamicForms()) {
$forms = $field->getDynamicForms();
if (isset($forms[$value])) {
$form = $forms[$value];
$dynamicFormFields = $form->getFields();
$values = $this->getFieldValues($dynamicFormFields, $values);
}
}
$fields->next();
}
$fields->rewind();
return $values;
}
/**
* @param array $data
* @return $this
*/
public function populate(array $data)
{
$fields = $this->fieldCollection;
$this->populateFields($fields, $data);
$this->displayErrors = true;
return $this;
}
/**
* @param array $dynamicForms
* @param array $data
*/
private function populateDynamicForms(array $dynamicForms, array $data)
{
/** @var FormInterface $form **/
foreach ($dynamicForms as $form) {
$fields = $form->getFields();
$this->populateFields($fields, $data);
}
}
/**
* @param FieldCollection $fields
* @param array $data
*/
private function populateFields(FieldCollection $fields, array $data)
{
$fields->rewind();
while ($fields->valid()) {
$field = $fields->current();
$this->populateField($field, $data);
$fields->next();
}
$fields->rewind();
}
/**
* @param FieldInterface $field
* @param array $data
*/
private function populateField(FieldInterface $field, array $data)
{
$name = $field->getName();
if (isset($data[$name])) {
$field->setValue($data[$name]);
}
if ($field->hasDynamicForms()) {
$forms = $field->getDynamicForms();
$this->populateDynamicForms($forms, $data);
}
}
/**
* @param string $name
* @return FieldInterface|null
*/
public function getField($name)
{
return $this->fieldCollection->findByName($name);
}
/**
* @return FieldCollection
*/
public function getFields()
{
return $this->fieldCollection;
}
/**
* @param FieldInterface $field
* @return $this
*/
public function addField(FieldInterface $field)
{
$this->fieldCollection->append($field);
return $this;
}
/**
* @return string
*/
public function render()
{
return $this->formRenderer->render($this, $this->isDisplayErrors());
}
/**
* @param $url
* @return $this
*/
public function setAction($url)
{
$this->setAttribute('action', $url);
return $this;
}
/**
* @return string
*/
public function getAction()
{
return $this->getAttribute('action');
}
/**
* @return string
*/
public function getId()
{
return $this->getAttribute('id');
}
/**
* @param string $id
* @return $this
*/
public function setId($id)
{
$this->setAttribute('id', $id);
return $this;
}
/**
* @param $encType
* @return $this
*/
public function setEncType($encType)
{
$this->setAttribute('enctype', $encType);
return $this;
}
/**
* @return string
*/
public function getEncType()
{
return $this->getAttribute('enctype');
}
/**
* @param string $method
* @return FormInterface
*/
public function setMethod($method)
{
$this->setAttribute('method', $method);
return $this;
}
/**
* @return string
*/
public function getMethod()
{
return $this->getAttribute('method');
}
/**
* @param $class
* @return FormInterface
*/
public function setClass($class)
{
$this->setAttribute('class', $class);
return $this;
}
/**
* @return string
*/
public function getClass()
{
return $this->getAttribute('class');
}
/**
* @return boolean
*/
public function isDisplayErrors()
{
return $this->displayErrors;
}
/**
* @param boolean $displayErrors
* @return AbstractForm
*/
public function setDisplayErrors($displayErrors)
{
$this->displayErrors = $displayErrors;
return $this;
}
/**
* @param FormRendererInterface $renderer
* @return AbstractForm
*/
public function setFormRenderer(FormRendererInterface $renderer)
{
$this->formRenderer = $renderer;
return $this;
}
public function moveUploadedFiles()
{
$this->fieldCollection->rewind();
while ($this->fieldCollection->valid()) {
$current = $this->fieldCollection->current();
$this->moveFileIfUploadField($current);
$this->fieldCollection->next();
}
}
/**
* @param FieldInterface $field
* @return bool
*/
public function moveFileIfUploadField(FieldInterface $field)
{
if ($field instanceof FileUpload) {
$field->moveUploadToDestination();
return true;
}
return false;
}
}
|