PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/doctrine-migrations/lib/Doctrine/DBAL/Migrations/Configuration/Configuration.php

https://bitbucket.org/cryofrost/portal
PHP | 538 lines | 371 code | 24 blank | 143 comment | 4 complexity | bb287d47da9d3a554c7969eee14e16f7 MD5 | raw file
Possible License(s): Apache-2.0, JSON, LGPL-2.1, LGPL-2.0, LGPL-3.0, BSD-3-Clause, BSD-2-Clause
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\DBAL\Migrations\Configuration;
  20. use Doctrine\DBAL\Connection,
  21. Doctrine\DBAL\Migrations\MigrationException,
  22. Doctrine\DBAL\Migrations\Version,
  23. Doctrine\DBAL\Migrations\OutputWriter,
  24. Doctrine\DBAL\Schema\Table,
  25. Doctrine\DBAL\Schema\Column,
  26. Doctrine\DBAL\Types\Type;
  27. /**
  28. * Default Migration Configurtion object used for configuring an instance of
  29. * the Migration class. Set the connection, version table name, register migration
  30. * classes/versions, etc.
  31. *
  32. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  33. * @link www.doctrine-project.org
  34. * @since 2.0
  35. * @author Jonathan H. Wage <jonwage@gmail.com>
  36. */
  37. class Configuration
  38. {
  39. /**
  40. * Name of this set of migrations
  41. *
  42. * @var string
  43. */
  44. private $name;
  45. /**
  46. * Flag for whether or not the migration table has been created
  47. *
  48. * @var bool
  49. */
  50. private $migrationTableCreated = false;
  51. /**
  52. * Connection instance to use for migrations
  53. *
  54. * @var Connection
  55. */
  56. private $connection;
  57. /**
  58. * OutputWriter instance for writing output during migrations
  59. *
  60. * @var OutputWriter
  61. */
  62. private $outputWriter;
  63. /**
  64. * The migration table name to track versions in
  65. *
  66. * @var string
  67. */
  68. private $migrationsTableName = 'doctrine_migration_versions';
  69. /**
  70. * The path to a directory where new migration classes will be written
  71. *
  72. * @var string
  73. */
  74. private $migrationsDirectory;
  75. /**
  76. * Namespace the migration classes live in
  77. *
  78. * @var string
  79. */
  80. private $migrationsNamespace;
  81. /**
  82. * Array of the registered migrations
  83. *
  84. * @var array
  85. */
  86. private $migrations = array();
  87. /**
  88. * Construct a migration configuration object.
  89. *
  90. * @param Connection $connection A Connection instance
  91. * @param OutputWriter $outputWriter A OutputWriter instance
  92. */
  93. public function __construct(Connection $connection, OutputWriter $outputWriter = null)
  94. {
  95. $this->connection = $connection;
  96. if ($outputWriter === null) {
  97. $outputWriter = new OutputWriter();
  98. }
  99. $this->outputWriter = $outputWriter;
  100. }
  101. /**
  102. * Validation that this instance has all the required properties configured
  103. *
  104. * @return void
  105. * @throws MigrationException
  106. */
  107. public function validate()
  108. {
  109. if ( ! $this->migrationsNamespace) {
  110. throw MigrationException::migrationsNamespaceRequired();
  111. }
  112. if ( ! $this->migrationsDirectory) {
  113. throw MigrationException::migrationsDirectoryRequired();
  114. }
  115. }
  116. /**
  117. * Set the name of this set of migrations
  118. *
  119. * @param string $name The name of this set of migrations
  120. */
  121. public function setName($name)
  122. {
  123. $this->name = $name;
  124. }
  125. /**
  126. * Returns the name of this set of migrations
  127. *
  128. * @return string $name The name of this set of migrations
  129. */
  130. public function getName()
  131. {
  132. return $this->name;
  133. }
  134. /**
  135. * Returns the OutputWriter instance
  136. *
  137. * @return OutputWriter $outputWriter The OutputWriter instance
  138. */
  139. public function getOutputWriter()
  140. {
  141. return $this->outputWriter;
  142. }
  143. /**
  144. * Returns a timestamp version as a formatted date
  145. *
  146. * @param string $version
  147. * @return string $formattedVersion The formatted version
  148. */
  149. public function formatVersion($version)
  150. {
  151. return sprintf('%s-%s-%s %s:%s:%s',
  152. substr($version, 0, 4),
  153. substr($version, 4, 2),
  154. substr($version, 6, 2),
  155. substr($version, 8, 2),
  156. substr($version, 10, 2),
  157. substr($version, 12, 2)
  158. );
  159. }
  160. /**
  161. * Returns the Connection instance
  162. *
  163. * @return Connection $connection The Connection instance
  164. */
  165. public function getConnection()
  166. {
  167. return $this->connection;
  168. }
  169. /**
  170. * Set the migration table name
  171. *
  172. * @param string $tableName The migration table name
  173. */
  174. public function setMigrationsTableName($tableName)
  175. {
  176. $this->migrationsTableName = $tableName;
  177. }
  178. /**
  179. * Returns the migration table name
  180. *
  181. * @return string $migrationsTableName The migration table name
  182. */
  183. public function getMigrationsTableName()
  184. {
  185. return $this->migrationsTableName;
  186. }
  187. /**
  188. * Set the new migrations directory where new migration classes are generated
  189. *
  190. * @param string $migrationsDirectory The new migrations directory
  191. */
  192. public function setMigrationsDirectory($migrationsDirectory)
  193. {
  194. $this->migrationsDirectory = $migrationsDirectory;
  195. }
  196. /**
  197. * Returns the new migrations directory where new migration classes are generated
  198. *
  199. * @return string $migrationsDirectory The new migrations directory
  200. */
  201. public function getMigrationsDirectory()
  202. {
  203. return $this->migrationsDirectory;
  204. }
  205. /**
  206. * Set the migrations namespace
  207. *
  208. * @param string $migrationsNamespace The migrations namespace
  209. */
  210. public function setMigrationsNamespace($migrationsNamespace)
  211. {
  212. $this->migrationsNamespace = $migrationsNamespace;
  213. }
  214. /**
  215. * Returns the migrations namespace
  216. *
  217. * @return string $migrationsNamespace The migrations namespace
  218. */
  219. public function getMigrationsNamespace()
  220. {
  221. return $this->migrationsNamespace;
  222. }
  223. /**
  224. * Register migrations from a given directory. Recursively finds all files
  225. * with the pattern VersionYYYYMMDDHHMMSS.php as the filename and registers
  226. * them as migrations.
  227. *
  228. * @param string $path The root directory to where some migration classes live.
  229. * @return $migrations The array of migrations registered.
  230. */
  231. public function registerMigrationsFromDirectory($path)
  232. {
  233. $path = realpath($path);
  234. $path = rtrim($path, '/');
  235. $files = glob($path . '/Version*.php');
  236. $versions = array();
  237. if ($files) {
  238. foreach ($files as $file) {
  239. require_once($file);
  240. $info = pathinfo($file);
  241. $version = substr($info['filename'], 7);
  242. $class = $this->migrationsNamespace . '\\' . $info['filename'];
  243. $versions[] = $this->registerMigration($version, $class);
  244. }
  245. }
  246. return $versions;
  247. }
  248. /**
  249. * Register a single migration version to be executed by a AbstractMigration
  250. * class.
  251. *
  252. * @param string $version The version of the migration in the format YYYYMMDDHHMMSS.
  253. * @param string $class The migration class to execute for the version.
  254. */
  255. public function registerMigration($version, $class)
  256. {
  257. $version = (string) $version;
  258. $class = (string) $class;
  259. if (isset($this->migrations[$version])) {
  260. throw MigrationException::duplicateMigrationVersion($version, get_class($this->migrations[$version]));
  261. }
  262. $version = new Version($this, $version, $class);
  263. $this->migrations[$version->getVersion()] = $version;
  264. ksort($this->migrations);
  265. return $version;
  266. }
  267. /**
  268. * Register an array of migrations. Each key of the array is the version and
  269. * the value is the migration class name.
  270. *
  271. *
  272. * @param array $migrations
  273. * @return void
  274. */
  275. public function registerMigrations(array $migrations)
  276. {
  277. $versions = array();
  278. foreach ($migrations as $version => $class) {
  279. $versions[] = $this->registerMigration($version, $class);
  280. }
  281. return $versions;
  282. }
  283. /**
  284. * Get the array of registered migration versions.
  285. *
  286. * @return array $migrations
  287. */
  288. public function getMigrations()
  289. {
  290. return $this->migrations;
  291. }
  292. /**
  293. * Returns the Version instance for a given version in the format YYYYMMDDHHMMSS.
  294. *
  295. * @param string $version The version string in the format YYYYMMDDHHMMSS.
  296. * @return Version $version
  297. * @throws MigrationException $exception Throws exception if migration version does not exist.
  298. */
  299. public function getVersion($version)
  300. {
  301. if ( ! isset($this->migrations[$version])) {
  302. throw MigrationException::unknownMigrationVersion($version);
  303. }
  304. return $this->migrations[$version];
  305. }
  306. /**
  307. * Check if a version exists.
  308. *
  309. * @param string $version
  310. * @return bool $exists
  311. */
  312. public function hasVersion($version)
  313. {
  314. return isset($this->migrations[$version]) ? true : false;
  315. }
  316. /**
  317. * Check if a version has been migrated or not yet
  318. *
  319. * @param Version $version
  320. * @return bool $migrated
  321. */
  322. public function hasVersionMigrated(Version $version)
  323. {
  324. $this->createMigrationTable();
  325. $version = $this->connection->fetchColumn("SELECT version FROM " . $this->migrationsTableName . " WHERE version = ?", array($version->getVersion()));
  326. return $version !== false ? true : false;
  327. }
  328. /**
  329. * Returns all migrated versions from the versions table, in an array.
  330. *
  331. * @return array $migrated
  332. */
  333. public function getMigratedVersions()
  334. {
  335. $this->createMigrationTable();
  336. $ret = $this->connection->fetchAll("SELECT version FROM " . $this->migrationsTableName);
  337. $versions = array();
  338. foreach ($ret as $version) {
  339. $versions[] = current($version);
  340. }
  341. return $versions;
  342. }
  343. /**
  344. * Returns an array of available migration version numbers.
  345. *
  346. * @return array $availableVersions
  347. */
  348. public function getAvailableVersions()
  349. {
  350. $availableVersions = array();
  351. foreach ($this->migrations as $migration) {
  352. $availableVersions[] = $migration->getVersion();
  353. }
  354. return $availableVersions;
  355. }
  356. /**
  357. * Returns the current migrated version from the versions table.
  358. *
  359. * @return bool $currentVersion
  360. */
  361. public function getCurrentVersion()
  362. {
  363. $this->createMigrationTable();
  364. $where = null;
  365. if ($this->migrations) {
  366. $migratedVersions = array();
  367. foreach ($this->migrations as $migration) {
  368. $migratedVersions[] = sprintf("'%s'", $migration->getVersion());
  369. }
  370. $where = " WHERE version IN (" . implode(', ', $migratedVersions) . ")";
  371. }
  372. $sql = sprintf("SELECT version FROM %s%s ORDER BY version DESC",
  373. $this->migrationsTableName, $where
  374. );
  375. $sql = $this->connection->getDatabasePlatform()->modifyLimitQuery($sql, 1);
  376. $result = $this->connection->fetchColumn($sql);
  377. return $result !== false ? (string) $result : '0';
  378. }
  379. /**
  380. * Returns the total number of executed migration versions
  381. *
  382. * @return integer $count
  383. */
  384. public function getNumberOfExecutedMigrations()
  385. {
  386. $this->createMigrationTable();
  387. $result = $this->connection->fetchColumn("SELECT COUNT(version) FROM " . $this->migrationsTableName);
  388. return $result !== false ? $result : 0;
  389. }
  390. /**
  391. * Returns the total number of available migration versions
  392. *
  393. * @return integer $count
  394. */
  395. public function getNumberOfAvailableMigrations()
  396. {
  397. return count($this->migrations);
  398. }
  399. /**
  400. * Returns the latest available migration version.
  401. *
  402. * @return string $version The version string in the format YYYYMMDDHHMMSS.
  403. */
  404. public function getLatestVersion()
  405. {
  406. $versions = array_keys($this->migrations);
  407. $latest = end($versions);
  408. return $latest !== false ? (string) $latest : '0';
  409. }
  410. /**
  411. * Create the migration table to track migrations with.
  412. *
  413. * @return bool $created Whether or not the table was created.
  414. */
  415. public function createMigrationTable()
  416. {
  417. $this->validate();
  418. if ($this->migrationTableCreated) {
  419. return false;
  420. }
  421. $schema = $this->connection->getSchemaManager()->createSchema();
  422. if ( ! $schema->hasTable($this->migrationsTableName)) {
  423. $columns = array(
  424. 'version' => new Column('version', Type::getType('string'), array('length' => 255)),
  425. );
  426. $table = new Table($this->migrationsTableName, $columns);
  427. $table->setPrimaryKey(array('version'));
  428. $this->connection->getSchemaManager()->createTable($table);
  429. $this->migrationTableCreated = true;
  430. return true;
  431. }
  432. return false;
  433. }
  434. /**
  435. * Returns the array of migrations to executed based on the given direction
  436. * and target version number.
  437. *
  438. * @param string $direction The direction we are migrating.
  439. * @param string $to The version to migrate to.
  440. * @return array $migrations The array of migrations we can execute.
  441. */
  442. public function getMigrationsToExecute($direction, $to)
  443. {
  444. if ($direction === 'down') {
  445. if (count($this->migrations)) {
  446. $allVersions = array_reverse(array_keys($this->migrations));
  447. $classes = array_reverse(array_values($this->migrations));
  448. $allVersions = array_combine($allVersions, $classes);
  449. } else {
  450. $allVersions = array();
  451. }
  452. } else {
  453. $allVersions = $this->migrations;
  454. }
  455. $versions = array();
  456. $migrated = $this->getMigratedVersions();
  457. foreach ($allVersions as $version) {
  458. if ($this->shouldExecuteMigration($direction, $version, $to, $migrated)) {
  459. $versions[$version->getVersion()] = $version;
  460. }
  461. }
  462. return $versions;
  463. }
  464. /**
  465. * Check if we should execute a migration for a given direction and target
  466. * migration version.
  467. *
  468. * @param string $direction The direction we are migrating.
  469. * @param Version $version The Version instance to check.
  470. * @param string $to The version we are migrating to.
  471. * @param array $migrated Migrated versions array.
  472. * @return void
  473. */
  474. private function shouldExecuteMigration($direction, Version $version, $to, $migrated)
  475. {
  476. if ($direction === 'down') {
  477. if ( ! in_array($version->getVersion(), $migrated)) {
  478. return false;
  479. }
  480. return $version->getVersion() > $to ? true : false;
  481. } else if ($direction === 'up') {
  482. if (in_array($version->getVersion(), $migrated)) {
  483. return false;
  484. }
  485. return $version->getVersion() <= $to ? true : false;
  486. }
  487. }
  488. }