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

Commit

Permalink
Merge branch 'hotfix/static-callback-php54' of https://github.com/cos…
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Jul 23, 2012
9 parents 7ab35a6 + 54a28dc + c9c769e + dda791d + 70d382a + 8bbad0e + 9321185 + cb39e7e + 67e5c35 commit 489be93
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 10 deletions.
41 changes: 31 additions & 10 deletions src/CallbackHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ class CallbackHandler
*/
protected $metadata;

/**
* PHP version is greater as 5.4rc1?
* @var boolean
*/
protected static $isPhp54;

/**
* Constructor
*
Expand Down Expand Up @@ -156,37 +162,49 @@ public function call(array $args = array())
return null;
}

$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>=');
// Minor performance tweak, if the callback gets called more than once
if (!isset(self::$isPhp54)) {
self::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>=');
}

$argCount = count($args);

if (self::$isPhp54 && is_string($callback)) {
$result = $this->validateStringCallbackFor54($callback);

if ($isPhp54 && is_string($callback)) {
$this->validateStringCallbackFor54($callback);
if ($result !== true && $argCount <= 3) {
$callback = $result;
// Minor performance tweak, if the callback gets called more
// than once
$this->callback = $result;
}
}

// Minor performance tweak; use call_user_func() until > 3 arguments
// reached
switch (count($args)) {
switch ($argCount) {
case 0:
if ($isPhp54) {
if (self::$isPhp54) {
return $callback();
}
return call_user_func($callback);
case 1:
if ($isPhp54) {
if (self::$isPhp54) {
return $callback(array_shift($args));
}
return call_user_func($callback, array_shift($args));
case 2:
$arg1 = array_shift($args);
$arg2 = array_shift($args);
if ($isPhp54) {
if (self::$isPhp54) {
return $callback($arg1, $arg2);
}
return call_user_func($callback, $arg1, $arg2);
case 3:
$arg1 = array_shift($args);
$arg2 = array_shift($args);
$arg3 = array_shift($args);
if ($isPhp54) {
if (self::$isPhp54) {
return $callback($arg1, $arg2, $arg3);
}
return call_user_func($callback, $arg1, $arg2, $arg3);
Expand Down Expand Up @@ -235,7 +253,7 @@ public function getMetadatum($name)
* Validates that a static method call in PHP 5.4 will actually work
*
* @param string $callback
* @return true
* @return true|array
* @throws Exception\InvalidCallbackException if invalid
*/
protected function validateStringCallbackFor54($callback)
Expand Down Expand Up @@ -268,6 +286,9 @@ protected function validateStringCallbackFor54($callback)
));
}

return true;
// returning a non boolean value may not be nice for a validate method,
// but that allows the usage of a static string callback without using
// the call_user_func function.
return array($class, $method);
}
}
34 changes: 34 additions & 0 deletions test/CallbackHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,40 @@ public function testStringCallbackConsistingOfNonStaticMethodShouldRaiseExceptio
}
}

public function testStringStaticCallbackForPhp54()
{
if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) {
$this->markTestSkipped('Requires PHP 5.4');
}

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

public function testStringStaticCallbackForPhp54WithMoreThan3Args()
{
if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) {
$this->markTestSkipped('Requires PHP 5.4');
}

$handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler');
$error = false;
set_error_handler(function ($errno, $errstr) use (&$error) {
$error = true;
}, E_STRICT);
$result = $handler->call(array(1, 2, 3, 4));
restore_error_handler();
$this->assertFalse($error);
$this->assertSame('staticHandler', $result);
}

public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException()
{
$this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException');
Expand Down
5 changes: 5 additions & 0 deletions test/SignalHandlers/InstanceMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ public function handler()
{
return __FUNCTION__;
}

static public function staticHandler()
{
return __FUNCTION__;
}
}

0 comments on commit 489be93

Please sign in to comment.