-
Notifications
You must be signed in to change notification settings - Fork 669
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(events): allows dynamic method callbacks to be unregistered
This adds a class for matching dynamic method callbacks using static method syntax and uses it to allow unregistering dynamic method callbacks from events/hooks. Fixes #7750
- Loading branch information
Showing
6 changed files
with
209 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
namespace Elgg; | ||
|
||
/** | ||
* Identify a static/dynamic method callable, even if contains an object to which you don't have a reference. | ||
* | ||
* @access private | ||
* @since 1.11.0 | ||
*/ | ||
class MethodMatcher { | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $type; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $method; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param string $type Class to match | ||
* @param string $method Method name to match | ||
*/ | ||
public function __construct($type, $method) { | ||
$this->type = strtolower(ltrim($type, '\\')); | ||
$this->method = strtolower($method); | ||
} | ||
|
||
/** | ||
* Does the given callable match the specification? | ||
* | ||
* @param callable $subject Callable to test | ||
* @return bool | ||
*/ | ||
public function matches($subject) { | ||
// We don't use the callable type-hint because it unnecessarily autoloads for static methods. | ||
|
||
if (is_string($subject)) { | ||
if (false === strpos($subject, '::')) { | ||
return false; | ||
} | ||
|
||
$subject = explode('::', $subject, 2); | ||
} | ||
|
||
if (!is_array($subject) || empty($subject[0]) || empty($subject[1]) || !is_string($subject[1])) { | ||
return false; | ||
} | ||
|
||
if (strtolower($subject[1]) !== $this->method) { | ||
return false; | ||
} | ||
|
||
if (is_object($subject[0])) { | ||
$subject[0] = get_class($subject[0]); | ||
} | ||
|
||
if (!is_string($subject[0])) { | ||
return false; | ||
} | ||
|
||
return (strtolower(ltrim($subject[0], '\\')) === $this->type); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
namespace Elgg; | ||
|
||
class MethodMatcherTest extends \PHPUnit_Framework_TestCase { | ||
|
||
public function testMatchesStrings() { | ||
$matcher = new MethodMatcher('stdClass', 'bar'); | ||
|
||
$this->assertTrue($matcher->matches('stdClass::bar')); | ||
$this->assertTrue($matcher->matches('\STDClass::BAR')); | ||
$this->assertFalse($matcher->matches('foooo::bar')); | ||
$this->assertFalse($matcher->matches('foo\bar')); | ||
} | ||
|
||
public function testMatchesStaticArrays() { | ||
$matcher = new MethodMatcher('stdClass', 'bar'); | ||
|
||
$this->assertTrue($matcher->matches(['stdClass', 'bar'])); | ||
$this->assertTrue($matcher->matches(['\STDClass', 'BAR'])); | ||
$this->assertFalse($matcher->matches(['foooo', 'bar'])); | ||
} | ||
|
||
public function testMatchesDynamicArrays() { | ||
$matcher = new MethodMatcher('stdClass', 'bar'); | ||
|
||
$this->assertTrue($matcher->matches([new \stdClass(), 'bar'])); | ||
$this->assertTrue($matcher->matches([new \stdClass(), 'BAR'])); | ||
$this->assertFalse($matcher->matches([new MethodMatcherTestObject, 'bar'])); | ||
} | ||
} | ||
|
||
class MethodMatcherTestObject {} |