Issues

ZF-3069: Cannot remove a decorator based on another decorator (with solution)

Description

This example shows the problem.



$form=new Zend_Form;
        
$form->addElement(
    'text',
    'mytextfield',
    array(
        'label' => 'My Textfield',
    )
);

$element=$form->getElement('mytextfield');

$element->addDecorator(array('MyDecorator'=>'HtmlTag'), array( 'tag' => 'dl', 'separator'=>PHP_EOL));

print_r(array_keys($element->getDecorators()); // Display element decorators

$element->removeDecorator('MyDecorator'); // Remove MyDecorator

print_r(array_keys($element->getDecorators()); // MyDecorator hasn't been removed, HtmlTag decorator has been removed instead.

Comments

My proposed solution:

Swap this:


/**
 * Remove a single decorator
 *
 * @param  string $name
 * @return bool
 */
public function removeDecorator($name)
{
    $decorator = $this->getDecorator($name);
    if ($decorator) {
        $name = get_class($decorator);
        unset($this->_decorators[$name]);
        return true;
    }

    return false;
}

For this:


/**
 * Remove a single decorator
 *
 * @param  string $name
 * @return bool
 */
public function removeDecorator($name)
{
    $decorator = $this->getDecorator($name);
    if ($decorator) {
        unset($this->_decorators[$name]);
        return true;
    }

    return false;
}

At Zend/Form/Element.php

There was an error in my previous proposed solution. Here is the correct solution:

Swap this:

/** * Remove a single decorator * * @param string $name * @return bool */ public function removeDecorator($name) { $decorator = $this->getDecorator($name); if ($decorator) { $name = get_class($decorator); unset($this->_decorators[$name]); return true; }

return false;

}

For this:

/** * Remove a single decorator * * @param string $name * @return bool */ public function removeDecorator($name) { $decorator = $this->getDecorator($name); if ($decorator) { if ( !isset( $this->_decorators[$name] ) ) $name = get_class($decorator); unset($this->_decorators[$name]); return true; }

return false;

}

At Zend/Form/Element.php

The decorator will be deleted using his class name only if is not found by key name.

2nd try.

Replace this:


/**
 * Remove a single decorator
 *
 * @param  string $name
 * @return bool
 */
public function removeDecorator($name)
{
    $decorator = $this->getDecorator($name);
    if ($decorator) {
        $name = get_class($decorator);
        unset($this->_decorators[$name]);
        return true;
    }

    return false;
}

For this:


/**
 * Remove a single decorator
 *
 * @param  string $name
 * @return bool
 */
public function removeDecorator($name)
{
    $decorator = $this->getDecorator($name);
    if ($decorator) {
        if ( !isset( $this->_decorators[$name] ) ) $name = get_class($decorator);
        unset($this->_decorators[$name]);
        return true;
    }

    return false;
}

At Zend/Form/Element.php

The decorator will be deleted using his class name only if is not found by the key name.

Please evaluate and categorize as necessary.

Scheduling for next mini release.

Fixed in trunk and 1.5 release branch as of r9365; applied fixes to form, element, and display group classes, as the issue was present in each.