PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/vendor/doctrine-migrations/lib/Doctrine/DBAL/Migrations/Version.php

https://github.com/Cesarh/symfony-sandbox
PHP | 326 lines | 169 code | 48 blank | 109 comment | 15 complexity | 1d6d415cbacd4f4bb57f2c5fd8dd1c1d MD5 | raw file
  1. <?php
  2. /*
  3. * $Id$
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information, see
  19. * <http://www.doctrine-project.org>.
  20. */
  21. namespace Doctrine\DBAL\Migrations;
  22. use Doctrine\DBAL\Migrations\Configuration\Configuration,
  23. Doctrine\DBAL\Schema\Schema;
  24. /**
  25. * Class which wraps a migration version and allows execution of the
  26. * individual migration version up or down method.
  27. *
  28. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  29. * @link www.doctrine-project.org
  30. * @since 2.0
  31. * @version $Revision$
  32. * @author Jonathan H. Wage <jonwage@gmail.com>
  33. */
  34. class Version
  35. {
  36. const STATE_NONE = 0;
  37. const STATE_PRE = 1;
  38. const STATE_EXEC = 2;
  39. const STATE_POST = 3;
  40. /**
  41. * The Migrations Configuration instance for this migration
  42. *
  43. * @var Configuration
  44. */
  45. private $_configuration;
  46. /**
  47. * The OutputWriter object instance used for outputting information
  48. *
  49. * @var OutputWriter
  50. */
  51. private $_outputWriter;
  52. /**
  53. * The version in timestamp format (YYYYMMDDHHMMSS)
  54. *
  55. * @param int
  56. */
  57. private $_version;
  58. /**
  59. * @var AbstractSchemaManager
  60. */
  61. private $_sm;
  62. /**
  63. * @var AbstractPlatform
  64. */
  65. private $_platform;
  66. /**
  67. * The migration instance for this version
  68. *
  69. * @var AbstractMigration
  70. */
  71. private $_migration;
  72. /**
  73. * @var Connection
  74. */
  75. private $_connection;
  76. /**
  77. * @var string
  78. */
  79. private $_class;
  80. /** The array of collected SQL statements for this version */
  81. private $_sql = array();
  82. /** The time in seconds that this migration version took to execute */
  83. private $_time;
  84. /**
  85. * @var int
  86. */
  87. private $_state = self::STATE_NONE;
  88. public function __construct(Configuration $configuration, $version, $class)
  89. {
  90. $this->_configuration = $configuration;
  91. $this->_outputWriter = $configuration->getOutputWriter();
  92. $this->_version = $version;
  93. $this->_class = $class;
  94. $this->_connection = $configuration->getConnection();
  95. $this->_sm = $this->_connection->getSchemaManager();
  96. $this->_platform = $this->_connection->getDatabasePlatform();
  97. $this->_migration = new $class($this);
  98. }
  99. /**
  100. * Returns the string version in the format YYYYMMDDHHMMSS
  101. *
  102. * @return string $version
  103. */
  104. public function getVersion()
  105. {
  106. return $this->_version;
  107. }
  108. /**
  109. * Returns the Migrations Configuration object instance
  110. *
  111. * @return Configuration $configuration
  112. */
  113. public function getConfiguration()
  114. {
  115. return $this->_configuration;
  116. }
  117. /**
  118. * Check if this version has been migrated or not.
  119. *
  120. * @param bool $bool
  121. * @return mixed
  122. */
  123. public function isMigrated()
  124. {
  125. return $this->_configuration->hasVersionMigrated($this);
  126. }
  127. public function markMigrated()
  128. {
  129. $this->_configuration->createMigrationTable();
  130. $this->_connection->executeQuery("INSERT INTO " . $this->_configuration->getMigrationsTableName() . " (version) VALUES (?)", array($this->_version));
  131. }
  132. public function markNotMigrated()
  133. {
  134. $this->_configuration->createMigrationTable();
  135. $this->_connection->executeQuery("DELETE FROM " . $this->_configuration->getMigrationsTableName() . " WHERE version = '$this->_version'");
  136. }
  137. /**
  138. * Add some SQL queries to this versions migration
  139. *
  140. * @param mixed $sql
  141. * @return void
  142. */
  143. public function addSql($sql)
  144. {
  145. if (is_array($sql)) {
  146. foreach ($sql as $query) {
  147. $this->_sql[] = $query;
  148. }
  149. } else {
  150. $this->_sql[] = $sql;
  151. }
  152. }
  153. /**
  154. * Write a migration SQL file to the given path
  155. *
  156. * @param string $path The path to write the migration SQL file.
  157. * @param string $direction The direction to execute.
  158. * @return bool $written
  159. */
  160. public function writeSqlFile($path, $direction = 'up')
  161. {
  162. $queries = $this->execute($direction, true);
  163. $string = sprintf("# Doctrine Migration File Generated on %s\n", date('Y-m-d H:m:s'));
  164. $string .= "\n# Version " . $this->_version . "\n";
  165. foreach ($queries as $query) {
  166. $string .= $query . ";\n";
  167. }
  168. if (is_dir($path)) {
  169. $path = realpath($path);
  170. $path = $path . '/doctrine_migration_' . date('YmdHis') . '.sql';
  171. }
  172. $this->_outputWriter->write("\n".sprintf('Writing migration file to "<info>%s</info>"', $path));
  173. return file_put_contents($path, $string);
  174. }
  175. /**
  176. * Execute this migration version up or down and and return the SQL.
  177. *
  178. * @param string $direction The direction to execute the migration.
  179. * @param string $dryRun Whether to not actually execute the migration SQL and just do a dry run.
  180. * @return array $sql
  181. * @throws Exception when migration fails
  182. */
  183. public function execute($direction, $dryRun = false)
  184. {
  185. $this->_sql = array();
  186. $this->_connection->beginTransaction();
  187. try {
  188. $start = microtime(true);
  189. $this->_state = self::STATE_PRE;
  190. $fromSchema = $this->_sm->createSchema();
  191. $this->_migration->{'pre' . ucfirst($direction)}($fromSchema);
  192. if ($direction === 'up') {
  193. $this->_outputWriter->write("\n" . sprintf(' <info>++</info> migrating <comment>%s</comment>', $this->_version) . "\n");
  194. } else {
  195. $this->_outputWriter->write("\n" . sprintf(' <info>--</info> reverting <comment>%s</comment>', $this->_version) . "\n");
  196. }
  197. $this->_state = self::STATE_EXEC;
  198. $toSchema = clone $fromSchema;
  199. $this->_migration->$direction($toSchema);
  200. $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->_platform));
  201. if ($dryRun === false) {
  202. if ($this->_sql) {
  203. $count = count($this->_sql);
  204. foreach ($this->_sql as $query) {
  205. $this->_outputWriter->write(' <comment>-></comment> ' . $query);
  206. $this->_connection->executeQuery($query);
  207. }
  208. } else {
  209. $this->_outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->_version));
  210. }
  211. if ($direction === 'up') {
  212. $this->markMigrated();
  213. } else {
  214. $this->markNotMigrated();
  215. }
  216. } else {
  217. foreach ($this->_sql as $query) {
  218. $this->_outputWriter->write(' <comment>-></comment> ' . $query);
  219. }
  220. }
  221. $this->_state = self::STATE_POST;
  222. $this->_migration->{'post' . ucfirst($direction)}($toSchema);
  223. $end = microtime(true);
  224. $this->_time = round($end - $start, 2);
  225. if ($direction === 'up') {
  226. $this->_outputWriter->write(sprintf("\n <info>++</info> migrated (%ss)", $this->_time));
  227. } else {
  228. $this->_outputWriter->write(sprintf("\n <info>--</info> reverted (%ss)", $this->_time));
  229. }
  230. $this->_connection->commit();
  231. return $this->_sql;
  232. } catch(SkipMigrationException $e) {
  233. $this->_connection->rollback();
  234. // now mark it as migrated
  235. if ($direction === 'up') {
  236. $this->markMigrated();
  237. } else {
  238. $this->markNotMigrated();
  239. }
  240. $this->_outputWriter->write(sprintf("\n <info>SS</info> skipped (Reason: %s)", $e->getMessage()));
  241. } catch (\Exception $e) {
  242. $this->_outputWriter->write(sprintf(
  243. '<error>Migration %s failed during %s. Error %s</error>',
  244. $this->_version, $this->getExecutionState(), $e->getMessage()
  245. ));
  246. $this->_connection->rollback();
  247. $this->_state = self::STATE_NONE;
  248. throw $e;
  249. }
  250. $this->_state = self::STATE_NONE;
  251. }
  252. public function getExecutionState()
  253. {
  254. switch($this->_state) {
  255. case self::STATE_PRE:
  256. return 'Pre-Checks';
  257. case self::STATE_POST:
  258. return 'Post-Checks';
  259. case self::STATE_EXEC:
  260. return 'Execution';
  261. default:
  262. return 'No State';
  263. }
  264. }
  265. /**
  266. * Returns the time this migration version took to execute
  267. *
  268. * @return integer $time The time this migration version took to execute
  269. */
  270. public function getTime()
  271. {
  272. return $this->_time;
  273. }
  274. public function __toString()
  275. {
  276. return $this->_version;
  277. }
  278. }