798 lines
30 KiB
PHP
798 lines
30 KiB
PHP
<?php
|
|
namespace DynCom\mysyde\common\classes;
|
|
use DynCom\mysyde\common\interfaces\ViewModel;
|
|
|
|
/**
|
|
* Created by PhpStorm.
|
|
* User: Bauer
|
|
* Date: 6/13/2015
|
|
* Time: 12:56 AM
|
|
*/
|
|
|
|
class Form {
|
|
|
|
/**
|
|
* @var \DOMNode
|
|
*/
|
|
protected $el;
|
|
protected $elText;
|
|
protected $isValid = null;
|
|
protected $fieldValidity = array();
|
|
protected $prefillFromSuperglobal = false;
|
|
protected $id = null;
|
|
protected $fields = null;
|
|
protected $fieldNames = null;
|
|
protected $fieldLabels = array();
|
|
protected $fieldRules = array();
|
|
protected $IDWrapperIDMap;
|
|
|
|
protected $isRendered = false;
|
|
protected $rendered;
|
|
protected $elementsByID = [];
|
|
|
|
/**
|
|
* @param \DOMElement $el
|
|
*/
|
|
public function __construct( \DOMElement $el ) {
|
|
|
|
if($el->tagName !== 'form') {
|
|
throw new \InvalidArgumentException('Parameter must be \DOMElement with tagName \'form\'.');
|
|
}
|
|
$this->el = $el;
|
|
$this->el->ownerDocument->validateOnParse = true;
|
|
$this->id = $el->getAttribute('id');
|
|
}
|
|
|
|
/**
|
|
* @param boolean $prefillFromSuperglobal
|
|
*/
|
|
public function setPrefillFromSuperglobal($prefillFromSuperglobal)
|
|
{
|
|
$this->prefillFromSuperglobal = (bool)$prefillFromSuperglobal;
|
|
}
|
|
|
|
/**
|
|
* @param FormElement $formElement
|
|
* @param null $parentElementID
|
|
* @param null $inputLabelText
|
|
*/
|
|
public function addElement(FormElement $formElement, $parentElementID = null, $inputLabelText = null) {
|
|
$newEl = $formElement->getEl();
|
|
$doc = &$this->el->ownerDocument;
|
|
@$doc->validate();
|
|
$formMethod = $this->el->getAttribute('method');
|
|
$formMethodArray = array();
|
|
|
|
$fieldType = $newEl->tagName;
|
|
$fieldName = $newEl->getAttribute('name');
|
|
$fieldValue = $newEl->getAttribute('value');
|
|
|
|
if(null !== $inputLabelText && $fieldName) {
|
|
$this->fieldLabels[$fieldName] = $inputLabelText;
|
|
}
|
|
$fieldID = $newEl->getAttribute('id');
|
|
$fieldIsHidden = ($newEl->getAttribute('type') === 'hidden');
|
|
$parent = null;
|
|
if($parentElementID) {
|
|
$parent = $this->elementsByID[$parentElementID];
|
|
}
|
|
|
|
if($this->prefillFromSuperglobal) {
|
|
|
|
if(strcasecmp($formMethod,'post') === 0) { $formMethod = 'post'; $formMethodArray = &$_POST;}
|
|
if(strcasecmp($formMethod,'get') === 0) { $formMethod = 'get'; $formMethodArray = &$_GET;}
|
|
|
|
if (($fieldType === 'input' || $fieldType === 'textarea') && isset($formMethodArray[$fieldName]) && !(mb_strlen($fieldValue, 'UTF-8') > 0)) {
|
|
$fieldValue = $formMethodArray[$fieldName];
|
|
$newEl->setAttribute('value', $fieldValue);
|
|
}
|
|
|
|
if ($fieldType === 'select' && isset($formMethodArray[$fieldName]) && !(mb_strlen($fieldValue, 'UTF-8') > 0)) {
|
|
$optionValue = $formMethodArray[$fieldName];
|
|
$this->setSelectedOptionByValue($newEl,$optionValue);
|
|
}
|
|
}
|
|
|
|
if(($fieldType === 'input' || $fieldType === 'textarea' || $fieldType === 'select') && !$fieldIsHidden) {
|
|
$this->fields[$fieldName] = $newEl->ownerDocument->saveXML($newEl);
|
|
$this->fieldNames[] = $fieldName;
|
|
if(null !== $inputLabelText) {
|
|
$label = $doc->createElement('label');
|
|
$label->setAttribute('for',$fieldName);
|
|
$textNode = $doc->createTextNode($inputLabelText);
|
|
$label->appendChild($textNode);
|
|
}
|
|
}
|
|
|
|
$fieldEL = $newEl;
|
|
if(($fieldType === 'input' || $fieldType === 'textarea' || $fieldType === 'select' || $fieldType === 'submit') && !$fieldIsHidden) {
|
|
$elWrappingDiv = $doc->createElement('div');
|
|
$totalID = '';
|
|
if($fieldName !== '') {
|
|
$totalID = 'input_' . $fieldName . '_wrapper';
|
|
} elseif($fieldID !== '') {
|
|
$totalID = 'input_' . $fieldID . '_wrapper';
|
|
}
|
|
$elWrappingDiv->setAttribute('id',$totalID);
|
|
$elWrappingDiv->setIdAttribute('id',true);
|
|
$elWrappingDiv->setAttribute('class','form_input_wrapper');
|
|
$this->el->appendChild($elWrappingDiv);
|
|
$elWrappingDiv->appendChild($newEl);
|
|
$fieldEL = $elWrappingDiv;
|
|
if($totalID !== '' && $fieldID !== '') {
|
|
$this->IDWrapperIDMap[$fieldID] = $totalID;
|
|
}
|
|
}
|
|
|
|
if(isset($label)) {
|
|
$labelWrappingDiv = $doc->createElement('div');
|
|
$labelWrappingDiv->setAttribute('class','form_label_wrapper');
|
|
$totalID = '';
|
|
if($fieldName !== '') {
|
|
$totalID = 'combined_' . $fieldName . '_wrapper';
|
|
} elseif($fieldID !== '') {
|
|
$totalID = 'combined_' . $fieldID . '_wrapper';
|
|
}
|
|
$labelWrappingDiv->setAttribute('id',$totalID);
|
|
$labelWrappingDiv->setIdAttribute('id',true);
|
|
$labelWrappingDiv->appendChild($label);
|
|
$totalWrappingDiv = $doc->createElement('div');
|
|
@$totalWrappingDiv->setAttribute('id',$totalID);
|
|
@$totalWrappingDiv->setIdAttribute('id',true);
|
|
$totalWrappingDiv->appendChild($labelWrappingDiv);
|
|
$totalWrappingDiv->appendChild($fieldEL);
|
|
$fieldEL = $totalWrappingDiv;
|
|
if($totalID !== '' && $fieldID !== '') {
|
|
$this->IDWrapperIDMap[$fieldID] = $totalID;
|
|
}
|
|
}
|
|
if(null !== $parent) {
|
|
$finalEl = $parent->appendChild($fieldEL);
|
|
} else {
|
|
$finalEl = $this->el->appendChild($fieldEL);
|
|
}
|
|
if($fieldID) {
|
|
$this->elementsByID[$fieldID] = &$finalEl;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param \DOMElement $el
|
|
* @param $value
|
|
*/
|
|
public function setSelectedOptionByValue(\DOMElement $el, $value) {
|
|
foreach($el->getElementsByTagName('option') as $option) {
|
|
if($option instanceof \DOMElement) {
|
|
$currValue = $option->getAttribute('value');
|
|
$option->removeAttribute('selected');
|
|
if ($currValue === $value) {
|
|
$option->setAttribute('selected', 'selected');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param \DOMText $textNode
|
|
* @param $id
|
|
*/
|
|
public function setElementTextNodeByID(\DOMText $textNode, $id ) {
|
|
$doc = $this->el->ownerDocument;
|
|
$el = $doc->getElementById($id);
|
|
if($el) {
|
|
$el->insertBefore($textNode,$el->firstChild);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $id
|
|
* @return bool
|
|
*/
|
|
public function removeElementByID($id ) {
|
|
$removalID = ($this->IDWrapperIDMap[$id]?:$id);
|
|
$doc = $this->el->ownerDocument;
|
|
$removalEl = $doc->getElementById($removalID);
|
|
if($removalEl) {
|
|
$removalParent = $removalEl->parentNode;
|
|
return ($removalParent->removeChild($removalEl) === $removalEl);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param array $rulesArr
|
|
*/
|
|
public function setFieldRules(array $rulesArr ) {
|
|
foreach($rulesArr as $fieldName => $rulesString) {
|
|
$sep = Validator::CONF_RULE_SEPARATOR;
|
|
$rules = explode($sep,$rulesString);
|
|
foreach($rules as $rule) {
|
|
$this->setFieldRule($fieldName,$rule);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $fieldName
|
|
* @param $rule
|
|
*/
|
|
public function setFieldRule($fieldName, $rule ) {
|
|
$ruleArr = explode(':',$rule,2);
|
|
$ruleName = $ruleArr[0];
|
|
if(!array_key_exists($fieldName,$this->fields)) {
|
|
throw new \InvalidArgumentException(
|
|
sprintf(
|
|
'%s is not the name of an input-Field in this form. Available fields are %s',
|
|
$fieldName,
|
|
print_r(array_keys($this->fields),1)
|
|
)
|
|
);
|
|
}
|
|
|
|
if(!Validator::isValidDefaultInlineRuleName($ruleName)) {
|
|
throw new \InvalidArgumentException(
|
|
sprintf(
|
|
'\'%s\' is not the name of a validation-rule.',
|
|
$ruleName
|
|
)
|
|
);
|
|
}
|
|
$this->fieldRules[$fieldName][$ruleName] = $rule;
|
|
}
|
|
|
|
public function render() {
|
|
$doc = $this->el->ownerDocument;
|
|
$this->addRequiredFieldClass();
|
|
$this->setInvalidFieldClass();
|
|
$this->rendered = $doc->saveHTML();
|
|
$this->isRendered = true;
|
|
}
|
|
|
|
public function getRenderedContent() {
|
|
$this->render();
|
|
return $this->rendered;
|
|
}
|
|
|
|
protected function addRequiredFieldClass() {
|
|
$doc = $this->getDOMDocument();
|
|
if(is_array($this->fieldRules)) {
|
|
$XPath = new \DOMXPath($doc);
|
|
$inputNodeList = $XPath->query('//input[@type!="hidden"] | //select | //textarea');
|
|
$nodeArr = [];
|
|
$inputCount = $inputNodeList->length;
|
|
for ($i = 0; $i < $inputCount; ++$i) {
|
|
$currNode = $inputNodeList->item($i);
|
|
$name = $currNode->attributes->getNamedItem('name');
|
|
if($name) {
|
|
$fieldName = $name->nodeValue;
|
|
$nodeArr[$fieldName] = $currNode;
|
|
}
|
|
}
|
|
if(count($nodeArr) > 0) {
|
|
foreach ($this->fieldRules as $fieldName => $ruleArr) {
|
|
foreach ($ruleArr as $ruleName => $rule) {
|
|
if ($ruleName === 'required') {
|
|
$labelNodeList = $XPath->query('//label[@for="' . $fieldName . '"]');
|
|
$labelCount = $labelNodeList->length;
|
|
if($labelCount === 1) {
|
|
$label = $labelNodeList->item(0);
|
|
$labelParent = $label->parentNode;
|
|
$labelClassAttr = $label->attributes->getNamedItem('class');
|
|
$labelParentClassAttr = $labelParent->attributes->getNamedItem('class');
|
|
if(!$labelClassAttr) {
|
|
$labelClassAttr = $label->appendChild(new \DOMAttr('class'));
|
|
}
|
|
$value = ($labelClassAttr->nodeValue) ?: '';
|
|
if(strpos($value,' required_input_label') === false) {
|
|
$value .= ' required_input_label';
|
|
}
|
|
$labelClassAttr->nodeValue = $value;
|
|
$parentValue = $labelParentClassAttr->nodeValue ?: '';
|
|
if(strpos($parentValue,' required_input_label_wrapper') === false) {
|
|
$parentValue .= ' required_input_label_wrapper';
|
|
}
|
|
$labelParentClassAttr->nodeValue = $parentValue;
|
|
}
|
|
$currNode = $nodeArr[$fieldName];
|
|
$classAttr = $currNode->attributes->getNamedItem('class');
|
|
if(!$classAttr) {
|
|
$classAttr = $currNode->appendChild(new \DOMAttr('class'));
|
|
}
|
|
$value = $classAttr->nodeValue ?: '';
|
|
if(strpos($value,' required_input') === false) {
|
|
$value .= ' required_input';
|
|
}
|
|
$classAttr->nodeValue = $value;
|
|
$parent = $currNode->parentNode;
|
|
$parentClassAttr = $parent->attributes->getNamedItem('class');
|
|
if (stristr($parentClassAttr->nodeValue, 'form_input_wrapper') &&
|
|
(strpos($parentClassAttr->nodeValue,' required_input_wrapper') === false)) {
|
|
$parentClassAttr->nodeValue .= ' required_input_wrapper';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return \DOMDocument
|
|
*/
|
|
public function getDOMDocument() {
|
|
return $this->el->ownerDocument;
|
|
}
|
|
|
|
/**
|
|
* @return \DOMElement
|
|
*/
|
|
public function getEl() {
|
|
return $this->el;
|
|
}
|
|
|
|
/**
|
|
* @return \DOMDocument
|
|
*/
|
|
public function getOwnerDocument() {
|
|
return $this->el->ownerDocument;
|
|
}
|
|
|
|
/**
|
|
* @return null
|
|
*/
|
|
public function getFieldNames() {
|
|
return $this->fieldNames;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getNamesValidatedFields() {
|
|
return array_keys($this->fieldRules);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function __sleep() {
|
|
$doc = $this->el->ownerDocument;
|
|
$this->elText = $doc->saveXML($this->el);
|
|
$this->el = null;
|
|
$propertiesToSerialize = array(
|
|
'elText',
|
|
'fields',
|
|
'fieldNames',
|
|
'fieldLabels',
|
|
'fieldRules',
|
|
'IDWrapperIDMap'
|
|
);
|
|
return $propertiesToSerialize;
|
|
}
|
|
|
|
public function __wakeup() {
|
|
$tmpDoc = new \DOMDocument();
|
|
@$tmpDoc->loadXML($this->elText);
|
|
$el = $tmpDoc->documentElement;
|
|
$this->el = $el;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function validateRequestAgainstRules() {
|
|
$method = $this->el->getAttribute('method');
|
|
$sourceArr = &$_REQUEST;
|
|
if(strcasecmp($method,'post') === 0) {
|
|
$sourceArr = &$_POST;
|
|
} elseif(strcasecmp($method,'get') === 0) {
|
|
$sourceArr = &$_GET;
|
|
}
|
|
$fieldNames = array_keys($this->fields);
|
|
$fieldData = array();
|
|
foreach($fieldNames as $name) {
|
|
if(isset($sourceArr[$name])) {
|
|
$fieldData[$name] = $sourceArr[$name];
|
|
}
|
|
}
|
|
$rules = $this->getFieldRules();
|
|
$ruleFields = array_keys($rules);
|
|
$validator = new Validator($rules, $fieldData);
|
|
$fieldStatusArr = array();
|
|
$isValid = $validator->isValid($fieldStatusArr);
|
|
|
|
foreach($ruleFields as $name) {
|
|
$fieldLabel = (array_key_exists($name,$this->fieldLabels) ? $this->fieldLabels[$name] : '');
|
|
$fieldStatusArr[$name]['fieldLabel'] = $fieldLabel;
|
|
}
|
|
|
|
$this->fieldValidity = $fieldStatusArr;
|
|
$this->setInvalidFieldClass();
|
|
$this->isValid = $isValid;
|
|
|
|
return $fieldStatusArr;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getFieldRules() {
|
|
$returnArr = array();
|
|
foreach($this->fieldRules as $fieldName => $ruleArr) {
|
|
$ruleStr = '';
|
|
$i = 0;
|
|
foreach($ruleArr as $ruleName) {
|
|
if($i > 0) {
|
|
$ruleStr .= Validator::CONF_RULE_SEPARATOR;
|
|
}
|
|
$ruleStr .= $ruleName;
|
|
if($ruleStr !== '') {
|
|
$returnArr[$fieldName] = $ruleStr;
|
|
}
|
|
++$i;
|
|
}
|
|
}
|
|
return $returnArr;
|
|
}
|
|
|
|
/**
|
|
* @return null
|
|
*/
|
|
public function isRequestValid() {
|
|
if(null === $this->isValid) {
|
|
throw new \LogicException(
|
|
sprintf(
|
|
'%s needs to be called before %s can be called.',
|
|
'"validateRequestAgainstRules"',
|
|
__METHOD__
|
|
)
|
|
);
|
|
}
|
|
return $this->isValid;
|
|
}
|
|
|
|
/**
|
|
* @return null|string
|
|
*/
|
|
public function getID() {
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getFieldStatusArr() {
|
|
return $this->fieldValidity;
|
|
}
|
|
|
|
public function validatePrefillAndAddErrors() {
|
|
$statusArr = $this->validateInputValuesAgainstRules();
|
|
$fields = array_keys($statusArr);
|
|
foreach($fields as $fieldName) {
|
|
$errorMsgs = $this->getFieldErrorMsgs($fieldName);
|
|
foreach($errorMsgs as $msg) {
|
|
$this->addUserFormError($msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function validateInputValuesAgainstRules() {
|
|
$inputs = $this->el->getElementsByTagName('input');
|
|
$nodeCount = $inputs->length;
|
|
$rules = $this->getFieldRules();
|
|
$ruleFields = array_keys($rules);
|
|
$fieldData = array();
|
|
for($i = 0;$i < $nodeCount;++$i) {
|
|
$currEl = $inputs->item($i);
|
|
$name = $currEl->getAttribute('name');
|
|
$value = $currEl->getAttribute('value');
|
|
if($name && $value && in_array($name,$ruleFields)) {
|
|
$fieldData[$name] = $value;
|
|
}
|
|
}
|
|
if((count($fieldData) > 0) && (count($rules) > 0)) {
|
|
$validator = new Validator($rules, $fieldData);
|
|
$fieldStatusArr = array();
|
|
$isValid = $validator->isValid($fieldStatusArr);
|
|
$this->fieldValidity = $fieldStatusArr;
|
|
$this->setInvalidFieldClass();
|
|
$this->isValid = $isValid;
|
|
|
|
return $fieldStatusArr;
|
|
} else {
|
|
return array();
|
|
}
|
|
}
|
|
|
|
protected function setInvalidFieldClass() {
|
|
if($this->fieldValidity) {
|
|
$doc = $this->getOwnerDocument();
|
|
$XPath = new \DOMXPath($doc);
|
|
$inputNodeList = $XPath->query('//input[@type!="hidden"] | //select | //textarea');
|
|
$nodeArr = [];
|
|
$inputCount = $inputNodeList->length;
|
|
for ($i = 0; $i < $inputCount; ++$i) {
|
|
$currNode = $inputNodeList->item($i);
|
|
$name = $currNode->attributes->getNamedItem('name');
|
|
if($name) {
|
|
$fieldName = $name->nodeValue;
|
|
$nodeArr[$fieldName] = $currNode;
|
|
}
|
|
}
|
|
foreach($this->fieldValidity as $fieldName => $fieldStatus) {
|
|
if(isset($fieldStatus['unmatchedRules'])) {
|
|
$currNode = $nodeArr[$fieldName];
|
|
$labelNodeList = $XPath->query('//label[@for="' . $fieldName . '"]');
|
|
$labelCount = $labelNodeList->length;
|
|
if($labelCount === 1) {
|
|
$label = $labelNodeList->item(0);
|
|
$labelParent = $label->parentNode;
|
|
$labelClassAttr = $label->attributes->getNamedItem('class');
|
|
if(!$labelClassAttr) {
|
|
$labelClassAttr = $label->appendChild(new \DOMAttr('class'));
|
|
}
|
|
$labelParentClassAttr = $labelParent->attributes->getNamedItem('class');
|
|
if(!$labelParentClassAttr) {
|
|
$labelParentClassAttr = $labelParent->appendChild(new \DOMAttr('class'));
|
|
}
|
|
$labelValue = $labelClassAttr->nodeValue ?: '';
|
|
$labelValue .= 'invalid_input_label';
|
|
$labelClassAttr->nodeValue = $labelValue;
|
|
$labelParentValue = $labelParentClassAttr->nodeValue ?: '';
|
|
$labelParentValue .= ' invalid_input_label_wrapper';
|
|
$labelParentClassAttr->nodeValue = $labelParentValue;
|
|
}
|
|
$classAttr = $currNode->attributes->getNamedItem('class');
|
|
$classAttr->nodeValue .= ' invalid_input';
|
|
$parent = $currNode->parentNode;
|
|
$parentClassAttr = $parent->attributes->getNamedItem('class');
|
|
if (stristr($parentClassAttr->nodeValue, 'form_input_wrapper')) {
|
|
$parentClassAttr->nodeValue .= ' invalid_input_wrapper';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $fieldName
|
|
* @return array
|
|
*/
|
|
public function getFieldErrorMsgs($fieldName ) {
|
|
$msgArr = array();
|
|
if(isset($this->fieldValidity[$fieldName]['unmatchedRules'])) {
|
|
$label = ((isset($this->fieldLabels[$fieldName])) ? $this->fieldLabels[$fieldName]:$fieldName);
|
|
foreach($this->fieldValidity[$fieldName]['unmatchedRules'] as $ruleArr) {
|
|
$errorMsgRaw = $ruleArr['ruleError'];
|
|
$errorMsg = str_replace('%fieldname%','<strong>'.$label.'</strong>',$errorMsgRaw);
|
|
$errorMsg = str_replace('%validationparam%','<strong>'.$ruleArr['ruleValue'].'</strong>',$errorMsg);
|
|
$msgArr[] = $errorMsg;
|
|
}
|
|
}
|
|
return $msgArr;
|
|
}
|
|
|
|
/**
|
|
* @param $errorText
|
|
*/
|
|
public function addUserFormError($errorText) {
|
|
$doc = $this->el->ownerDocument;
|
|
$errorDiv = $doc->createElement('div');
|
|
$errorDiv->setAttribute('class','form_error form_error_' . $this->id);
|
|
$errorDivText = $doc->createTextNode(strip_tags($errorText));
|
|
$errorDiv->appendChild($errorDivText);
|
|
$this->el->insertBefore($errorDiv,$this->el->firstChild);
|
|
}
|
|
|
|
/**
|
|
* @param array $arr
|
|
*/
|
|
public function doPrefillFromArray(array &$arr) {
|
|
$XPath = new \DOMXPath($this->el->ownerDocument);
|
|
$inputNodeList = $XPath->query('//input[@type!=\'button\' and @type!=\'submit\' and not(starts-with(@name,\'fmd\'))] | //textarea | //select');
|
|
$inputCount = $inputNodeList->length;
|
|
for($i=0;$i<$inputCount;++$i) {
|
|
$currNode = $inputNodeList->item($i);
|
|
$nameAttr = $currNode->attributes->getNamedItem('name');
|
|
$nameAttr = $nameAttr ?: $currNode->attributes->getNamedItem('id');
|
|
$currNodeName = $nameAttr->nodeValue;
|
|
$newVal = (array_key_exists($currNodeName,$arr)) ? $arr[$currNodeName] : null;
|
|
if(isset($newVal) && mb_strlen($currNodeName,'UTF-8') > 0) {
|
|
if($currNode->nodeName === 'select') {
|
|
$this->setSelectedOptionByValue($currNode,$newVal);
|
|
} else {
|
|
$valueAttr = $currNode->attributes->getNamedItem('value');
|
|
$valueAttr = $valueAttr ?: $currNode->appendChild(new \DOMAttr('value'));
|
|
$prevVal = $valueAttr->nodeValue;
|
|
$newVal = $newVal ?: $prevVal;
|
|
$valueAttr->nodeValue = $newVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param ViewModel $viewModel
|
|
*/
|
|
public function doPrefillFromViewModel(ViewModel $viewModel) {
|
|
$arr = $viewModel->getData();
|
|
$this->doPrefillFromArray($arr);
|
|
}
|
|
|
|
public function doPrefillFromSuperglobal() {
|
|
$formMethod = $this->el->getAttribute('method');
|
|
$formMethodArray = array();
|
|
if(strcasecmp($formMethod,'post') === 0) { $formMethod = 'post'; $formMethodArray = &$_POST;}
|
|
if(strcasecmp($formMethod,'get') === 0) { $formMethod = 'get'; $formMethodArray = &$_GET;}
|
|
$this->doPrefillFromArray($formMethodArray);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function removeMetaDataFields() {
|
|
return $this->removeElementsByXPathQuery('//input[starts-with(@name,\'fmd\')]');
|
|
}
|
|
|
|
/**
|
|
* @param $query
|
|
* @return bool
|
|
*/
|
|
public function removeElementsByXPathQuery($query) {
|
|
$xpath = new \DOMXPath($this->el->ownerDocument);
|
|
$somethingRemoved = false;
|
|
foreach($xpath->query($query) as $e ) {
|
|
// Delete this node
|
|
$e->parentNode->removeChild($e);
|
|
$somethingRemoved = true;
|
|
}
|
|
return $somethingRemoved;
|
|
}
|
|
|
|
/**
|
|
* @param $id
|
|
* @param $class
|
|
*/
|
|
public function wrapInDIV($id, $class) {
|
|
$div = $this->el->ownerDocument->createElement('div');
|
|
$div->setAttribute('id',strip_tags($id));
|
|
$div->setAttribute('class',strip_tags($class));
|
|
$this->el->ownerDocument->appendChild($div);
|
|
$div->appendChild($this->el);
|
|
}
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $registeredViewModels = [];
|
|
|
|
/**
|
|
* @param ViewModel $viewModel
|
|
* @param array $fieldInputMappings
|
|
* @throws \InvalidArgumentException
|
|
*/
|
|
public function registerViewModel(ViewModel $viewModel, array $fieldInputMappings) {
|
|
$viewModelClassName = get_class($viewModel);
|
|
$viewModelInitValues = $viewModel->getData();
|
|
//$this->viewModelInitValues[$viewModelClassName] = $viewModel->getData();
|
|
$viewModelFields = array_keys($viewModelInitValues);
|
|
$formFields = array_keys($this->fields);
|
|
$mappingFormFields = array_keys($fieldInputMappings);
|
|
$mappingViewModelFields = array_values($fieldInputMappings);
|
|
$allFormFieldsValid = count(array_intersect($mappingFormFields, $formFields)) === count($mappingFormFields);
|
|
$allViewModelFieldsValid = count(array_intersect($mappingViewModelFields,$viewModelFields)) === count($mappingViewModelFields);
|
|
if(!$allFormFieldsValid) {
|
|
throw new \InvalidArgumentException('The keys of paramter fieldInputMappings must all be inputs registered with the form.');
|
|
}
|
|
if(!$allViewModelFieldsValid) {
|
|
throw new \InvalidArgumentException('The values of paramter fieldInputMappings must all be fields of the viewModel.');
|
|
}
|
|
$this->registeredViewModels[$viewModelClassName]['initValuesArray'] = $viewModelInitValues;
|
|
$this->registeredViewModels[$viewModelClassName]['fieldMappings'] = $fieldInputMappings;
|
|
}
|
|
|
|
/**
|
|
* @param ViewModel $viewModel
|
|
* @param array $fieldFilter
|
|
*/
|
|
public function prefillFromViewModel(ViewModel $viewModel, array $fieldFilter = []) {
|
|
$viewModelClassName = get_class($viewModel);
|
|
if(!array_key_exists('fieldMappings',$this->registeredViewModels[$viewModelClassName])) {
|
|
throw new \InvalidArgumentException("ViewModel $viewModelClassName has not already been registered successfully.");
|
|
}
|
|
$viewModelFieldMappings = $this->registeredViewModels[$viewModelClassName]['fieldMappings'];
|
|
$mapToFields = array_keys($viewModelFieldMappings);
|
|
$mapFromViewModelFields = array_values($viewModelFieldMappings);
|
|
$mappingData = [];
|
|
$viewModelData = $viewModel->getData();
|
|
foreach($mapToFields as $fieldName) {
|
|
$mappingData[$fieldName] = $viewModelData[$fieldName];
|
|
}
|
|
$XPath = new \DOMXPath($this->el->ownerDocument);
|
|
$inputNodeList = $XPath->query('//input[not(starts-with(@name,\'fmd\'))] | //textarea | //select');
|
|
$inputCount = $inputNodeList->length;
|
|
for($i=0;$i<$inputCount;++$i) {
|
|
$currNode = $inputNodeList->item($i);
|
|
$currNodeName = '';
|
|
@$currNodeName = $currNode->attributes->getNamedItem('name')->nodeValue;
|
|
if(array_key_exists($currNodeName,$mappingData) && isset($formMethodArray[$currNodeName]) && mb_strlen($currNodeName, 'UTF-8') > 0) {
|
|
if ($currNode->nodeName === 'select') {
|
|
$val = $mappingData[$currNodeName];
|
|
$this->setSelectedOptionByValue($currNode, $val);
|
|
} else {
|
|
@$currNode->setAttribute('value', $mappingData[$currNodeName]);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isFormRendered() {
|
|
return $this->isRendered;
|
|
}
|
|
|
|
/**
|
|
* @param $fieldName
|
|
* @param $fieldValue
|
|
*/
|
|
public function setFieldData($fieldName, $fieldValue) {
|
|
if(!in_array($fieldName,$this->fieldNames,false)) {
|
|
throw new \InvalidArgumentException(
|
|
'No field of name ' . strip_tags($fieldName) . ' is registered in the current form.'
|
|
);
|
|
}
|
|
$XPath = new \DOMXPath(($this->el->ownerDocument));
|
|
$nodeList = $XPath->query('//input[@name=\'' . $fieldName . '\']');
|
|
if(!$nodeList->length > 0) {
|
|
$nodeList = $XPath->query('//select[@name=\'' . $fieldName . '\']');
|
|
if(!$nodeList->length > 0) {
|
|
$nodeList = $XPath->query('//textarea[@name=\'' . $fieldName . '\']');
|
|
}
|
|
}
|
|
if($nodeList->length === 1) {
|
|
$field = $nodeList->item(0);
|
|
$tagName = $field->nodeName;
|
|
switch($tagName) {
|
|
case 'input':
|
|
@$field->setAttribute('value', strip_tags($fieldValue));
|
|
break;
|
|
case 'select':
|
|
$this->setSelectedOptionByValue($field,$fieldValue);
|
|
break;
|
|
case 'textarea':
|
|
@$field->setAttribute('value', strip_tags($fieldValue));
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getAllFieldData() {
|
|
$XPath = new \DOMXPath(($this->el->ownerDocument));
|
|
$nodeList = $XPath->query('//input | //select | //textarea');
|
|
$arr = [];
|
|
$len = $nodeList->length;
|
|
for($i=0;$i < $len;++$i) {
|
|
$currItem = $nodeList->item($i);
|
|
@$nameAttr = $currItem->attributes->getNamedItem('name');
|
|
@$valueAttr = $currItem->attributes->getNamedItem('value');
|
|
@$nameVal = $nameAttr->nodeValue;
|
|
@$valueVal = $valueAttr->nodeValue;
|
|
if($nameVal && $valueVal) {
|
|
$arr[$nameVal] = $valueVal;
|
|
}
|
|
}
|
|
return $arr;
|
|
}
|
|
|
|
|
|
|
|
} |