ZF2-113: Uncaught ReflectionExcemption being thrown from within Zend\Loader\PluginBroker

Description

Under the following conditions it is possible for \Zend\Filter\FilterChain to cause an Uncaught ReflectionExeption to be thrown from within \Zend\Loader\PluginBroker::load()

Given the following code snippets:


class myFilter extends \Zend\Filter\AbstractFilter {
    public function filter($text) {
        return 'test';
    }
}


$f = new \Zend\Filter\FilterChain(array(
    'filters' => array(
        'name' => 'myFilter'
    ),
));

Things seem to go awry within the \Zend\Filter\FilterChain::attachByName method when the $options array is empty. This results in: 1) an array with an empty array within it to (eventually) be sent to \Zend\Loader\Plugin::load() as the $options; 2) the above results in the incorrect logic to be executed within the load() method.

Comments

If no options (or an empty array) is passed to attachByName then the following conditional will evaluate true.


if(range(0, count($options) - 1) != array_keys($options))

I propose altering the function to the following:


public function attachByName($name, $options = array(), $priority = self::DEFAULT_PRIORITY)
{
    if (!is_array($options)) {
        $options = (array) $options);
    } else {
        if ((count($options) > 0) && (range(0, count($options) - 1) != array_keys($options))) {
            $options = array($options);
        }
    }
    $filter = $this->broker($name, $options);
    return $this->attach($filter, $priority);
}

I will draw up a couple of tests when I get home tonight.

Based on your reproduce case, you've got incorrect structure in the array you're passing to the constructor of FilterChain. Each filter needs to be listed as an associative array itself:


$f = new \Zend\Filter\FilterChain(array(
    'filters' => array(
        array('name' => 'myFilter'),
    ),
));

When I do the above, I run into no issues whatsoever.

Cannot reproduce, and appears to be incorrect usage.

There's a typo within my original use case. I feel like an idiot now. :(


class myFilter extends \Zend\Filter\AbstractFilter {
    public function filter($text) {
        return 'test';
    }
}
class myFilterB extends \Zend\Filter\AbstractFilter {
    public function __construct() {}
    public function filter($text) {
        return 'filterB';
    }
}

$f = new \Zend\Filter\FilterChain(array(
        'filters' => array(
            array('name' => 'myFilterB'),
            array('name' => 'myFilter'),
        ),
));

results in the following stack trace: Fatal error: Uncaught exception 'ReflectionException' with message 'Class myFilter does not have a constructor, so you cannot pass any constructor arguments' in /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Loader/PluginBroker.php:191 Stack trace:

0 /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Loader/PluginBroker.php(191): ReflectionClass->newInstanceArgs(Array)

1 /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Loader/PluginSpecBroker.php(179): Zend\Loader\PluginBroker->load('myFilter', Array)

2 /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Filter/FilterChain.php(143): Zend\Loader\PluginSpecBroker->load('myFilter', Array)

3 /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Filter/FilterChain.php(188): Zend\Filter\FilterChain->broker('myFilter', Array)

4 /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Filter/FilterChain.php(97): Zend\Filter\FilterChain->attachByName('myFilter', Array, 1000)

5 /Users/ in /Users/shaunbramley/Downloads/ZendFramework-2.0.0dev3/library/Zend/Loader/PluginBroker.php on line 191

Is my use case not adhering to the intended usage? I see no difference in the the files between master and beta3.

Confirming this with the standard "Int" filter (master branch)

I'm able to reproduce this with the Int filter and the StripNewlines filter. The range function will generate an array with two empty value in it when the options variable is empty.

Reproduced.

I've got a PR in for this now: https://github.com/zendframework/zf2/pull/1128

PR #1128 merged to master, fixing the issue.