diff --git a/CHANGELOG b/CHANGELOG index 282406f271a..db9ecf1ae1e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -191,6 +191,7 @@ - When phalcon.register_psr3_classes php.ini option is set, Phalcon\Logger\Adapter and derived classes throw Psr\Log\InvalidArgumentException instead of Phalcon\Logger\Exception when the arguments are not valid (#1888) - Phalcon\Mvc: + - Added support for route names in Phalcon\Mvc\Micro\Collection (#1868) - Phalcon\Mvc\Application::handle() now checks whether the class exists before include()'ing its file (#812, #818) - Phalcon\Mvc\Model\Criteria::fromInput() now sets _modelName (#866, #873) - Phalcon\Mvc\Model\Query\Builder may now use both integer and string placeholders (#701) diff --git a/ext/mvc/micro.c b/ext/mvc/micro.c index 286de411d21..7061f3a2c9a 100644 --- a/ext/mvc/micro.c +++ b/ext/mvc/micro.c @@ -19,6 +19,7 @@ */ #include "mvc/micro.h" +#include "mvc/micro/collectioninterface.h" #include "mvc/micro/exception.h" #include "mvc/micro/lazyloader.h" #include "mvc/micro/middlewareinterface.h" @@ -433,8 +434,8 @@ PHP_METHOD(Phalcon_Mvc_Micro, options){ PHP_METHOD(Phalcon_Mvc_Micro, mount){ zval *collection, *main_handler, *handlers, *lazy; - zval *lazy_handler = NULL, *prefix, *handler = NULL, *methods = NULL; - zval *pattern = NULL, *sub_handler = NULL, *real_handler = NULL, *prefixed_pattern = NULL; + zval *lazy_handler = NULL, *prefix, *handler = NULL; + zval *real_handler = NULL, *prefixed_pattern = NULL; zval *route = NULL; HashTable *ah0; HashPosition hp0; @@ -443,15 +444,9 @@ PHP_METHOD(Phalcon_Mvc_Micro, mount){ PHALCON_MM_GROW(); phalcon_fetch_params(1, 1, 0, &collection); + PHALCON_VERIFY_INTERFACE_EX(collection, phalcon_mvc_micro_collectioninterface_ce, phalcon_mvc_micro_exception_ce, 1); - if (Z_TYPE_P(collection) != IS_OBJECT) { - PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_micro_exception_ce, "The collection is not valid"); - return; - } - - /** - * Get the main handler - */ + /* Get the main handler */ PHALCON_INIT_VAR(main_handler); phalcon_call_method(main_handler, collection, "gethandler"); if (PHALCON_IS_EMPTY(main_handler)) { @@ -468,9 +463,7 @@ PHP_METHOD(Phalcon_Mvc_Micro, mount){ if (Z_TYPE_P(handlers) == IS_ARRAY) { - /** - * Check if handler is lazy - */ + /* Check if handler is lazy */ PHALCON_INIT_VAR(lazy); phalcon_call_method(lazy, collection, "islazy"); if (zend_is_true(lazy)) { @@ -482,39 +475,37 @@ PHP_METHOD(Phalcon_Mvc_Micro, mount){ PHALCON_CPY_WRT(lazy_handler, main_handler); } - /** - * Get the main prefix for the collection - */ + /* Get the main prefix for the collection */ PHALCON_INIT_VAR(prefix); phalcon_call_method(prefix, collection, "getprefix"); phalcon_is_iterable(handlers, &ah0, &hp0, 0, 0); while (zend_hash_get_current_data_ex(ah0, (void**) &hd, &hp0) == SUCCESS) { - + zval *methods, *pattern, *sub_handler, *name; + PHALCON_GET_HVALUE(handler); if (Z_TYPE_P(handler) != IS_ARRAY) { PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_micro_exception_ce, "One of the registered handlers is invalid"); return; } + + if ( + !phalcon_array_isset_long_fetch(&methods, handler, 0) + || !phalcon_array_isset_long_fetch(&pattern, handler, 1) + || !phalcon_array_isset_long_fetch(&sub_handler, handler, 2) + || !phalcon_array_isset_long_fetch(&name, handler, 3) + ) { + PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_micro_exception_ce, "One of the registered handlers is invalid"); + return; + } - PHALCON_OBS_NVAR(methods); - phalcon_array_fetch_long(&methods, handler, 0, PH_NOISY); - - PHALCON_OBS_NVAR(pattern); - phalcon_array_fetch_long(&pattern, handler, 1, PH_NOISY); - - PHALCON_OBS_NVAR(sub_handler); - phalcon_array_fetch_long(&sub_handler, handler, 2, PH_NOISY); - - /** - * Create a real handler - */ + /* Create a real handler */ PHALCON_INIT_NVAR(real_handler); array_init_size(real_handler, 2); - phalcon_array_append(&real_handler, lazy_handler, PH_SEPARATE); - phalcon_array_append(&real_handler, sub_handler, PH_SEPARATE); + phalcon_array_append(&real_handler, lazy_handler, 0); + phalcon_array_append(&real_handler, sub_handler, 0); if (PHALCON_IS_NOT_EMPTY(prefix)) { if (PHALCON_IS_STRING(pattern, "/")) { PHALCON_CPY_WRT(prefixed_pattern, prefix); @@ -526,14 +517,16 @@ PHP_METHOD(Phalcon_Mvc_Micro, mount){ PHALCON_CPY_WRT(prefixed_pattern, pattern); } - /** - * Map the route manually - */ + /* Map the route manually */ PHALCON_INIT_NVAR(route); phalcon_call_method_p2(route, this_ptr, "map", prefixed_pattern, real_handler); - if (zend_is_true(methods)) { + if (Z_TYPE_P(methods) != IS_NULL) { phalcon_call_method_p1_noret(route, "via", methods); } + + if (Z_TYPE_P(name) != IS_NULL) { + phalcon_call_method_p1_noret(route, "setname", name); + } zend_hash_move_forward_ex(ah0, &hp0); } @@ -1184,7 +1177,7 @@ PHALCON_DOC_METHOD(Phalcon_Mvc_Micro, offsetSet); * Alias for Phalcon\Mvc\Micro::getService() * * - * var_dump($di['request']); + * var_dump($app['request']); * * * @param string $alias diff --git a/ext/mvc/micro/collection.c b/ext/mvc/micro/collection.c index 3d0a6a6da81..6167282074b 100644 --- a/ext/mvc/micro/collection.c +++ b/ext/mvc/micro/collection.c @@ -105,25 +105,41 @@ PHALCON_INIT_CLASS(Phalcon_Mvc_Micro_Collection){ /** * Internal function to add a handler to the group * - * @param string|array $method + * @param string|null $method * @param string $routePattern * @param mixed $handler + * @param string $name */ -void phalcon_mvc_collection_addmap(zval *this_ptr, zval *method, zval *route_pattern, zval *handler TSRMLS_DC) { - +void phalcon_mvc_collection_addmap(zval *this_ptr, const char *method, zval *route_pattern, zval *handler, zval *name TSRMLS_DC) +{ zval *handler_definition; + zval *z_method; + + MAKE_STD_ZVAL(z_method); + if (method) { + PHALCON_ZVAL_MAYBE_INTERNED_STRING(z_method, method); + } + else { + ZVAL_NULL(z_method); + } - Z_ADDREF_P(method); Z_ADDREF_P(route_pattern); Z_ADDREF_P(handler); - MAKE_STD_ZVAL(handler_definition); - array_init_size(handler_definition, 3); - add_next_index_zval(handler_definition, method); + PHALCON_ALLOC_GHOST_ZVAL(handler_definition); + array_init_size(handler_definition, 3 + (name != NULL ? 1 : 0)); + add_next_index_zval(handler_definition, z_method); add_next_index_zval(handler_definition, route_pattern); add_next_index_zval(handler_definition, handler); + if (name) { + Z_ADDREF_P(name); + add_next_index_zval(handler_definition, name); + } + else { + add_next_index_null(handler_definition); + } + phalcon_update_property_array_append(this_ptr, SL("_handlers"), handler_definition TSRMLS_CC); - zval_ptr_dtor(&handler_definition); } /** @@ -233,13 +249,11 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, getHandler){ */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, map){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 1, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), NULL, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -248,18 +262,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, map){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, get){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 1, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_GET); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_GET, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -268,18 +280,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, get){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, post){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_POST); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_POST, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -288,18 +298,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, post){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, put){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_PUT); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_PUT, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -308,18 +316,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, put){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, patch){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_PATCH); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_PATCH, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -328,18 +334,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, patch){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, head){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_HEAD); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_HEAD, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -348,18 +352,16 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, head){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, delete){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_DELETE); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_DELETE, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } @@ -368,17 +370,15 @@ PHP_METHOD(Phalcon_Mvc_Micro_Collection, delete){ * * @param string $routePattern * @param callable $handler + * @param string $name * @return Phalcon\Mvc\Micro\CollectionInterface */ PHP_METHOD(Phalcon_Mvc_Micro_Collection, options){ - zval *route_pattern, *handler, *method; + zval *route_pattern, *handler, *name = NULL; - phalcon_fetch_params(0, 2, 0, &route_pattern, &handler); + phalcon_fetch_params(0, 2, 0, &route_pattern, &handler, &name); - ALLOC_INIT_ZVAL(method); - PHALCON_ZVAL_MAYBE_INTERNED_STRING(method, phalcon_interned_OPTIONS); - phalcon_mvc_collection_addmap(getThis(), method, route_pattern, handler TSRMLS_CC); - zval_ptr_dtor(&method); + phalcon_mvc_collection_addmap(getThis(), phalcon_interned_OPTIONS, route_pattern, handler, name TSRMLS_CC); RETURN_ZVAL(getThis(), 1, 0); } diff --git a/unit-tests/MicroMvcCollectionsTest.php b/unit-tests/MicroMvcCollectionsTest.php index ddd47ff3ed0..7e449ffb3f8 100644 --- a/unit-tests/MicroMvcCollectionsTest.php +++ b/unit-tests/MicroMvcCollectionsTest.php @@ -72,18 +72,19 @@ public function testMicroCollections() $collection->setHandler($controller); - $collection->map('/', 'index'); + $collection->map('/', 'index', 'index_route'); - $collection->map('/edit/{number}', 'edit'); + $collection->map('/edit/{number}', 'edit', 'edit_route'); $app->mount($collection); $app->handle('/'); - $this->assertEquals($controller->getEntered(), 1); + $this->assertEquals(1, $controller->getEntered()); + $this->assertEquals('index_route', $app->getRouter()->getMatchedRoute()->getName()); $app->handle('/edit/100'); - $this->assertEquals($controller->getEntered(), 101); - + $this->assertEquals(101, $controller->getEntered()); + $this->assertEquals('edit_route', $app->getRouter()->getMatchedRoute()->getName()); } public function testMicroCollectionsPrefixed()