Form: Fix id protection

Altering element ids upon rendering makes it impossible to reference
them elsewhere. Zend_Form::getId() should be preferred over getName()
as it falls automatically back to getName() in case there is no id attribute
set. Setter are required to return their instance. Overwriting methods
without calling the parent (getId) without any valid (or at least
documented) reason is very bad practice.

refs #8460
This commit is contained in:
Johannes Meyer 2015-02-27 09:01:46 +01:00
parent 6d81a194ab
commit 48c3199a2d
1 changed files with 42 additions and 47 deletions

View File

@ -383,6 +383,29 @@ class Form extends Zend_Form
return $this->validatePartial; return $this->validatePartial;
} }
/**
* Set whether each element's id should be altered to avoid duplicates
*
* @param bool $value
*
* @return Form
*/
public function setProtectIds($value = true)
{
$this->protectIds = (bool) $value;
return $this;
}
/**
* Return whether each element's id is being altered to avoid duplicates
*
* @return bool
*/
public function getProtectIds()
{
return $this->protectIds;
}
/** /**
* Create this form * Create this form
* *
@ -562,6 +585,10 @@ class Form extends Zend_Form
unset($el->autosubmit); unset($el->autosubmit);
} }
if ($this->protectIds) {
$el->setAttrib('id', $this->getRequest()->protectId($this->getId(false) . '_' . $el->getId()));
}
return $this->ensureElementAccessibility($el); return $this->ensureElementAccessibility($el);
} }
@ -795,6 +822,21 @@ class Form extends Zend_Form
return $this; return $this;
} }
/**
* Get element id
*
* Returns the protected id, in case id protection is enabled.
*
* @param bool $protect
*
* @return string
*/
public function getId($protect = true)
{
$id = parent::getId();
return $protect && $this->protectIds ? $this->getRequest()->protectId($id) : $id;
}
/** /**
* Return the name of this form * Return the name of this form
* *
@ -913,28 +955,6 @@ class Form extends Zend_Form
public function render(Zend_View_Interface $view = null) public function render(Zend_View_Interface $view = null)
{ {
$this->create(); $this->create();
if ($this->protectIds) {
if (null !== $this->getAttrib('id')) {
$this->setAttrib('id', $this->getRequest()->protectId($this->getAttrib('id')));
} else {
$this->setAttrib('id', $this->getRequest()->protectId($this->name));
}
/** @var Zend_Form_Element $element */
foreach ($this->getElements() as $element) {
if (null !== $element->getAttrib('id')) {
$element->setAttrib(
'id',
$this->getRequest()->protectId($this->getName() . '-' . $element->getAttrib('id'))
);
} else {
$element->setAttrib(
'id',
$this->getRequest()->protectId($this->getName() . '-' . $element->getName())
);
}
}
}
return parent::render($view); return parent::render($view);
} }
@ -976,29 +996,4 @@ class Form extends Zend_Form
throw new SecurityException('No permission for %s', $permission); throw new SecurityException('No permission for %s', $permission);
} }
} }
/**
* Enable or disable whether ids should be altered to guard them against duplications
*
* @param $value boolean Whether or not protect ids against collisions through other requests
*/
public function setProtectIds($value)
{
$this->protectIds = $value;
}
/**
* Get the id that is written into the output html when rendering this form
*
* This will return the protected id, in case $protectIds is enabled.
*
* @return string The id
*/
public function getId()
{
if ($this->protectIds) {
return $this->getRequest()->protectId($this->getName());
}
return $this->getName();
}
} }