Skip to content
This repository has been archived by the owner on Jan 31, 2020. It is now read-only.

Commit

Permalink
Merge pull request zendframework/zendframework#822 from weierophinney…
Browse files Browse the repository at this point in the history
…/hotfix/zf2-172

[ZF2-172] Properly detect static method validity in PHP 5.4
  • Loading branch information
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 9 deletions.
46 changes: 46 additions & 0 deletions src/CallbackHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ public function call(array $args = array())

$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>=');

if ($isPhp54 && is_string($callback)) {
$this->validateStringCallbackFor54($callback);
}

// Minor performance tweak; use call_user_func() until > 3 arguments
// reached
switch (count($args)) {
Expand Down Expand Up @@ -234,4 +238,46 @@ public function getMetadatum($name)
}
return null;
}

/**
* Validate a static method call
*
* Validates that a static method call in PHP 5.4 will actually work
*
* @param string $callback
* @return true
* @throws Exception\InvalidCallbackException if invalid
*/
protected function validateStringCallbackFor54($callback)
{
if (!strstr($callback, '::')) {
return true;
}

list($class, $method) = explode('::', $callback, 2);

if (!class_exists($class)) {
throw new Exception\InvalidCallbackException(sprintf(
'Static method call "%s" refers to a class that does not exist',
$callback
));
}

$r = new ReflectionClass($class);
if (!$r->hasMethod($method)) {
throw new Exception\InvalidCallbackException(sprintf(
'Static method call "%s" refers to a method that does not exist',
$callback
));
}
$m = $r->getMethod($method);
if (!$m->isStatic()) {
throw new Exception\InvalidCallbackException(sprintf(
'Static method call "%s" refers to a method that is not static',
$callback
));
}

return true;
}
}
25 changes: 16 additions & 9 deletions test/CallbackHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ public function testStringCallbackResolvingToClassDefiningInvokeNameShouldRaiseE
public function testStringCallbackReferringToClassWithoutDefinedInvokeShouldRaiseException()
{
$this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException');
$handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod');
$class = new SignalHandlers\InstanceMethod();
$handler = new CallbackHandler($class);
}

public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldNotRaiseExceptionButWillRaiseEStrict()
Expand All @@ -108,16 +109,22 @@ public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldNo
$this->assertTrue($error);
}

public function testStringCallbackConsistingOfNonStaticMethodShouldNotRaiseExceptionButWillRaiseEStrict()
public function testStringCallbackConsistingOfNonStaticMethodShouldRaiseException()
{
$handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::handler');
$error = false;
set_error_handler(function ($errno, $errstr) use (&$error) {
$error = true;
}, E_STRICT);
$handler->call();
restore_error_handler();
$this->assertTrue($error);

if (version_compare(PHP_VERSION, '5.4.0rc1', '>=')) {
$this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException');
$handler->call();
} else {
$error = false;
set_error_handler(function ($errno, $errstr) use (&$error) {
$error = true;
}, E_STRICT);
$handler->call();
restore_error_handler();
$this->assertTrue($error);
}
}

public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException()
Expand Down

0 comments on commit 213395c

Please sign in to comment.