. */ namespace SP\Services\Upgrade; use SP\Config\ConfigData; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Services\Service; use SP\Storage\Database\Database; use SP\Storage\Database\MySQLFileParser; use SP\Storage\Database\QueryData; use SP\Storage\File\FileException; use SP\Storage\File\FileHandler; use SP\Util\Version; /** * Class UpgradeDatabaseService * * @package SP\Services\Upgrade */ final class UpgradeDatabaseService extends Service implements UpgradeInterface { /** * @var array Versiones actualizables */ const UPGRADES = ['300.18010101', '300.18072302', '300.18072501', '300.18083001', '300.18083002']; /** * @var Database */ protected $db; /** * Check if it needs to be upgraded * * @param $version * * @return bool */ public static function needsUpgrade($version) { return empty($version) || Version::checkVersion($version, self::UPGRADES); } /** * Inicia el proceso de actualización de la BBDD. * * @param int $version con la versión de la BBDD actual * @param ConfigData $configData * * @return bool * @throws UpgradeException * @throws FileException */ public function upgrade($version, ConfigData $configData) { $this->eventDispatcher->notifyEvent('upgrade.db.start', new Event($this, EventMessage::factory() ->addDescription(__u('Actualizar BBDD'))) ); foreach (self::UPGRADES as $upgradeVersion) { if (Version::checkVersion($version, $upgradeVersion)) { if ($this->applyPreUpgrade($upgradeVersion) === false) { throw new UpgradeException( __u('Error al aplicar la actualización auxiliar'), UpgradeException::CRITICAL, __u('Compruebe el registro de eventos para más detalles') ); } if ($this->applyUpgrade($upgradeVersion) === false) { throw new UpgradeException( __u('Error al aplicar la actualización de la Base de Datos'), UpgradeException::CRITICAL, __u('Compruebe el registro de eventos para más detalles') ); } logger('DB Upgrade: ' . $upgradeVersion); $configData->setDatabaseVersion($upgradeVersion); $this->config->saveConfig($configData, false); } } // foreach (self::AUX_UPGRADES as $auxVersion) { // if (Util::checkVersion($version, $auxVersion) // && $this->auxUpgrades($auxVersion) === false // ) { // throw new UpgradeException( // __u('Error al aplicar la actualización auxiliar'), // UpgradeException::CRITICAL, // __u('Compruebe el registro de eventos para más detalles') // ); // } // } $this->eventDispatcher->notifyEvent('upgrade.db.end', new Event($this, EventMessage::factory() ->addDescription(__u('Actualizar BBDD'))) ); return true; } /** * Aplicar actualizaciones auxiliares antes de actualizar la BBDD * * @param $version * * @return bool */ private function applyPreUpgrade($version) { return true; } /** * Actualiza la BBDD según la versión. * * @param int $version con la versión a actualizar * * @returns bool * @return bool * @throws UpgradeException */ private function applyUpgrade($version) { $queries = $this->getQueriesFromFile($version); if (count($queries) === 0) { logger(__('El archivo de actualización no contiene datos'), 'ERROR'); throw new UpgradeException(__u('El archivo de actualización no contiene datos'), UpgradeException::ERROR, $version); } foreach ($queries as $query) { try { $this->eventDispatcher->notifyEvent('upgrade.db.process', new Event($this, EventMessage::factory() ->addDetail(__u('Versión'), $version)) ); $queryData = new QueryData(); $queryData->setQuery($query); $this->db->doQuery($queryData); } catch (\Exception $e) { processException($e); logger('SQL: ' . $query); $this->eventDispatcher->notifyEvent('exception', new Event($this, EventMessage::factory() ->addDescription(__u('Error al aplicar la actualización de la Base de Datos')) ->addDetail('ERROR', sprintf('%s (%s)', $e->getMessage(), $e->getCode()))) ); throw new UpgradeException(__u('Error al aplicar la actualización de la Base de Datos')); } } $this->eventDispatcher->notifyEvent('upgrade.db.process', new Event($this, EventMessage::factory() ->addDescription(__u('Actualización de la Base de Datos realizada correctamente.'))) ); return true; } /** * Obtener las consultas de actualización desde un archivo * * @param $filename * * @return array|bool * @throws UpgradeException */ private function getQueriesFromFile($filename) { $fileName = SQL_PATH . DIRECTORY_SEPARATOR . str_replace('.', '', $filename) . '.sql'; try { $parser = new MySQLFileParser(new FileHandler($fileName)); return $parser->parse('$$'); } catch (FileException $e) { processException($e); throw new UpgradeException($e->getMessage()); } } protected function initialize() { $this->db = $this->dic->get(Database::class); } }