From c02b7ca2a14e4be1dcb18588002fbd0864459c15 Mon Sep 17 00:00:00 2001 From: Rack Lin Date: Thu, 6 Sep 2012 15:15:08 +0800 Subject: [PATCH] Added CLI console framework, and support single / multiple modules and namespace for command-line tasks. Signed-off-by: Rack Lin --- dev/cli/console.c | 377 +++++++++++++++++++ dev/cli/dispatcher.c | 674 ++++++++++++++++++++++++++++++++++ dev/cli/router.c | 363 ++++++++++++++++++ dev/cli/task.c | 83 +++++ dev/config.m4 | 2 +- dev/phalcon.c | 45 +++ dev/phalcon.h | 180 +++++++++ unit-tests/CliTest.php | 202 ++++++++++ unit-tests/phpunit.xml | 1 + unit-tests/tasks/MainTask.php | 18 + 10 files changed, 1944 insertions(+), 1 deletion(-) create mode 100644 dev/cli/console.c create mode 100644 dev/cli/dispatcher.c create mode 100644 dev/cli/router.c create mode 100755 dev/cli/task.c create mode 100644 unit-tests/CliTest.php create mode 100644 unit-tests/tasks/MainTask.php diff --git a/dev/cli/console.c b/dev/cli/console.c new file mode 100644 index 00000000000..b6603ff9c85 --- /dev/null +++ b/dev/cli/console.c @@ -0,0 +1,377 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2012 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 | + | Rack Lin | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +#include "kernel/exception.h" +#include "kernel/fcall.h" +#include "kernel/object.h" +#include "kernel/array.h" +#include "kernel/concat.h" + +/** + * Phalcon\CLI\Console + * + * + */ + +PHP_METHOD(Phalcon_CLI_Console, __construct){ + + PHALCON_MM_GROW(); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the DependencyInjector container + * + * @param Phalcon\DI $dependencyInjector + */ +PHP_METHOD(Phalcon_CLI_Console, setDI){ + + zval *dependency_injector = NULL; + zval *default_router = NULL, *default_dispatcher = NULL; + zval *service = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dependency_injector) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + if (Z_TYPE_P(dependency_injector) != IS_OBJECT) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_console_exception_ce, "Dependency Injector is invalid"); + return; + } + + PHALCON_INIT_VAR(default_router); + ZVAL_STRING(default_router, "Phalcon\\CLI\\Router", 1); + + PHALCON_INIT_VAR(default_dispatcher); + ZVAL_STRING(default_dispatcher, "Phalcon\\CLI\\Dispatcher", 1); + + PHALCON_INIT_VAR(service); + ZVAL_STRING(service, "router", 1); + PHALCON_CALL_METHOD_PARAMS_2_NORETURN(dependency_injector, "set", service, default_router, PH_NO_CHECK); + + PHALCON_INIT_VAR(service); + ZVAL_STRING(service, "dispatcher", 1); + PHALCON_CALL_METHOD_PARAMS_2_NORETURN(dependency_injector, "set", service, default_dispatcher, PH_NO_CHECK); + + phalcon_update_property_zval(this_ptr, SL("_dependencyInjector"), dependency_injector TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the DependencyInjector container + * + * @return Phalcon\DI + */ +PHP_METHOD(Phalcon_CLI_Console, getDI){ + + zval *dependency_injector = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(dependency_injector); + phalcon_read_property(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + + RETURN_CCTOR(dependency_injector); +} + +/** + * Sets the events manager + * + * @param Phalcon\Events\Manager $eventsManager + */ +PHP_METHOD(Phalcon_CLI_Console, setEventsManager){ + + zval *events_manager = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &events_manager) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_eventsManager"), events_manager TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the internal event manager + * + * @return Phalcon\Events\Manager + */ +PHP_METHOD(Phalcon_CLI_Console, getEventsManager){ + + zval *events_manager = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(events_manager); + phalcon_read_property(&events_manager, this_ptr, SL("_eventsManager"), PH_NOISY_CC); + + RETURN_CCTOR(events_manager); +} + +/** + * Register an array of modules present in the console + * + * + * $this->registerModules(array( + * 'frontend' => array( + * 'className' => 'Multiple\Frontend\Module', + * 'path' => '../apps/frontend/Module.php' + * ), + * 'backend' => array( + * 'className' => 'Multiple\Backend\Module', + * 'path' => '../apps/backend/Module.php' + * ) + * )); + * + * + * @param array $modules + */ +PHP_METHOD(Phalcon_CLI_Console, registerModules){ + + zval *modules = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &modules) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + if (Z_TYPE_P(modules) != IS_ARRAY) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_console_exception_ce, "Modules must be an Array"); + return; + } + phalcon_update_property_zval(this_ptr, SL("_modules"), modules TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Return the modules registered in the console + * + * @return array + */ +PHP_METHOD(Phalcon_CLI_Console, getModules){ + + zval *modules = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(modules); + phalcon_read_property(&modules, this_ptr, SL("_modules"), PH_NOISY_CC); + + RETURN_CCTOR(modules); +} + +/** + * Handle the whole command-line tasks + * + * @return mixed + */ +PHP_METHOD(Phalcon_CLI_Console, handle){ + + zval *dependency_injector = NULL, *events_manager = NULL; + zval *event_name = NULL, *status = NULL; + zval *arguments = NULL; + zval *module_name = NULL; + zval *task_name = NULL; + zval *action_name = NULL; + zval *params = NULL; + zval *modules = NULL, *module = NULL; + zval *path = NULL, *exception_msg = NULL, *exception = NULL; + zval *class_name = NULL, *module_object = NULL; + zval *task = NULL; + zval *service = NULL, *router = NULL, *dispatcher = NULL; + int eval_int = 0; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arguments) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + if (!arguments) { + PHALCON_ALLOC_ZVAL_MM(arguments); + array_init(arguments); + } + + phalcon_update_property_zval(this_ptr, SL("_arguments"), arguments TSRMLS_CC); + + PHALCON_INIT_VAR(dependency_injector); + phalcon_read_property(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + if (Z_TYPE_P(dependency_injector) != IS_OBJECT) { + PHALCON_THROW_EXCEPTION_STR(phalcon_mvc_micro_exception_ce, "A dependency injection container is required to access related dispatching services"); + return; + } + + PHALCON_INIT_VAR(events_manager); + phalcon_read_property(&events_manager, this_ptr, SL("_eventsManager"), PH_NOISY_CC); + + PHALCON_INIT_VAR(service); + ZVAL_STRING(service, "router", 1); + + PHALCON_INIT_VAR(router); + PHALCON_CALL_METHOD_PARAMS_1(router, dependency_injector, "getshared", service, PH_NO_CHECK); + PHALCON_CALL_METHOD_PARAMS_1_NORETURN(router, "handle", arguments, PH_NO_CHECK); + + PHALCON_INIT_VAR(module_name); + PHALCON_CALL_METHOD(module_name, router, "getmodulename", PH_NO_CHECK); + if (zend_is_true(module_name)) { + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "console:beforeStartModule", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + PHALCON_MM_RESTORE(); + RETURN_FALSE; + } + } + PHALCON_INIT_VAR(modules); + phalcon_read_property(&modules, this_ptr, SL("_modules"), PH_NOISY_CC); + eval_int = phalcon_array_isset(modules, module_name); + if (!eval_int) { + PHALCON_INIT_VAR(exception_msg); + PHALCON_CONCAT_SVS(exception_msg, "Module '", module_name, "' isn't registered in the console container"); + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_console_exception_ce, Z_STRVAL_P(exception_msg)); + return; + } + + PHALCON_INIT_VAR(module); + phalcon_array_fetch(&module, modules, module_name, PH_NOISY_CC); + if (Z_TYPE_P(module) != IS_ARRAY) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_console_exception_ce, "Invalid module definition path"); + return; + } + + eval_int = phalcon_array_isset_string(module, SL("path")+1); + if (eval_int) { + PHALCON_INIT_VAR(path); + phalcon_array_fetch_string(&path, module, SL("path"), PH_NOISY_CC); + if (phalcon_file_exists(path TSRMLS_CC) == SUCCESS) { + if (phalcon_require(path TSRMLS_CC) == FAILURE) { + return; + } + } else { + PHALCON_INIT_VAR(exception_msg); + PHALCON_CONCAT_SVS(exception_msg, "Module definition path '", path, "\" doesn't exists"); + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_console_exception_ce, Z_STRVAL_P(exception_msg)); + return; + } + } + + eval_int = phalcon_array_isset_string(module, SL("className")+1); + if (eval_int) { + PHALCON_INIT_VAR(class_name); + phalcon_array_fetch_string(&class_name, module, SL("className"), PH_NOISY_CC); + } else { + PHALCON_INIT_VAR(class_name); + ZVAL_STRING(class_name, "Module", 1); + } + + PHALCON_INIT_VAR(module_object); + PHALCON_CALL_METHOD_PARAMS_1(module_object, dependency_injector, "get", class_name, PH_NO_CHECK); + PHALCON_CALL_METHOD_NORETURN(module_object, "registerautoloaders", PH_NO_CHECK); + PHALCON_CALL_METHOD_PARAMS_1_NORETURN(module_object, "registerservices", dependency_injector, PH_NO_CHECK); + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + phalcon_update_property_zval(this_ptr, SL("_moduleObject"), module_object TSRMLS_CC); + + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "console:afterStartModule", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + PHALCON_MM_RESTORE(); + RETURN_FALSE; + } + } + } + + PHALCON_INIT_VAR(task_name); + PHALCON_CALL_METHOD(task_name, router, "gettaskname", PH_NO_CHECK); + + PHALCON_INIT_VAR(action_name); + PHALCON_CALL_METHOD(action_name, router, "getactionname", PH_NO_CHECK); + + PHALCON_INIT_VAR(params); + PHALCON_CALL_METHOD(params, router, "getparams", PH_NO_CHECK); + + PHALCON_INIT_VAR(service); + ZVAL_STRING(service, "dispatcher", 1); + + PHALCON_INIT_VAR(dispatcher); + PHALCON_CALL_METHOD_PARAMS_1(dispatcher, dependency_injector, "getshared", service, PH_NO_CHECK); + PHALCON_CALL_METHOD_PARAMS_1_NORETURN(dispatcher, "settaskname", task_name, PH_NO_CHECK); + PHALCON_CALL_METHOD_PARAMS_1_NORETURN(dispatcher, "setactionname", action_name, PH_NO_CHECK); + PHALCON_CALL_METHOD_PARAMS_1_NORETURN(dispatcher, "setparams", params, PH_NO_CHECK); + + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "console:beforeHandleTask", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + PHALCON_MM_RESTORE(); + RETURN_FALSE; + } + } + + PHALCON_INIT_VAR(task); + PHALCON_CALL_METHOD(task, dispatcher, "dispatch", PH_NO_CHECK); + + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "application:afterHandleTask", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + PHALCON_MM_RESTORE(); + RETURN_FALSE; + } + } + + PHALCON_MM_RESTORE(); +} diff --git a/dev/cli/dispatcher.c b/dev/cli/dispatcher.c new file mode 100644 index 00000000000..766d7e4d77f --- /dev/null +++ b/dev/cli/dispatcher.c @@ -0,0 +1,674 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2012 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 | + | Rack Lin | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +#include "kernel/object.h" +#include "kernel/array.h" +#include "kernel/exception.h" +#include "kernel/fcall.h" +#include "kernel/concat.h" + +/** + * Phalcon\CLI\Dispatcher + * + * Dispatching is the process of taking the command-line arguments, extracting the module name, + * task name, action name, and optional parameters contained in it, and then + * instantiating a task and calling an action of that task. + * + * + * + * $di = new Phalcon\DI(); + * + * $dispatcher = new Phalcon\CLI\Dispatcher(); + * + * $dispatcher->setDI($di); + * + * $dispatcher->setControllerName('posts'); + * $dispatcher->setActionName('index'); + * $dispatcher->setParams(array()); + * + * $controller = $dispatcher->dispatch(); + * + * + */ + +PHP_METHOD(Phalcon_CLI_Dispatcher, __construct){ + + zval *a0 = NULL; + + PHALCON_MM_GROW(); + + + PHALCON_ALLOC_ZVAL_MM(a0); + array_init(a0); + zend_update_property(phalcon_cli_dispatcher_ce, this_ptr, SL("_params"), a0 TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the dependency injector + * + * @param Phalcon\DI $dependencyInjector + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setDI){ + + zval *dependency_injector = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dependency_injector) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_dependencyInjector"), dependency_injector TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the internal dependency injector + * + * @return Phalcon\DI + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getDI){ + + zval *dependency_injector = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(dependency_injector); + phalcon_read_property(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + + RETURN_CCTOR(dependency_injector); +} + +/** + * Sets the events manager + * + * @param Phalcon\Events\Manager $eventsManager + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setEventsManager){ + + zval *events_manager = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &events_manager) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_eventsManager"), events_manager TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the internal event manager + * + * @return Phalcon\Events\Manager + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getEventsManager){ + + zval *events_manager = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(events_manager); + phalcon_read_property(&events_manager, this_ptr, SL("_eventsManager"), PH_NOISY_CC); + + RETURN_CCTOR(events_manager); +} + +/** + * Sets the default namespace + * + * @param string $namespace + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultNamespace){ + + zval *namespace = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &namespace) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultNamespace"), namespace TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the default task name + * + * @param string $taskName + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultTask){ + + zval *task_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &task_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultTask"), task_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the default action name + * + * @param string $actionName + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultAction){ + + zval *action_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &action_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultAction"), action_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the task name to be dispatched + * + * @param string $taskName + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setTaskName){ + + zval *task_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &task_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_taskName"), task_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Gets last dispatched task name + * + * @return string + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getTaskName){ + + zval *task_name = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(task_name); + phalcon_read_property(&task_name, this_ptr, SL("_taskName"), PH_NOISY_CC); + + RETURN_CCTOR(task_name); +} + +/** + * Sets the action name to be dispatched + * + * @param string $actionName + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setActionName){ + + zval *action_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &action_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_actionName"), action_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Gets last dispatched action name + * + * @return string + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getActionName){ + + zval *action_name = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(action_name); + phalcon_read_property(&action_name, this_ptr, SL("_actionName"), PH_NOISY_CC); + + RETURN_CCTOR(action_name); +} + +/** + * Sets action params to be dispatched + * + * @param array $params + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, setParams){ + + zval *params = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_params"), params TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Gets action params + * + * @return array + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getParams){ + + zval *params = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(params); + phalcon_read_property(¶ms, this_ptr, SL("_params"), PH_NOISY_CC); + + RETURN_CCTOR(params); +} + +/** + * Dispatches a controller action taking into account the routing parameters + * + * @return Phalcon\Mvc\Controller + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, dispatch){ + + zval *dependency_injector = NULL, *events_manager = NULL; + zval *event_name = NULL, *status = NULL, *value = NULL, *task = NULL; + zval *number_dispatches = NULL, *maximum_routes = NULL; + zval *default_namespace = NULL, *finished = NULL, *task_name = NULL; + zval *has_namespace = NULL, *camelized_class = NULL, *task_class = NULL; + zval *has_service = NULL, *exception_message = NULL, *action_name = NULL; + zval *action_method = NULL, *params = NULL, *call_object = NULL, *cyclic_routing = NULL; + zval *t0 = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(dependency_injector); + phalcon_read_property(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + if (Z_TYPE_P(dependency_injector) != IS_OBJECT) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_dispatcher_exception_ce, "A dependency injection container is required to access related dispatching services"); + return; + } + + PHALCON_INIT_VAR(events_manager); + phalcon_read_property(&events_manager, this_ptr, SL("_eventsManager"), PH_NOISY_CC); + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:beforeDispatchLoop", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + PHALCON_MM_RESTORE(); + RETURN_FALSE; + } + } + + PHALCON_INIT_VAR(value); + ZVAL_NULL(value); + + PHALCON_INIT_VAR(task); + ZVAL_NULL(task); + + PHALCON_INIT_VAR(number_dispatches); + ZVAL_LONG(number_dispatches, 0); + + PHALCON_INIT_VAR(maximum_routes); + ZVAL_LONG(maximum_routes, 256); + + PHALCON_INIT_VAR(default_namespace); + phalcon_read_property(&default_namespace, this_ptr, SL("_defaultNamespace"), PH_NOISY_CC); + phalcon_update_property_bool(this_ptr, SL("_finished"), 0 TSRMLS_CC); + ws_1d57_0: + + PHALCON_INIT_VAR(t0); + phalcon_read_property(&t0, this_ptr, SL("_finished"), PH_NOISY_CC); + PHALCON_CPY_WRT(finished, t0); + if (zend_is_true(finished)) { + goto we_1d57_0; + } + phalcon_update_property_bool(this_ptr, SL("_finished"), 1 TSRMLS_CC); + + PHALCON_INIT_VAR(task_name); + phalcon_read_property(&task_name, this_ptr, SL("_taskName"), PH_NOISY_CC); + if (!zend_is_true(task_name)) { + PHALCON_INIT_VAR(task_name); + phalcon_read_property(&task_name, this_ptr, SL("_defaultTask"), PH_NOISY_CC); + phalcon_update_property_zval(this_ptr, SL("_taskName"), task_name TSRMLS_CC); + } + + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:beforeDispatch", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + goto ws_1d57_0; + } + + PHALCON_INIT_VAR(finished); + phalcon_read_property(&finished, this_ptr, SL("_finished"), PH_NOISY_CC); + if (Z_TYPE_P(finished) == IS_BOOL && !Z_BVAL_P(finished)) { + goto ws_1d57_0; + } + } + + PHALCON_INIT_VAR(has_namespace); + phalcon_fast_strpos_str(has_namespace, task_name, SL("\\") TSRMLS_CC); + if (Z_TYPE_P(has_namespace) == IS_BOOL && !Z_BVAL_P(has_namespace)) { + PHALCON_INIT_VAR(camelized_class); + PHALCON_CALL_STATIC_PARAMS_1(camelized_class, "phalcon\\text", "camelize", task_name); + } else { + PHALCON_CPY_WRT(camelized_class, task_name); + } + + PHALCON_INIT_VAR(task_class); + PHALCON_CONCAT_VVS(task_class, default_namespace, camelized_class, "Task"); + + PHALCON_INIT_VAR(has_service); + PHALCON_CALL_METHOD_PARAMS_1(has_service, dependency_injector, "has", task_class, PH_NO_CHECK); + if (!zend_is_true(has_service)) { + PHALCON_INIT_VAR(has_service); + PHALCON_CALL_FUNC_PARAMS_1(has_service, "class_exists", task_class); + } + + if (!zend_is_true(has_service)) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_VS(exception_message, task_class, " task class cannot be loaded"); + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_dispatcher_exception_ce, Z_STRVAL_P(exception_message)); + return; + } + + PHALCON_INIT_VAR(task); + PHALCON_CALL_METHOD_PARAMS_1(task, dependency_injector, "getshared", task_class, PH_NO_CHECK); + phalcon_update_property_zval(this_ptr, SL("_activeTask"), task TSRMLS_CC); + if (phalcon_method_exists_ex(task, SL("initialize") TSRMLS_CC) == SUCCESS) { + PHALCON_CALL_METHOD_NORETURN(task, "initialize", PH_NO_CHECK); + } + + PHALCON_INIT_VAR(action_name); + phalcon_read_property(&action_name, this_ptr, SL("_actionName"), PH_NOISY_CC); + if (!zend_is_true(action_name)) { + PHALCON_INIT_VAR(action_name); + phalcon_read_property(&action_name, this_ptr, SL("_defaultAction"), PH_NOISY_CC); + phalcon_update_property_zval(this_ptr, SL("_actionName"), action_name TSRMLS_CC); + } + + PHALCON_INIT_VAR(action_method); + PHALCON_CONCAT_VS(action_method, action_name, "Action"); + if (phalcon_method_exists(task, action_method TSRMLS_CC) == SUCCESS) { + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:beforeExecuteRoute", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + goto ws_1d57_0; + } + + PHALCON_INIT_VAR(finished); + phalcon_read_property(&finished, this_ptr, SL("_finished"), PH_NOISY_CC); + if (Z_TYPE_P(finished) == IS_BOOL && !Z_BVAL_P(finished)) { + goto ws_1d57_0; + } + } + + PHALCON_INIT_VAR(params); + phalcon_read_property(¶ms, this_ptr, SL("_params"), PH_NOISY_CC); + + PHALCON_INIT_VAR(call_object); + array_init(call_object); + phalcon_array_append(&call_object, task, PH_SEPARATE TSRMLS_CC); + phalcon_array_append(&call_object, action_method, PH_SEPARATE TSRMLS_CC); + + PHALCON_INIT_VAR(value); + PHALCON_CALL_FUNC_PARAMS_2(value, "call_user_func_array", call_object, params); + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:afterExecuteRoute", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + goto ws_1d57_0; + } + + PHALCON_INIT_VAR(finished); + phalcon_read_property(&finished, this_ptr, SL("_finished"), PH_NOISY_CC); + if (Z_TYPE_P(finished) == IS_BOOL && !Z_BVAL_P(finished)) { + goto ws_1d57_0; + } + } + } else { + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:beforeNotFoundAction", 1); + + PHALCON_INIT_VAR(status); + PHALCON_CALL_METHOD_PARAMS_2(status, events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + if (Z_TYPE_P(status) == IS_BOOL && !Z_BVAL_P(status)) { + goto ws_1d57_0; + } + + PHALCON_INIT_VAR(finished); + phalcon_read_property(&finished, this_ptr, SL("_finished"), PH_NOISY_CC); + if (Z_TYPE_P(finished) == IS_BOOL && !Z_BVAL_P(finished)) { + goto ws_1d57_0; + } + } + if (phalcon_method_exists_ex(task, SL("notfoundaction") TSRMLS_CC) == SUCCESS) { + PHALCON_INIT_VAR(call_object); + array_init(call_object); + phalcon_array_append(&call_object, task, PH_SEPARATE TSRMLS_CC); + add_next_index_stringl(call_object, SL("notFoundAction"), 1); + + PHALCON_INIT_VAR(value); + PHALCON_CALL_FUNC_PARAMS_2(value, "call_user_func_array", call_object, params); + } else { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVSVS(exception_message, "Action '", action_name, "' was not found on task '", task_name, "'"); + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_dispatcher_exception_ce, Z_STRVAL_P(exception_message)); + return; + } + } + + PHALCON_SEPARATE(number_dispatches); + increment_function(number_dispatches); + + PHALCON_INIT_VAR(cyclic_routing); + is_smaller_function(cyclic_routing, maximum_routes, number_dispatches TSRMLS_CC); + if (Z_TYPE_P(cyclic_routing) == IS_BOOL && Z_BVAL_P(cyclic_routing)) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_dispatcher_exception_ce, "Dispatcher has detected a cyclic routing causing stability problems"); + return; + } + + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:afterDispatch", 1); + PHALCON_CALL_METHOD_PARAMS_2_NORETURN(events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + } + goto ws_1d57_0; + we_1d57_0: + if (Z_TYPE_P(events_manager) == IS_OBJECT) { + PHALCON_INIT_VAR(event_name); + ZVAL_STRING(event_name, "dispatch:afterDispatchLoop", 1); + PHALCON_CALL_METHOD_PARAMS_2_NORETURN(events_manager, "fire", event_name, this_ptr, PH_NO_CHECK); + } + + phalcon_update_property_zval(this_ptr, SL("_returnedValue"), value TSRMLS_CC); + phalcon_update_property_zval(this_ptr, SL("_lastTask"), task TSRMLS_CC); + + RETURN_CCTOR(task); +} + +/** + * @param array $forward + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, forward){ + + zval *forward = NULL, *task_name = NULL, *action_name = NULL; + zval *params = NULL; + int eval_int; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &forward) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + if (Z_TYPE_P(forward) != IS_ARRAY) { + PHALCON_THROW_EXCEPTION_STR(phalcon_cli_dispatcher_exception_ce, "$forward parameter must be an Array"); + return; + } + eval_int = phalcon_array_isset_string(forward, SL("task")+1); + if (eval_int) { + PHALCON_INIT_VAR(task_name); + phalcon_array_fetch_string(&task_name, forward, SL("task"), PH_NOISY_CC); + phalcon_update_property_zval(this_ptr, SL("_taskName"), task_name TSRMLS_CC); + } + + eval_int = phalcon_array_isset_string(forward, SL("action")+1); + if (eval_int) { + PHALCON_INIT_VAR(action_name); + phalcon_array_fetch_string(&action_name, forward, SL("action"), PH_NOISY_CC); + phalcon_update_property_zval(this_ptr, SL("_actionName"), action_name TSRMLS_CC); + } + + eval_int = phalcon_array_isset_string(forward, SL("params")+1); + if (eval_int) { + PHALCON_INIT_VAR(params); + phalcon_array_fetch_string(¶ms, forward, SL("params"), PH_NOISY_CC); + phalcon_update_property_zval(this_ptr, SL("_params"), params TSRMLS_CC); + } + + phalcon_update_property_bool(this_ptr, SL("_finished"), 0 TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Checks if the dispatch loop is finished or have more pendent controller to disptach + * + * @return boolean + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, isFinished){ + + zval *finished = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(finished); + phalcon_read_property(&finished, this_ptr, SL("_finished"), PH_NOISY_CC); + + RETURN_CCTOR(finished); +} + +/** + * Returns the lastest dispatched task + * + * @return Phalcon\CLI\Task + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getLastTask){ + + zval *last_task = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(last_task); + phalcon_read_property(&last_task, this_ptr, SL("_lastTask"), PH_NOISY_CC); + + RETURN_CCTOR(last_task); +} + +/** + * Returns value returned by the lastest dispatched action + * + * @return mixed + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getReturnedValue){ + + zval *returned_value = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(returned_value); + phalcon_read_property(&returned_value, this_ptr, SL("_returnedValue"), PH_NOISY_CC); + + RETURN_CCTOR(returned_value); +} + +/** + * Returns the active task in the dispatcher + * + * @return Phalcon\CLI\Task + */ +PHP_METHOD(Phalcon_CLI_Dispatcher, getActiveTask){ + + zval *task = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(task); + phalcon_read_property(&task, this_ptr, SL("_activeTask"), PH_NOISY_CC); + + RETURN_CCTOR(task); +} + diff --git a/dev/cli/router.c b/dev/cli/router.c new file mode 100644 index 00000000000..8c767cd5b37 --- /dev/null +++ b/dev/cli/router.c @@ -0,0 +1,363 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2012 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 | + | Rack Lin | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +#include "kernel/operators.h" +#include "kernel/fcall.h" +#include "kernel/array.h" +#include "kernel/object.h" +#include "kernel/exception.h" + +/** + * Phalcon\CLI\Router + * + *

Phalcon\CLI\Router is the standard framework router. Routing is the + * process of taking a command-line arguments and + * decomposing it into parameters to determine which module, task, and + * action of that task should receive the request

+ * + * + * $router = new Phalcon\CLI\Router(); + * $router->handle(array()); + * echo $router->getTaskName(); + * + * + */ + + +/** + * Phalcon\CLI\Router constructor + * + */ +PHP_METHOD(Phalcon_CLI_Router, __construct){ + + PHALCON_MM_GROW(); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the dependency injector + * + * @param Phalcon\DI $dependencyInjector + */ +PHP_METHOD(Phalcon_CLI_Router, setDI){ + + zval *dependency_injector = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dependency_injector) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_dependencyInjector"), dependency_injector TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the internal dependency injector + * + * @return Phalcon\DI + */ +PHP_METHOD(Phalcon_CLI_Router, getDI){ + + zval *dependency_injector = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(dependency_injector); + phalcon_read_property(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + + RETURN_CCTOR(dependency_injector); +} + +/** + * Sets the name of the default module + * + * @param string $moduleName + */ +PHP_METHOD(Phalcon_CLI_Router, setDefaultModule){ + + zval *module_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &module_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultModule"), module_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the default task name + * + * @param string $taskName + */ +PHP_METHOD(Phalcon_CLI_Router, setDefaultTask){ + + zval *task_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &task_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultTask"), task_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Sets the default action name + * + * @param string $actionName + */ +PHP_METHOD(Phalcon_CLI_Router, setDefaultAction){ + + zval *action_name = NULL; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &action_name) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + phalcon_update_property_zval(this_ptr, SL("_defaultAction"), action_name TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Handles routing information received from command-line arguments + * + * @param array $arguments + */ +PHP_METHOD(Phalcon_CLI_Router, handle){ + + zval *arguments = NULL, *arguments_count = NULL, *params = NULL, *arg = NULL; + zval *module_name = NULL, *default_module = NULL; + zval *task_name = NULL, *default_task = NULL, *task_name_tmp = NULL, *task_name_parts = NULL; + zval *delimiter = NULL, *status = NULL; + zval *action_name = NULL, *default_action = NULL; + int eval_int; + + PHALCON_MM_GROW(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arguments) == FAILURE) { + PHALCON_MM_RESTORE(); + RETURN_NULL(); + } + + if (!arguments) { + PHALCON_ALLOC_ZVAL_MM(arguments); + array_init(arguments); + } + + /* + * process arguments + */ + // initial and set default to null + PHALCON_INIT_VAR(module_name); + PHALCON_INIT_VAR(task_name); + PHALCON_INIT_VAR(task_name_tmp); + PHALCON_INIT_VAR(action_name); + PHALCON_INIT_VAR(params); + PHALCON_INIT_VAR(delimiter); + + ZVAL_NULL(module_name); + ZVAL_NULL(task_name); + ZVAL_NULL(action_name); + ZVAL_NULL(task_name_tmp); + array_init(params); + + phalcon_update_property_zval(this_ptr, SL("_module"), module_name TSRMLS_CC); + phalcon_update_property_zval(this_ptr, SL("_task"), task_name TSRMLS_CC); + phalcon_update_property_zval(this_ptr, SL("_action"), action_name TSRMLS_CC); + phalcon_update_property_zval(this_ptr, SL("_params"), params TSRMLS_CC); + + ZVAL_STRING(delimiter, ":", 1); + + PHALCON_INIT_VAR(arguments_count); + phalcon_fast_count(arguments_count, arguments TSRMLS_CC); + + if (Z_LVAL_P(arguments_count) > 3) { + // script, task, action, params..... + PHALCON_INIT_VAR(action_name); + phalcon_array_fetch_long(&task_name_tmp, arguments, 1, PH_NOISY_CC); + phalcon_array_fetch_long(&action_name, arguments, 2, PH_NOISY_CC); + + // process params + long i; + for (i = 3; i < Z_LVAL_P(arguments_count); i++) { + PHALCON_INIT_VAR(arg); + phalcon_array_fetch_long(&arg, arguments, i, PH_NOISY_CC); + phalcon_array_append(¶ms, arg, PH_SEPARATE TSRMLS_CC); + } + } else if (Z_LVAL_P(arguments_count) > 2) { + // script, task, action + PHALCON_INIT_VAR(task_name_tmp); + PHALCON_INIT_VAR(action_name); + phalcon_array_fetch_long(&task_name_tmp, arguments, 1, PH_NOISY_CC); + phalcon_array_fetch_long(&action_name, arguments, 2, PH_NOISY_CC); + } else if (Z_LVAL_P(arguments_count) > 1) { + // script, task + PHALCON_INIT_VAR(task_name_tmp); + phalcon_array_fetch_long(&task_name_tmp, arguments, 1, PH_NOISY_CC); + } + + // if task_name settings, parse task_name for module_name + if (Z_TYPE_P(task_name_tmp) != IS_NULL) { + PHALCON_INIT_VAR(task_name_parts); + phalcon_fast_explode(task_name_parts, delimiter, task_name_tmp TSRMLS_CC); + PHALCON_INIT_VAR(status); + phalcon_fast_count(status, task_name_parts TSRMLS_CC); + if (Z_LVAL_P(status) == 2) { + PHALCON_INIT_VAR(module_name); + PHALCON_INIT_VAR(task_name); + phalcon_array_fetch_long(&module_name, task_name_parts, 0, PH_NOISY_CC); + phalcon_array_fetch_long(&task_name, task_name_parts, 1, PH_NOISY_CC); + }else { + PHALCON_INIT_VAR(task_name); + phalcon_array_fetch_long(&task_name, task_name_parts, 0, PH_NOISY_CC); + } + } + + // update properties + if (Z_TYPE_P(module_name) != IS_NULL) { + phalcon_update_property_zval(this_ptr, SL("_module"), module_name TSRMLS_CC); + } else { + PHALCON_INIT_VAR(default_module); + phalcon_read_property(&default_module, this_ptr, SL("_defaultModule"), PH_NOISY_CC); + if (Z_TYPE_P(default_module) != IS_NULL) phalcon_update_property_zval(this_ptr, SL("_module"), default_module TSRMLS_CC); + } + PHALCON_INIT_VAR(module_name); + phalcon_read_property(&module_name, this_ptr, SL("_module"), PH_NOISY_CC); + + if (Z_TYPE_P(task_name) != IS_NULL) { + phalcon_update_property_zval(this_ptr, SL("_task"), task_name TSRMLS_CC); + } else { + PHALCON_INIT_VAR(default_task); + phalcon_read_property(&default_task, this_ptr, SL("_defaultTask"), PH_NOISY_CC); + if (Z_TYPE_P(default_task) != IS_NULL) phalcon_update_property_zval(this_ptr, SL("_task"), default_task TSRMLS_CC); + } + PHALCON_INIT_VAR(task_name); + phalcon_read_property(&task_name, this_ptr, SL("_task"), PH_NOISY_CC); + + if (Z_TYPE_P(action_name) != IS_NULL) { + phalcon_update_property_zval(this_ptr, SL("_action"), action_name TSRMLS_CC); + } else { + PHALCON_INIT_VAR(default_action); + phalcon_read_property(&default_action, this_ptr, SL("_defaultAction"), PH_NOISY_CC); + if (Z_TYPE_P(default_action) != IS_NULL) phalcon_update_property_zval(this_ptr, SL("_action"), default_action TSRMLS_CC); + } + PHALCON_INIT_VAR(action_name); + phalcon_read_property(&action_name, this_ptr, SL("_action"), PH_NOISY_CC); + + phalcon_update_property_zval(this_ptr, SL("_params"), params TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns proccesed module name + * + * @return string + */ +PHP_METHOD(Phalcon_CLI_Router, getModuleName){ + + zval *module = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(module); + phalcon_read_property(&module, this_ptr, SL("_module"), PH_NOISY_CC); + + RETURN_CCTOR(module); +} + +/** + * Returns proccesed task name + * + * @return string + */ +PHP_METHOD(Phalcon_CLI_Router, getTaskName){ + + zval *task = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(task); + phalcon_read_property(&task, this_ptr, SL("_task"), PH_NOISY_CC); + + RETURN_CCTOR(task); +} + +/** + * Returns proccesed action name + * + * @return string + */ +PHP_METHOD(Phalcon_CLI_Router, getActionName){ + + zval *action = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(action); + phalcon_read_property(&action, this_ptr, SL("_action"), PH_NOISY_CC); + + RETURN_CCTOR(action); +} + +/** + * Returns proccesed extra params + * + * @return array + */ +PHP_METHOD(Phalcon_CLI_Router, getParams){ + + zval *params = NULL; + + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(params); + phalcon_read_property(¶ms, this_ptr, SL("_params"), PH_NOISY_CC); + + RETURN_CCTOR(params); +} diff --git a/dev/cli/task.c b/dev/cli/task.c new file mode 100755 index 00000000000..b0abb0971e1 --- /dev/null +++ b/dev/cli/task.c @@ -0,0 +1,83 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2012 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 | + | Rack Lin | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +/** + * Phalcon\CLI\Task + * + * Every command-line task should extend this class that encapsulates all the task functionality + * + * The task can be used to run "tasks" such as migrations, cronjobs, unit-tests, or anything that want. + * The Task class should at least have a "runAction" method + * + * + * + * + *class HelloTask extends \Phalcon\CLI\Task + *{ + * + * //This action will be executed by default + * public function runAction() + * { + * + * } + * + * public function findAction() + * { + * + * } + * + * //This action will be executed when a non existent action is requested + * public function notFoundAction() + * { + * + * } + * + *} + * + * + */ + +/** + * Phalcon\CLI\Task constructor + * + */ +PHP_METHOD(Phalcon_CLI_Task, __construct){ + + + PHALCON_MM_GROW(); + + PHALCON_MM_RESTORE(); +} + diff --git a/dev/config.m4 b/dev/config.m4 index 8bc30f47648..7714c174d55 100755 --- a/dev/config.m4 +++ b/dev/config.m4 @@ -2,5 +2,5 @@ PHP_ARG_ENABLE(phalcon, whether to enable phalcon framework, [ --enable-phalcon if test "$PHP_PHALCON" = "yes"; then AC_DEFINE(HAVE_PHALCON, 1, [Whether you have Phalcon Framework]) - PHP_NEW_EXTENSION(phalcon, phalcon.c kernel/main.c kernel/fcall.c kernel/require.c kernel/debug.c kernel/assert.c kernel/object.c kernel/array.c kernel/operators.c kernel/concat.c kernel/exception.c kernel/memory.c session/adapter/files.c session/bag.c loader.c di.c text.c mvc/router/exception.c mvc/router/route.c mvc/router.c mvc/micro.c mvc/dispatcher/exception.c mvc/view.c mvc/view/engine.c mvc/view/exception.c mvc/view/engine/php.c mvc/url.c mvc/controller.c mvc/application/exception.c mvc/url/exception.c mvc/user.c mvc/dispatcher.c mvc/model.c mvc/micro/exception.c mvc/model/validator/uniqueness.c mvc/model/validator/exclusionin.c mvc/model/validator/regex.c mvc/model/validator/inclusionin.c mvc/model/validator/numericality.c mvc/model/validator/email.c mvc/model/query.c mvc/model/resultset/complex.c mvc/model/resultset/simple.c mvc/model/query/status.c mvc/model/query/lang.c mvc/model/exception.c mvc/model/criteria.c mvc/model/validator.c mvc/model/row.c mvc/model/transaction/exception.c mvc/model/transaction/failed.c mvc/model/transaction/manager.c mvc/model/metadata.c mvc/model/message.c mvc/model/manager.c mvc/model/metadata/memory.c mvc/model/metadata/apc.c mvc/model/metadata/session.c mvc/model/resultset.c mvc/model/transaction.c mvc/user/plugin.c mvc/user/component.c mvc/application.c test.c config/exception.c config/adapter/ini.c exception.c db.c logger.c cache/exception.c cache/frontend/output.c cache/frontend/none.c cache/frontend/data.c cache/backend.c cache/backend/memcache.c cache/backend/apc.c cache/backend/file.c acl/exception.c acl/adapter/memory.c acl/role.c acl/resource.c paginator/exception.c paginator/adapter/model.c paginator/adapter/nativearray.c tag/exception.c tag/select.c internal/test.c internal/testparent.c internal/testtemp.c internal/testdummy.c filter/exception.c flash/direct.c flash/exception.c flash/session.c translate.c db/profiler.c db/exception.c db/reference.c db/dialect.c db/adapter/pdo/mysql.c db/adapter/pdo/postgresql.c db/adapter/pdo/sqlite.c db/adapter/pdo.c db/profiler/item.c db/rawvalue.c db/column.c db/index.c db/result/pdo.c db/dialect/mysql.c db/dialect/postgresql.c db/dialect/sqlite.c tag.c http/request/exception.c http/request/file.c http/response/exception.c http/response/headers.c http/response.c http/request.c session.c version.c flash.c config.c filter.c di/exception.c di/factorydefault.c events/event.c events/exception.c events/manager.c acl.c translate/exception.c translate/adapter/nativearray.c logger/exception.c logger/adapter/file.c logger/item.c loader/exception.c mvc/model/query/parser.c mvc/model/query/scanner.c, $ext_shared) + PHP_NEW_EXTENSION(phalcon, phalcon.c kernel/main.c kernel/fcall.c kernel/require.c kernel/debug.c kernel/assert.c kernel/object.c kernel/array.c kernel/operators.c kernel/concat.c kernel/exception.c kernel/memory.c session/adapter/files.c session/bag.c loader.c di.c text.c mvc/router/exception.c mvc/router/route.c mvc/router.c mvc/micro.c mvc/dispatcher/exception.c mvc/view.c mvc/view/engine.c mvc/view/exception.c mvc/view/engine/php.c mvc/url.c mvc/controller.c mvc/application/exception.c mvc/url/exception.c mvc/user.c mvc/dispatcher.c mvc/model.c mvc/micro/exception.c mvc/model/validator/uniqueness.c mvc/model/validator/exclusionin.c mvc/model/validator/regex.c mvc/model/validator/inclusionin.c mvc/model/validator/numericality.c mvc/model/validator/email.c mvc/model/query.c mvc/model/resultset/complex.c mvc/model/resultset/simple.c mvc/model/query/status.c mvc/model/query/lang.c mvc/model/exception.c mvc/model/criteria.c mvc/model/validator.c mvc/model/row.c mvc/model/transaction/exception.c mvc/model/transaction/failed.c mvc/model/transaction/manager.c mvc/model/metadata.c mvc/model/message.c mvc/model/manager.c mvc/model/metadata/memory.c mvc/model/metadata/apc.c mvc/model/metadata/session.c mvc/model/resultset.c mvc/model/transaction.c mvc/user/plugin.c mvc/user/component.c mvc/application.c test.c config/exception.c config/adapter/ini.c exception.c db.c logger.c cache/exception.c cache/frontend/output.c cache/frontend/none.c cache/frontend/data.c cache/backend.c cache/backend/memcache.c cache/backend/apc.c cache/backend/file.c acl/exception.c acl/adapter/memory.c acl/role.c acl/resource.c paginator/exception.c paginator/adapter/model.c paginator/adapter/nativearray.c tag/exception.c tag/select.c internal/test.c internal/testparent.c internal/testtemp.c internal/testdummy.c filter/exception.c flash/direct.c flash/exception.c flash/session.c translate.c db/profiler.c db/exception.c db/reference.c db/dialect.c db/adapter/pdo/mysql.c db/adapter/pdo/postgresql.c db/adapter/pdo/sqlite.c db/adapter/pdo.c db/profiler/item.c db/rawvalue.c db/column.c db/index.c db/result/pdo.c db/dialect/mysql.c db/dialect/postgresql.c db/dialect/sqlite.c tag.c http/request/exception.c http/request/file.c http/response/exception.c http/response/headers.c http/response.c http/request.c session.c version.c flash.c config.c filter.c di/exception.c di/factorydefault.c events/event.c events/exception.c events/manager.c acl.c translate/exception.c translate/adapter/nativearray.c logger/exception.c logger/adapter/file.c logger/item.c loader/exception.c mvc/model/query/parser.c mvc/model/query/scanner.c cli/task.c cli/console.c cli/router.c cli/dispatcher.c, $ext_shared) fi diff --git a/dev/phalcon.c b/dev/phalcon.c index 3dd38b3de10..eb10f8edae0 100755 --- a/dev/phalcon.c +++ b/dev/phalcon.c @@ -155,6 +155,13 @@ zend_class_entry *phalcon_logger_exception_ce; zend_class_entry *phalcon_logger_adapter_file_ce; zend_class_entry *phalcon_logger_item_ce; zend_class_entry *phalcon_loader_exception_ce; +zend_class_entry *phalcon_cli_task_ce; +zend_class_entry *phalcon_cli_console_ce; +zend_class_entry *phalcon_cli_console_exception_ce; +zend_class_entry *phalcon_cli_router_ce; +zend_class_entry *phalcon_cli_dispatcher_ce; +zend_class_entry *phalcon_cli_dispatcher_exception_ce; + ZEND_DECLARE_MODULE_GLOBALS(phalcon) @@ -734,6 +741,44 @@ PHP_MINIT_FUNCTION(phalcon){ zend_declare_property_string(phalcon_logger_adapter_file_ce, SL("_format"), "[%date%][%type%] %message%", ZEND_ACC_PROTECTED TSRMLS_CC); PHALCON_REGISTER_CLASS_EX(Phalcon\\Loader, Exception, loader_exception, "phalcon\\exception", NULL, 0); + + PHALCON_REGISTER_CLASS_EX(Phalcon\\CLI, Task, cli_task, "phalcon\\mvc\\user", phalcon_cli_task_method_entry, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); + + PHALCON_REGISTER_CLASS(Phalcon\\CLI, Console, cli_console, phalcon_cli_console_method_entry, 0); + zend_declare_property_null(phalcon_cli_console_ce, SL("_arguments"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_console_ce, SL("_dependencyInjector"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_console_ce, SL("_eventsManager"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_console_ce, SL("_modules"), ZEND_ACC_PROTECTED TSRMLS_CC); + + PHALCON_REGISTER_CLASS_EX(Phalcon\\CLI\\Console, Exception, cli_console_exception, "phalcon\\exception", NULL, 0); + + PHALCON_REGISTER_CLASS(Phalcon\\CLI, Router, cli_router, phalcon_cli_router_method_entry, 0); + zend_declare_property_null(phalcon_cli_router_ce, SL("_dependencyInjector"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_module"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_task"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_action"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_params"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_defaultModule"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_defaultTask"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_defaultAction"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_router_ce, SL("_defaultParams"), ZEND_ACC_PROTECTED TSRMLS_CC); + + PHALCON_REGISTER_CLASS(Phalcon\\CLI, Dispatcher, cli_dispatcher, phalcon_cli_dispatcher_method_entry, 0); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_dependencyInjector"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_eventsManager"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_finished"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_activeTask"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_string(phalcon_cli_dispatcher_ce, SL("_taskName"), "", ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_string(phalcon_cli_dispatcher_ce, SL("_actionName"), "", ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_params"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_returnedValue"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_cli_dispatcher_ce, SL("_lastTask"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_string(phalcon_cli_dispatcher_ce, SL("_defaultNamespace"), "", ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_string(phalcon_cli_dispatcher_ce, SL("_defaultTask"), "main", ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_string(phalcon_cli_dispatcher_ce, SL("_defaultAction"), "main", ZEND_ACC_PROTECTED TSRMLS_CC); + + PHALCON_REGISTER_CLASS_EX(Phalcon\\CLI\\Dispatcher, Exception, cli_dispatcher_exception, "phalcon\\exception", NULL, 0); + return SUCCESS; } diff --git a/dev/phalcon.h b/dev/phalcon.h index 9a7c8404c3f..02889cc102d 100755 --- a/dev/phalcon.h +++ b/dev/phalcon.h @@ -140,6 +140,12 @@ extern zend_class_entry *phalcon_logger_exception_ce; extern zend_class_entry *phalcon_logger_adapter_file_ce; extern zend_class_entry *phalcon_logger_item_ce; extern zend_class_entry *phalcon_loader_exception_ce; +extern zend_class_entry *phalcon_cli_task_ce; +extern zend_class_entry *phalcon_cli_console_ce; +extern zend_class_entry *phalcon_cli_console_exception_ce; +extern zend_class_entry *phalcon_cli_router_ce; +extern zend_class_entry *phalcon_cli_dispatcher_ce; +extern zend_class_entry *phalcon_cli_dispatcher_exception_ce; PHP_METHOD(Phalcon_Session_Bag, __construct); @@ -1107,6 +1113,51 @@ PHP_METHOD(Phalcon_Logger_Item, getType); PHP_METHOD(Phalcon_Logger_Item, getTime); +PHP_METHOD(Phalcon_CLI_Task, __construct); + +PHP_METHOD(Phalcon_CLI_Console, __construct); +PHP_METHOD(Phalcon_CLI_Console, setDI); +PHP_METHOD(Phalcon_CLI_Console, getDI); +PHP_METHOD(Phalcon_CLI_Console, setEventsManager); +PHP_METHOD(Phalcon_CLI_Console, getEventsManager); +PHP_METHOD(Phalcon_CLI_Console, registerModules); +PHP_METHOD(Phalcon_CLI_Console, getModules); +PHP_METHOD(Phalcon_CLI_Console, handle); + +PHP_METHOD(Phalcon_CLI_Router, __construct); +PHP_METHOD(Phalcon_CLI_Router, setDI); +PHP_METHOD(Phalcon_CLI_Router, getDI); +PHP_METHOD(Phalcon_CLI_Router, setDefaultModule); +PHP_METHOD(Phalcon_CLI_Router, setDefaultTask); +PHP_METHOD(Phalcon_CLI_Router, setDefaultAction); +PHP_METHOD(Phalcon_CLI_Router, handle); +PHP_METHOD(Phalcon_CLI_Router, getModuleName); +PHP_METHOD(Phalcon_CLI_Router, getTaskName); +PHP_METHOD(Phalcon_CLI_Router, getActionName); +PHP_METHOD(Phalcon_CLI_Router, getParams); + +PHP_METHOD(Phalcon_CLI_Dispatcher, __construct); +PHP_METHOD(Phalcon_CLI_Dispatcher, setDI); +PHP_METHOD(Phalcon_CLI_Dispatcher, getDI); +PHP_METHOD(Phalcon_CLI_Dispatcher, setEventsManager); +PHP_METHOD(Phalcon_CLI_Dispatcher, getEventsManager); +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultNamespace); +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultTask); +PHP_METHOD(Phalcon_CLI_Dispatcher, setDefaultAction); +PHP_METHOD(Phalcon_CLI_Dispatcher, setTaskName); +PHP_METHOD(Phalcon_CLI_Dispatcher, getTaskName); +PHP_METHOD(Phalcon_CLI_Dispatcher, setActionName); +PHP_METHOD(Phalcon_CLI_Dispatcher, getActionName); +PHP_METHOD(Phalcon_CLI_Dispatcher, setParams); +PHP_METHOD(Phalcon_CLI_Dispatcher, getParams); +PHP_METHOD(Phalcon_CLI_Dispatcher, dispatch); +PHP_METHOD(Phalcon_CLI_Dispatcher, forward); +PHP_METHOD(Phalcon_CLI_Dispatcher, isFinished); +PHP_METHOD(Phalcon_CLI_Dispatcher, getLastTask); +PHP_METHOD(Phalcon_CLI_Dispatcher, getReturnedValue); +PHP_METHOD(Phalcon_CLI_Dispatcher, getActiveTask); + + ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_bag_setdi, 0, 0, 1) ZEND_ARG_INFO(0, dependencyInjector) ZEND_END_ARG_INFO() @@ -3116,6 +3167,79 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_logger_item___construct, 0, 0, 2) ZEND_ARG_INFO(0, time) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_console_setdi, 0, 0, 1) + ZEND_ARG_INFO(0, dependencyInjector) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_console_seteventsmanager, 0, 0, 1) + ZEND_ARG_INFO(0, eventsManager) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_console_registermodules, 0, 0, 1) + ZEND_ARG_INFO(0, modules) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_console_handle, 0, 0, 1) + ZEND_ARG_INFO(0, arguments) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_router_setdi, 0, 0, 1) + ZEND_ARG_INFO(0, dependencyInjector) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_router_setdefaultmodule, 0, 0, 1) + ZEND_ARG_INFO(0, moduleName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_router_setdefaulttask, 0, 0, 1) + ZEND_ARG_INFO(0, taskName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_router_setdefaultaction, 0, 0, 1) + ZEND_ARG_INFO(0, actionName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_router_handle, 0, 0, 0) + ZEND_ARG_INFO(0, arguments) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setdi, 0, 0, 1) + ZEND_ARG_INFO(0, dependencyInjector) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_seteventsmanager, 0, 0, 1) + ZEND_ARG_INFO(0, eventsManager) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setdefaultnamespace, 0, 0, 1) + ZEND_ARG_INFO(0, namespace) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setdefaulttask, 0, 0, 1) + ZEND_ARG_INFO(0, taskName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setdefaultaction, 0, 0, 1) + ZEND_ARG_INFO(0, actionName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_settaskname, 0, 0, 1) + ZEND_ARG_INFO(0, taskName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setactionname, 0, 0, 1) + ZEND_ARG_INFO(0, actionName) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_setparams, 0, 0, 1) + ZEND_ARG_INFO(0, params) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_cli_dispatcher_forward, 0, 0, 1) + ZEND_ARG_INFO(0, forward) +ZEND_END_ARG_INFO() + + PHALCON_INIT_FUNCS(phalcon_session_bag_method_entry){ PHP_ME(Phalcon_Session_Bag, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Phalcon_Session_Bag, setDI, arginfo_phalcon_session_bag_setdi, ZEND_ACC_PUBLIC) @@ -4339,3 +4463,59 @@ PHALCON_INIT_FUNCS(phalcon_logger_item_method_entry){ PHP_FE_END }; +PHALCON_INIT_FUNCS(phalcon_cli_task_method_entry){ + PHP_ME(Phalcon_CLI_Task, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL|ZEND_ACC_CTOR) + PHP_FE_END +}; + +PHALCON_INIT_FUNCS(phalcon_cli_console_method_entry){ + PHP_ME(Phalcon_CLI_Console, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL|ZEND_ACC_CTOR) + PHP_ME(Phalcon_CLI_Console, setDI, arginfo_phalcon_cli_console_setdi, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, getDI, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, setEventsManager, arginfo_phalcon_cli_console_seteventsmanager, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, getEventsManager, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, registerModules, arginfo_phalcon_cli_console_registermodules, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, getModules, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Console, handle, arginfo_phalcon_cli_console_handle, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +PHALCON_INIT_FUNCS(phalcon_cli_router_method_entry){ + PHP_ME(Phalcon_CLI_Router, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(Phalcon_CLI_Router, setDI, arginfo_phalcon_cli_router_setdi, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, getDI, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, setDefaultModule, arginfo_phalcon_cli_router_setdefaultmodule, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, setDefaultTask, arginfo_phalcon_cli_router_setdefaulttask, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, setDefaultAction, arginfo_phalcon_cli_router_setdefaultaction, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, handle, arginfo_phalcon_cli_router_handle, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, getModuleName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, getTaskName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, getActionName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Router, getParams, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +PHALCON_INIT_FUNCS(phalcon_cli_dispatcher_method_entry){ + PHP_ME(Phalcon_CLI_Dispatcher, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(Phalcon_CLI_Dispatcher, setDI, arginfo_phalcon_cli_dispatcher_setdi, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getDI, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setEventsManager, arginfo_phalcon_cli_dispatcher_seteventsmanager, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getEventsManager, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setDefaultNamespace, arginfo_phalcon_cli_dispatcher_setdefaultnamespace, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setDefaultTask, arginfo_phalcon_cli_dispatcher_setdefaulttask, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setDefaultAction, arginfo_phalcon_cli_dispatcher_setdefaultaction, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setTaskName, arginfo_phalcon_cli_dispatcher_settaskname, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getTaskName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setActionName, arginfo_phalcon_cli_dispatcher_setactionname, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getActionName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, setParams, arginfo_phalcon_cli_dispatcher_setparams, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getParams, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, dispatch, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, forward, arginfo_phalcon_cli_dispatcher_forward, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, isFinished, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getLastTask, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getReturnedValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_CLI_Dispatcher, getActiveTask, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + diff --git a/unit-tests/CliTest.php b/unit-tests/CliTest.php new file mode 100644 index 00000000000..fd020211c13 --- /dev/null +++ b/unit-tests/CliTest.php @@ -0,0 +1,202 @@ + | + | Eduar Carvajal | + | Rack Lin | + +------------------------------------------------------------------------+ +*/ + +class CliTest extends PHPUnit_Framework_TestCase +{ + + public function setup() { + + require_once 'unit-tests/tasks/MainTask.php'; + + } + + + public function testTasks() + { + + $di = new Phalcon\DI(); + + $di->set('data', function(){ + return "data"; + }); + + $task = new MainTask(); + $task->setDI($di); + + $this->assertEquals($task->requestDiAction(), 'data'); + $this->assertEquals($task->helloAction(), 'Hello !'); + $this->assertEquals($task->helloAction('World'), 'Hello World!'); + } + + + public function testRouters() + { + + $di = new Phalcon\DI(); + + $di->set('data', function(){ + return "data"; + }); + + $router = new \Phalcon\CLI\Router(); + + $router->handle(array()); + $this->assertEquals($router->getModuleName(), null); + $this->assertEquals($router->getTaskName(), null); + $this->assertEquals($router->getActionName(), null); + $this->assertEquals($router->getParams(), array()); + + + $router->handle(array('shell_script_name', 'main')); + $this->assertEquals($router->getModuleName(), null); + $this->assertEquals($router->getTaskName(), 'main'); + $this->assertEquals($router->getActionName(), null); + $this->assertEquals($router->getParams(), array()); + + + $router->handle(array('shell_script_name', 'main', 'hello')); + $this->assertEquals($router->getModuleName(), null); + $this->assertEquals($router->getTaskName(), 'main'); + $this->assertEquals($router->getActionName(), 'hello'); + $this->assertEquals($router->getParams(), array()); + + $router->handle(array('shell_script_name', 'main', 'hello', 'arg1', 'arg2')); + $this->assertEquals($router->getModuleName(), null); + $this->assertEquals($router->getTaskName(), 'main'); + $this->assertEquals($router->getActionName(), 'hello'); + $this->assertEquals($router->getParams(), array('arg1', 'arg2')); + + $router->handle(array('shell_script_name', 'devtools:main', 'hello', 'arg1', 'arg2')); + $this->assertEquals($router->getModuleName(), 'devtools'); + $this->assertEquals($router->getTaskName(), 'main'); + $this->assertEquals($router->getActionName(), 'hello'); + $this->assertEquals($router->getParams(), array('arg1', 'arg2')); + + } + + public function testDispatchers() + { + + $di = new Phalcon\DI(); + + $di->set('data', function(){ + return "data"; + }); + + $dispatcher = new \Phalcon\CLI\Dispatcher(); + $dispatcher->setDI($di); + $dispatcher->dispatch(); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'main'); + $this->assertEquals($dispatcher->getParams(), array()); + $this->assertEquals($dispatcher->getReturnedValue(), 'mainAction'); + + $dispatcher->setActionName('hello'); + $dispatcher->dispatch(); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array()); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello !'); + + $dispatcher->setActionName('hello'); + $dispatcher->setParams(array('World', '######')); + $dispatcher->dispatch(); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array('World', '######')); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello World######'); + + // testing namespace + try { + $dispatcher->setDefaultNamespace('Dummy\\'); + $dispatcher->setTaskName('main'); + $dispatcher->setActionName('hello'); + $dispatcher->setParams(array('World')); + $dispatcher->dispatch(); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array('World')); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello World!'); + }catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Dummy\MainTask task class cannot be loaded'); + } + + } + + public function testConsoles() + { + + $di = new Phalcon\DI(); + + $di->set('data', function(){ + return "data"; + }); + + $console = new \Phalcon\CLI\Console(); + $console->setDI($di); + $dispatcher = $console->getDI()->getShared('dispatcher'); + + $console->handle(array('shell_script_name')); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'main'); + $this->assertEquals($dispatcher->getParams(), array()); + $this->assertEquals($dispatcher->getReturnedValue(), 'mainAction'); + + $console->handle(array('shell_script_name', 'main', 'hello')); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array()); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello !'); + + $console->handle(array('shell_script_name', 'main', 'hello', 'World', '######')); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array('World', '######')); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello World######'); + + // testing module + try { + $console->handle(array('shell_script_name', 'devtools:main', 'hello', 'World', '######')); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array('World', '######')); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello World######'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), "Module 'devtools' isn't registered in the console container"); + } + + + // testing namespace + try { + + $dispatcher->setDefaultNamespace('Dummy\\'); + $console->handle(array('shell_script_name', 'main', 'hello', 'World', '!')); + $this->assertEquals($dispatcher->getTaskName(), 'main'); + $this->assertEquals($dispatcher->getActionName(), 'hello'); + $this->assertEquals($dispatcher->getParams(), array('World')); + $this->assertEquals($dispatcher->getReturnedValue(), 'Hello World!'); + }catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Dummy\MainTask task class cannot be loaded'); + } + + } + +} \ No newline at end of file diff --git a/unit-tests/phpunit.xml b/unit-tests/phpunit.xml index c33c17f7ccc..1c798f00988 100644 --- a/unit-tests/phpunit.xml +++ b/unit-tests/phpunit.xml @@ -56,6 +56,7 @@ unit-tests/LoaderTest.php unit-tests/ModelsResultsetCacheTest.php unit-tests/VersionTest.php + unit-tests/CliTest.php diff --git a/unit-tests/tasks/MainTask.php b/unit-tests/tasks/MainTask.php new file mode 100644 index 00000000000..0ad59fc24d0 --- /dev/null +++ b/unit-tests/tasks/MainTask.php @@ -0,0 +1,18 @@ +di->get('data') ; + } + + public function helloAction($world = "", $symbol = "!") { + return "Hello " . $world . $symbol; + } +}