1
2/**
3 * This file is part of the Phalcon Framework.
4 *
5 * (c) Phalcon Team <team@phalcon.io>
6 *
7 * For the full copyright and license information, please view the LICENSE.txt
8 * file that was distributed with this source code.
9 */
10
11namespace Phalcon\Cli;
12
13use Phalcon\Cli\Dispatcher\Exception;
14use Phalcon\Dispatcher\AbstractDispatcher as CliDispatcher;
15use Phalcon\Events\ManagerInterface;
16use Phalcon\Filter\FilterInterface;
17
18/**
19 * Dispatching is the process of taking the command-line arguments, extracting
20 * the module name, task name, action name, and optional parameters contained in
21 * it, and then instantiating a task and calling an action on it.
22 *
23 * ```php
24 * use Phalcon\Di;
25 * use Phalcon\Cli\Dispatcher;
26 *
27 * $di = new Di();
28 *
29 * $dispatcher = new Dispatcher();
30 *
31 * $dispatcher->setDi($di);
32 *
33 * $dispatcher->setTaskName("posts");
34 * $dispatcher->setActionName("index");
35 * $dispatcher->setParams([]);
36 *
37 * $handle = $dispatcher->dispatch();
38 * ```
39 */
40class Dispatcher extends CliDispatcher implements DispatcherInterface
41{
42    /**
43     * @var string
44     */
45    protected defaultHandler = "main";
46
47    /**
48     * @var string
49     */
50    protected defaultAction = "main";
51
52    /**
53     * @var string
54     */
55    protected handlerSuffix = "Task";
56
57    /**
58     * @var array
59     */
60    protected options = [];
61
62    /**
63     * Calls the action method.
64     */
65    public function callActionMethod(handler, string actionMethod, array! params = []) -> var
66    {
67        var params;
68
69        // This is to make sure that the parameters are zero-indexed and
70        // their order isn't overriden by any options when we merge the array.
71        let params = array_values(params);
72        let params = array_merge(params, this->options);
73
74        return call_user_func_array(
75            [handler, actionMethod],
76            params
77        );
78    }
79
80    /**
81     * Returns the active task in the dispatcher
82     */
83    public function getActiveTask() -> <TaskInterface>
84    {
85        return this->activeHandler;
86    }
87
88    /**
89     * Returns the latest dispatched controller
90     */
91    public function getLastTask() -> <TaskInterface>
92    {
93        return this->lastHandler;
94    }
95
96    /**
97     * Gets an option by its name or numeric index
98     *
99     * @param  mixed $option
100     * @param  string|array $filters
101     * @param  mixed $defaultValue
102     */
103    public function getOption(option, filters = null, defaultValue = null) -> var
104    {
105        var options, filter, optionValue, container;
106
107        let options = this->options;
108
109        if !fetch optionValue, options[option] {
110            return defaultValue;
111        }
112
113        if filters === null {
114            return optionValue;
115        }
116
117        let container = this->container;
118
119        if typeof container != "object" {
120            this->{"throwDispatchException"}(
121                Exception::containerServiceNotFound("the 'filter' service"),
122                Exception::EXCEPTION_NO_DI
123            );
124        }
125
126        let filter = <FilterInterface> container->getShared("filter");
127
128        return filter->sanitize(optionValue, filters);
129    }
130
131    /**
132     * Get dispatched options
133     */
134    public function getOptions() -> array
135    {
136        return this->options;
137    }
138
139    /**
140     * Gets last dispatched task name
141     */
142    public function getTaskName() -> string
143    {
144        return this->handlerName;
145    }
146
147    /**
148     * Gets the default task suffix
149     */
150    public function getTaskSuffix() -> string
151    {
152        return this->handlerSuffix;
153    }
154
155    /**
156     * Check if an option exists
157     */
158    public function hasOption(var option) -> bool
159    {
160        return isset this->options[option];
161    }
162
163    /**
164     * Sets the default task name
165     */
166    public function setDefaultTask(string taskName) -> void
167    {
168        let this->defaultHandler = taskName;
169    }
170
171    /**
172     * Set the options to be dispatched
173     */
174    public function setOptions(array options) -> void
175    {
176        let this->options = options;
177    }
178
179    /**
180     * Sets the task name to be dispatched
181     */
182    public function setTaskName(string taskName) -> void
183    {
184        let this->handlerName = taskName;
185    }
186
187    /**
188     * Sets the default task suffix
189     */
190    public function setTaskSuffix(string taskSuffix) -> void
191    {
192        let this->handlerSuffix = taskSuffix;
193    }
194
195    /**
196     * Handles a user exception
197     */
198    protected function handleException(<\Exception> exception)
199    {
200        var eventsManager;
201
202        let eventsManager = <ManagerInterface> this->eventsManager;
203
204        if typeof eventsManager == "object" {
205            if eventsManager->fire("dispatch:beforeException", this, exception) === false {
206                return false;
207            }
208        }
209    }
210
211    /**
212     * Throws an internal exception
213     */
214    protected function throwDispatchException(string message, int exceptionCode = 0)
215    {
216        var exception;
217
218        let exception = new Exception(message, exceptionCode);
219
220        if this->handleException(exception) === false {
221            return false;
222        }
223
224        throw exception;
225    }
226}
227