namespace Ice\Mvc; use Ice\Di; use Ice\Di\Access; use Ice\Http\Response\ResponseInterface; /** * This component allows to create MVC applications. * * @package Ice/Mvc * @category Application * @author Ice Team * @copyright (c) 2014-2023 Ice Team * @license http://iceframework.org/license */ class App extends Access { protected autoRender = true { get, set }; protected modules { get, set }; /** * App constructor * * @param Di $di */ public function __construct(di = null) { // Set the dependency injector let this->di = di; // Register the app itself as a service this->di->set("app", this); } /** * Handles a MVC request. * * @param string method * @param string uri * @return ResponseInterface|boolean */ public function handle(method = null, uri = null) -> | boolean { var argv, router, request, response, dispatcher, returned, controller, view; let request = this->di->get("request"); if method == null { let method = request->getMethod(); } if uri == null { let uri = request->get("_url"); } // Set the default method & uri for the CLI if !method && PHP_SAPI === "cli" { let method = "GET", argv = _SERVER["argv"]; if !uri && isset argv[1] { let uri = argv[1]; } } let router = this->di->get("router"), response = router->handle(method, uri), dispatcher = this->di->get("dispatcher"); this->di->applyHook("app.after.router.handle", [response]); if !(typeof response == "object" && (response instanceof ResponseInterface)) { dispatcher->setModules(this->modules); dispatcher->setMethod(method); dispatcher->setModule(response["module"]); dispatcher->setHandler(response["handler"]); dispatcher->setAction(response["action"]); dispatcher->setParams(response["params"]); let response = dispatcher->dispatch(), returned = dispatcher->getReturnedValue(); if typeof returned == "object" && (returned instanceof ResponseInterface) { let response = returned; } this->di->applyHook("app.after.dispatcher.dispatch", [response]); if !(typeof response == "object" && (response instanceof ResponseInterface)) { let controller = response, response = this->di->get("response"), view = controller->view; // Load views and set the response body if auto render // and there is no content in the response if this->autoRender && response->getBody() === null { if view->getContent() === null { if !view->getFile() { view->setSilent(true); view->setFile(dispatcher->getHandler() . "/" . dispatcher->getAction()); } if !view->count() { view->merge(dispatcher->getParams()); } view->setContent(view->render()); } // if there is main layout view, other case e.g. load partial view through ajax if view->getMainView() { response->setBody(view->layout(view->getMainView())); } else { response->setBody(view->getContent()); } } } } this->di->applyHook("app.after.handle", [response]); return response->send(); } /** * Add module with its dir path, initial class name and namespace * * @param string name * @param array options The keys can be [path|class|namespace] * @return object App */ public function addModule(string name, array options) { // add or replace module let this->modules[name] = options; return this; } }