diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d2d82e106c..692bff039ce 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
-# [3.1.0](https://github.com/phalcon/cphalcon/releases/tag/v3.1.0) (2016-XX-XX)``
+# [3.1.0](https://github.com/phalcon/cphalcon/releases/tag/v3.1.0) (2016-XX-XX)
- Added `Phalcon\Validation\Validator\Callback`, `Phalcon\Validation::getData`
- Added the ability to truncate database tables
+- Added `Phalcon\Mvc\Model\Binder`, class used for binding models to parameters in dispatcher, micro, added `Phalcon\Dispatcher::getBoundModels` and `Phalcon\Mvc\Micro::getBoundModels` to getting bound models, added `Phalcon\Mvc\Micro\Collection\LazyLoader::callMethod`
# [3.0.2](https://github.com/phalcon/cphalcon/releases/tag/v3.0.2) (2016-XX-XX)
- Fixed saving snapshot data while caching model [#12170](https://github.com/phalcon/cphalcon/issues/12170), [#12000](https://github.com/phalcon/cphalcon/issues/12000)
diff --git a/phalcon/dispatcher.zep b/phalcon/dispatcher.zep
index 5eaf61b016d..487d9b431ab 100755
--- a/phalcon/dispatcher.zep
+++ b/phalcon/dispatcher.zep
@@ -26,6 +26,8 @@ use Phalcon\DispatcherInterface;
use Phalcon\Events\ManagerInterface;
use Phalcon\Di\InjectionAwareInterface;
use Phalcon\Events\EventsAwareInterface;
+use Phalcon\Mvc\Model\Binder;
+use Phalcon\Mvc\Model\BinderInterface;
/**
* Phalcon\Dispatcher
@@ -78,6 +80,8 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
protected _modelBinding = false;
+ protected _modelBinder = null;
+
const EXCEPTION_NO_DI = 0;
const EXCEPTION_CYCLIC_ROUTING = 1;
@@ -322,11 +326,61 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
/**
* Enable/Disable model binding during dispatch
*
- * @param boolean value
+ *
+ * $di->set('dispatcher', function() {
+ * $dispatcher = new Dispatcher();
+ *
+ * $dispatcher->setModelBinding(true, 'cache');
+ * return $dispatcher;
+ * });
+ *
*/
- public function setModelBinding(boolean value)
+ public function setModelBinding(boolean value, var cache = null) ->
{
+ var dependencyInjector;
+
+ if typeof cache == "string" {
+ let dependencyInjector = this->_dependencyInjector;
+ let cache = dependencyInjector->get(cache);
+ }
+
let this->_modelBinding = value;
+ if value {
+ let this->_modelBinder = new Binder(cache);
+ }
+
+ return this;
+ }
+
+ /**
+ * Enable model binding during dispatch
+ *
+ *
+ * $di->set('dispatcher', function() {
+ * $dispatcher = new Dispatcher();
+ *
+ * $dispatcher->setModelBinder(new Binder(), 'cache');
+ * return $dispatcher;
+ * });
+ *
+ */
+ public function setModelBinder( modelBinder, var cache = null) ->
+ {
+ var dependencyInjector;
+
+ if typeof cache == "string" {
+ let dependencyInjector = this->_dependencyInjector;
+ let cache = dependencyInjector->get(cache);
+ }
+
+ if cache != null {
+ modelBinder->setCache(cache);
+ }
+
+ let this->_modelBinding = true;
+ let this->_modelBinder = modelBinder;
+
+ return this;
}
/**
@@ -362,9 +416,8 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
int numberDispatches;
var value, handler, dependencyInjector, namespaceName, handlerName,
actionName, params, eventsManager,
- actionSuffix, handlerClass, status, actionMethod, reflectionMethod, methodParams,
- className, paramKey, methodParam, modelName, bindModel,
- wasFresh = false, e;
+ actionSuffix, handlerClass, status, actionMethod, modelBinder, wasFresh = false,
+ e, bindCacheKey;
let dependencyInjector = this->_dependencyInjector;
if typeof dependencyInjector != "object" {
@@ -551,34 +604,10 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
}
}
- if this->_modelBinding === true {
- //Check if we can bind a model based on what the controller action is expecting
- let reflectionMethod = new \ReflectionMethod(handlerClass, actionMethod);
- let methodParams = reflectionMethod->getParameters();
-
- for paramKey, methodParam in methodParams {
- if methodParam->getClass() {
- let className = methodParam->getClass()->getName();
- if typeof className == "string" {
- //If we are in a base class and the child implements BindModelInterface we getModelName
- if className == "Phalcon\\Mvc\\Model" {
- if in_array("Phalcon\\Mvc\\Controller\\BindModelInterface", class_implements(handlerClass)) {
- let modelName = call_user_func([handlerClass, "getModelName"]);
- let bindModel = call_user_func_array([modelName, "findFirst"], [params[paramKey]]);
- let params[paramKey] = bindModel;
- break;
- }
- }
-
- //Check if Model is defined
- if is_subclass_of(className, "Phalcon\\Mvc\\Model") {
- let bindModel = call_user_func_array([className, "findFirst"], [params[paramKey]]);
- let params[paramKey] = bindModel;
- break;
- }
- }
- }
- }
+ if this->_modelBinding {
+ let modelBinder = this->_modelBinder;
+ let bindCacheKey = "_PHMB_" . handlerClass . "_" . actionMethod;
+ let params = modelBinder->bindToHandler(handler, params, bindCacheKey, actionMethod);
}
let this->_lastHandler = handler;
@@ -736,6 +765,32 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
return call_user_func_array([handler, actionMethod], params);
}
+ /**
+ * Returns bound models from binder instance
+ *
+ *
+ * class UserController extends Controller
+ * {
+ * public function showAction(User $user)
+ * {
+ * $boundModels = $this->dispatcher->getBoundModels(); // return array with $user
+ * }
+ * }
+ *
+ */
+ public function getBoundModels() -> array
+ {
+ var modelBinder;
+
+ let modelBinder = this->_modelBinder;
+
+ if modelBinder != null {
+ return modelBinder->getBoundModels();
+ }
+
+ return [];
+ }
+
/**
* Set empty properties to their defaults (where defaults are available)
*/
diff --git a/phalcon/mvc/micro.zep b/phalcon/mvc/micro.zep
index b4a6d0cb758..6a08d5f2903 100644
--- a/phalcon/mvc/micro.zep
+++ b/phalcon/mvc/micro.zep
@@ -30,6 +30,8 @@ use Phalcon\Http\ResponseInterface;
use Phalcon\Mvc\Router\RouteInterface;
use Phalcon\Mvc\Micro\MiddlewareInterface;
use Phalcon\Mvc\Micro\CollectionInterface;
+use Phalcon\Mvc\Controller;
+use Phalcon\Mvc\Model\BinderInterface;
/**
* Phalcon\Mvc\Micro
@@ -76,6 +78,8 @@ class Micro extends Injectable implements \ArrayAccess
protected _returnedValue;
+ protected _modelBinder;
+
/**
* Phalcon\Mvc\Micro constructor
*/
@@ -365,7 +369,7 @@ class Micro extends Injectable implements \ArrayAccess
public function mount( collection) ->
{
var mainHandler, handlers, lazyHandler, prefix, methods, pattern,
- subHandler, realHandler, prefixedPattern, route, handler, name;
+ subHandler, realHandler, prefixedPattern, route, handler, name, modelBinder;
/**
* Get the main handler
@@ -581,7 +585,7 @@ class Micro extends Injectable implements \ArrayAccess
var dependencyInjector, eventsManager, status = null, router, matchedRoute,
handler, beforeHandlers, params, returnedValue, e, errorHandler,
afterHandlers, notFoundHandler, finishHandlers, finish, before, after,
- response;
+ response, modelBinder, bindCacheKey, routeName, realHandler = null, methodName, lazyReturned;
let dependencyInjector = this->_dependencyInjector;
if typeof dependencyInjector != "object" {
@@ -690,17 +694,52 @@ class Micro extends Injectable implements \ArrayAccess
let params = router->getParams();
+ let modelBinder = this->_modelBinder;
+
/**
* Bound the app to the handler
*/
if typeof handler == "object" && handler instanceof \Closure {
let handler = \Closure::bind(handler, this);
+ if modelBinder != null {
+ let routeName = matchedRoute->getName();
+ if routeName != null {
+ let bindCacheKey = "_PHMB_" . routeName;
+ } else {
+ let bindCacheKey = "_PHMB_" . matchedRoute->getPattern();
+ }
+ let params = modelBinder->bindToHandler(handler, params, bindCacheKey);
+ }
}
/**
* Calling the Handler in the PHP userland
*/
- let returnedValue = call_user_func_array(handler, params);
+
+ if typeof handler == "array" {
+
+ let realHandler = handler[0];
+
+ if realHandler instanceof Controller && modelBinder != null {
+ let methodName = handler[1];
+ let bindCacheKey = "_PHMB_" . get_class(realHandler) . "_" . methodName;
+ let params = modelBinder->bindToHandler(realHandler, params, bindCacheKey, methodName);
+ }
+ }
+
+ /**
+ * Instead of double call_user_func_array when lazy loading we will just call method
+ */
+ if realHandler != null && realHandler instanceof LazyLoader {
+ let methodName = handler[1];
+ /**
+ * There is seg fault if we try set directly value of method to returnedValue
+ */
+ let lazyReturned = realHandler->callMethod(methodName, params, modelBinder);
+ let returnedValue = lazyReturned;
+ } else {
+ let returnedValue = call_user_func_array(handler, params);
+ }
/**
* Update the returned value
@@ -1040,4 +1079,46 @@ class Micro extends Injectable implements \ArrayAccess
{
return this->_handlers;
}
+
+ /**
+ * Sets model binder
+ *
+ *
+ * $micro = new Micro($di);
+ * $micro->setModelBinder(new Binder(), 'cache');
+ *
+ */
+ public function setModelBinder( modelBinder, var cache = null) ->
+ {
+ var dependencyInjector;
+
+ if typeof cache == "string" {
+ let dependencyInjector = this->_dependencyInjector;
+ let cache = dependencyInjector->get(cache);
+ }
+
+ if cache != null {
+ modelBinder->setCache(cache);
+ }
+
+ let this->_modelBinder = modelBinder;
+
+ return this;
+ }
+
+ /**
+ * Returns bound models from binder instance
+ */
+ public function getBoundModels() -> array
+ {
+ var modelBinder;
+
+ let modelBinder = this->_modelBinder;
+
+ if modelBinder != null {
+ return modelBinder->getBoundModels();
+ }
+
+ return [];
+ }
}
diff --git a/phalcon/mvc/micro/lazyloader.zep b/phalcon/mvc/micro/lazyloader.zep
index d1e4ab44940..d3369098b05 100644
--- a/phalcon/mvc/micro/lazyloader.zep
+++ b/phalcon/mvc/micro/lazyloader.zep
@@ -19,6 +19,8 @@
namespace Phalcon\Mvc\Micro;
+use Phalcon\Mvc\Model\BinderInterface;
+
/**
* Phalcon\Mvc\Micro\LazyLoader
*
@@ -28,6 +30,8 @@ class LazyLoader
{
protected _handler;
+ protected _modelBinder;
+
protected _definition {
get
};
@@ -49,19 +53,41 @@ class LazyLoader
*/
public function __call(string! method, arguments)
{
- var handler, definition;
+ var handler, definition, modelBinder, bindCacheKey;
let handler = this->_handler;
+ let definition = this->_definition;
+
if typeof handler != "object" {
- let definition = this->_definition;
let handler = new {definition}();
let this->_handler = handler;
}
+ let modelBinder = this->_modelBinder;
+
+ if modelBinder != null {
+ let bindCacheKey = "_PHMB_" . definition . "_" . method;
+ let arguments = modelBinder->bindToHandler(handler, arguments, bindCacheKey, method);
+ }
+
/**
* Call the handler
*/
return call_user_func_array([handler, method], arguments);
}
+
+ /**
+ * Calling __call method
+ *
+ * @param string method
+ * @param array arguments
+ * @return mixed
+ */
+ public function callMethod(string! method, arguments, modelBinder = null)
+ {
+ let this->_modelBinder = modelBinder;
+
+ return this->__call(method, arguments);
+ }
}
diff --git a/phalcon/mvc/model/binder.zep b/phalcon/mvc/model/binder.zep
new file mode 100644
index 00000000000..2bb72cde253
--- /dev/null
+++ b/phalcon/mvc/model/binder.zep
@@ -0,0 +1,196 @@
+
+/*
+ +------------------------------------------------------------------------+
+ | Phalcon Framework |
+ +------------------------------------------------------------------------+
+ | Copyright (c) 2011-2016 Phalcon Team (http://www.phalconphp.com) |
+ +------------------------------------------------------------------------+
+ | This source file is subject to the New BSD License that is bundled |
+ | with this package in the file docs/LICENSE.txt. |
+ | |
+ | If you did not receive a copy of the license and are unable to |
+ | obtain it through the world-wide-web, please send an email |
+ | to license@phalconphp.com so we can send you a copy immediately. |
+ +------------------------------------------------------------------------+
+ | Authors: Andres Gutierrez |
+ | Eduar Carvajal |
+ | Wojciech Ślawski |
+ +------------------------------------------------------------------------+
+ */
+
+namespace Phalcon\Mvc\Model;
+
+use Phalcon\Mvc\Controller\BindModelInterface;
+use Phalcon\Mvc\Model\Binder\BindableInterface;
+use Phalcon\Cache\BackendInterface;
+
+/**
+ * Phalcon\Mvc\Model\Binding
+ *
+ * This is an class for binding models into params for handler
+ */
+class Binder implements BinderInterface
+{
+ /**
+ * Array for storing active bound models
+ *
+ * @var array
+ */
+ protected boundModels = [] { get };
+
+ /**
+ * Cache object used for caching parameters for model binding
+ */
+ protected cache ;
+
+ /**
+ * Internal cache for caching parameters for model binding during request
+ */
+ protected internalCache = [];
+
+ /**
+ * Phalcon\Mvc\Model\Binder constructor
+ */
+ public function __construct( cache = null)
+ {
+ let this->cache = cache;
+ }
+
+ /**
+ * Gets cache instance
+ */
+ public function setCache( cache) ->
+ {
+ let this->cache = cache;
+
+ return this;
+ }
+
+ /**
+ * Sets cache instance
+ */
+ public function getCache() ->
+ {
+ return this->cache;
+ }
+
+ /**
+ * Bind models into params in proper handler
+ */
+ public function bindToHandler(object handler, array params, string cacheKey, var methodName = null) -> array
+ {
+ var paramKey, className, boundModel, paramsCache;
+
+ if handler instanceof \Closure || methodName != null {
+ let this->boundModels = [];
+ let paramsCache = this->getParamsFromCache(cacheKey);
+ if typeof paramsCache == "array" {
+ for paramKey, className in paramsCache {
+ let boundModel = {className}::findFirst(params[paramKey]);
+ let params[paramKey] = boundModel;
+ let this->boundModels[paramKey] = boundModel;
+ }
+
+ return params;
+ }
+
+ return this->getParamsFromReflection(handler, params, cacheKey, methodName);
+ }
+ throw new Exception("You must specify methodName for handler or pass Closure as handler");
+ }
+
+ /**
+ * Get params classes from cache by key
+ */
+ protected function getParamsFromCache(string cacheKey) -> array | null
+ {
+ var cache, internalParams;
+
+ if fetch internalParams, this->internalCache[cacheKey] {
+ return internalParams;
+ }
+
+ let cache = this->cache;
+
+ if cache != null && cache->exists(cacheKey) {
+ return cache->get(cacheKey);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get modified params for handler using reflection
+ */
+ protected function getParamsFromReflection(object handler, array params, string cacheKey, var methodName) -> array
+ {
+ var methodParams, reflection, paramKey, methodParam, paramsCache, className, realClasses = null,
+ boundModel, cache, handlerClass, reflectionClass, paramsKeys;
+ let paramsCache = [];
+ if methodName != null {
+ let reflection = new \ReflectionMethod(handler, methodName);
+ } else {
+ let reflection = new \ReflectionFunction(handler);
+ }
+
+ let cache = this->cache;
+
+ let methodParams = reflection->getParameters();
+ let paramsKeys = array_keys(params);
+ for paramKey, methodParam in methodParams {
+ let reflectionClass = methodParam->getClass();
+
+ if !reflectionClass {
+ continue;
+ }
+
+ let className = reflectionClass->getName();
+ if !isset params[paramKey] {
+ let paramKey = paramsKeys[paramKey];
+ }
+ let boundModel = null;
+ if className == "Phalcon\\Mvc\\Model" {
+ if realClasses == null {
+ if handler instanceof BindModelInterface {
+ let handlerClass = get_class(handler);
+ let realClasses = {handlerClass}::getModelName();
+ } elseif handler instanceof BindableInterface {
+ let realClasses = handler->getModelName();
+ } else {
+ throw new Exception("Handler must implement Phalcon\\Mvc\\Model\\Binder\\BindableInterface in order to use Phalcon\\Mvc\\Model as parameter");
+ }
+ }
+ if typeof realClasses == "array" {
+ if fetch className, realClasses[paramKey] {
+ let boundModel = {className}::findFirst(params[paramKey]);
+ } else {
+ throw new Exception("You should provide model class name for ".paramKey." parameter");
+ }
+ } elseif typeof realClasses == "string" {
+ let boundModel = {realClasses}::findFirst(params[paramKey]);
+ let className = realClasses;
+ } else {
+ throw new Exception("getModelName should return array or string");
+ }
+ } elseif is_subclass_of(className, "Phalcon\\Mvc\\Model") {
+ let boundModel = {className}::findFirst(params[paramKey]);
+ }
+
+ if boundModel != null {
+ let params[paramKey] = boundModel;
+ let this->boundModels[paramKey] = boundModel;
+ if cache != null {
+ let paramsCache[paramKey] = className;
+ }
+ }
+ }
+
+ if cache != null {
+ cache->save(cacheKey, paramsCache);
+ }
+
+ let this->internalCache[cacheKey] = paramsCache;
+
+ return params;
+ }
+}
diff --git a/phalcon/mvc/model/binder/bindableinterface.zep b/phalcon/mvc/model/binder/bindableinterface.zep
new file mode 100644
index 00000000000..0e47b1394d9
--- /dev/null
+++ b/phalcon/mvc/model/binder/bindableinterface.zep
@@ -0,0 +1,34 @@
+
+/*
+ +------------------------------------------------------------------------+
+ | Phalcon Framework |
+ +------------------------------------------------------------------------+
+ | Copyright (c) 2011-2016 Phalcon Team (https://phalconphp.com) |
+ +------------------------------------------------------------------------+
+ | This source file is subject to the New BSD License that is bundled |
+ | with this package in the file docs/LICENSE.txt. |
+ | |
+ | If you did not receive a copy of the license and are unable to |
+ | obtain it through the world-wide-web, please send an email |
+ | to license@phalconphp.com so we can send you a copy immediately. |
+ +------------------------------------------------------------------------+
+ | Authors: Andres Gutierrez |
+ | Eduar Carvajal |
+ | Wojciech Ślawski |
+ +------------------------------------------------------------------------+
+ */
+
+namespace Phalcon\Mvc\Model\Binder;
+
+/**
+ * Phalcon\Mvc\Controller\Binder\BindableInterface
+ *
+ * Interface for bindable classes
+ */
+interface BindableInterface
+{
+ /**
+ * Return the model name or models names and parameters keys associated with this class
+ */
+ abstract function getModelName() -> string | array;
+}
diff --git a/phalcon/mvc/model/binderinterface.zep b/phalcon/mvc/model/binderinterface.zep
new file mode 100644
index 00000000000..b3376ffc02a
--- /dev/null
+++ b/phalcon/mvc/model/binderinterface.zep
@@ -0,0 +1,51 @@
+
+/*
+ +------------------------------------------------------------------------+
+ | Phalcon Framework |
+ +------------------------------------------------------------------------+
+ | Copyright (c) 2011-2016 Phalcon Team (http://www.phalconphp.com) |
+ +------------------------------------------------------------------------+
+ | This source file is subject to the New BSD License that is bundled |
+ | with this package in the file docs/LICENSE.txt. |
+ | |
+ | If you did not receive a copy of the license and are unable to |
+ | obtain it through the world-wide-web, please send an email |
+ | to license@phalconphp.com so we can send you a copy immediately. |
+ +------------------------------------------------------------------------+
+ | Authors: Andres Gutierrez |
+ | Eduar Carvajal |
+ | Wojciech Ślawski |
+ +------------------------------------------------------------------------+
+ */
+
+namespace Phalcon\Mvc\Model;
+
+use Phalcon\Cache\BackendInterface;
+
+/**
+ * Phalcon\Mvc\Model\BinderInterface
+ *
+ * Interface for Phalcon\Mvc\Model\Binder
+ */
+interface BinderInterface
+{
+ /**
+ * Gets active bound models
+ */
+ public function getBoundModels() -> array;
+
+ /**
+ * Gets cache instance
+ */
+ public function getCache() -> ;
+
+ /**
+ * Sets cache instance
+ */
+ public function setCache( cache) -> ;
+
+ /**
+ * Bind models into params in proper handler
+ */
+ public function bindToHandler(object handler, array params, string cacheKey, string! methodName = null) -> array;
+}
diff --git a/tests/_data/controllers/Test10Controller.php b/tests/_data/controllers/Test10Controller.php
index b9e81aee322..40b837c4669 100644
--- a/tests/_data/controllers/Test10Controller.php
+++ b/tests/_data/controllers/Test10Controller.php
@@ -2,6 +2,7 @@
use Phalcon\Mvc\Controller;
use Phalcon\Test\Models\People;
+use Phalcon\Test\Models\Robots;
class Test10Controller extends Controller
{
@@ -9,4 +10,9 @@ public function viewAction(People $people)
{
return $people;
}
+
+ public function multipleAction(People $people, Robots $robots)
+ {
+ return [$people, $robots];
+ }
}
diff --git a/tests/_data/controllers/Test11Controller.php b/tests/_data/controllers/Test11Controller.php
new file mode 100644
index 00000000000..09e3f445209
--- /dev/null
+++ b/tests/_data/controllers/Test11Controller.php
@@ -0,0 +1,26 @@
+ 'Phalcon\Test\Models\People',
+ 'robots' => 'Phalcon\Test\Models\Robots'
+ ];
+ }
+
+ public function viewAction(Model $people)
+ {
+ return $people;
+ }
+
+ public function multipleAction(Model $people, Model $robots)
+ {
+ return [$people, $robots];
+ }
+}
diff --git a/tests/integration/Mvc/ControllersCest.php b/tests/integration/Mvc/ControllersCest.php
index 1a3e3689b48..57a12b7bd51 100644
--- a/tests/integration/Mvc/ControllersCest.php
+++ b/tests/integration/Mvc/ControllersCest.php
@@ -3,6 +3,7 @@
namespace Phalcon\Test\Integration\Mvc;
use Phalcon\Di;
+use Phalcon\Test\Integration\Mvc\Model\BinderCest;
use Test4Controller;
use IntegrationTester;
use Phalcon\Mvc\Dispatcher;
@@ -64,6 +65,11 @@ public function testControllers(IntegrationTester $I)
$I->assertEquals(count($view->getParamsToView()), 1);
}
+ /**
+ * @todo Remove in 4.0.0
+ * @see BinderCest::testDispatcher()
+ * @param IntegrationTester $I
+ */
public function testModelBinding(IntegrationTester $I)
{
$dispatcher = new Dispatcher;
diff --git a/tests/integration/Mvc/Model/BinderCest.php b/tests/integration/Mvc/Model/BinderCest.php
new file mode 100644
index 00000000000..61d8ba6233a
--- /dev/null
+++ b/tests/integration/Mvc/Model/BinderCest.php
@@ -0,0 +1,849 @@
+
+ * @author Serghei Iakovlev
+ * @author Wojciech Ślawski
+ * @package Phalcon\Test\Integration\Mvc\Model
+ *
+ * The contents of this file are subject to the New BSD License that is
+ * bundled with this package in the file docs/LICENSE.txt
+ *
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world-wide-web, please send an email to license@phalconphp.com
+ * so that we can send you a copy immediately.
+ */
+class BinderCest
+{
+ /**
+ * @var Apc
+ */
+ private $cache;
+
+ /**
+ * @var Binder
+ */
+ private $modelBinder;
+
+ /**
+ * @var Manager
+ */
+ private $modelsManager;
+
+ /**
+ * @var Robots
+ */
+ private $robot;
+
+ /**
+ * @var People
+ */
+ private $people;
+
+ /**
+ * Executed before each test
+ *
+ * @param IntegrationTester $I
+ */
+ public function _before(IntegrationTester $I)
+ {
+ Di::setDefault($I->getApplication()->getDI());
+
+ $this->cache = new Apc(new Data(['lifetime' => 20]));
+ $this->modelBinder = new Binder($this->cache);
+
+ $this->modelsManager = $I->getApplication()->getDI()->getShared('modelsManager');
+ $this->robot = Robots::findFirst();
+ $this->people = People::findFirst();
+
+ $I->haveServiceInDi(
+ 'modelsMetadata',
+ function () {
+ return new Memory;
+ },
+ true
+ );
+ }
+
+ /**
+ * Tests dispatcher and single model
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testDispatcherSingleBinding(IntegrationTester $I)
+ {
+ $dispatcher = $this->createDispatcher();
+ $this->assertDispatcher($dispatcher, $I);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $this->returnDispatcherValueForAction(
+ $dispatcher,
+ 'test10',
+ 'view',
+ ['people' => $this->people->cedula]
+ );
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests dispatcher and multiple model
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testDispatcherMultiBinding(IntegrationTester $I)
+ {
+
+ $dispatcher = $this->createDispatcher();
+ $this->assertDispatcher($dispatcher, $I);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $this->returnDispatcherValueForAction(
+ $dispatcher,
+ 'test10',
+ 'multiple',
+ [
+ 'people' => $this->people->cedula,
+ 'robots' => $this->robot->id,
+ ]
+ );
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests dispatcher and single model with interface
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testDispatcherSingleBindingWithInterface(IntegrationTester $I)
+ {
+ $dispatcher = $this->createDispatcher();
+ $this->assertDispatcher($dispatcher, $I);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $this->returnDispatcherValueForAction(
+ $dispatcher,
+ 'test11',
+ 'view',
+ [
+ 'people' => $this->people->cedula,
+ ]
+ );
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests dispatcher and multi model with interface
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testDispatcherMultiBindingWithInterface(IntegrationTester $I)
+ {
+ $dispatcher = $this->createDispatcher();
+ $this->assertDispatcher($dispatcher, $I);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $this->returnDispatcherValueForAction(
+ $dispatcher,
+ 'test11',
+ 'multiple',
+ [
+ 'people' => $this->people->cedula,
+ 'robots' => $this->robot->id,
+ ]
+ );
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests dispatcher and single binding exception
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testDispatcherSingleBindingException(IntegrationTester $I)
+ {
+ $dispatcher = $this->createDispatcher(false);
+ $this->assertDispatcher($dispatcher, $I);
+ $this->returnDispatcherValueForAction(
+ $dispatcher,
+ 'test9',
+ 'view',
+ ['people' => $this->people->cedula],
+ false
+ );
+ try {
+ $dispatcher->dispatch();
+
+ $I->assertTrue(
+ false,
+ 'Here must be the exception about passing non model to the controller action'
+ );
+ } catch (\Exception $e) {
+ // PHP 5.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ } catch (\TypeError $e) {
+ // PHP 7.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ }
+
+ $dispatcher->setModelBinder($this->modelBinder);
+
+ for ($i = 0; $i <= 1; $i++) {
+
+ $dispatcher->dispatch();
+
+ $returnedValue = $dispatcher->getReturnedValue();
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($returnedValue->cedula, $this->people->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test9Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with handlers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroHandlerSingleBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $micro->get(
+ '/{people}',
+ function (People $people) {
+ return $people;
+ }
+ )->setName('people');
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_people')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with handler and multi binding
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroHandlerMultiBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+ $micro->get(
+ '/{people}/robot/{robots}',
+ function (People $people, Robots $robot) {
+ return [$people, $robot];
+ }
+ );
+
+ for ($i = 0; $i <= 1; $i++) {
+
+ $returnedValue = $micro->handle('/'.$this->people->cedula.'/robot/'.$this->robot->id);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_/{people}/robot/{robots}')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with handler and single binding exception
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroHandlerSingleBindingException(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I, false);
+ $micro->get(
+ '/{people}',
+ function (People $people) {
+ return $people;
+ }
+ );
+ try {
+ $micro->handle('/'.$this->people->cedula);
+
+ $I->assertTrue(
+ false,
+ 'Here must be the exception about passing non model to the micro handler'
+ );
+ } catch (\Exception $e) {
+ // PHP 5.x
+ $I->assertEquals(
+ 'Argument 1 passed to Phalcon\Test\Integration\Mvc\Model\BinderCest::Phalcon\Test\Integration\Mvc\Model\{closure}() must be an instance of Phalcon\Test\Models\People, string given',
+ $e->getMessage()
+ );
+ } catch (\TypeError $e) {
+ // PHP 7.x
+ $I->assertEquals(
+ 'Argument 1 passed to Phalcon\Test\Integration\Mvc\Model\BinderCest::Phalcon\Test\Integration\Mvc\Model\{closure}() must be an instance of Phalcon\Test\Models\People, string given',
+ $e->getMessage()
+ );
+ }
+
+ $micro->setModelBinder($this->modelBinder);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_/{people}')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroControllerSingleBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test10 = new Collection();
+ $test10->setHandler(new \Test10Controller());
+ $test10->get('/{people}', 'viewAction');
+ $micro->mount($test10);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroControllerMultiBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test10 = new Collection();
+ $test10->setHandler(new \Test10Controller());
+ $test10->get('/{people}/robot/{robots}', 'multipleAction');
+ $micro->mount($test10);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula.'/robot/'.$this->robot->id);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with controller and single binding using interface
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroControllerSingleBindingWithInterface(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test11 = new Collection();
+ $test11->setHandler(new \Test11Controller());
+ $test11->get('/{people}', 'viewAction');
+ $micro->mount($test11);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with controller and multi binding using interface
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroControllerMultiBindingWithInterface(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test11 = new Collection();
+ $test11->setHandler(new \Test11Controller());
+ $test11->get('/{people}/robot/{robots}', 'multipleAction');
+ $micro->mount($test11);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula.'/robot/'.$this->robot->id);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with controller and single binding exception
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroControllerSingleBindingException(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I, false);
+
+ $test9 = new Collection();
+ $test9->setHandler(new \Test9Controller());
+ $test9->get('/{people}', 'viewAction');
+ $micro->mount($test9);
+
+ try {
+ $micro->handle('/'.$this->people->cedula);
+
+ $I->assertTrue(
+ false,
+ 'Here must be the exception about passing non model to the micro handler'
+ );
+ } catch (\Exception $e) {
+ // PHP 5.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ } catch (\TypeError $e) {
+ // PHP 7.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ }
+
+ $micro->setModelBinder($this->modelBinder);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test9Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with lazy controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroLazySingleBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test10 = new Collection();
+ $test10->setHandler('Test10Controller', true);
+ $test10->get('/{people}', 'viewAction');
+ $micro->mount($test10);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with lazy controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroLazyMultiBinding(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test10 = new Collection();
+ $test10->setHandler('Test10Controller', true);
+ $test10->get('/{people}/robot/{robots}', 'multipleAction');
+ $micro->mount($test10);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula.'/robot/'.$this->robot->id);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test10Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with lazy controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroLazySingleBindingWithInterface(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test11 = new Collection();
+ $test11->setHandler('Test11Controller', true);
+ $test11->get('/{people}', 'viewAction');
+ $micro->mount($test11);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with lazy controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroLazyMultiBindingWithInterface(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I);
+
+ $test11 = new Collection();
+ $test11->setHandler('Test11Controller', true);
+ $test11->get('/{people}/robot/{robots}', 'multipleAction');
+ $micro->mount($test11);
+
+ for ($i = 0; $i <= 1; $i++) {
+ $returnedValue = $micro->handle('/'.$this->people->cedula.'/robot/'.$this->robot->id);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue[0]);
+ $I->assertInstanceOf('Phalcon\Test\Models\Robots', $returnedValue[1]);
+ $I->assertEquals($this->people->cedula, $returnedValue[0]->cedula);
+ $I->assertEquals($this->robot->id, $returnedValue[1]->id);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ 'robots' => 'Phalcon\\Test\\Models\\Robots',
+ ],
+ $this->cache->get('_PHMB_Test11Controller_multipleAction')
+ );
+ }
+ }
+
+ /**
+ * Tests micro with lazy controllers and model binder
+ *
+ * @author Wojciech Ślawski
+ * @since 2016-10-29
+ *
+ * @param IntegrationTester $I
+ */
+ public function testMicroLazySingleBindingException(IntegrationTester $I)
+ {
+ $micro = $this->createMicro($I, false);
+
+ $test9 = new Collection();
+ $test9->setHandler('Test9Controller', true);
+ $test9->get('/{people}', 'viewAction');
+ $micro->mount($test9);
+
+ try {
+ $micro->handle('/'.$this->people->cedula);
+
+ $I->assertTrue(
+ false,
+ 'Here must be the exception about passing non model to the micro handler'
+ );
+ } catch (\Exception $e) {
+ // PHP 5.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ } catch (\TypeError $e) {
+ // PHP 7.x
+ $I->assertEquals(
+ 'Argument 1 passed to Test9Controller::viewAction() must be an instance of Phalcon\Mvc\Model, string given',
+ $e->getMessage()
+ );
+ }
+
+ $micro->setModelBinder($this->modelBinder);
+
+ for ($i = 0; $i <= 1; $i++) {
+
+ $returnedValue = $micro->handle('/'.$this->people->cedula);
+
+ $I->assertInstanceOf('Phalcon\Test\Models\People', $returnedValue);
+ $I->assertEquals($this->people->cedula, $returnedValue->cedula);
+ $I->assertEquals(
+ [
+ 'people' => 'Phalcon\\Test\\Models\\People',
+ ],
+ $this->cache->get('_PHMB_Test9Controller_viewAction')
+ );
+ }
+ }
+
+ /**
+ * @param bool $useModelBinder
+ * @return Dispatcher
+ */
+ private function createDispatcher($useModelBinder = true)
+ {
+ $this->cache->flush();
+ $dispatcher = new Dispatcher;
+ if ($useModelBinder) {
+ $dispatcher->setModelBinder($this->modelBinder);
+ }
+ $dispatcher->setDI(Di::getDefault());
+
+ return $dispatcher;
+ }
+
+ /**
+ * @param $dispatcher
+ * @param IntegrationTester $I
+ */
+ private function assertDispatcher($dispatcher, IntegrationTester $I)
+ {
+ $I->assertInstanceOf('Phalcon\Di', $dispatcher->getDI());
+ $I->haveServiceInDi('dispatcher', $dispatcher);
+ }
+
+ /**
+ * @param Dispatcher $dispatcher
+ * @param $controllerName
+ * @param $actionName
+ * @param $params
+ * @param bool $returnValue
+ * @return mixed
+ */
+ private function returnDispatcherValueForAction(
+ Dispatcher $dispatcher,
+ $controllerName,
+ $actionName,
+ $params,
+ $returnValue = true
+ ) {
+ $dispatcher->setReturnedValue(null);
+ $dispatcher->setControllerName($controllerName);
+ $dispatcher->setActionName($actionName);
+ $dispatcher->setParams($params);
+
+ if ($returnValue) {
+ $dispatcher->dispatch();
+
+ return $dispatcher->getReturnedValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * @param IntegrationTester $I
+ * @param bool $useModelBinder
+ * @return Micro
+ */
+ private function createMicro(IntegrationTester $I, $useModelBinder = true)
+ {
+ $this->cache->flush();
+ $micro = new Micro(Di::getDefault());
+ if ($useModelBinder) {
+ $micro->setModelBinder($this->modelBinder);
+ }
+
+ $I->assertInstanceOf('Phalcon\Di', $micro->getDI());
+
+ return $micro;
+ }
+}