From cdecd3a06bcb04b5ba7b29eb45d06d1d14896536 Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 12 Mar 2018 12:00:40 +0100 Subject: [PATCH] * [ADD] Delegate initialization to modules --- app/modules/api/Init.php | 108 ++++++++++ app/modules/web/Init.php | 284 ++++++++++++++++++++++++++ lib/Base.php | 2 - lib/SP/Bootstrap.php | 316 +++-------------------------- lib/SP/Config/Config.php | 27 ++- lib/SP/Core/Context/ApiContext.php | 189 +++++++++++++++++ lib/SP/Core/ModuleBase.php | 136 +++++++++++++ 7 files changed, 762 insertions(+), 300 deletions(-) create mode 100644 app/modules/api/Init.php create mode 100644 app/modules/web/Init.php create mode 100644 lib/SP/Core/Context/ApiContext.php create mode 100644 lib/SP/Core/ModuleBase.php diff --git a/app/modules/api/Init.php b/app/modules/api/Init.php new file mode 100644 index 00000000..8e95c2b6 --- /dev/null +++ b/app/modules/api/Init.php @@ -0,0 +1,108 @@ +. + */ + +namespace SP\Modules\Api; + +use DI\Container; +use SP\Core\Context\ApiContext; +use SP\Core\Exceptions\InitializationException; +use SP\Core\Language; +use SP\Core\ModuleBase; +use SP\Storage\Database; +use SP\Storage\DBUtil; +use SP\Util\HttpUtil; + +/** + * Class Init + * @package api + */ +class Init extends ModuleBase +{ + /** + * @var ApiContext + */ + protected $context; + /** + * @var Language + */ + protected $language; + + /** + * Module constructor. + * + * @param Container $container + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + */ + public function __construct(Container $container) + { + parent::__construct($container); + + $this->context = $container->get(ApiContext::class); + $this->language = $container->get(Language::class); + } + + /** + * @param $controller + * @throws InitializationException + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + * @throws \SP\Core\Exceptions\SPException + */ + public function initialize($controller) + { + debugLog(__FUNCTION__); + + // Cargar la configuración + $this->config->loadConfig($this->context); + + // Cargar el lenguaje + $this->language->setLanguage(); + + // Comprobar si es necesario cambiar a HTTPS + HttpUtil::checkHttps($this->configData); + + // Comprobar si está instalado + if (!$this->checkInstalled()) { + throw new InitializationException('Not installed'); + } + + // Comprobar si el modo mantenimiento está activado + $this->checkMaintenanceMode($this->context); + + // Comprobar si la Base de datos existe + DBUtil::checkDatabaseExist($this->container->get(Database::class)->getDbHandler(), $this->configData->getDbName()); + + $this->initEventHandlers(); + } + + /** + * Comprueba que la aplicación esté instalada + * Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador. + */ + private function checkInstalled() + { + return $this->configData->isInstalled(); + } +} \ No newline at end of file diff --git a/app/modules/web/Init.php b/app/modules/web/Init.php new file mode 100644 index 00000000..5fb0383f --- /dev/null +++ b/app/modules/web/Init.php @@ -0,0 +1,284 @@ +. + */ + +namespace SP\Modules\Web; + +use Defuse\Crypto\Exception\CryptoException; +use DI\Container; +use SP\Bootstrap; +use SP\Core\Context\SessionContext; +use SP\Core\Crypt\CryptSessionHandler; +use SP\Core\Crypt\SecureKeyCookie; +use SP\Core\Crypt\Session as CryptSession; +use SP\Core\Exceptions\InitializationException; +use SP\Core\Language; +use SP\Core\ModuleBase; +use SP\Core\Plugin\PluginUtil; +use SP\Core\UI\Theme; +use SP\Core\Upgrade\Upgrade; +use SP\Http\Request; +use SP\Services\UserProfile\UserProfileService; +use SP\Storage\Database; +use SP\Storage\DBUtil; +use SP\Util\HttpUtil; + +/** + * Class Init + * @package SP\Modules\Web + */ +class Init extends ModuleBase +{ + const PARTIAL_INIT = ['resource', 'install', 'bootstrap']; + + /** + * @var SessionContext + */ + protected $context; + /** + * @var Theme + */ + protected $theme; + /** + * @var Language + */ + protected $language; + /** + * @var Upgrade + */ + protected $upgrade; + + /** + * Init constructor. + * @param Container $container + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + */ + public function __construct(Container $container) + { + parent::__construct($container); + + $this->context = $container->get(SessionContext::class); + $this->theme = $container->get(Theme::class); + $this->language = $container->get(Language::class); + $this->upgrade = $container->get(Upgrade::class); + } + + /** + * Initialize Web App + * + * @param string $controller + * @throws InitializationException + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + * @throws \SP\Core\Exceptions\SPException + */ + public function initialize($controller) + { + debugLog(__FUNCTION__); + + // Iniciar la sesión de PHP + $this->initSession($this->configData->isEncryptSession()); + + // Volver a cargar la configuración si se recarga la página + if (Request::checkReload($this->router) === false) { + // Cargar la configuración + $this->config->loadConfig($this->context); + + // Cargar el lenguaje + $this->language->setLanguage(); + } else { + debugLog('Browser reload'); + + $this->context->setAppStatus(SessionContext::APP_STATUS_RELOADED); + + // Cargar la configuración + $this->config->loadConfig($this->context, true); + + // Restablecer el idioma y el tema visual + $this->language->setLanguage(true); + $this->theme->initTheme(true); + } + + // Comprobar si es necesario cambiar a HTTPS + HttpUtil::checkHttps($this->configData); + + if (in_array($controller, self::PARTIAL_INIT, true) === false) { + // Comprobar si está instalado + if ($this->checkInstalled() === false) { + $this->router->response()->redirect('index.php?r=install/index')->send(); + + throw new InitializationException('Not installed'); + } + + // Comprobar si el modo mantenimiento está activado + $this->checkMaintenanceMode($this->context); + + try { + // Comprobar si la Base de datos existe + DBUtil::checkDatabaseExist($this->container->get(Database::class)->getDbHandler(), $this->configData->getDbName()); + } catch (\Exception $e) { + if ($e->getCode() === 1049) { + $this->router->response()->redirect('index.php?r=install/index')->send(); + } + } + + + // Comprobar si es necesario actualizar componentes +// $this->checkUpgrade(); + + $this->initEventHandlers(); + + // Inicializar la sesión + $this->initUserSession(); + + // Cargar los plugins + PluginUtil::loadPlugins(); + + // Comprobar acciones en URL +// $this->checkPreLoginActions(); + + if ($this->context->isLoggedIn() && $this->context->getAppStatus() === SessionContext::APP_STATUS_RELOADED) { + debugLog('Reload user profile'); + // Recargar los permisos del perfil de usuario + $this->context->setUserProfile($this->container->get(UserProfileService::class)->getById($this->context->getUserData()->getUserProfileId())->getProfile()); + } + + return; + } + + // Do not keep the PHP's session opened + SessionContext::close(); + } + + /** + * Iniciar la sesión PHP + * + * @param bool $encrypt Encriptar la sesión de PHP + * @throws InitializationException + */ + private function initSession($encrypt = false) + { + if ($encrypt === true + && Bootstrap::$checkPhpVersion + && ($key = SecureKeyCookie::getKey()) !== false) { + session_set_save_handler(new CryptSessionHandler($key), true); + } + + try { + $this->context->initialize(); + } catch (InitializationException $e) { + $this->router->response()->header('HTTP/1.1', '500 Internal Server Error'); + + throw $e; + } + } + + /** + * Comprueba que la aplicación esté instalada + * Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador. + */ + private function checkInstalled() + { + return $this->configData->isInstalled() + && $this->router->request()->param('r') !== 'install/index'; + } + + /** + * Inicializar la sesión de usuario + * + */ + private function initUserSession() + { + $lastActivity = $this->context->getLastActivity(); + $inMaintenance = $this->configData->isMaintenance(); + + // Timeout de sesión + if ($lastActivity > 0 + && !$inMaintenance + && time() > ($lastActivity + $this->getSessionLifeTime()) + ) { + if ($this->router->request()->cookies()->get(session_name()) !== null) { + $this->router->response()->cookie(session_name(), '', time() - 42000); + } + + SessionContext::restart(); + } else { + + $sidStartTime = $this->context->getSidStartTime(); + + // Regenerar el Id de sesión periódicamente para evitar fijación + if ($sidStartTime === 0) { + // Intentar establecer el tiempo de vida de la sesión en PHP + @ini_set('session.gc_maxlifetime', $this->getSessionLifeTime()); + + $this->context->setSidStartTime(time()); + $this->context->setStartActivity(time()); + } else if (!$inMaintenance + && time() > ($sidStartTime + 120) + && $this->context->isLoggedIn() + ) { + try { + CryptSession::reKey($this->context); + + // Recargar los permisos del perfil de usuario +// $this->session->setUserProfile(Profile::getItem()->getById($this->session->getUserData()->getUserProfileId())); + } catch (CryptoException $e) { + debugLog($e->getMessage()); + + SessionContext::restart(); + return; + } + } + + $this->context->setLastActivity(time()); + } + } + + /** + * Obtener el timeout de sesión desde la configuración. + * + * @return int con el tiempo en segundos + */ + private function getSessionLifeTime() + { + if (($timeout = $this->context->getSessionTimeout()) === null) { + return $this->context->setSessionTimeout($this->configData->getSessionTimeout()); + } + + return $timeout; + } + + /** + * Comprobar si es necesario actualizar componentes + * + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + private function checkUpgrade() + { + if (Bootstrap::$SUBURI === '/index.php') { + $this->upgrade->checkDbVersion(); + $this->upgrade->checkAppVersion(); + } + } +} \ No newline at end of file diff --git a/lib/Base.php b/lib/Base.php index a6a48367..3dd48885 100644 --- a/lib/Base.php +++ b/lib/Base.php @@ -55,8 +55,6 @@ define('VENDOR_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'vendor'); define('SQL_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas'); define('PUBLIC_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'public'); -define('APP_PARTIAL_INIT', ['resource', 'install', 'bootstrap']); - define('DEBUG', true); // Empezar a calcular la memoria utilizada diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index d8da2cff..f8651e2c 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -24,7 +24,6 @@ namespace SP; -use Defuse\Crypto\Exception\CryptoException; use DI\Container; use Interop\Container\ContainerInterface; use Klein\Klein; @@ -33,26 +32,16 @@ use RuntimeException; use SP\Config\Config; use SP\Config\ConfigData; use SP\Config\ConfigUtil; -use SP\Core\Context\SessionContext; -use SP\Core\Crypt\CryptSessionHandler; -use SP\Core\Crypt\SecureKeyCookie; -use SP\Core\Crypt\Session as CryptSession; -use SP\Core\Events\EventDispatcher; +use SP\Core\Context\ContextInterface; use SP\Core\Exceptions\ConfigException; use SP\Core\Exceptions\InitializationException; use SP\Core\Exceptions\SPException; use SP\Core\Language; -use SP\Core\Plugin\PluginUtil; use SP\Core\UI\Theme; use SP\Core\Upgrade\Upgrade; -use SP\Http\Request; use SP\Log\Log; -use SP\Providers\Log\LogHandler; -use SP\Providers\Mail\MailHandler; -use SP\Providers\Notification\NotificationHandler; -use SP\Services\UserProfile\UserProfileService; -use SP\Storage\Database; -use SP\Storage\DBUtil; +use SP\Modules\Api\Init as InitApi; +use SP\Modules\Web\Init as InitWeb; use SP\Util\Checks; use SP\Util\HttpUtil; use SP\Util\Util; @@ -87,25 +76,25 @@ class Bootstrap */ public static $LOCK; /** - * @var ContainerInterface|Container + * @var bool Indica si la versión de PHP es correcta */ - protected static $container; + public static $checkPhpVersion; /** * @var string */ - private static $SUBURI = ''; + public static $SUBURI = ''; /** - * @var bool Indica si la versión de PHP es correcta + * @var ContainerInterface|Container */ - private static $checkPhpVersion; + protected static $container; /** * @var Upgrade */ protected $upgrade; /** - * @var SessionContext + * @var ContextInterface */ - protected $session; + protected $context; /** * @var Theme */ @@ -140,11 +129,8 @@ class Bootstrap $this->config = $container->get(Config::class); $this->configData = $this->config->getConfigData(); - $this->session = $container->get(SessionContext::class); - $this->theme = $container->get(Theme::class); $this->router = $container->get(Klein::class); $this->language = $container->get(Language::class); - $this->upgrade = $container->get(Upgrade::class); $this->initRouter(); } @@ -169,7 +155,7 @@ class Bootstrap $router->response()->body($err_msg); }); - // Manejar URLs con módulo indicado + // Manejar URLs de módulo web $this->router->respond(['GET', 'POST'], '@/(index\.php)?', function ($request, $response, $service) use ($oops) { @@ -177,16 +163,17 @@ class Bootstrap /** @var \Klein\Request $request */ $route = filter_var($request->param('r', 'index/index'), FILTER_SANITIZE_STRING); - if (!preg_match_all('#(?P[a-zA-Z]+)(?:/(?P[a-zA-Z]+))?(?P(/[a-zA-Z\d]+)+)?#', $route, $components)) { + if (!preg_match_all('#(?Pweb|api)?(?P[a-zA-Z]+)(?:/(?P[a-zA-Z]+))?(?P(/[a-zA-Z\d]+)+)?#', $route, $matches)) { throw new RuntimeException($oops); } - $controller = $components['controller'][0]; - $method = !empty($components['action'][0]) ? $components['action'][0] . 'Action' : 'indexAction'; + $app = $matches['app'][0] ?: 'web'; + $controller = $matches['controller'][0]; + $method = !empty($matches['action'][0]) ? $matches['action'][0] . 'Action' : 'indexAction'; $params = []; - if (!empty($components['params'][0])) { - foreach (explode('/', $components['params'][0]) as $value) { + if (!empty($matches['params'][0])) { + foreach (explode('/', $matches['params'][0]) as $value) { if (is_numeric($value)) { $params[] = (int)filter_var($value, FILTER_SANITIZE_NUMBER_INT); } elseif (!empty($value)) { @@ -205,11 +192,15 @@ class Bootstrap $this->initializeCommon(); - if (!in_array($controller, APP_PARTIAL_INIT, true)) { - $this->initializeApp(); - } else { - // Do not keep the PHP's session opened - SessionContext::close(); + switch ($app) { + case 'web': + self::$container->get(InitWeb::class) + ->initialize($controller); + break; + case 'api': + self::$container->get(InitApi::class) + ->initialize($controller); + break; } debugLog('Routing call: ' . $controllerClass . '::' . $method . '::' . print_r($params, true)); @@ -252,9 +243,6 @@ class Bootstrap // Establecer las rutas de la aplicación $this->initPaths(); - // Cargar las extensiones -// self::loadExtensions(); - // Establecer el lenguaje por defecto $this->language->setLocales('en_US'); @@ -268,32 +256,6 @@ class Bootstrap // Comprobar la configuración $this->initConfig(); - - // Iniciar la sesión de PHP - $this->initSession($this->configData->isEncryptSession()); - - // Volver a cargar la configuración si se recarga la página - if (Request::checkReload($this->router) === false) { - // Cargar la configuración - $this->config->loadConfig(); - - // Cargar el lenguaje - $this->language->setLanguage(); - } else { - debugLog('Browser reload'); - - $this->session->setAppStatus(SessionContext::APP_STATUS_RELOADED); - - // Cargar la configuración - $this->config->loadConfig(true); - - // Restablecer el idioma y el tema visual - $this->language->setLanguage(true); - $this->theme->initTheme(true); - } - - // Comprobar si es necesario cambiar a HTTPS - HttpUtil::checkHttps($this->configData); } /** @@ -433,216 +395,6 @@ class Bootstrap } } - /** - * Iniciar la sesión PHP - * - * @param bool $encrypt Encriptar la sesión de PHP - * @throws InitializationException - */ - private function initSession($encrypt = false) - { - if ($encrypt === true - && self::$checkPhpVersion - && ($key = SecureKeyCookie::getKey()) !== false) { - session_set_save_handler(new CryptSessionHandler($key), true); - } - - try { - $this->session->initialize(); - } catch (InitializationException $e) { - $this->router->response()->header('HTTP/1.1', '500 Internal Server Error'); - - throw $e; - } - } - - /** - * Inicializar la aplicación - * - * @throws InitializationException - * @throws SPException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface - */ - protected function initializeApp() - { - debugLog(__FUNCTION__); - - // Comprobar si está instalado - $this->checkInstalled(); - - // Comprobar si el modo mantenimiento está activado - $this->checkMaintenanceMode(); - - try { - // Comprobar si la Base de datos existe - DBUtil::checkDatabaseExist(self::$container->get(Database::class)->getDbHandler(), $this->configData->getDbName()); - } catch (\Exception $e) { - if ($e->getCode() === 1049) { - $this->router->response()->redirect('index.php?r=install/index')->send(); - } - } - - // Comprobar si es necesario actualizar componentes -// $this->checkUpgrade(); - - $this->initEventHandlers(); - - // Inicializar la sesión - $this->initUserSession(); - - // Cargar los plugins - PluginUtil::loadPlugins(); - - // Comprobar acciones en URL -// $this->checkPreLoginActions(); - - if ($this->session->isLoggedIn() && $this->session->getAppStatus() === SessionContext::APP_STATUS_RELOADED) { - debugLog('Reload user profile'); - // Recargar los permisos del perfil de usuario - $this->session->setUserProfile(self::$container->get(UserProfileService::class)->getById($this->session->getUserData()->getUserProfileId())->getProfile()); - } - } - - /** - * Comprueba que la aplicación esté instalada - * Esta función comprueba si la aplicación está instalada. Si no lo está, redirige al instalador. - * - * @throws InitializationException - */ - private function checkInstalled() - { - // Redirigir al instalador si no está instalada - if (!$this->configData->isInstalled() - && $this->router->request()->param('r') !== 'install/index' - ) { - $this->router->response()->redirect('index.php?r=install/index')->send(); - - throw new InitializationException('Not installed'); - -// FIXME: -// if ($this->session->getAuthCompleted()) { -// session_destroy(); -// -// $this->initialize(); -// return; -// } -// - } - } - - /** - * Comprobar si el modo mantenimiento está activado - * Esta función comprueba si el modo mantenimiento está activado. - * Devuelve un error 503 y un reintento de 120s al cliente. - * - * @param bool $check sólo comprobar si está activado el modo - * @throws InitializationException - */ - public function checkMaintenanceMode($check = false) - { - if ($this->configData->isMaintenance()) { - self::$LOCK = Util::getAppLock(); - - if ($check === true - || Checks::isAjax($this->router) - || Request::analyzeInt('nodbupgrade') === 1 - || (self::$LOCK !== false && self::$LOCK->userId > 0 && $this->session->isLoggedIn() && self::$LOCK->userId === $this->session->getUserData()->getId()) - ) { - return; - } - - throw new InitializationException( - __u('Aplicación en mantenimiento'), - InitializationException::INFO, - __u('En breve estará operativa') - ); - } - } - - /** - * Initializes event handlers - */ - protected function initEventHandlers() - { - $eventDispatcher = self::$container->get(EventDispatcher::class); - - if ($this->configData->isLogEnabled()) { - $eventDispatcher->attach(self::$container->get(LogHandler::class)); - } - - if ($this->configData->isMailEnabled()) { - $eventDispatcher->attach(self::$container->get(MailHandler::class)); - } - - $eventDispatcher->attach(self::$container->get(NotificationHandler::class)); - } - - /** - * Inicializar la sesión de usuario - * - */ - private function initUserSession() - { - $lastActivity = $this->session->getLastActivity(); - $inMaintenance = $this->configData->isMaintenance(); - - // Timeout de sesión - if ($lastActivity > 0 - && !$inMaintenance - && time() > ($lastActivity + $this->getSessionLifeTime()) - ) { - if ($this->router->request()->cookies()->get(session_name()) !== null) { - $this->router->response()->cookie(session_name(), '', time() - 42000); - } - - SessionContext::restart(); - } else { - - $sidStartTime = $this->session->getSidStartTime(); - - // Regenerar el Id de sesión periódicamente para evitar fijación - if ($sidStartTime === 0) { - // Intentar establecer el tiempo de vida de la sesión en PHP - @ini_set('session.gc_maxlifetime', $this->getSessionLifeTime()); - - $this->session->setSidStartTime(time()); - $this->session->setStartActivity(time()); - } else if (!$inMaintenance - && time() > ($sidStartTime + 120) - && $this->session->isLoggedIn() - ) { - try { - CryptSession::reKey($this->session); - - // Recargar los permisos del perfil de usuario -// $this->session->setUserProfile(Profile::getItem()->getById($this->session->getUserData()->getUserProfileId())); - } catch (CryptoException $e) { - debugLog($e->getMessage()); - - SessionContext::restart(); - return; - } - } - - $this->session->setLastActivity(time()); - } - } - - /** - * Obtener el timeout de sesión desde la configuración. - * - * @return int con el tiempo en segundos - */ - private function getSessionLifeTime() - { - if (($timeout = $this->session->getSessionTimeout()) === null) { - return $this->session->setSessionTimeout($this->configData->getSessionTimeout()); - } - - return $timeout; - } - /** * @return ContainerInterface */ @@ -666,24 +418,14 @@ class Bootstrap case 'web': $bs->router->dispatch(); break; + case 'api': + $bs->router->dispatch(); + break; default; throw new InitializationException('Unknown module'); } } - /** - * Comprobar si es necesario actualizar componentes - * - * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException - */ - private function checkUpgrade() - { - if (self::$SUBURI === '/index.php') { - $this->upgrade->checkDbVersion(); - $this->upgrade->checkAppVersion(); - } - } - /** * Registrar la actualización de la configuración * diff --git a/lib/SP/Config/Config.php b/lib/SP/Config/Config.php index e2035356..d1805441 100644 --- a/lib/SP/Config/Config.php +++ b/lib/SP/Config/Config.php @@ -64,8 +64,8 @@ class Config * Config constructor. * * @param XmlFileStorageInterface $fileStorage - * @param SessionContext $session - * @param Container $dic + * @param SessionContext $session + * @param Container $dic * @throws ConfigException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface @@ -121,37 +121,42 @@ class Config /** * Cargar la configuración desde el archivo * + * @param SessionContext $sessionContext * @param bool $reload * @return ConfigData */ - public function loadConfig($reload = false) + public function loadConfig(SessionContext $sessionContext, $reload = false) { - $configData = $this->session->getConfig(); + $configData = $sessionContext->getConfig(); if ($reload === true || $configData === null - || time() >= ($this->session->getConfigTime() + $configData->getSessionTimeout() / 2) + || time() >= ($sessionContext->getConfigTime() + $configData->getSessionTimeout() / 2) ) { - $this->saveConfigInSession(); + return $this->saveConfigInSession($sessionContext); } - return $this->configData; + return $configData; } /** * Guardar la configuración en la sesión + * @param SessionContext $sessionContext + * @return ConfigData */ - private function saveConfigInSession() + private function saveConfigInSession(SessionContext $sessionContext) { - $this->session->setConfig($this->configData); - $this->session->setConfigTime(time()); + $sessionContext->setConfig($this->configData); + $sessionContext->setConfigTime(time()); + + return $this->configData; } /** * Guardar la configuración * * @param ConfigData $configData - * @param bool $backup + * @param bool $backup */ public function saveConfig(ConfigData $configData, $backup = true) { diff --git a/lib/SP/Core/Context/ApiContext.php b/lib/SP/Core/Context/ApiContext.php new file mode 100644 index 00000000..f9b9aa5f --- /dev/null +++ b/lib/SP/Core/Context/ApiContext.php @@ -0,0 +1,189 @@ +. + */ + +namespace SP\Core\Context; + +use SP\Config\ConfigData; +use SP\DataModel\ProfileData; +use SP\Services\User\UserLoginResponse; + +/** + * Class ApiContext + * @package SP\Core\Context + */ +class ApiContext extends ContextBase +{ + /** + * @return void + */ + public function initialize() + { + $this->setContext([]); + } + + /** + * Establecer la configuración + * + * @param ConfigData $config + */ + public function setConfig(ConfigData $config) + { + $this->setContextKey('config', $config); + } + + /** + * Establece los datos del usuario en la sesión. + * + * @param UserLoginResponse $userLoginResponse + */ + public function setUserData(UserLoginResponse $userLoginResponse = null) + { + $this->setContextKey('userData', $userLoginResponse); + } + + /** + * Obtiene el objeto de perfil de usuario de la sesión. + * + * @return ProfileData + */ + public function getUserProfile() + { + return $this->getContextKey('userProfile'); + } + + /** + * Establece el objeto de perfil de usuario en la sesión. + * + * @param ProfileData $ProfileData + */ + public function setUserProfile(ProfileData $ProfileData) + { + $this->setContextKey('userProfile', $ProfileData); + } + + /** + * Returns if user is logged in + * + * @return bool + */ + public function isLoggedIn() + { + return $this->getUserData()->getLogin(); + } + + /** + * Devuelve los datos del usuario en la sesión. + * + * @return UserLoginResponse + */ + public function getUserData() + { + return $this->getContextKey('userData', new UserLoginResponse()); + } + + /** + * @return mixed + */ + public function getSecurityKey() + { + return $this->getContextKey('sk'); + } + + /** + * @return string + */ + public function generateSecurityKey() + { + return $this->setSecurityKey(sha1(time() . $this->getConfig()->getPasswordSalt())); + } + + /** + * @param $sk + * @return mixed + */ + public function setSecurityKey($sk) + { + return $this->setContextKey('sk', $sk); + } + + /** + * Devolver la configuración + * + * @return ConfigData + */ + public function getConfig() + { + return $this->getContextKey('config'); + } + + /** + * Establecer el lenguaje de la sesión + * + * @param $locale + */ + public function setLocale($locale) + { + $this->setContextKey('locale', $locale); + } + + /** + * Devuelve el lenguaje de la sesión + * + * @return string + */ + public function getLocale() + { + return $this->getContextKey('locale'); + } + + /** + * Devuelve el estado de la aplicación + * + * @return bool + */ + public function getAppStatus() + { + return $this->getContextKey('status'); + } + + /** + * Establecer el estado de la aplicación + * + * @param string $status + */ + public function setAppStatus($status) + { + $this->setContextKey('status', $status); + } + + /** + * Reset del estado de la aplicación + * + * @return bool + */ + public function resetAppStatus() + { + return $this->setContextKey('status', null); + } +} \ No newline at end of file diff --git a/lib/SP/Core/ModuleBase.php b/lib/SP/Core/ModuleBase.php new file mode 100644 index 00000000..92d04506 --- /dev/null +++ b/lib/SP/Core/ModuleBase.php @@ -0,0 +1,136 @@ +. + */ + +namespace SP\Core; + +use DI\Container; +use Klein\Klein; +use SP\Bootstrap; +use SP\Config\Config; +use SP\Core\Context\ContextInterface; +use SP\Core\Events\EventDispatcher; +use SP\Core\Exceptions\InitializationException; +use SP\Http\Request; +use SP\Providers\Log\LogHandler; +use SP\Providers\Mail\MailHandler; +use SP\Providers\Notification\NotificationHandler; +use SP\Util\Checks; +use SP\Util\Util; + +/** + * Class ModuleBase + * + * @package SP\Core + */ +abstract class ModuleBase +{ + /** + * @var \SP\Config\ConfigData + */ + protected $configData; + /** + * @var Config + */ + protected $config; + /** + * @var Klein + */ + protected $router; + /** + * @var Container + */ + protected $container; + + /** + * Module constructor. + * + * @param Container $container + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + */ + public function __construct(Container $container) + { + $this->container = $container; + $this->config = $container->get(Config::class); + $this->configData = $this->config->getConfigData(); + $this->router = $container->get(Klein::class); + } + + /** + * @param $controller + * @return mixed + */ + abstract public function initialize($controller); + + /** + * Comprobar si el modo mantenimiento está activado + * Esta función comprueba si el modo mantenimiento está activado. + * Devuelve un error 503 y un reintento de 120s al cliente. + * + * @param ContextInterface $context + * @param bool $check sólo comprobar si está activado el modo + * @throws InitializationException + */ + public function checkMaintenanceMode(ContextInterface $context, $check = false) + { + if ($this->configData->isMaintenance()) { + Bootstrap::$LOCK = Util::getAppLock(); + + if ($check === true + || Checks::isAjax($this->router) + || Request::analyzeInt('nodbupgrade') === 1 + || (Bootstrap::$LOCK !== false && Bootstrap::$LOCK->userId > 0 && $context->isLoggedIn() && Bootstrap::$LOCK->userId === $context->getUserData()->getId()) + ) { + return; + } + + throw new InitializationException( + __u('Aplicación en mantenimiento'), + InitializationException::INFO, + __u('En breve estará operativa') + ); + } + } + + /** + * Initializes event handlers + * + * @throws \DI\DependencyException + * @throws \DI\NotFoundException + */ + protected function initEventHandlers() + { + $eventDispatcher = $this->container->get(EventDispatcher::class); + + if ($this->configData->isLogEnabled()) { + $eventDispatcher->attach($this->container->get(LogHandler::class)); + } + + if ($this->configData->isMailEnabled()) { + $eventDispatcher->attach($this->container->get(MailHandler::class)); + } + + $eventDispatcher->attach($this->container->get(NotificationHandler::class)); + } +} \ No newline at end of file