Merge branch '2.3' into 2.5

* 2.3:
  Revert "[DependencyInjection] backport perf optim"
  [WebProfilerBundle] replaced pattern to path attribute in routes definitions.
  [FrameworkBundle][Template name] avoid  error message for the shortcut notation.
  [DependencyInjection] perf optim: call dirname() at most 5x
  [DependencyInjection] backport perf optim
  [2.3] Remove possible call_user_func()

Conflicts:
	src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
	src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php
	src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php
	src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
This commit is contained in:
Fabien Potencier 2014-12-11 20:53:06 +01:00
commit 7e573f4f8a
27 changed files with 104 additions and 60 deletions

View File

@ -11,9 +11,9 @@
namespace Symfony\Bundle\FrameworkBundle\Templating; namespace Symfony\Bundle\FrameworkBundle\Templating;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReferenceInterface; use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Templating\TemplateNameParser as BaseTemplateNameParser;
/** /**
* TemplateNameParser converts template names from the short notation * TemplateNameParser converts template names from the short notation
@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class TemplateNameParser implements TemplateNameParserInterface class TemplateNameParser extends BaseTemplateNameParser
{ {
protected $kernel; protected $kernel;
protected $cache = array(); protected $cache = array();
@ -56,7 +56,7 @@ class TemplateNameParser implements TemplateNameParserInterface
} }
if (!preg_match('/^([^:]*):([^:]*):(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches)) { if (!preg_match('/^([^:]*):([^:]*):(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches)) {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid (format is "bundle:section:template.format.engine").', $name)); return parent::parse($name);
} }
$template = new TemplateReference($matches[1], $matches[2], $matches[3], $matches[4], $matches[5]); $template = new TemplateReference($matches[1], $matches[2], $matches[3], $matches[4], $matches[5]);

View File

@ -105,7 +105,8 @@ class AppKernel extends Kernel
public function unserialize($str) public function unserialize($str)
{ {
call_user_func_array(array($this, '__construct'), unserialize($str)); $a = unserialize($str);
$this->__construct($a[0], $a[1], $a[2], $a[3]);
} }
protected function getKernelParameters() protected function getKernelParameters()

View File

@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser; use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference; use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\Templating\TemplateReference as BaseTemplateReference;
class TemplateNameParserTest extends TestCase class TemplateNameParserTest extends TestCase
{ {
@ -63,25 +64,17 @@ class TemplateNameParserTest extends TestCase
array(':Post:index.html.php', new TemplateReference('', 'Post', 'index', 'html', 'php')), array(':Post:index.html.php', new TemplateReference('', 'Post', 'index', 'html', 'php')),
array('::index.html.php', new TemplateReference('', '', 'index', 'html', 'php')), array('::index.html.php', new TemplateReference('', '', 'index', 'html', 'php')),
array('FooBundle:Post:foo.bar.index.html.php', new TemplateReference('FooBundle', 'Post', 'foo.bar.index', 'html', 'php')), array('FooBundle:Post:foo.bar.index.html.php', new TemplateReference('FooBundle', 'Post', 'foo.bar.index', 'html', 'php')),
array('/path/to/section/name.php', new BaseTemplateReference('/path/to/section/name.php', 'php')),
array('name.twig', new BaseTemplateReference('name.twig', 'twig')),
array('name', new BaseTemplateReference('name')),
); );
} }
/** /**
* @dataProvider getInvalidLogicalNameProvider
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
*/ */
public function testParseInvalidName($name) public function testParseValidNameWithNotFoundBundle()
{ {
$this->parser->parse($name); $this->parser->parse('BarBundle:Post:index.html.php');
}
public function getInvalidLogicalNameProvider()
{
return array(
array('BarBundle:Post:index.html.php'),
array('FooBundle:Post:index'),
array('FooBundle:Post'),
array('FooBundle:Post:foo:bar'),
);
} }
} }

View File

@ -105,7 +105,8 @@ class AppKernel extends Kernel
public function unserialize($str) public function unserialize($str)
{ {
call_user_func_array(array($this, '__construct'), unserialize($str)); $a = unserialize($str);
$this->__construct($a[0], $a[1], $a[2], $a[3]);
} }
protected function getKernelParameters() protected function getKernelParameters()

View File

@ -4,47 +4,47 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_profiler_home" pattern="/"> <route id="_profiler_home" path="/">
<default key="_controller">web_profiler.controller.profiler:homeAction</default> <default key="_controller">web_profiler.controller.profiler:homeAction</default>
</route> </route>
<route id="_profiler_search" pattern="/search"> <route id="_profiler_search" path="/search">
<default key="_controller">web_profiler.controller.profiler:searchAction</default> <default key="_controller">web_profiler.controller.profiler:searchAction</default>
</route> </route>
<route id="_profiler_search_bar" pattern="/search_bar"> <route id="_profiler_search_bar" path="/search_bar">
<default key="_controller">web_profiler.controller.profiler:searchBarAction</default> <default key="_controller">web_profiler.controller.profiler:searchBarAction</default>
</route> </route>
<route id="_profiler_purge" pattern="/purge"> <route id="_profiler_purge" path="/purge">
<default key="_controller">web_profiler.controller.profiler:purgeAction</default> <default key="_controller">web_profiler.controller.profiler:purgeAction</default>
</route> </route>
<route id="_profiler_info" pattern="/info/{about}"> <route id="_profiler_info" path="/info/{about}">
<default key="_controller">web_profiler.controller.profiler:infoAction</default> <default key="_controller">web_profiler.controller.profiler:infoAction</default>
</route> </route>
<route id="_profiler_phpinfo" pattern="/phpinfo"> <route id="_profiler_phpinfo" path="/phpinfo">
<default key="_controller">web_profiler.controller.profiler:phpinfoAction</default> <default key="_controller">web_profiler.controller.profiler:phpinfoAction</default>
</route> </route>
<route id="_profiler_search_results" pattern="/{token}/search/results"> <route id="_profiler_search_results" path="/{token}/search/results">
<default key="_controller">web_profiler.controller.profiler:searchResultsAction</default> <default key="_controller">web_profiler.controller.profiler:searchResultsAction</default>
</route> </route>
<route id="_profiler" pattern="/{token}"> <route id="_profiler" path="/{token}">
<default key="_controller">web_profiler.controller.profiler:panelAction</default> <default key="_controller">web_profiler.controller.profiler:panelAction</default>
</route> </route>
<route id="_profiler_router" pattern="/{token}/router"> <route id="_profiler_router" path="/{token}/router">
<default key="_controller">web_profiler.controller.router:panelAction</default> <default key="_controller">web_profiler.controller.router:panelAction</default>
</route> </route>
<route id="_profiler_exception" pattern="/{token}/exception"> <route id="_profiler_exception" path="/{token}/exception">
<default key="_controller">web_profiler.controller.exception:showAction</default> <default key="_controller">web_profiler.controller.exception:showAction</default>
</route> </route>
<route id="_profiler_exception_css" pattern="/{token}/exception.css"> <route id="_profiler_exception_css" path="/{token}/exception.css">
<default key="_controller">web_profiler.controller.exception:cssAction</default> <default key="_controller">web_profiler.controller.exception:cssAction</default>
</route> </route>

View File

@ -4,7 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_wdt" pattern="/{token}"> <route id="_wdt" path="/{token}">
<default key="_controller">web_profiler.controller.profiler:toolbarAction</default> <default key="_controller">web_profiler.controller.profiler:toolbarAction</default>
</route> </route>
</routes> </routes>

View File

@ -225,8 +225,10 @@ class ExprBuilder
{ {
foreach ($expressions as $k => $expr) { foreach ($expressions as $k => $expr) {
if ($expr instanceof ExprBuilder) { if ($expr instanceof ExprBuilder) {
$expressions[$k] = function ($v) use ($expr) { $if = $expr->ifPart;
return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v; $then = $expr->thenPart;
$expressions[$k] = function ($v) use ($if, $then) {
return $if($v) ? $then($v) : $v;
}; };
} }
} }

View File

@ -49,7 +49,9 @@ class VariableNode extends BaseNode implements PrototypeNodeInterface
*/ */
public function getDefaultValue() public function getDefaultValue()
{ {
return $this->defaultValue instanceof \Closure ? call_user_func($this->defaultValue) : $this->defaultValue; $v = $this->defaultValue;
return $v instanceof \Closure ? $v() : $v;
} }
/** /**

View File

@ -22,6 +22,6 @@ class FileLoaderImportCircularReferenceException extends FileLoaderLoadException
{ {
$message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]);
call_user_func('Exception::__construct', $message, $code, $previous); \Exception::__construct($message, $code, $previous);
} }
} }

View File

@ -109,17 +109,19 @@ class PhpDumper extends Dumper
), $options); ), $options);
if (!empty($options['file']) && is_dir($dir = dirname($options['file']))) { if (!empty($options['file']) && is_dir($dir = dirname($options['file']))) {
// Build a regexp where the first two root dirs are mandatory, // Build a regexp where the first root dirs are mandatory,
// but every other sub-dir is optional up to the full path in $dir // but every other sub-dir is optional up to the full path in $dir
// Mandate at least 2 root dirs and not more that 5 optional dirs.
$dir = explode(DIRECTORY_SEPARATOR, realpath($dir)); $dir = explode(DIRECTORY_SEPARATOR, realpath($dir));
$i = count($dir); $i = count($dir);
if (3 <= $i) { if (3 <= $i) {
$regex = ''; $regex = '';
$this->targetDirMaxMatches = $i - 3; $lastOptionalDir = $i > 8 ? $i - 5 : 3;
$this->targetDirMaxMatches = $i - $lastOptionalDir;
while (2 < --$i) { while (--$i >= $lastOptionalDir) {
$regex = sprintf('(%s%s)?', preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex); $regex = sprintf('(%s%s)?', preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex);
} }
@ -786,6 +788,9 @@ $bagClass
*/ */
class $class extends $baseClass class $class extends $baseClass
{ {
private \$parameters;
private \$targetDirs = array();
EOF; EOF;
} }
@ -796,6 +801,7 @@ EOF;
*/ */
private function addConstructor() private function addConstructor()
{ {
$targetDirs = $this->exportTargetDirs();
$arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
$code = <<<EOF $code = <<<EOF
@ -804,7 +810,7 @@ EOF;
* Constructor. * Constructor.
*/ */
public function __construct() public function __construct()
{ {{$targetDirs}
parent::__construct($arguments); parent::__construct($arguments);
EOF; EOF;
@ -833,6 +839,8 @@ EOF;
*/ */
private function addFrozenConstructor() private function addFrozenConstructor()
{ {
$targetDirs = $this->exportTargetDirs();
$code = <<<EOF $code = <<<EOF
private \$parameters; private \$parameters;
@ -841,7 +849,7 @@ EOF;
* Constructor. * Constructor.
*/ */
public function __construct() public function __construct()
{ {{$targetDirs}
EOF; EOF;
if ($this->container->getParameterBag()->all()) { if ($this->container->getParameterBag()->all()) {
@ -1405,6 +1413,17 @@ EOF;
return $this->expressionLanguage; return $this->expressionLanguage;
} }
private function exportTargetDirs()
{
return null === $this->targetDirRegex ? '' : <<<EOF
\$dir = __DIR__;
for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
\$this->targetDirs[\$i] = \$dir = dirname(\$dir);
}
EOF;
}
private function export($value) private function export($value)
{ {
if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
@ -1413,8 +1432,8 @@ EOF;
$suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : ''; $suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : '';
$dirname = '__DIR__'; $dirname = '__DIR__';
for ($i = $this->targetDirMaxMatches - count($matches); 0 <= $i; --$i) { if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) {
$dirname = sprintf('dirname(%s)', $dirname); $dirname = sprintf('$this->targetDirs[%d]', $offset);
} }
if ($prefix || $suffix) { if ($prefix || $suffix) {

View File

@ -85,13 +85,14 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$definition = new Definition(); $definition = new Definition();
$definition->setClass('stdClass'); $definition->setClass('stdClass');
$definition->addArgument('%foo%'); $definition->addArgument('%foo%');
$definition->addArgument(array('%foo%' => '%foo%')); $definition->addArgument(array('%foo%' => '%buz%/'));
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$container->setDefinition('test', $definition); $container->setDefinition('test', $definition);
$container->setParameter('foo', 'wiz'.dirname(dirname(__FILE__))); $container->setParameter('foo', 'wiz'.dirname(dirname(__FILE__)));
$container->setParameter('bar', dirname(__FILE__)); $container->setParameter('bar', dirname(__FILE__));
$container->setParameter('baz', '%bar%/PhpDumperTest.php'); $container->setParameter('baz', '%bar%/PhpDumperTest.php');
$container->setParameter('buz', dirname(dirname(__DIR__)));
$container->compile(); $container->compile();
$dumper = new PhpDumper($container); $dumper = new PhpDumper($container);

View File

@ -17,6 +17,9 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
*/ */
class Container extends AbstractContainer class Container extends AbstractContainer
{ {
private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.
*/ */

View File

@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
*/ */
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.
*/ */

View File

@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters; private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.

View File

@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters; private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.

View File

@ -16,11 +16,18 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
*/ */
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.
*/ */
public function __construct() public function __construct()
{ {
$dir = __DIR__;
for ($i = 1; $i <= 5; ++$i) {
$this->targetDirs[$i] = $dir = dirname($dir);
}
$this->parameters = $this->getDefaultParameters(); $this->parameters = $this->getDefaultParameters();
$this->services = $this->services =
@ -48,7 +55,7 @@ class ProjectServiceContainer extends Container
*/ */
protected function getTestService() protected function getTestService()
{ {
return $this->services['test'] = new \stdClass(('wiz'.dirname(__DIR__)), array(('wiz'.dirname(__DIR__)) => ('wiz'.dirname(__DIR__)))); return $this->services['test'] = new \stdClass(('wiz'.$this->targetDirs[1]), array(('wiz'.$this->targetDirs[1]) => ($this->targetDirs[2].'/')));
} }
/** /**
@ -102,9 +109,10 @@ class ProjectServiceContainer extends Container
protected function getDefaultParameters() protected function getDefaultParameters()
{ {
return array( return array(
'foo' => ('wiz'.dirname(__DIR__)), 'foo' => ('wiz'.$this->targetDirs[1]),
'bar' => __DIR__, 'bar' => __DIR__,
'baz' => (__DIR__.'/PhpDumperTest.php'), 'baz' => (__DIR__.'/PhpDumperTest.php'),
'buz' => $this->targetDirs[2],
); );
} }
} }

View File

@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
*/ */
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.
*/ */

View File

@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
*/ */
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.
*/ */

View File

@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
class ProjectServiceContainer extends Container class ProjectServiceContainer extends Container
{ {
private $parameters; private $parameters;
private $targetDirs = array();
/** /**
* Constructor. * Constructor.

View File

@ -246,14 +246,14 @@ class Command
*/ */
public function execute() public function execute()
{ {
if (null === $this->errorHandler) { if (null === $errorHandler = $this->errorHandler) {
exec($this->join(), $output); exec($this->join(), $output);
} else { } else {
$process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
$output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
if ($error = stream_get_contents($pipes[2])) { if ($error = stream_get_contents($pipes[2])) {
call_user_func($this->errorHandler, $error); $errorHandler($error);
} }
proc_close($process); proc_close($process);

View File

@ -72,8 +72,8 @@ class TestHttpKernel extends HttpKernel implements ControllerResolverInterface
$response = new Response($this->body, $this->status, $this->headers); $response = new Response($this->body, $this->status, $this->headers);
if (null !== $this->customizer) { if (null !== $customizer = $this->customizer) {
call_user_func($this->customizer, $request, $response); $customizer($request, $response);
} }
return $response; return $response;

View File

@ -1371,11 +1371,12 @@ class Process
$result = $this->processPipes->read($blocking); $result = $this->processPipes->read($blocking);
} }
$callback = $this->callback;
foreach ($result as $type => $data) { foreach ($result as $type => $data) {
if (3 == $type) { if (3 == $type) {
$this->fallbackExitcode = (int) $data; $this->fallbackExitcode = (int) $data;
} else { } else {
call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data); $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
} }
} }
} }

View File

@ -844,7 +844,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
{ {
$process = $this->getProcess('php -m'); $process = $this->getProcess('php -m');
$this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method)); $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method));
call_user_func(array($process, $method)); $process->{$method}();
} }
public function provideMethodsThatNeedARunningProcess() public function provideMethodsThatNeedARunningProcess()
@ -866,7 +866,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process = $this->getProcess('php -r "sleep(1);"'); $process = $this->getProcess('php -r "sleep(1);"');
$process->start(); $process->start();
try { try {
call_user_func(array($process, $method)); $process->{$method}();
$process->stop(0); $process->stop(0);
$this->fail('A LogicException must have been thrown'); $this->fail('A LogicException must have been thrown');
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -37,7 +37,7 @@ class ClosureLoader extends Loader
*/ */
public function load($closure, $type = null) public function load($closure, $type = null)
{ {
return call_user_func($closure); return $closure();
} }
/** /**

View File

@ -50,7 +50,9 @@ class CallbackValidator extends ConstraintValidator
$methods = $constraint->methods ?: array($constraint->callback); $methods = $constraint->methods ?: array($constraint->callback);
foreach ($methods as $method) { foreach ($methods as $method) {
if (is_array($method) || $method instanceof \Closure) { if ($method instanceof \Closure) {
$method($object, $this->context);
} elseif (is_array($method)) {
if (!is_callable($method)) { if (!is_callable($method)) {
throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1])); throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1]));
} }

View File

@ -49,13 +49,12 @@ class ChoiceValidator extends ConstraintValidator
} }
if ($constraint->callback) { if ($constraint->callback) {
if (is_callable(array($this->context->getClassName(), $constraint->callback))) { if (!is_callable($choices = array($this->context->getClassName(), $constraint->callback))
$choices = call_user_func(array($this->context->getClassName(), $constraint->callback)); && !is_callable($choices = $constraint->callback)
} elseif (is_callable($constraint->callback)) { ) {
$choices = call_user_func($constraint->callback);
} else {
throw new ConstraintDefinitionException('The Choice constraint expects a valid callback'); throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
} }
$choices = call_user_func($choices);
} else { } else {
$choices = $constraint->choices; $choices = $constraint->choices;
} }

View File

@ -40,9 +40,9 @@ class TypeValidator extends ConstraintValidator
$isFunction = 'is_'.$type; $isFunction = 'is_'.$type;
$ctypeFunction = 'ctype_'.$type; $ctypeFunction = 'ctype_'.$type;
if (function_exists($isFunction) && call_user_func($isFunction, $value)) { if (function_exists($isFunction) && $isFunction($value)) {
return; return;
} elseif (function_exists($ctypeFunction) && call_user_func($ctypeFunction, $value)) { } elseif (function_exists($ctypeFunction) && $ctypeFunction($value)) {
return; return;
} elseif ($value instanceof $constraint->type) { } elseif ($value instanceof $constraint->type) {
return; return;