Browse Source

Initial implementation of isAction().

Having a hook method will allow userland code to customize which methods
are exposed as an action.
mark_story 11 years ago
parent
commit
307a66955b
2 changed files with 41 additions and 14 deletions
  1. 26 14
      src/Controller/Controller.php
  2. 15 0
      tests/TestCase/Controller/ControllerTest.php

+ 26 - 14
src/Controller/Controller.php

@@ -30,6 +30,8 @@ use Cake\Utility\Inflector;
 use Cake\Utility\MergeVariablesTrait;
 use Cake\View\ViewVarsTrait;
 use LogicException;
+use ReflectionClass;
+use ReflectionException;
 
 /**
  * Application controller class for organization of business logic.
@@ -231,14 +233,6 @@ class Controller implements EventListener {
 	public $passedArgs = array();
 
 /**
- * Holds current methods of the controller. This is a list of all the methods reachable
- * via URL. Modifying this array, will allow you to change which methods can be reached.
- *
- * @var array
- */
-	public $methods = array();
-
-/**
  * Constructor.
  *
  * Sets a number of properties based on conventions if they are empty. To override the
@@ -267,10 +261,6 @@ class Controller implements EventListener {
 			$this->viewPath = $viewPath;
 		}
 
-		$childMethods = get_class_methods($this);
-		$baseMethods = get_class_methods('Cake\Controller\Controller');
-		$this->methods = array_diff($childMethods, $baseMethods);
-
 		if ($request instanceof Request) {
 			$this->setRequest($request);
 		}
@@ -442,8 +432,7 @@ class Controller implements EventListener {
  */
 	protected function _isPrivateAction(\ReflectionMethod $method) {
 		return (
-			!$method->isPublic() ||
-			!in_array($method->name, $this->methods)
+			!$method->isPublic() || !$this->isAction($method->name)
 		);
 	}
 
@@ -682,6 +671,29 @@ class Controller implements EventListener {
 	}
 
 /**
+ * Method to check that an action is accessible from a URL.
+ *
+ * Override this method to change which controller methods can be reached.
+ * The default implementation disallows access to all methods defined on Cake\Controller\Controller,
+ * and allows all public methods on all subclasses of this class.
+ *
+ * @param string $action The action to check.
+ * @return boolean Whether or not the method is accesible from a URL.
+ */
+	public function isAction($action) {
+		$reflection = new ReflectionClass($this);
+		try {
+			$method = $reflection->getMethod($action);
+		} catch (\ReflectionException $e) {
+			return false;
+		}
+		if ($method->getDeclaringClass()->name == 'Cake\Controller\Controller') {
+			return false;
+		}
+		return true;
+	}
+
+/**
  * Called before the controller action. You can use this method to configure and customize components
  * or perform logic that needs to happen before each controller action.
  *

+ 15 - 0
tests/TestCase/Controller/ControllerTest.php

@@ -845,4 +845,19 @@ class ControllerTest extends TestCase {
 		}
 	}
 
+/**
+ * Test the isAction method.
+ *
+ * @return void
+ */
+	public function testIsAction() {
+		$request = new Request('/');
+		$response = $this->getMock('Cake\Network\Response');
+		$controller = new TestController($request, $response);
+
+		$this->assertFalse($controller->isAction('redirect'));
+		$this->assertFalse($controller->isAction('beforeFilter'));
+		$this->assertTrue($controller->isAction('index'));
+	}
+
 }