[Pkg-owncloud-commits] [owncloud] 42/172: implement most of the basic stuff that was suggested in #8290

David Prévot taffit at moszumanska.debian.org
Sun May 18 20:09:38 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository owncloud.

commit 80648da43197c91ed52f36cee8bc818038b88eb6
Author: Bernhard Posselt <dev at bernhard-posselt.com>
Date:   Tue May 6 16:29:19 2014 +0200

    implement most of the basic stuff that was suggested in #8290
---
 .../dependencyinjection/dicontainer.php            |  16 +-
 lib/private/appframework/http/dispatcher.php       |  88 ++++++++++-
 .../middleware/security/securitymiddleware.php     |  16 +-
 ...ionreader.php => controllermethodreflector.php} |  46 +++++-
 lib/public/appframework/controller.php             |  65 ++++++++
 .../appframework/http/iresponseserializer.php      |  36 +----
 lib/public/appframework/http/templateresponse.php  |  10 +-
 .../lib/appframework/controller/ControllerTest.php |  55 ++++++-
 tests/lib/appframework/http/DispatcherTest.php     | 164 +++++++++++++++++++--
 .../lib/appframework/http/TemplateResponseTest.php |  46 ++----
 .../middleware/security/SecurityMiddlewareTest.php |  33 +++--
 .../utility/ControllerMethodReflectorTest.php      | 115 +++++++++++++++
 12 files changed, 585 insertions(+), 105 deletions(-)

diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php
index becd755..c6139df 100644
--- a/lib/private/appframework/dependencyinjection/dicontainer.php
+++ b/lib/private/appframework/dependencyinjection/dicontainer.php
@@ -33,6 +33,7 @@ use OC\AppFramework\Middleware\Security\SecurityMiddleware;
 use OC\AppFramework\Middleware\Security\CORSMiddleware;
 use OC\AppFramework\Utility\SimpleContainer;
 use OC\AppFramework\Utility\TimeFactory;
+use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\AppFramework\IApi;
 use OCP\AppFramework\IAppContainer;
 use OCP\AppFramework\Middleware;
@@ -81,7 +82,11 @@ class DIContainer extends SimpleContainer implements IAppContainer{
 		});
 
 		$this['Dispatcher'] = $this->share(function($c) {
-			return new Dispatcher($c['Protocol'], $c['MiddlewareDispatcher']);
+			return new Dispatcher(
+				$c['Protocol'], 
+				$c['MiddlewareDispatcher'], 
+				$c['ControllerMethodReflector']
+			);
 		});
 
 
@@ -90,7 +95,11 @@ class DIContainer extends SimpleContainer implements IAppContainer{
 		 */
 		$app = $this;
 		$this['SecurityMiddleware'] = $this->share(function($c) use ($app){
-			return new SecurityMiddleware($app, $c['Request']);
+			return new SecurityMiddleware(
+				$app, 
+				$c['Request'], 
+				$c['ControllerMethodReflector']
+			);
 		});
 
 		$this['CORSMiddleware'] = $this->share(function($c) {
@@ -118,6 +127,9 @@ class DIContainer extends SimpleContainer implements IAppContainer{
 			return new TimeFactory();
 		});
 
+		$this['ControllerMethodReflector'] = $this->share(function($c) {
+			return new ControllerMethodReflector();
+		});
 
 	}
 
diff --git a/lib/private/appframework/http/dispatcher.php b/lib/private/appframework/http/dispatcher.php
index a2afb53..532e495 100644
--- a/lib/private/appframework/http/dispatcher.php
+++ b/lib/private/appframework/http/dispatcher.php
@@ -26,7 +26,11 @@ namespace OC\AppFramework\Http;
 
 use \OC\AppFramework\Middleware\MiddlewareDispatcher;
 use \OC\AppFramework\Http;
+use \OC\AppFramework\Utility\ControllerMethodReflector;
+
 use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Response;
+use OCP\IRequest;
 
 
 /**
@@ -36,17 +40,25 @@ class Dispatcher {
 
 	private $middlewareDispatcher;
 	private $protocol;
-
+	private $reflector;
+	private $request;
 
 	/**
 	 * @param Http $protocol the http protocol with contains all status headers
 	 * @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
 	 * runs the middleware
+	 * @param ControllerMethodReflector the reflector that is used to inject
+	 * the arguments for the controller
+	 * @param IRequest $request the incoming request
 	 */
 	public function __construct(Http $protocol,
-	                            MiddlewareDispatcher $middlewareDispatcher) {
+	                            MiddlewareDispatcher $middlewareDispatcher,
+	                            ControllerMethodReflector $reflector,
+	                            IRequest $request) {
 		$this->protocol = $protocol;
 		$this->middlewareDispatcher = $middlewareDispatcher;
+		$this->reflector = $reflector;
+		$this->request = $request;
 	}
 
 
@@ -63,10 +75,13 @@ class Dispatcher {
 		$out = array(null, array(), null);
 
 		try {
+			// prefill reflector with everything thats needed for the 
+			// middlewares
+			$this->reflector->reflect($controller, $methodName);
 
 			$this->middlewareDispatcher->beforeController($controller,
 				$methodName);
-			$response = $controller->$methodName();
+			$response = $this->executeController($controller, $methodName);
 
 			// if an exception appears, the middleware checks if it can handle the
 			// exception and creates a response. If no response is created, it is
@@ -98,4 +113,71 @@ class Dispatcher {
 	}
 
 
+	/**
+	 * Uses the reflected parameters, types and request parameters to execute
+	 * the controller
+	 * @return Response
+	 */
+	private function executeController($controller, $methodName) {
+		$arguments = array();
+
+		// valid types that will be casted
+		$types = array('int', 'integer', 'bool', 'boolean', 'float');
+
+		foreach($this->reflector->getParameters() as $param) {
+
+			// try to get the parameter from the request object and cast
+			// it to the type annotated in the @param annotation
+			$value = $this->request->getParam($param);
+			$type = $this->reflector->getType($param);
+			
+			// if this is submitted using GET or a POST form, 'false' should be 
+			// converted to false
+			if(($type === 'bool' || $type === 'boolean') &&
+				$value === 'false' && 
+				(
+					$this->request->method === 'GET' ||
+					(
+						$this->request->method === 'POST' &&
+						strpos($this->request->getHeader('Content-Type'), 
+								'application/x-www-form-urlencoded') !== false
+					)
+				)
+			) {
+				$value = false;
+
+			} elseif(in_array($type, $types)) {
+				settype($value, $type);
+			}
+			
+			$arguments[] = $value;
+		}
+
+		$response = call_user_func_array(array($controller, $methodName), $arguments);
+
+		// format response if not of type response
+		if(!($response instanceof Response)) {
+			
+			// get format from the url format or request format parameter
+			$format = $this->request->getParam('format');
+			
+			// if none is given try the first Accept header
+			if($format === null) {
+				$header = $this->request->getHeader('Accept');
+				$formats = explode(',', $header);
+
+				if($header !== null && count($formats) > 0) {
+					$accept = strtolower(trim($formats[0]));
+					$format = str_replace('application/', '', $accept);
+				} else {
+					$format = 'json';
+				}
+			}
+
+			$response = $controller->formatResponse($response, $format);
+		}
+
+		return $response;
+	}
+
 }
diff --git a/lib/private/appframework/middleware/security/securitymiddleware.php b/lib/private/appframework/middleware/security/securitymiddleware.php
index 0f160d2..b4ace5d 100644
--- a/lib/private/appframework/middleware/security/securitymiddleware.php
+++ b/lib/private/appframework/middleware/security/securitymiddleware.php
@@ -25,7 +25,7 @@
 namespace OC\AppFramework\Middleware\Security;
 
 use OC\AppFramework\Http;
-use OC\AppFramework\Utility\MethodAnnotationReader;
+use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\AppFramework\Http\RedirectResponse;
 use OCP\AppFramework\Middleware;
 use OCP\AppFramework\Http\Response;
@@ -55,10 +55,13 @@ class SecurityMiddleware extends Middleware {
 	/**
 	 * @param IAppContainer $app
 	 * @param IRequest $request
+	 * @param ControllerMethodReflector $reflector
 	 */
-	public function __construct(IAppContainer $app, IRequest $request){
+	public function __construct(IAppContainer $app, IRequest $request,
+	                            ControllerMethodReflector $reflector){
 		$this->app = $app;
 		$this->request = $request;
+		$this->reflector = $reflector;
 	}
 
 
@@ -72,28 +75,25 @@ class SecurityMiddleware extends Middleware {
 	 */
 	public function beforeController($controller, $methodName){
 
-		// get annotations from comments
-		$annotationReader = new MethodAnnotationReader($controller, $methodName);
-
 		// this will set the current navigation entry of the app, use this only
 		// for normal HTML requests and not for AJAX requests
 		$this->app->getServer()->getNavigationManager()->setActiveEntry($this->app->getAppName());
 
 		// security checks
-		$isPublicPage = $annotationReader->hasAnnotation('PublicPage');
+		$isPublicPage = $this->reflector->hasAnnotation('PublicPage');
 		if(!$isPublicPage) {
 			if(!$this->app->isLoggedIn()) {
 				throw new SecurityException('Current user is not logged in', Http::STATUS_UNAUTHORIZED);
 			}
 
-			if(!$annotationReader->hasAnnotation('NoAdminRequired')) {
+			if(!$this->reflector->hasAnnotation('NoAdminRequired')) {
 				if(!$this->app->isAdminUser()) {
 					throw new SecurityException('Logged in user must be an admin', Http::STATUS_FORBIDDEN);
 				}
 			}
 		}
 
-		if(!$annotationReader->hasAnnotation('NoCSRFRequired')) {
+		if(!$this->reflector->hasAnnotation('NoCSRFRequired')) {
 			if(!$this->request->passesCSRFCheck()) {
 				throw new SecurityException('CSRF check failed', Http::STATUS_PRECONDITION_FAILED);
 			}
diff --git a/lib/private/appframework/utility/methodannotationreader.php b/lib/private/appframework/utility/controllermethodreflector.php
similarity index 59%
rename from lib/private/appframework/utility/methodannotationreader.php
rename to lib/private/appframework/utility/controllermethodreflector.php
index 42060a0..d6209ca 100644
--- a/lib/private/appframework/utility/methodannotationreader.php
+++ b/lib/private/appframework/utility/controllermethodreflector.php
@@ -28,23 +28,59 @@ namespace OC\AppFramework\Utility;
 /**
  * Reads and parses annotations from doc comments
  */
-class MethodAnnotationReader {
+class ControllerMethodReflector {
 
 	private $annotations;
+	private $types;
+	private $parameters;
+
+	public function __construct() {
+		$this->types = array();
+		$this->parameters = array();
+		$this->annotations = array();
+	}
+
 
 	/**
 	 * @param object $object an object or classname
-	 * @param string $method the method which we want to inspect for annotations
+	 * @param string $method the method which we want to inspect
 	 */
-	public function __construct($object, $method){
-		$this->annotations = array();
-
+	public function reflect($object, $method){
 		$reflection = new \ReflectionMethod($object, $method);
 		$docs = $reflection->getDocComment();
 
 		// extract everything prefixed by @ and first letter uppercase
 		preg_match_all('/@([A-Z]\w+)/', $docs, $matches);
 		$this->annotations = $matches[1];
+
+		// extract type parameter information
+		preg_match_all('/@param (?<type>\w+) \$(?<var>\w+)/', $docs, $matches);
+		$this->types = array_combine($matches['var'], $matches['type']);
+
+		// get method parameters
+		foreach ($reflection->getParameters() as $param) {
+			$this->parameters[] = $param->name;
+		}
+	}
+
+
+	/**
+	 * Inspects the PHPDoc parameters for types
+	 * @param strint $parameter the parameter whose type comments should be 
+	 * parsed
+	 * @return string type in the type parameters (@param int $something) would
+	 * return int
+	 */
+	public function getType($parameter) {
+		return $this->types[$parameter];
+	}
+
+
+	/**
+	 * @return array the arguments of the method
+	 */
+	public function getParameters() {
+		return $this->parameters;
 	}
 
 
diff --git a/lib/public/appframework/controller.php b/lib/public/appframework/controller.php
index f42eba1..f28a1d8 100644
--- a/lib/public/appframework/controller.php
+++ b/lib/public/appframework/controller.php
@@ -28,6 +28,8 @@
 namespace OCP\AppFramework;
 
 use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\IResponseSerializer;
 use OCP\IRequest;
 
 
@@ -48,6 +50,8 @@ abstract class Controller {
 	 */
 	protected $request;
 
+	private $serializer;
+	private $formatters;
 
 	/**
 	 * constructor of the controller
@@ -66,11 +70,66 @@ abstract class Controller {
 	                            IRequest $request){
 		$this->appName = $appName;
 		$this->request = $request;
+
+		// default formatters
+		$this->formatters = array(
+			'json' => function ($response) {
+				return new JSONResponse($response);
+			}
+		);
+	}
+
+
+	/** 
+	 * Registers a serializer that is executed before a formatter is being 
+	 * called, useful for turning any data into PHP arrays that can be used
+	 * by a JSONResponse for instance
+	 * @param IResponseSerializer $serializer 
+	 */
+	protected function registerSerializer(IResponseSerializer $serializer) {
+		$this->serializer = $serializer;
+	}
+
+
+	/**
+	 * Registers a formatter for a type
+	 * @param string $format
+	 * @param \Closure $closure
+	 */
+	protected function registerFormatter($format, \Closure $formatter) {
+		$this->formatters[$format] = $formatter;
+	}
+
+
+	/**
+	 * Serializes and formats a response
+	 * @param mixed response the value that was returned from a controller and
+	 * is not a Response instance
+	 * @param string $format the format for which a formatter has been registered
+	 * @throws \DomainException if format does not match a registered formatter
+	 * @return Response
+	 */
+	public function formatResponse($response, $format='json') {
+		if(array_key_exists($format, $this->formatters)) {
+
+			if ($this->serializer) {
+				$response = $this->serializer->serialize($response);
+			}
+
+			$formatter = $this->formatters[$format];
+			
+			return $formatter($response);
+
+		} else {
+			throw new \DomainException('No formatter registered for format ' . 
+				$format . '!');
+		}
 	}
 
 
 	/**
 	 * Lets you access post and get parameters by the index
+	 * @deprecated write your parameters as method arguments instead
 	 * @param string $key the key which you want to access in the URL Parameter
 	 *                     placeholder, $_POST or $_GET array.
 	 *                     The priority how they're returned is the following:
@@ -88,6 +147,7 @@ abstract class Controller {
 	/**
 	 * Returns all params that were received, be it from the request
 	 * (as GET or POST) or throuh the URL by the route
+	 * @deprecated use $this->request instead
 	 * @return array the array with all parameters
 	 */
 	public function getParams() {
@@ -97,6 +157,7 @@ abstract class Controller {
 
 	/**
 	 * Returns the method of the request
+	 * @deprecated use $this->request instead
 	 * @return string the method of the request (POST, GET, etc)
 	 */
 	public function method() {
@@ -106,6 +167,7 @@ abstract class Controller {
 
 	/**
 	 * Shortcut for accessing an uploaded file through the $_FILES array
+	 * @deprecated use $this->request instead
 	 * @param string $key the key that will be taken from the $_FILES array
 	 * @return array the file in the $_FILES element
 	 */
@@ -116,6 +178,7 @@ abstract class Controller {
 
 	/**
 	 * Shortcut for getting env variables
+	 * @deprecated use $this->request instead
 	 * @param string $key the key that will be taken from the $_ENV array
 	 * @return array the value in the $_ENV element
 	 */
@@ -126,6 +189,7 @@ abstract class Controller {
 
 	/**
 	 * Shortcut for getting cookie variables
+	 * @deprecated use $this->request instead
 	 * @param string $key the key that will be taken from the $_COOKIE array
 	 * @return array the value in the $_COOKIE element
 	 */
@@ -136,6 +200,7 @@ abstract class Controller {
 
 	/**
 	 * Shortcut for rendering a template
+	 * @deprecated return a template response instead
 	 * @param string $templateName the name of the template
 	 * @param array $params the template parameters in key => value structure
 	 * @param string $renderAs user renders a full page, blank only your template
diff --git a/tests/lib/appframework/utility/MethodAnnotationReaderTest.php b/lib/public/appframework/http/iresponseserializer.php
similarity index 52%
rename from tests/lib/appframework/utility/MethodAnnotationReaderTest.php
rename to lib/public/appframework/http/iresponseserializer.php
index c68812a..8ffdd45 100644
--- a/tests/lib/appframework/utility/MethodAnnotationReaderTest.php
+++ b/lib/public/appframework/http/iresponseserializer.php
@@ -1,5 +1,4 @@
 <?php
-
 /**
  * ownCloud - App Framework
  *
@@ -21,35 +20,8 @@
  *
  */
 
+namespace OCP\AppFramework\Http;
 
-namespace OC\AppFramework\Utility;
-
-
-class MethodAnnotationReaderTest extends \PHPUnit_Framework_TestCase {
-
-
-	/**
-	 * @Annotation
-	 */
-	public function testReadAnnotation(){
-		$reader = new MethodAnnotationReader('\OC\AppFramework\Utility\MethodAnnotationReaderTest',
-				'testReadAnnotation');
-
-		$this->assertTrue($reader->hasAnnotation('Annotation'));
-	}
-
-
-	/**
-	 * @Annotation
-	 * @param test
-	 */
-	public function testReadAnnotationNoLowercase(){
-		$reader = new MethodAnnotationReader('\OC\AppFramework\Utility\MethodAnnotationReaderTest',
-				'testReadAnnotationNoLowercase');
-
-		$this->assertTrue($reader->hasAnnotation('Annotation'));
-		$this->assertFalse($reader->hasAnnotation('param'));
-	}
-
-
-}
+interface IResponseSerializer {
+    function serialize($response);
+}
\ No newline at end of file
diff --git a/lib/public/appframework/http/templateresponse.php b/lib/public/appframework/http/templateresponse.php
index f5baf78..52355f9 100644
--- a/lib/public/appframework/http/templateresponse.php
+++ b/lib/public/appframework/http/templateresponse.php
@@ -61,12 +61,16 @@ class TemplateResponse extends Response {
 	 * constructor of TemplateResponse
 	 * @param string $appName the name of the app to load the template from
 	 * @param string $templateName the name of the template
+	 * @param array $params an array of parameters which should be passed to the
+	 * template
+	 * @param string $renderAs how the page should be rendered, defaults to user
 	 */
-	public function __construct($appName, $templateName) {
+	public function __construct($appName, $templateName, array $params=array(),
+	                            $renderAs='user') {
 		$this->templateName = $templateName;
 		$this->appName = $appName;
-		$this->params = array();
-		$this->renderAs = 'user';
+		$this->params = $params;
+		$this->renderAs = $renderAs;
 	}
 
 
diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php
index b6c8312..4785c68 100644
--- a/tests/lib/appframework/controller/ControllerTest.php
+++ b/tests/lib/appframework/controller/ControllerTest.php
@@ -26,9 +26,31 @@ namespace OCP\AppFramework;
 
 use OC\AppFramework\Http\Request;
 use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\IResponseSerializer;
 
 
-class ChildController extends Controller {};
+class ToUpperCaseSerializer implements IResponseSerializer {
+	public function serialize($response) {
+		return array(strtoupper($response));
+	}
+}
+
+class ChildController extends Controller {
+	public function custom($in) {
+		$this->registerFormatter('json', function ($response) {
+			return new JSONResponse(array(strlen($response)));
+		});
+
+		return $in;
+	}
+
+	public function serializer($in) {
+		$this->registerSerializer(new ToUpperCaseSerializer());
+
+		return $in;
+	}
+};
 
 class ControllerTest extends \PHPUnit_Framework_TestCase {
 
@@ -129,4 +151,35 @@ class ControllerTest extends \PHPUnit_Framework_TestCase {
 	}
 
 
+	/**
+	 * @expectedException \DomainException
+	 */
+	public function testFormatResonseInvalidFormat() {
+		$this->controller->formatResponse(null, 'test');
+	}
+
+
+	public function testFormat() {
+		$response = $this->controller->formatResponse(array('hi'), 'json');
+
+		$this->assertEquals(array('hi'), $response->getData());
+	}
+
+
+	public function testCustomFormatter() {
+		$response = $this->controller->custom('hi');
+		$response = $this->controller->formatResponse($response, 'json');
+
+		$this->assertEquals(array(2), $response->getData());		
+	}
+
+
+	public function testCustomSerializer() {
+		$response = $this->controller->serializer('hi');
+		$response = $this->controller->formatResponse($response, 'json');
+
+		$this->assertEquals(array('HI'), $response->getData());	
+	}
+
+
 }
diff --git a/tests/lib/appframework/http/DispatcherTest.php b/tests/lib/appframework/http/DispatcherTest.php
index 9841dca..ba1e989 100644
--- a/tests/lib/appframework/http/DispatcherTest.php
+++ b/tests/lib/appframework/http/DispatcherTest.php
@@ -25,8 +25,28 @@
 namespace OC\AppFramework\Http;
 
 use OC\AppFramework\Middleware\MiddlewareDispatcher;
+use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\AppFramework\Http;
-//require_once(__DIR__ . "/../classloader.php");
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Controller;
+
+
+class TestController extends Controller {
+	public function __construct($appName, $request) {
+		parent::__construct($appName, $request);
+	}
+
+	/**
+	 * @param int $int
+	 * @param bool $bool
+	 */
+	public function exec($int, $bool) {
+		$this->registerFormatter('text', function($in) {
+			return new JSONResponse(array('text' => $in));
+		});
+		return array($int, $bool);
+	}
+}
 
 
 class DispatcherTest extends \PHPUnit_Framework_TestCase {
@@ -39,6 +59,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 	private $lastModified;
 	private $etag;
 	private $http;
+	private $reflector;
 
 	protected function setUp() {
 		$this->controllerMethod = 'test';
@@ -64,8 +85,17 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 			'\OCP\AppFramework\Controller',
 			array($this->controllerMethod), array($app, $request));
 		
+		$this->request = $this->getMockBuilder(
+			'\OC\AppFramework\Http\Request')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->reflector = new ControllerMethodReflector();
+
 		$this->dispatcher = new Dispatcher(
-			$this->http, $this->middlewareDispatcher);
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
 		
 		$this->response = $this->getMockBuilder(
 			'\OCP\AppFramework\Http\Response')
@@ -81,7 +111,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 	 * @param string $out
 	 * @param string $httpHeaders
 	 */
-	private function setMiddlewareExpections($out=null, 
+	private function setMiddlewareExpectations($out=null, 
 		$httpHeaders=null, $responseHeaders=array(),
 		$ex=false, $catchEx=true) {
 
@@ -159,14 +189,12 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 			->with($this->equalTo($this->controller), 
 				$this->equalTo($this->controllerMethod),
 				$this->equalTo($out))
-			->will($this->returnValue($out));
-
-		
+			->will($this->returnValue($out));		
 	}
 
 
 	public function testDispatcherReturnsArrayWith2Entries() {
-		$this->setMiddlewareExpections();
+		$this->setMiddlewareExpectations();
 
 		$response = $this->dispatcher->dispatch($this->controller, 
 			$this->controllerMethod);
@@ -180,7 +208,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$out = 'yo';
 		$httpHeaders = 'Http';
 		$responseHeaders = array('hell' => 'yeah');
-		$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders);
+		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders);
 
 		$response = $this->dispatcher->dispatch($this->controller, 
 			$this->controllerMethod);
@@ -195,7 +223,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$out = 'yo';
 		$httpHeaders = 'Http';
 		$responseHeaders = array('hell' => 'yeah');
-		$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true);		
+		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true);		
 
 		$response = $this->dispatcher->dispatch($this->controller, 
 			$this->controllerMethod);
@@ -210,7 +238,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 		$out = 'yo';
 		$httpHeaders = 'Http';
 		$responseHeaders = array('hell' => 'yeah');
-		$this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true, false);
+		$this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true, false);
 
 		$this->setExpectedException('\Exception');
 		$response = $this->dispatcher->dispatch($this->controller, 
@@ -218,4 +246,120 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase {
 
 	}
 
+
+	private function dispatcherPassthrough() {
+		$this->middlewareDispatcher->expects($this->once())
+				->method('beforeController');
+		$this->middlewareDispatcher->expects($this->once())
+			->method('afterController')
+			->will($this->returnCallback(function($a, $b, $in) {
+				return $in;
+			}));
+		$this->middlewareDispatcher->expects($this->once())
+			->method('beforeOutput')
+			->will($this->returnCallback(function($a, $b, $in) {
+				return $in;
+			}));
+	}
+
+	public function testControllerParametersInjected() {
+		$this->request = new Request(array(
+			'post' => array(
+				'int' => '3',
+				'bool' => 'false'
+			),
+			'method' => 'POST'
+		));
+		$this->dispatcher = new Dispatcher(
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
+		$controller = new TestController('app', $this->request);
+
+		// reflector is supposed to be called once
+		$this->dispatcherPassthrough();
+		$response = $this->dispatcher->dispatch($controller, 'exec');
+
+		$this->assertEquals('[3,true]', $response[2]);
+	}
+
+
+	public function testResponseTransformedByUrlFormat() {
+		$this->request = new Request(array(
+			'post' => array(
+				'int' => '3',
+				'bool' => 'false'
+			),
+			'urlParams' => array(
+				'format' => 'text'
+			),
+			'method' => 'GET'
+		));
+		$this->dispatcher = new Dispatcher(
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
+		$controller = new TestController('app', $this->request);
+
+		// reflector is supposed to be called once
+		$this->dispatcherPassthrough();
+		$response = $this->dispatcher->dispatch($controller, 'exec');
+
+		$this->assertEquals('{"text":[3,false]}', $response[2]);
+	}
+
+
+	public function testResponseTransformedByAcceptHeader() {
+		$this->request = new Request(array(
+			'post' => array(
+				'int' => '3',
+				'bool' => 'false'
+			),
+			'server' => array(
+				'HTTP_ACCEPT' => 'application/text, test',
+				'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded'
+			),
+			'method' => 'POST'
+		));
+		$this->dispatcher = new Dispatcher(
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
+		$controller = new TestController('app', $this->request);
+
+		// reflector is supposed to be called once
+		$this->dispatcherPassthrough();
+		$response = $this->dispatcher->dispatch($controller, 'exec');
+
+		$this->assertEquals('{"text":[3,false]}', $response[2]);
+	}
+
+
+	public function testResponsePrimarilyTransformedByParameterFormat() {
+		$this->request = new Request(array(
+			'post' => array(
+				'int' => '3',
+				'bool' => 'false'
+			),
+			'get' => array(
+				'format' => 'text'
+			),
+			'server' => array(
+				'HTTP_ACCEPT' => 'application/json, test'
+			),
+			'method' => 'POST'
+		));
+		$this->dispatcher = new Dispatcher(
+			$this->http, $this->middlewareDispatcher, $this->reflector,
+			$this->request
+		);
+		$controller = new TestController('app', $this->request);
+
+		// reflector is supposed to be called once
+		$this->dispatcherPassthrough();
+		$response = $this->dispatcher->dispatch($controller, 'exec');
+
+		$this->assertEquals('{"text":[3,true]}', $response[2]);
+	}
+
 }
diff --git a/tests/lib/appframework/http/TemplateResponseTest.php b/tests/lib/appframework/http/TemplateResponseTest.php
index 0b158ed..29ce8cf 100644
--- a/tests/lib/appframework/http/TemplateResponseTest.php
+++ b/tests/lib/appframework/http/TemplateResponseTest.php
@@ -51,6 +51,22 @@ class TemplateResponseTest extends \PHPUnit_Framework_TestCase {
 	}
 
 
+	public function testSetParamsConstructor(){
+		$params = array('hi' => 'yo');
+		$this->tpl = new TemplateResponse($this->api, 'home', $params);
+
+		$this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams());
+	}
+
+
+	public function testSetRenderAsConstructor(){
+		$renderAs = 'myrender';
+		$this->tpl = new TemplateResponse($this->api, 'home', array(), $renderAs);
+
+		$this->assertEquals($renderAs, $this->tpl->getRenderAs());
+	}
+
+
 	public function testSetParams(){
 		$params = array('hi' => 'yo');
 		$this->tpl->setParams($params);
@@ -63,36 +79,6 @@ class TemplateResponseTest extends \PHPUnit_Framework_TestCase {
 		$this->assertEquals('home', $this->tpl->getTemplateName());
 	}
 
-
-//	public function testRender(){
-//		$ocTpl = $this->getMock('Template', array('fetchPage'));
-//		$ocTpl->expects($this->once())
-//				->method('fetchPage');
-//
-//		$tpl = new TemplateResponse('core', 'error');
-//
-//		$tpl->render();
-//	}
-//
-//
-//	public function testRenderAssignsParams(){
-//		$params = array('john' => 'doe');
-//
-//		$tpl = new TemplateResponse('app', 'home');
-//		$tpl->setParams($params);
-//
-//		$tpl->render();
-//	}
-//
-//
-//	public function testRenderDifferentApp(){
-//
-//		$tpl = new TemplateResponse('app', 'home', 'app2');
-//
-//		$tpl->render();
-//	}
-
-
 	public function testGetRenderAs(){
 		$render = 'myrender';
 		$this->tpl->renderAs($render);
diff --git a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
index 19e8a68..e91aaca 100644
--- a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
+++ b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
@@ -26,6 +26,7 @@ namespace OC\AppFramework\Middleware\Security;
 
 use OC\AppFramework\Http;
 use OC\AppFramework\Http\Request;
+use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\AppFramework\Http\RedirectResponse;
 use OCP\AppFramework\Http\JSONResponse;
 
@@ -37,14 +38,16 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 	private $secException;
 	private $secAjaxException;
 	private $request;
+	private $reader;
 
 	public function setUp() {
 		$api = $this->getMock('OC\AppFramework\DependencyInjection\DIContainer', array(), array('test'));
 		$this->controller = $this->getMock('OCP\AppFramework\Controller',
 				array(), array($api, new Request()));
+		$this->reader = new ControllerMethodReflector();
 
 		$this->request = new Request();
-		$this->middleware = new SecurityMiddleware($api, $this->request);
+		$this->middleware = new SecurityMiddleware($api, $this->request, $this->reader);
 		$this->secException = new SecurityException('hey', false);
 		$this->secAjaxException = new SecurityException('hey', true);
 	}
@@ -68,7 +71,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 		$api->expects($this->any())->method('getServer')
 			->will($this->returnValue($serverMock));
 
-		$sec = new SecurityMiddleware($api, $this->request);
+		$sec = new SecurityMiddleware($api, $this->request, $this->reader);
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method);
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method);
 	}
 
@@ -99,11 +103,12 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 				->will($this->returnValue(true));
 		}
 
-		$sec = new SecurityMiddleware($api, $this->request);
+		$sec = new SecurityMiddleware($api, $this->request, $this->reader);
 
 		try {
-			$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest',
-					$method);
+			$controller = '\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest';
+			$this->reader->reflect($controller, $method);
+			$sec->beforeController($controller,	$method);
 		} catch (SecurityException $ex){
 			$this->assertEquals($status, $ex->getCode());
 		}
@@ -184,7 +189,9 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 				->method('isLoggedIn')
 				->will($this->returnValue(true));
 
-		$sec = new SecurityMiddleware($api, $this->request);
+		$sec = new SecurityMiddleware($api, $this->request, $this->reader);
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest',
+				'testNoChecks');
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest',
 				'testNoChecks');
 	}
@@ -207,7 +214,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 				->will($this->returnValue(true));
 		}
 
-		$sec = new SecurityMiddleware($api, $this->request);
+		$sec = new SecurityMiddleware($api, $this->request, $this->reader);
 
 		if($shouldFail){
 			$this->setExpectedException('\OC\AppFramework\Middleware\Security\SecurityException');
@@ -215,6 +222,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			$this->setExpectedException(null);
 		}
 
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method);
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method);
 	}
 
@@ -230,7 +238,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			->method('passesCSRFCheck')
 			->will($this->returnValue(false));
 
-		$sec = new SecurityMiddleware($api, $request);
+		$sec = new SecurityMiddleware($api, $request, $this->reader);
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testCsrfCheck');
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testCsrfCheck');
 	}
 
@@ -246,7 +255,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			->method('passesCSRFCheck')
 			->will($this->returnValue(false));
 
-		$sec = new SecurityMiddleware($api, $request);
+		$sec = new SecurityMiddleware($api, $request, $this->reader);
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testNoCsrfCheck');
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testNoCsrfCheck');
 	}
 
@@ -261,7 +271,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			->method('passesCSRFCheck')
 			->will($this->returnValue(true));
 
-		$sec = new SecurityMiddleware($api, $request);
+		$sec = new SecurityMiddleware($api, $request, $this->reader);
+		$this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testFailCsrfCheck');
 		$sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testFailCsrfCheck');
 	}
 
@@ -318,7 +329,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase {
 
 		$this->request = new Request(
 			array('server' => array('HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')));
-		$this->middleware = new SecurityMiddleware($api, $this->request);
+		$this->middleware = new SecurityMiddleware($api, $this->request, $this->reader);
 		$response = $this->middleware->afterException($this->controller, 'test',
 				$this->secException);
 
diff --git a/tests/lib/appframework/utility/ControllerMethodReflectorTest.php b/tests/lib/appframework/utility/ControllerMethodReflectorTest.php
new file mode 100644
index 0000000..2a7c003
--- /dev/null
+++ b/tests/lib/appframework/utility/ControllerMethodReflectorTest.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale at gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Utility;
+
+
+class ControllerMethodReflectorTest extends \PHPUnit_Framework_TestCase {
+
+
+	/**
+	 * @Annotation
+	 */
+	public function testReadAnnotation(){
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'testReadAnnotation'
+		);
+
+		$this->assertTrue($reader->hasAnnotation('Annotation'));
+	}
+
+
+	/**
+	 * @Annotation
+	 * @param test
+	 */
+	public function testReadAnnotationNoLowercase(){
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'testReadAnnotationNoLowercase'
+		);
+
+		$this->assertTrue($reader->hasAnnotation('Annotation'));
+		$this->assertFalse($reader->hasAnnotation('param'));
+	}
+
+
+	/**
+	 * @Annotation
+	 * @param int $test
+	 */
+	public function testReadTypeIntAnnotations(){
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'testReadTypeIntAnnotations'
+		);
+
+		$this->assertEquals('int', $reader->getType('test'));
+	}
+
+
+	/**
+	 * @Annotation
+	 * @param double $test
+	 */
+	public function testReadTypeDoubleAnnotations(){
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'testReadTypeDoubleAnnotations'
+		);
+
+		$this->assertEquals('double', $reader->getType('test'));
+	}
+
+
+	public function arguments($arg, $arg2) {}
+	public function testReflectParameters() {
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'arguments'
+		);
+
+		$this->assertEquals(array('arg', 'arg2'), $reader->getParameters());	
+	}
+
+
+	public function arguments2($arg) {}
+	public function testReflectParameters2() {
+		$reader = new ControllerMethodReflector();
+		$reader->reflect(
+			'\OC\AppFramework\Utility\ControllerMethodReflectorTest',
+			'arguments2'
+		);
+
+		$this->assertEquals(array('arg',), $reader->getParameters());	
+	}
+
+
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list