-
Notifications
You must be signed in to change notification settings - Fork 2
Updated the router and dispatcher to accept routing to controllers th… #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -179,6 +179,7 @@ public static function filterURI($uri) | |
/** | ||
* Uses PHP's ReflectionClass to test the given object for the given method's callability. | ||
* Only public, non-abstract, non-constructor/destructors are considered callable. | ||
* Also supports objects that implement the magic methods __call or __callStatic. | ||
* | ||
* @param Object $obj The object we're searching | ||
* @param string $method The name of the method we're looking for in $obj | ||
|
@@ -195,8 +196,32 @@ public static function isCallable($obj, $method, $inheritsFrom = 'Controller') | |
return false; | ||
} | ||
|
||
$reflectedMethod = false; | ||
try { | ||
$reflectedMethod = $reflectedObj->getMethod($method); | ||
} catch (ReflectionException $e) { | ||
// The method does not exist on the object, but could still be available, e.g., via __call | ||
} | ||
|
||
// If the method does not exist, but is still callable (e.g. via __call), then only ensure it meets | ||
// the same criteria on inheritance and public uncallables | ||
if ($reflectedMethod === false) { | ||
try { | ||
return ( | ||
is_callable([$obj, $method]) | ||
&& !in_array(strtolower($method), $publicUncallables) | ||
&& ( | ||
$inheritsFrom === null | ||
|| $reflectedObj->getName() == $inheritsFrom | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ===? |
||
|| $reflectedObj->isSubclassOf($inheritsFrom) | ||
) | ||
); | ||
} catch (Exception $e) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What Exception instance is possible here? Should probably catch the most specific avalable. |
||
return false; | ||
} | ||
} | ||
|
||
try { | ||
$declaredClass = $reflectedMethod->getDeclaringClass(); | ||
|
||
// A method may be required to inherit from the given class | ||
|
@@ -218,6 +243,8 @@ public static function isCallable($obj, $method, $inheritsFrom = 'Controller') | |
return true; | ||
} catch (ReflectionException $e) { | ||
return false; | ||
} catch (Exception $e) { | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure what this catch adds. |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,6 +138,31 @@ public function testIsCallable() | |
$this->assertFalse(Router::isCallable($controller, 'preAction')); | ||
$this->assertFalse(Router::isCallable($controller, 'nonexistentMethod')); | ||
$this->assertFalse(Router::isCallable(null, null)); | ||
|
||
# | ||
# TODO: add tests for __call | ||
# NOTE: phpunit currently cannot handle mocking __call properly | ||
# see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/275 | ||
# | ||
/* | ||
$magicController = $this->getMockBuilder('Controller') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not create a test controller that uses magic methods and assert it works as example expected? |
||
->disableOriginalConstructor() | ||
->setMethods(['__call']) | ||
->getMock(); | ||
|
||
$value = 'testAbc'; | ||
$magicController->expects($this->any()) | ||
->method('__call') | ||
->willReturnCallback(function($name, $arguments) use ($value) { | ||
return $value; | ||
}); | ||
|
||
$this->assertTrue(Router::isCallable($magicController, 'index')); | ||
$this->assertTrue(Router::isCallable($magicController, '__construct')); | ||
$this->assertTrue(Router::isCallable($magicController, 'preAction')); | ||
$this->assertTrue(Router::isCallable($magicController, 'nonexistentMethod')); | ||
* | ||
*/ | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it makes sense to just use 'is_callable'? Seems like that covers method_exists.