openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

Update.class.php (4270B)


      1 <?php
      2 
      3 namespace cms\update;
      4 
      5 use cms\base\Startup;
      6 use cms\base\Version;
      7 use database\Database;
      8 use Exception;
      9 use logger\Logger;
     10 
     11 
     12 class Update
     13 {
     14 	// This is the required DB version:
     15 	const SUPPORTED_VERSION = 31;
     16 	// -----------------------^^-----------------------------
     17 
     18 	const STATUS_UPDATE_PROGRESS = 0;
     19 	const STATUS_UPDATE_SUCCESS  = 1;
     20 
     21 	/**
     22 	 * Detects if the database must be upgraded.
     23 	 *
     24 	 * @param Database $db
     25 	 * @return bool true if database must be updated
     26 	 */
     27 	public function isUpdateRequired(Database $db)
     28 	{
     29 		$version = $this->getDbVersion($db);
     30 
     31 		Logger::debug("Need DB-Version: " . self::SUPPORTED_VERSION . "; Actual DB-Version: " . $version);
     32 
     33 		if ($version == self::SUPPORTED_VERSION)
     34 			// Cool, der aktuelle DB-Stand passt zu dieser Version. Das ist auch der Normalfall. Weiter so.
     35 			return false;
     36 
     37 		elseif ($version > self::SUPPORTED_VERSION)
     38 			// Oh oh, in der Datenbank ist eine neuere Version, als wir unterstützen.
     39 			throw new \LogicException('Actual DB version is not supported. ' . "DB-Version is $version, but " . Startup::TITLE . " " . Startup::VERSION . " only supports version " . self::SUPPORTED_VERSION);
     40 
     41 		else
     42 			return true; // Update required.
     43 	}
     44 
     45 
     46 	/**
     47 	 * Update the database to a newer version.
     48 	 *
     49 	 * @param Database $db
     50 	 */
     51 	public function update(Database $db)
     52 	{
     53 		$version = $this->getDbVersion($db);
     54 
     55 
     56 		for ($installVersion = $version + 1; $installVersion <= self::SUPPORTED_VERSION; $installVersion++) {
     57 			if ($installVersion > 2) // Up to version 2 there was no table 'version'.
     58 			{
     59 				$db->start();
     60 				$sql = $db->sql('INSERT INTO {{version}} (id,version,status,installed) VALUES( {id},{version},{status},{time} )', $db->id);
     61 				$sql->setInt('id', $installVersion);
     62 				$sql->setInt('version', $installVersion);
     63 				$sql->setInt('status', self::STATUS_UPDATE_PROGRESS);
     64 				$sql->setInt('time', time());
     65 				$sql->execute();
     66 				$db->commit();
     67 			}
     68 
     69 			$updaterClassName = __NAMESPACE__.'\version\DBVersion' . str_pad($installVersion, 6, '0', STR_PAD_LEFT);
     70 
     71 			$db->start();
     72 			/** @var \database\DbVersion $updater */
     73 			$updater = new $updaterClassName($db);
     74 
     75 			$updater->update();
     76 			$db->commit();
     77 
     78 			if ($installVersion > 2) {
     79 				$db->start();
     80 				$sql = $db->sql('UPDATE {{version}} SET status={status},installed={time} WHERE version={version}', $db->id);
     81 				$sql->setInt('status', self::STATUS_UPDATE_SUCCESS);
     82 				$sql->setInt('version', $installVersion);
     83 				$sql->setInt('time', time());
     84 				$sql->execute();
     85 				$db->commit();
     86 			}
     87 		}
     88 	}
     89 
     90 
     91 	/**
     92 	 * Detects the actual version of the database scheme.
     93 	 *
     94 	 * @param Database $db
     95 	 * @return int
     96 	 */
     97 	private function getDbVersion(Database $db)
     98 	{
     99 		$versionTableExists = $this->testQuery($db, 'SELECT 1 FROM {{version}}');
    100 
    101 		if ($versionTableExists) {
    102 			// Prüfen, ob die vorherigen Updates fehlerfrei sind. 
    103 			$sql = $db->sql(<<<SQL
    104 	SELECT COUNT(*) FROM {{version}} WHERE STATUS=0
    105 SQL
    106 				, $db->id);
    107 			$countErrors = $sql->getOne();
    108 			if ($countErrors > 0)
    109 				throw new \LogicException('Database error: There are dirty versions (means: versions with status 0), see table VERSION for details.');
    110 
    111 			// Aktuelle Version ermitteln.
    112 			$sql = $db->sql(<<<SQL
    113 	SELECT MAX(version) FROM {{version}}
    114 SQL
    115 				, $db->id);
    116 			$version = $sql->getOne();
    117 
    118 			if (is_numeric($version))
    119 				return $version; // Aktuelle Version.s
    120 			else
    121 				// Tabelle 'version' ist noch leer.
    122 				// Tabelle 'version' wurde in Version 2 angelegt.
    123 				return 2;
    124 		} else {
    125 			// no version table exists.
    126 
    127 			// find out if there is the project table...
    128 			$projectTableExists = $this->testQuery($db, 'SELECT 1 FROM {{project}}');
    129 
    130 			if ($projectTableExists)
    131 				// seems to be the old baseline version without a version table.
    132 				return 1;
    133 			else
    134 				// there are no tables, everything must be created.
    135 				return 0;
    136 		}
    137 	}
    138 
    139 
    140 	/**
    141 	 * Stellt fest, ob eine DB-Anfrage funktioniert.
    142 	 *
    143 	 * @param $db Database
    144 	 * @param $sql
    145 	 * @return <code>true</code> falls SQL funktioniert.
    146 	 */
    147 	private function testQuery($db, $sql)
    148 	{
    149 		try {
    150 			$sql = $db->sql($sql, $db->id);
    151 			$sql->execute();
    152 			return true; // Bisher alles ok? Dann funktioniert die Query.
    153 		} catch (Exception $e) {
    154 			// Query funktioniert nicht.
    155 			return false;
    156 		}
    157 	}
    158 }
    159 
    160 ?>