Permalink
Browse files

Moving private method detection into Controller.

This fixes an issue where potected methods would
not be called, and no exception would be raised.
  • Loading branch information...
1 parent 8bfc0a8 commit 177cd39abb26686cc8fe73292e89ed735079a9fb @markstory markstory committed with markstory Jul 9, 2011
@@ -443,6 +443,61 @@ public function setRequest(CakeRequest $request) {
}
/**
+ * Dispatches the controller action. Checks that the action
+ * exists and isn't private.
+ *
+ * @param CakeRequest $request
+ * @return The resulting response.
+ */
+ public function invokeAction(CakeRequest $request) {
+ $reflection = new ReflectionClass($this);
+ try {
+ $method = $reflection->getMethod($request->params['action']);
+
+ if ($this->_isPrivateAction($method, $request)) {
+ throw new PrivateActionException(array(
+ 'controller' => $this->name . "Controller",
+ 'action' => $request->params['action']
+ ));
+ }
+ return $method->invokeArgs($this, $request->params['pass']);
+
+ } catch (ReflectionException $e) {
+ if ($this->scaffold !== false) {
+ return new Scaffold($this, $request);
+ }
+ throw new MissingActionException(array(
+ 'controller' => $this->name . "Controller",
+ 'action' => $request->params['action']
+ ));
+ }
+ }
+
+/**
+ * Check if the request's action is marked as private, with an underscore, of if the request is attempting to
+ * directly accessing a prefixed action.
+ *
+ * @param ReflectionMethod $method The method to be invoked.
+ * @param CakeRequest $request The request to check.
+ * @return boolean
+ */
+ protected function _isPrivateAction(ReflectionMethod $method, CakeRequest $request) {
+ $privateAction = (
+ $method->name[0] === '_' ||
+ !$method->isPublic() ||
+ !in_array($method->name, $this->methods)
+ );
+ $prefixes = Router::prefixes();
+
+ if (!$privateAction && !empty($prefixes)) {
+ if (empty($request->params['prefix']) && strpos($request->params['action'], '_') > 0) {
+ list($prefix, $action) = explode('_', $request->params['action']);
+ $privateAction = in_array($prefix, $prefixes);
+ }
+ }
+ return $privateAction;
+ }
+/**
* Merge components, helpers, and uses vars from Controller::$_mergeParent and PluginAppController.
*
* @return void
@@ -93,38 +93,10 @@ public function dispatch(CakeRequest $request, CakeResponse $response, $addition
));
}
- if ($this->_isPrivateAction($request)) {
- throw new PrivateActionException(array(
- 'controller' => Inflector::camelize($request->params['controller']) . "Controller",
- 'action' => $request->params['action']
- ));
- }
-
return $this->_invoke($controller, $request, $response);
}
/**
- * Check if the request's action is marked as private, with an underscore, of if the request is attempting to
- * directly accessing a prefixed action.
- *
- * @param CakeRequest $request The request to check
- * @return boolean
- */
- protected function _isPrivateAction($request) {
- $privateAction = $request->params['action'][0] === '_';
- $prefixes = Router::prefixes();
-
- if (!$privateAction && !empty($prefixes)) {
- if (empty($request->params['prefix']) && strpos($request->params['action'], '_') > 0) {
- list($prefix, $action) = explode('_', $request->params['action']);
- $privateAction = in_array($prefix, $prefixes);
- }
- }
-
- return $privateAction;
- }
-
-/**
* Initializes the components and models a controller will be using.
* Triggers the controller action, and invokes the rendering if Controller::$autoRender is true and echo's the output.
* Otherwise the return value of the controller action are returned.
@@ -138,22 +110,11 @@ protected function _invoke(Controller $controller, CakeRequest $request, CakeRes
$controller->constructClasses();
$controller->startupProcess();
- $methods = array_flip($controller->methods);
-
- if (!isset($methods[$request->params['action']])) {
- if ($controller->scaffold !== false) {
- return new Scaffold($controller, $request);
- }
- throw new MissingActionException(array(
- 'controller' => Inflector::camelize($request->params['controller']) . "Controller",
- 'action' => $request->params['action']
- ));
- }
- $result = call_user_func_array(array(&$controller, $request->params['action']), $request->params['pass']);
-
+ $result = $controller->invokeAction($request);
if ($result instanceof CakeResponse) {
$response = $result;
}
+
if ($controller->autoRender) {
$response = $controller->render();
} elseif ($response->body() === null) {
@@ -50,11 +50,7 @@ class TestDispatcher extends Dispatcher {
* @return void
*/
protected function _invoke(Controller $controller, CakeRequest $request, CakeResponse $response) {
- if ($result = parent::_invoke($controller, $request, $response)) {
- if ($result[0] === 'missingAction') {
- return $result;
- }
- }
+ $result = parent::_invoke($controller, $request, $response);
return $controller;
}
@@ -733,13 +729,13 @@ public function testMissingAction() {
}
/**
- * test that methods declared in Controller are treated as missing methods.
+ * test that methods declared in Controller are treated as private methods.
*
- * @expectedException MissingActionException
- * @expectedExceptionMessage Action SomePagesController::redirect() could not be found.
+ * @expectedException PrivateActionException
+ * @expectedExceptionMessage Private Action SomePagesController::redirect() is not directly accessible.
* @return void
*/
- public function testMissingActionFromBaseClassMethods() {
+ public function testPrivateActionFromBaseClassMethods() {
$Dispatcher = new TestDispatcher();
Configure::write('App.baseUrl','/index.php');
$url = new CakeRequest('some_pages/redirect/param:value/param2:value2');

0 comments on commit 177cd39

Please sign in to comment.