phalconplus Documentation v1.2.0
Class
Class PhalconPlus App

# App

        namespace PhalconPlus\App;
    use Phalcon\Application as BaseApplication;
    use PhalconPlus\Enum\Sys as Sys;
    use PhalconPlus\App\Module\ModuleDef;
    use Phalcon\DiInterface;
    use Phalcon\Di;
    use PhalconPlus\App\Module\AbstractModule;
    use PhalconPlus\Enum\RunEnv;
    use PhalconPlus\Enum\Facade;
    use Phalcon\Config;
    use PhalconPlus\Base\Exception as BaseException;
    use Phalcon\Events\ManagerInterface;

    final class App extends BaseApplication
    {
        // <\Phalcon\Debug>
        protected debug = null;
        // 默认运行环境
        // 其实框架定义了<\PhalconPlus\Enum\RunEnv>，但考虑再三，此处不能做枚举限制
        // Enum: ['dev', 'test', 'pre-production', 'production']
        protected env = RunEnv::DEV;
        protected booted = false;
        // 全局配置 <\Phalcon\Config>
        protected config = null { get };

        public function __construct( config)
        {
            // 全局配置
            let this->config = config;
            Sys::initApp(this);
        }

        public function boot(string env = "", string runMode = "") ->
        {
            // 获取并初始化运行环境
            if likely empty env {
                // 获取php.ini中设置的env
                var sysEnv = trim(get_cfg_var(Sys::ENV_NAME));
                // 这里不能强约束env的值为枚举中的一个
                // 你可能会有非常多的环境，只要env值和配置文件名能对应上就行
                if !empty sysEnv { let this->env = sysEnv; }
            } else {
                let this->env = env;
            }

            // 定义全局常量
            define("APP_ENV", this->env, false); // 为了兼容, 同下
            define("APP_RUN_ENV", this->env, false);
            define("APP_ROOT_DIR", Sys::getRootDir(), false);
            define("APP_MODULE_DIR", Sys::getPrimaryModuleDir(), false); // 为了兼容, 同下
            define("APP_PRI_MODULE_DIR", Sys::getPrimaryModuleDir(), false);
            define("APP_ROOT_COMMON_DIR", Sys::getCommonDir(), false);
            define("APP_ROOT_COMMON_LOAD_DIR", Sys::getGlobalLoadDir(), false);
            define("APP_ROOT_COMMON_CONF_DIR", Sys::getGlobalConfigDir(), false);

            // 加载Facacdes
            Facade::register(this, "\\Ph\\");

            return this->bootPrimaryModule(runMode);
        }

        private function bootPrimaryModule(string runMode = "") ->
        {
            // 初始化主模块
            var primaryModuleDef;
            let primaryModuleDef = new ModuleDef(this, Sys::getPrimaryModuleDir(), true, runMode);
            this->setDI(primaryModuleDef->newDI());
            this->getDI()->setShared("superApp", this);
            this->getDI()->setShared("config", this->config);
            this->getDI()->setShared("loader", new \Phalcon\Loader());
            // App启动成功
            let this->booted = true;
            // 注册主模块
            var module = this->registerModule(primaryModuleDef);
            if module->isWeb() {
                if !RunEnv::isInProd(this->env) {
                    let this->debug = new \Phalcon\Debug();
                    this->debug->listen();
                }
            }
            return this;
        }

        private function registerModule( moduleDef) ->
        {
            if unlikely isset(this->_modules[moduleDef->getName()]) {
                return this->_modules[moduleDef->getName()];
            }
            if unlikely is_null(this->_dependencyInjector) {
                throw new BaseException("DI doesn't load yet, failed to register module " . moduleDef->getName());
            }
            if unlikely is_null(this->config) {
                throw new BaseException("Config doesn't initial yet, failed to register module " . moduleDef->getName());
            }
            // Load PrimaryModule-Related Config and Global-Script
            if moduleDef->isPrimary() {
                // 定义工作模式
                if !defined("APP_RUN_MODE") { define("APP_RUN_MODE", moduleDef->getMode(), false); }
                // 获取模块配置
                var moduleConf = moduleDef->getConfig();
                // 合并配置，Module配置优先级更高
                this->config->merge(moduleConf);
            }
            // checkout a module instance from it's defintion
            var module = moduleDef->checkout();
            if module->isPrimary() {
                let this->_defaultModule = module;
            }

            // Maintain a HashMap of loaded modules
            let this->_modules[moduleDef->getName()] = module;
            return module;
        }

        public function dependModule(string! moduleName) ->
        {
            var module, moduleDef, moduleDir, moduleConf;
            let moduleDir = Sys::getModuleDirByName(moduleName);
            let moduleDef = new ModuleDef(this, moduleDir);
            // 注册模块
            let module = this->registerModule(moduleDef);
            // 参与合并的模块配置
            var tmp = Sys::load(moduleDef->getConfigPath());
            let moduleConf = new Config(tmp);
            // 全局配置文件优先级高于被依赖的模块
            moduleConf->merge(this->config);
            this->setConfig(moduleConf);
            return module;
        }

        // 传入的 Config 优先级更高
        public function setConfig( config) ->
        {
            if is_null(this->config) {
                let this->config = new Config();
            }
            this->config->merge(config);
            // this->getDI()->setShared("config", this->config);
            return this;
        }

        public function isDebug() -> boolean
        {
            return null !== this->debug;
        }

        public function isBooted() -> boolean
        {
            return this->booted === true;
        }

        public function getDebug() -> <\Phalcon\Debug>
        {
            return this->debug;
        }

        public function getEnv() -> string
        {
            return this->env;
        }

        public function setEnv(string env) ->
        {
            let this->env = env;
            return this;
        }

        public function handle()
        {
            if false == this->booted {
                this->bootPrimaryModule();
            }

            var eventsManager, response, params = func_get_args();

            let eventsManager =  this->_eventsManager;
            if typeof eventsManager == "object" {
                if eventsManager->fire("superapp:beforeExecModule", this, [this->_defaultModule, params]) === false {
                    //
                    // error_log(var_export(params, true));
                }
            }

            let response = this->_defaultModule->exec(params);

            if typeof eventsManager == "object" {
                if eventsManager->fire("superapp:afterExecModule", this, [this->_defaultModule, response]) === false {
                    //
                    // error_log(var_export(response, true));
                }
            }

            return response;
        }

        public function terminate()
        {
            if session_status() == PHP_SESSION_ACTIVE {
                session_write_close();
            }

            // empty session id
            if !headers_sent() { session_id(""); }

            // reset global variables
            let _SESSION = [], _POST = [],  _GET = [], _SERVER = [],
                _REQUEST = [], _COOKIE = [], _FILES = [];

            let this->_modules = [];
            let this->_defaultModule = null;
            let this->booted = false;
            Di::reset();

            let this->_dependencyInjector = null;
            // let this->config = null;

        }

        public function getDefaultModuleDef() ->
        {
            return this->_defaultModule->def();
        }

        public function getPrimaryModuleDef() ->
        {
            return this->_defaultModule->def();
        }

        public function setDefaultModule(string defaultModule) ->
        {
            //
            return this;
        }

        public function getDefaultModule() -> string
        {
            return this->_defaultModule->getName();
        }

        public function getPrimaryModule() ->
        {
            var name = this->_defaultModule->getName();
            if !isset(this->_modules[name]) {
                throw new BaseException("Module not exists: " . name);
            }
            return this->_modules[name];
        }

        public function getModule(string! name = "") ->
        {
            if name === "" {
                return this->_defaultModule;
            }
            if !isset(this->_modules[name]) {
                throw new BaseException("Module not exists: " . name);
            }
            return this->_modules[name];
        }

        public function getModuleDef(string! name = "") ->
        {
            if name === "" {
                return this->_defaultModule->def();
            }
            if !isset(this->_modules[name]) {
                throw new BaseException("Module not exists: " . name);
            }
            return this->_modules[name]->def();
        }

        public function config() ->
        {
            return this->config;
        }

        public function di() ->
        {
            return this->_dependencyInjector;
        }

        public function __call(string method, array params)
        {
            var dependencyInjector, service;
            if ! this->isBooted() {
                return null;
            }
            let dependencyInjector =  this->_dependencyInjector;
            if dependencyInjector->has(method) {
                let service = dependencyInjector->get(method, params);
                return service;
            }
            return null;
        }
    }