private function _loadController($oControllerName, string $sActionName, array $aParams = array())
    {
        $aPhpDoc = PhpDoc::getPhpDocOfMethod($oControllerName, $sActionName);

        if (isset($aPhpDoc['Cache'])) {

            if (!isset($aPhpDoc['Cache']['maxage'])) { $aPhpDoc['Cache']['maxage'] = 0; }

            $oMobileDetect = new \Mobile_Detect;

            if ($oMobileDetect->isMobile()) { $sCacheExt = '.mobi'; }
            else { $sCacheExt = ''; }

            $mCacheReturn = Cache::get($sActionName.$sCacheExt, $aPhpDoc['Cache']['maxage']);

            if ($mCacheReturn !== false) { return $mCacheReturn; }
        }

        if (isset($aPhpDoc['Secure'])) {

            if (isset($aPhpDoc['Secure']['roles']) && $this->_oSecurity->getUserRole() != $aPhpDoc['Secure']['roles']) {

                $this->_getPage403();
            }
        }

        $oController = new $oControllerName;

        ob_start();

        if (!defined('PORTAL')) { define('PORTAL', 'Batch'); }

        if (method_exists($oController, 'beforeExecuteRoute')) {

            call_user_func_array(array($oController, 'beforeExecuteRoute'), array());
        }

        $mReturnController = call_user_func_array(array($oController, $sActionName), $aParams);

        if (method_exists($oController, 'afterExecuteRoute')) {

            call_user_func_array(array($oController, 'afterExecuteRoute'), array());
        }

        $mReturn = ob_get_clean();

        if ($mReturn == '') { $mReturn = $mReturnController; }

        if (isset($aPhpDoc['Cache'])) {

            $oMobileDetect = new \Mobile_Detect;

            if ($oMobileDetect->isMobile()) { $sCacheExt = '.mobi'; }
            else { $sCacheExt = ''; }

            if (defined('COMPRESS_HTML') && COMPRESS_HTML) {

                $mReturn = str_replace(array("\t", "\r", "  "), array("", "", "", " "), $mReturn);
            }

            Cache::set($sActionName.$sCacheExt, $mReturn, $aPhpDoc['Cache']['maxage']);
        }

        return $mReturn;
    }