<?php
 define('MODEL_PATH', ROOT_PATH . 'models' . DIRECTORY_SEPARATOR);
 define('TCMS_VIEW_ENGINE', '.tcms');
 class Config {
 public static $appConfig = null;
 public static $extensionConfig = null;
 public static $moduleConfig = null;
 public static $dbConfig = null;
 public static $envConfig = null;
 public static function loadConfig() {
 self::$appConfig = require_once(CONFIG_PATH . 'app.php');
 if (defined('APP_PATH_M')) {
 if (file_exists(APP_PATH_M . 'env.php')) self::$envConfig = require(APP_PATH_M . 'env.php');
 }
 }
 public static function getAppConfig($key = null) {
 if (isset($key)) {
 if (array_key_exists($key, self::$appConfig)) {
 return self::$appConfig[$key];
 }
 return false;
 }
 return self::$appConfig;
 }
 }
 class ENUM_METHOD {
 const GET = 0;
 const POST = 1;
 const API = 2;
 }
 class FIELD_DATA_TYPE {
 const STRING = 0;
 const TEXT = 1;
 const BOOLEAN = 2;
 const INTEGER = 3;
 const DOUBLE = 4;
 const IMAGE = 5;
 const FILE = 6;
 const DATETIME = 7;
 const PRICE = 8;
 const EMAIL = 10;
 const SELECT = 11;
 const DATE = 12;
 const TIME = 13;
 const PHONE = 14;
 const BIGINT = 15;
 const PASSWORD = 16;
 const CHECKBOX_LIST = 17;
 const RADIO_LIST = 18;
 const FILE_LIST = 19;
 const IMAGE_LIST = 20;
 const JSON = 21;
 }
 class Request {
 public static $method = 1000;
 private static $isAjaxRequest = false;
 public static function isAjax() {
 return self::$isAjaxRequest;
 }
 public static function isAPI() {
 return self::$isAjaxRequest;
 }
 public static function isPost() {
 return self::$method == ENUM_METHOD::POST;
 }
 public static function isGet() {
 return self::$method == ENUM_METHOD::GET;
 }
 public static function parseRequestInfo() {
 if (\GlobalVars::$_areaKey == 'api') {
 self::$isAjaxRequest = true;
 }
 switch ($_SERVER['REQUEST_METHOD']) {
 case 'GET': self::$method = ENUM_METHOD::GET;
 break;
 case 'POST': self::$method = ENUM_METHOD::POST;
 break;
 default: self::$method = ENUM_METHOD::API;
 self::$isAjaxRequest = true;
 break;
 }
 if (!self::$isAjaxRequest && isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 self::$isAjaxRequest = true;
 }
 if (self::$method == 1000 && self::$isAjaxRequest === false) {
 throw new \TCMS\TException("Method Not Allowed", 405);
 }
 }
 public static function get($key, $defaultValue = false) {
 if (isset($_POST[$key])) {
 return $_POST[$key];
 }
 if (isset($_GET[$key])) {
 return $_GET[$key];
 }
 if (\Request::isAjax() && \Request::isPost()) {
 $dd = json_decode(file_get_contents('php://input'), true);
 if (isset($dd[$key])) {
 return $dd[$key];
 }
 }
 return $defaultValue;
 }
 public static function has($key) {
 if (isset($_POST[$key])) {
 return true;
 }
 if (isset($_GET[$key])) {
 return true;
 }
 if (\Request::isAjax() && \Request::isPost()) {
 $dd = json_decode(file_get_contents('php://input'), true);
 if ($dd && isset($dd[$key])) {
 return true;
 }
 }
 return false;
 }
 public static function all() {
 if (self::isPost()) {
 if (count($_POST)) {
 return $_POST;
 }
 if (self::isAjax()) {
 return json_decode(file_get_contents('php://input'), true);
 }
 }
 return $_GET;
 }
 }
 class LayoutData {
 public static $layoutMenuItem = [];
 public static function addMenuItem(string $id, string $url, string $text, string $layoutMenuId, callable $setMenuFunction = null) {
 $_layoutMenuItem = new LayoutMenuItem();
 $_layoutMenuItem->id = $id;
 $_layoutMenuItem->url = $url;
 $_layoutMenuItem->text = $text;
 $_layoutMenuItem->layoutMenuId = $layoutMenuId;
 if ($setMenuFunction != null && is_callable($setMenuFunction)) {
 call_user_func($setMenuFunction, $_layoutMenuItem);
 }
 self::$layoutMenuItem[$url] = $_layoutMenuItem;
 }
 public static function addSubMenuItem(string $id, string $url, string $text, string $parentMenuId, string $layoutMenuId, callable $setMenuFunction = null) {
 $_layoutMenuItem = new LayoutMenuItem();
 $_layoutMenuItem->id = $id;
 $_layoutMenuItem->url = $url;
 $_layoutMenuItem->text = $text;
 $_layoutMenuItem->layoutMenuId = $layoutMenuId;
 $_layoutMenuItem->parentMenuId = $parentMenuId;
 if ($setMenuFunction != null && is_callable($setMenuFunction)) {
 call_user_func($setMenuFunction, $_layoutMenuItem);
 }
 self::$layoutMenuItem[$url] = $_layoutMenuItem;
 }
 }
 class LayoutMenuItem {
 public $id = null;
 public $url = null;
 public $text = null;
 public $layoutMenuId = null;
 public $icon = null;
 public $class = null;
 public $displayAfter = null;
 public $parentMenuId = null;
 public $subMenu = null;
 public $subMenuTitle = null;
 public $middleware = null;
 }
 class GlobalVars {
 public static $requestInfo = [ 'module' => '', 'controller' => '', 'action' => '', 'url' => '', 'params' => [], 'area_url' => '', 'base_url' => '', 'cur_lang' => 'vi', 'route_name' => null, 'route_url' => null, 'module_key' => null, 'host' => null, 'subdomain' => null, 'is_local' => null ];
 public static $isNeedCloseDbConnection = false;
 public static $extensionLoaded = [];
 public static $styleScriptAdded = [];
 public static $__langFileLoaded = null;
 public static $isHasCallRenderViewFromCtr = false;
 public static $__hookExtensions = null;
 public static $isRelease = false;
 public static $csrfToken = false;
 public static $curModulePath = false;
 public static $eventLists = null;
 public static $_mviewDataArg = null;
 public static $_mviewDataArg2 = null;
 public static $useViewHelper = false;
 public static $mViewClass = null;
 public static $returnJson = false;
 public static $mRouteClass = null;
 public static $models = [];
 public static $_areaKey = null;
 public static $isPublish = false;
 public static $routeList = [];
 public static $mobileDevice = false;
 public static $minifyView = false;
 public static $overrideModels = [];
 }
 class Route {
 public static function get($url, $controller, $action = 'index') {
 return \GlobalVars::$mRouteClass->_get($url, $controller, $action);
 }
 public static function post($url, $controller, $action = 'postIndex') {
 return \GlobalVars::$mRouteClass->_post($url, $controller, $action);
 }
 public static function any($url, $controller, $action = 'postIndex') {
 \GlobalVars::$mRouteClass->_get($url, $controller, $action);
 return \GlobalVars::$mRouteClass->_post($url, $controller, $action);
 }
 }
 class Model {
 public static function add($modelKey, $namespace = null, $path = null) {
 if (isset(GlobalVars::$models[$modelKey])) return;
 if (!$path) {
 $path = model_path() . $modelKey . '.php';
 }
 else {
 if (is_string($path)) {
 if (\GlobalVars::$isPublish) {
 $path = $path;
 }
 else {
 if (substr($path, strlen($path) - 1) !== DIRECTORY_SEPARATOR) $path .= DIRECTORY_SEPARATOR . $modelKey . '.php';
 else $path .= $modelKey . '.php';
 }
 }
 else {
 $path = model_path(true) . $modelKey . '.php';
 }
 }
 if (defined('PUBLISH_PATH_2')) {
 if (file_exists($path)) {
 include_once($path);
 if (defined("REMOVE_MODEL_CMD")) {
 $u = debug_backtrace()[0]['file'];
 if ($u) {
 $u = str_replace(ROOT_PATH, "", $u);
 }
 else {
 $u = "";
 }
 GlobalVars::$models[$modelKey] = [!$namespace ? 'Model\\' . $modelKey : $namespace, $path, $u];
 }
 else {
 GlobalVars::$models[$modelKey] = [!$namespace ? 'Model\\' . $modelKey : $namespace, $path];
 $dds = debug_backtrace();
 if (isset($dds[1])) {
 if ($dds[1]['function'] == 'boot') {
 GlobalVars::$models[$modelKey]['b'] = true;
 }
 }
 }
 }
 }
 else {
 GlobalVars::$models[$modelKey] = [!$namespace ? 'Model\\' . $modelKey : $namespace, $path];
 }
 }
 public static function overrideModel($modelFile, $overrideModelPath) {
 if (defined('PUBLISHING')) {
 if (debug_backtrace()[1]['function'] != 'boot') return;
 }
 GlobalVars::$overrideModels[$modelFile] = $overrideModelPath;
 }
 public static function load($modelKey) {
 if (isset(GlobalVars::$models[$modelKey])) {
 $n = GlobalVars::$models[$modelKey];
 if (!isset($n['l'])) {
 $icFileName = $n[1];
 if (isset(GlobalVars::$overrideModels[$icFileName])) {
 include_once(GlobalVars::$overrideModels[$icFileName]);
 }
 else {
 include_once($icFileName);
 }
 include_once($icFileName);
 GlobalVars::$models[$modelKey]['l'] = true;
 }
 return new $n[0]();
 }
 throw new \TCMS\TException("Không tìm thấy model $modelKey, vui lòng add model vào module để dùng");
 }
 public static function include($modelKey) {
 if (isset(GlobalVars::$models[$modelKey])) {
 $n = GlobalVars::$models[$modelKey];
 if (!isset($n['l'])) {
 $icFileName = $n[1];
 if (isset(GlobalVars::$overrideModels[$icFileName])) {
 include_once(GlobalVars::$overrideModels[$icFileName]);
 }
 else {
 include_once($icFileName);
 }
 include_once($icFileName);
 GlobalVars::$models[$modelKey]['l'] = true;
 }
 return true;
 }
 return false;
 }
 public static function has($modelKey) {
 return self::include($modelKey);
 }
 }
 class Event {
 public static function raise(string $eventName, $eventData) {
 if (\GlobalVars::$isPublish && !\AppPublish::$isReadEvent) {
 \AppPublish::$isReadEvent = true;
 if (!\GlobalVars::$eventLists) \GlobalVars::$eventLists = include_once(BIN_PATH . 'event-data.php');
 else {
 $evts = include_once(BIN_PATH . 'event-data.php');
 foreach ($evts as $k => $v) {
 \GlobalVars::$eventLists[$k] = $v;
 }
 }
 }
 if (!\GlobalVars::$eventLists) {
 return;
 }
 if (isset(\GlobalVars::$eventLists[$eventName])) {
 $event = \GlobalVars::$eventLists[$eventName];
 if (is_string($event)) {
 $event = str_replace("&apos;", "'", $event);
 $mdFun = "_my_evt_" . rand();
 eval("function " . $mdFun . $event);
 if (function_exists($mdFun)) {
 $mdFun($eventData);
 }
 }
 else {
 call_user_func($event, $eventData);
 }
 }
 }
 public static function listen(string $eventName, callable $eventFun) {
 if (!\GlobalVars::$eventLists) {
 \GlobalVars::$eventLists = [];
 }
 if (defined('PUBLISHING')) {
 if (debug_backtrace()[1]['function'] != 'boot') return;
 }
 \GlobalVars::$eventLists[$eventName] = $eventFun;
 }
 }
 function releaseApp() {
 if (GlobalVars::$isRelease) {
 return;
 }
 GlobalVars::$isRelease = true;
 if (class_exists("Db")) {
 \Db::closeConnection();
 }
 if (class_exists("Cache")) {
 \Cache::__save_1Cache__Data();
 }
 }
 function __exec_hook_exte(string $hookFunc, $value) {
 if (!GlobalVars::$__hookExtensions) {
 if (GlobalVars::$__hookExtensions === false) {
 return true;
 }
 if (!empty(Config::$appConfig['hook_extension'][GlobalVars::$_areaKey])) {
 GlobalVars::$__hookExtensions = Config::$appConfig['hook_extension'][GlobalVars::$_areaKey];
 }
 else {
 GlobalVars::$__hookExtensions = false;
 return;
 }
 }
 foreach (GlobalVars::$__hookExtensions as $v) {
 $ext = load_extension($v);
 if ($ext) {
 $ext->$hookFunc($value);
 }
 }
 }
 function host_url() {
 if (!GlobalVars::$requestInfo['host']) {
 if ( isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
 $protocol = 'https://';
 }
 else {
 $protocol = 'http://';
 }
 GlobalVars::$requestInfo['host'] = $protocol . $_SERVER["HTTP_HOST"];
 $webPort = env('web_port', 80);
 if ($webPort && $webPort != 80 && $webPort != 443) GlobalVars::$requestInfo['host'] .= ":" . $webPort;
 }
 return GlobalVars::$requestInfo['host'];
 }
 function subdomain_area($areaKey, $url = null) {
 if (!\Config::getAppConfig('subdomain_area')) {
 $areaUrl = \Config::getAppConfig('areas')[$areaKey];
 return base_url($areaUrl . $url);
 }
 if (GlobalVars::$_areaKey == $areaKey) return url($url);
 if (\GlobalVars::$requestInfo['is_local'] === null) {
 \GlobalVars::$requestInfo['is_local'] = strpos($_SERVER['HTTP_HOST'], 'localhost') === 0;
 }
 if (\GlobalVars::$requestInfo['is_local']) {
 $areaUrl = \Config::getAppConfig('areas')[$areaKey];
 return base_url($areaUrl . $url);
 }
 if ( isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
 $protocol = 'https://';
 }
 else {
 $protocol = 'http://';
 }
 if (\GlobalVars::$requestInfo['subdomain']) {
 $h = substr($_SERVER["HTTP_HOST"], strlen(GlobalVars::$_areaKey) + 1);
 return $protocol . $areaKey . '.' . $h . $url;
 }
 return $protocol . $areaKey . '.' . $_SERVER["HTTP_HOST"] . $url;
 }
 function url($url = null) {
 if (empty($url) || $url == '/') {
 if (!GlobalVars::$requestInfo['area_url']) return host_url();
 return GlobalVars::$requestInfo['area_url'];
 }
 if (substr($url, 0, 4) == "http") {
 return $url;
 }
 if (substr($url, 0, 1) != "/") return GlobalVars::$requestInfo['area_url'] . '/' . $url;
 return GlobalVars::$requestInfo['area_url'] . $url;
 }
 function base_url($url = null) {
 if (empty($url) || $url == '/') {
 if (!GlobalVars::$requestInfo['base_url']) return host_url();
 return GlobalVars::$requestInfo['base_url'];
 }
 if (substr($url, 0, 4) == "http") {
 return $url;
 }
 if (substr($url, 0, 1) != "/") {
 return GlobalVars::$requestInfo['base_url'] . '/' . $url;
 }
 return GlobalVars::$requestInfo['base_url'] . $url;
 }
 function asset($path = null) {
 return base_url($path);
 }
 function combine_path($args) {
 $path = '';
 foreach ($args as $arg) {
 if (is_array($arg)) {
 foreach ($arg as $v) {
 $path .= DIRECTORY_SEPARATOR . $v;
 }
 }
 else {
 $path .= DIRECTORY_SEPARATOR . $arg;
 }
 }
 return $path . DIRECTORY_SEPARATOR;
 }
 function public_path() {
 $args = func_get_args();
 if (count($args) == 0) return ROOT_PATH . 'public' . DIRECTORY_SEPARATOR;
 return ROOT_PATH . 'public' . combine_path($args);
 }
 function module_path($inApp = false) {
 $args = func_get_args();
 if (count($args) == 0) return ROOT_PATH . ($inApp ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'modules' : 'modules') . DIRECTORY_SEPARATOR;
 if ($inApp === true) {
 unset($args[0]);
 }
 return ROOT_PATH . ($inApp === true ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'modules' : 'modules') . combine_path($args);
 }
 function model_path($inApp = false) {
 $args = func_get_args();
 if (count($args) == 0) return ROOT_PATH . ($inApp ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'models' : 'models') . DIRECTORY_SEPARATOR;
 if ($inApp === true) {
 unset($args[0]);
 }
 return ROOT_PATH . ($inApp === true ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'models' : 'models') . combine_path($args);
 }
 function extension_path($inApp = false) {
 $args = func_get_args();
 if (count($args) == 0) return ROOT_PATH . ($inApp ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'extensions' : 'extensions') . DIRECTORY_SEPARATOR;
 if ($inApp === true) {
 unset($args[0]);
 }
 return ROOT_PATH . ($inApp === true ? 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR . 'extensions' : 'extensions') . combine_path($args);
 }
 function full_http_url() {
 return host_url() . "$_SERVER[REQUEST_URI]";
 }
 function route_url() {
 return GlobalVars::$requestInfo['route_url'];
 }
 function route_name() {
 return GlobalVars::$requestInfo['route_name'];
 }
 function full_url() {
 return GlobalVars::$requestInfo['area_url'] . GlobalVars::$requestInfo['url'];
 }
 function module_name() {
 return GlobalVars::$requestInfo['module_key'];
 }
 function area_name() {
 return GlobalVars::$_areaKey;
 }
 if (!function_exists('array_key_last')) {
 function array_key_last($array) {
 foreach ($array as $k => $v) {
 }
 if (isset($k)) return $k;
 return null;
 }
 }
 function load_extension($extensionGroupKey) {
 if (isset(GlobalVars::$extensionLoaded[$extensionGroupKey])) {
 return GlobalVars::$extensionLoaded[$extensionGroupKey];
 }
 if (isset(Config::$extensionConfig[$extensionGroupKey])) {
 $ext = Config::$extensionConfig[$extensionGroupKey];
 $lastKey = array_key_last($ext);
 if (!$lastKey) {
 throw new \TCMS\TException("Không tìm thấy extension " . $extensionGroupKey);
 }
 $ext = $ext[$lastKey];
 if (is_string($ext)) {
 $filePath = ROOT_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 $namespace = $ext;
 }
 else {
 if (!isset($ext['namespace'])) {
 throw new \TCMS\TException("Không tìm thấy namespace trong extension " . $extensionGroupKey);
 }
 $namespace = $ext['namespace'];
 if (isset($ext['private'])) {
 $filePath = APP_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 }
 else {
 $filePath = ROOT_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 }
 }
 include_once($filePath);
 $ext = new $namespace();
 if (isset($ext->__isNeedKeyInMemory)) {
 GlobalVars::$extensionLoaded[$extensionGroupKey] = $ext;
 }
 return $ext;
 }
 return false;
 }
 function load_sub_extension($extensiopKey) {
 foreach (Config::$extensionConfig as $k => $ext) {
 if (isset($ext[$extensiopKey])) {
 return load_extension($k);
 }
 }
 return false;
 }
 function load_auth($authKey = null) {
 $authCfg = \Config::$appConfig['auth_extension'];
 if (!$authKey) {
 $area = area_name();
 if (!empty($authCfg[$area])) {
 $authKey = $authCfg[$area];
 }
 }
 if (!$authKey) {
 return false;
 }
 $auth = load_extension($authKey);
 if (!$auth) {
 throw new \TCMS\TException('Không tìm thấy auth extension ' . $authKey, 500);
 }
 return $auth;
 }
 function copy_option(&$desc, $src) {
 if ($desc == null || $src == null || is_array($desc) === false || is_array($src) === false) {
 return;
 }
 foreach ($src as $k => $v) {
 if (array_key_exists($k, $desc)) {
 if (is_array($v) && is_array($desc[$k])) {
 copy_option($desc[$k], $v);
 }
 else {
 $desc[$k] = $v;
 }
 }
 else {
 $desc[$k] = $v;
 }
 }
 }
 function lang(string $langKey = null, array $args = null) {
 if (!$langKey) {
 return GlobalVars::$requestInfo['cur_lang'];
 }
 $langKeyArray = explode(".", $langKey);
 if (count($langKeyArray) == 2) {
 if (GlobalVars::$__langFileLoaded == null) {
 GlobalVars::$__langFileLoaded = [];
 }
 $fileName = $langKeyArray[0];
 $key = $langKeyArray[1];
 if (array_key_exists($fileName, GlobalVars::$__langFileLoaded)) {
 if (array_key_exists($key, GlobalVars::$__langFileLoaded[$fileName])) $text = GlobalVars::$__langFileLoaded[$fileName][$key];
 else return $langKey;
 }
 else {
 $langFile = ROOT_PATH . 'langs' . DIRECTORY_SEPARATOR . $fileName . '.' . GlobalVars::$requestInfo['cur_lang'] . '.php';
 if (file_exists($langFile)) {
 $lData = require_once($langFile);
 if ($lData && is_array($lData)) {
 GlobalVars::$__langFileLoaded[$fileName] = $lData;
 if (array_key_exists($key, $lData)) {
 $text = $lData[$key];
 }
 }
 }
 else {
 $langFile = APP_PATH . 'langs' . DIRECTORY_SEPARATOR . $fileName . '.' . GlobalVars::$requestInfo['cur_lang'] . '.php';
 if (file_exists($langFile)) {
 $lData = require_once($langFile);
 if ($lData && is_array($lData)) {
 GlobalVars::$__langFileLoaded[$fileName] = $lData;
 if (array_key_exists($key, $lData)) {
 $text = $lData[$key];
 }
 }
 }
 else {
 $langFile = \GlobalVars::$curModulePath . 'langs' . DIRECTORY_SEPARATOR . $fileName . '.' . GlobalVars::$requestInfo['cur_lang'] . '.php';
 if (file_exists($langFile)) {
 $lData = require_once($langFile);
 if ($lData && is_array($lData)) {
 GlobalVars::$__langFileLoaded[$fileName] = $lData;
 if (array_key_exists($key, $lData)) {
 $text = $lData[$key];
 }
 }
 }
 }
 }
 }
 }
 if (isset($text)) {
 if ($args == null) {
 return $text;
 }
 foreach ($args as $k => $v) {
 $text = str_replace('{' . $k . '}', $v, $text);
 }
 return $text;
 }
 return $langKey;
 }
 function include_library($libName) {
 include_once(LIB_PATH . 'libs' . DIRECTORY_SEPARATOR . $libName . '.php');
 }
 function csrf_token($returnInputField = true) {
 if (!GlobalVars::$csrfToken) {
 return false;
 }
 if ($returnInputField) return '<input type="hidden" name="__csrf_token" value="' . GlobalVars::$csrfToken . '" />';
 return GlobalVars::$csrfToken;
 }
 function view($arg = null, $arg2 = null) {
 \GlobalVars::$useViewHelper = true;
 \GlobalVars::$_mviewDataArg = $arg;
 \GlobalVars::$_mviewDataArg2 = $arg2;
 return \GlobalVars::$mViewClass;
 }
 function redirect($url, string $message = null, string $messageType = null) {
 if (!empty($message)) {
 $stdCls = new \stdClass();
 $stdCls->message = $message;
 $stdCls->type = $messageType == null ? 'success' : $messageType;
 \Session::flash('message', $stdCls);
 }
 releaseApp();
 header("Location: " . $url);
 exit();
 }
 function route_redirect(string $routeName, string $message = null, string $messageType = null, array $param = null) {
 $url = view()->route($routeName, $param);
 if ($url != '') {
 redirect($url, $message, $messageType);
 }
 else {
 throw new \TCMS\TException("Không tìm thấy route " . $routeName, 501);
 }
 }
 function json($data) {
 \GlobalVars::$returnJson = true;
 \GlobalVars::$_mviewDataArg = $data;
 }
 function route(string $routeName, array $param = null) {
 if (GlobalVars::$mViewClass) {
 return GlobalVars::$mViewClass->route($routeName, $param);
 }
 if ($param == null) {
 return GlobalVars::$mRouteClass->findRouteByName($routeName);
 }
 $url = GlobalVars::$mRouteClass->findRouteByName($routeName);
 if ($url) {
 foreach ($param as $k => $v) {
 $url = str_replace('{' . $k . '}', $v, $url);
 }
 }
 return $url;
 }
 function route_exist(string $routeUrl) {
 return !empty(GlobalVars::$routeList[$routeUrl]);
 }
 function is_mobile() {
 return \GlobalVars::$mobileDevice;
 }
 function dd() {
 echo "<pre>";
 array_map(function ($x) {
 if (is_bool($x)) {
 echo $x ? 'True' : 'False';
 }
 else {
 if(is_object($x)) {
 if(method_exists($x, "exportJson")) {
 print_r($x->exportJson());
 }
 else {
 print_r(get_object_vars($x));
 }
 }
 else print_r($x);
 }
 echo "\n\n---------------------------------------------------\n";
 }
, func_get_args());
 echo "</pre>";
 exit();
 }
 function env($key, $defaultValue = false) {
 if (!Config::$envConfig) return $defaultValue;
 if (isset(Config::$envConfig[$key])) return Config::$envConfig[$key];
 return $defaultValue;
 }
 if (!defined('BIN_PATH')) {
 function devParseParamUrl($route) {
 $paramRegex = [];
 $startIndex = 0;
 $endIndex = 0;
 $arrUrl = explode('/', $route->url);
 foreach ($arrUrl as $url) {
 $isRegex = false;
 $regexUrl = '';
 $paramArray = [];
 while (true) {
 $startIndex = strpos($url, '{');
 if ($startIndex === false) {
 $regexUrl .= $url;
 break;
 }
 $startIndex++;
 $endIndex = strpos($url, '}', $startIndex);
 if ($endIndex === false) {
 $regexUrl .= $url;
 break;
 }
 if ($startIndex > 0) {
 $regexUrl .= "(" . substr($url, 0, $startIndex - 1) . ")";
 if ($regexUrl == '()') {
 $regexUrl = '';
 }
 }
 $isRegex = true;
 $param = substr($url, $startIndex, $endIndex - $startIndex);
 $regex = ($route->regex != null && array_key_exists($param, $route->regex)) ? $route->regex[$param] : '[a-zA-Z0-9-]+';
 $paramArray[] = [ 'param' => $param, 'value' => '' ];
 if (strpos($regex, '(') !== 0) $regexUrl .= '(' . $regex . ')';
 else $regexUrl .= $regex;
 $url = substr($url, $endIndex + 1);
 }
 $paramRegex[] = [ 'url' => $regexUrl, 'isRegex' => $isRegex, 'paramArray' => $paramArray ];
 }
 return $paramRegex;
 }
 function devIsHasParam($url) {
 if (isset($url) == false || $url == '' || $url == '/') return false;
 $startIndex = strpos($url, '{');
 if ($startIndex !== false) {
 $endIndex = strpos($url, "}");
 if ($endIndex !== false && $endIndex > $startIndex) return true;
 }
 return false;
 }
 function devIsMatcherUrl($routes, $url, $findNotAllow = false) {
 foreach ($routes as $route) {
 if (!$findNotAllow) {
 if ($route->type != \Request::$method) {
 continue;
 }
 }
 else {
 if ($route->type == \Request::$method) {
 continue;
 }
 }
 $routeUrl = \GlobalVars::$requestInfo['route_url'];
 if ($routeUrl != null && $routeUrl != $route->url) {
 continue;
 }
 if ($route->url == $url) {
 \GlobalVars::$requestInfo['controller'] = $route->controller;
 \GlobalVars::$requestInfo['action'] = $route->action;
 \GlobalVars::$requestInfo['route_name'] = $route->name;
 \GlobalVars::$requestInfo['route_url'] = $route->url;
 return true;
 }
 if (devIsHasParam($route->url)) {
 if (substr_count($route->url, "/") == substr_count($url, "/")) {
 $paramRegex = devParseParamUrl($route);
 $arrUrl = explode('/', $url);
 $isMatcher = true;
 foreach ($paramRegex as $key => &$param) {
 if ($param['isRegex']) {
 if (preg_match("/" . $param['url'] . "/", $arrUrl[$key], $match)) {
 if (count($match) > 1) {
 $j = 0;
 for ($i = 1;
 $i < count($match);
 $i++) {
 if ($match[$i] != '' && $match[$i] != '-' && $match[$i] != '_') {
 $param['paramArray'][$j++]['value'] = $match[$i];
 }
 }
 }
 }
 else {
 $isMatcher = false;
 break;
 }
 }
 else {
 if ($param['url'] != $arrUrl[$key]) {
 $isMatcher = false;
 break;
 }
 }
 }
 if ($isMatcher) {
 \GlobalVars::$requestInfo['controller'] = $route->controller;
 \GlobalVars::$requestInfo['action'] = $route->action;
 \GlobalVars::$requestInfo['route_name'] = $route->name;
 \GlobalVars::$requestInfo['route_url'] = $route->url;
 \GlobalVars::$requestInfo['params'] = [];
 $length = count($paramRegex);
 for ($i = 0;
 $i < $length;
 $i++) {
 if (count($paramRegex[$i]['paramArray']) > 0) {
 $l = count($paramRegex[$i]['paramArray']);
 for ($j = 0;
 $j < $l;
 $j++) {
 \GlobalVars::$requestInfo['params'][$paramRegex[$i]['paramArray'][$j]['param']] = $paramRegex[$i]['paramArray'][$j]['value'];
 }
 }
 }
 return true;
 }
 }
 }
 }
 return false;
 }
 }
 