PageRenderTime 52ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php

https://gitlab.com/techniconline/kmc
PHP | 400 lines | 153 code | 66 blank | 181 comment | 10 complexity | e77c80e5f68ae3810edb13118b26cffc MD5 | raw file
  1. <?php namespace Illuminate\Database\Migrations;
  2. use Illuminate\Filesystem\Filesystem;
  3. use Illuminate\Database\ConnectionResolverInterface as Resolver;
  4. class Migrator
  5. {
  6. /**
  7. * The migration repository implementation.
  8. *
  9. * @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
  10. */
  11. protected $repository;
  12. /**
  13. * The filesystem instance.
  14. *
  15. * @var \Illuminate\Filesystem\Filesystem
  16. */
  17. protected $files;
  18. /**
  19. * The connection resolver instance.
  20. *
  21. * @var \Illuminate\Database\ConnectionResolverInterface
  22. */
  23. protected $resolver;
  24. /**
  25. * The name of the default connection.
  26. *
  27. * @var string
  28. */
  29. protected $connection;
  30. /**
  31. * The notes for the current operation.
  32. *
  33. * @var array
  34. */
  35. protected $notes = array();
  36. /**
  37. * Create a new migrator instance.
  38. *
  39. * @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
  40. * @param \Illuminate\Database\ConnectionResolverInterface $resolver
  41. * @param \Illuminate\Filesystem\Filesystem $files
  42. * @return void
  43. */
  44. public function __construct(MigrationRepositoryInterface $repository,
  45. Resolver $resolver,
  46. Filesystem $files)
  47. {
  48. $this->files = $files;
  49. $this->resolver = $resolver;
  50. $this->repository = $repository;
  51. }
  52. /**
  53. * Run the outstanding migrations at a given path.
  54. *
  55. * @param string $path
  56. * @param bool $pretend
  57. * @return void
  58. */
  59. public function run($path, $pretend = false)
  60. {
  61. $this->notes = array();
  62. $files = $this->getMigrationFiles($path);
  63. // Once we grab all of the migration files for the path, we will compare them
  64. // against the migrations that have already been run for this package then
  65. // run each of the outstanding migrations against a database connection.
  66. $ran = $this->repository->getRan();
  67. $migrations = array_diff($files, $ran);
  68. $this->requireFiles($path, $migrations);
  69. $this->runMigrationList($migrations, $pretend);
  70. }
  71. /**
  72. * Run an array of migrations.
  73. *
  74. * @param array $migrations
  75. * @param bool $pretend
  76. * @return void
  77. */
  78. public function runMigrationList($migrations, $pretend = false)
  79. {
  80. // First we will just make sure that there are any migrations to run. If there
  81. // aren't, we will just make a note of it to the developer so they're aware
  82. // that all of the migrations have been run against this database system.
  83. if (count($migrations) == 0) {
  84. $this->note('<info>Nothing to migrate.</info>');
  85. return;
  86. }
  87. $batch = $this->repository->getNextBatchNumber();
  88. // Once we have the array of migrations, we will spin through them and run the
  89. // migrations "up" so the changes are made to the databases. We'll then log
  90. // that the migration was run so we don't repeat it next time we execute.
  91. foreach ($migrations as $file) {
  92. $this->runUp($file, $batch, $pretend);
  93. }
  94. }
  95. /**
  96. * Run "up" a migration instance.
  97. *
  98. * @param string $file
  99. * @param int $batch
  100. * @param bool $pretend
  101. * @return void
  102. */
  103. protected function runUp($file, $batch, $pretend)
  104. {
  105. // First we will resolve a "real" instance of the migration class from this
  106. // migration file name. Once we have the instances we can run the actual
  107. // command such as "up" or "down", or we can just simulate the action.
  108. $migration = $this->resolve($file);
  109. if ($pretend) {
  110. return $this->pretendToRun($migration, 'up');
  111. }
  112. $migration->up();
  113. // Once we have run a migrations class, we will log that it was run in this
  114. // repository so that we don't try to run it next time we do a migration
  115. // in the application. A migration repository keeps the migrate order.
  116. $this->repository->log($file, $batch);
  117. $this->note("<info>Migrated:</info> $file");
  118. }
  119. /**
  120. * Rollback the last migration operation.
  121. *
  122. * @param bool $pretend
  123. * @return int
  124. */
  125. public function rollback($pretend = false)
  126. {
  127. $this->notes = array();
  128. // We want to pull in the last batch of migrations that ran on the previous
  129. // migration operation. We'll then reverse those migrations and run each
  130. // of them "down" to reverse the last migration "operation" which ran.
  131. $migrations = $this->repository->getLast();
  132. if (count($migrations) == 0) {
  133. $this->note('<info>Nothing to rollback.</info>');
  134. return count($migrations);
  135. }
  136. // We need to reverse these migrations so that they are "downed" in reverse
  137. // to what they run on "up". It lets us backtrack through the migrations
  138. // and properly reverse the entire database schema operation that ran.
  139. foreach ($migrations as $migration) {
  140. $this->runDown((object)$migration, $pretend);
  141. }
  142. return count($migrations);
  143. }
  144. /**
  145. * Rolls all of the currently applied migrations back.
  146. *
  147. * @param bool $pretend
  148. * @return int
  149. */
  150. public function reset($pretend = false)
  151. {
  152. $this->notes = [];
  153. $migrations = array_reverse($this->repository->getRan());
  154. if (count($migrations) == 0) {
  155. $this->note('<info>Nothing to rollback.</info>');
  156. return count($migrations);
  157. }
  158. foreach ($migrations as $migration) {
  159. $this->runDown((object)['migration' => $migration], $pretend);
  160. }
  161. return count($migrations);
  162. }
  163. /**
  164. * Run "down" a migration instance.
  165. *
  166. * @param object $migration
  167. * @param bool $pretend
  168. * @return void
  169. */
  170. protected function runDown($migration, $pretend)
  171. {
  172. $file = $migration->migration;
  173. // First we will get the file name of the migration so we can resolve out an
  174. // instance of the migration. Once we get an instance we can either run a
  175. // pretend execution of the migration or we can run the real migration.
  176. $instance = $this->resolve($file);
  177. if ($pretend) {
  178. return $this->pretendToRun($instance, 'down');
  179. }
  180. $instance->down();
  181. // Once we have successfully run the migration "down" we will remove it from
  182. // the migration repository so it will be considered to have not been run
  183. // by the application then will be able to fire by any later operation.
  184. $this->repository->delete($migration);
  185. $this->note("<info>Rolled back:</info> $file");
  186. }
  187. /**
  188. * Get all of the migration files in a given path.
  189. *
  190. * @param string $path
  191. * @return array
  192. */
  193. public function getMigrationFiles($path)
  194. {
  195. $files = $this->files->glob($path . '/*_*.php');
  196. // Once we have the array of files in the directory we will just remove the
  197. // extension and take the basename of the file which is all we need when
  198. // finding the migrations that haven't been run against the databases.
  199. if ($files === false) return array();
  200. $files = array_map(function ($file) {
  201. return str_replace('.php', '', basename($file));
  202. }, $files);
  203. // Once we have all of the formatted file names we will sort them and since
  204. // they all start with a timestamp this should give us the migrations in
  205. // the order they were actually created by the application developers.
  206. sort($files);
  207. return $files;
  208. }
  209. /**
  210. * Require in all the migration files in a given path.
  211. *
  212. * @param string $path
  213. * @param array $files
  214. * @return void
  215. */
  216. public function requireFiles($path, array $files)
  217. {
  218. foreach ($files as $file) $this->files->requireOnce($path . '/' . $file . '.php');
  219. }
  220. /**
  221. * Pretend to run the migrations.
  222. *
  223. * @param object $migration
  224. * @param string $method
  225. * @return void
  226. */
  227. protected function pretendToRun($migration, $method)
  228. {
  229. foreach ($this->getQueries($migration, $method) as $query) {
  230. $name = get_class($migration);
  231. $this->note("<info>{$name}:</info> {$query['query']}");
  232. }
  233. }
  234. /**
  235. * Get all of the queries that would be run for a migration.
  236. *
  237. * @param object $migration
  238. * @param string $method
  239. * @return array
  240. */
  241. protected function getQueries($migration, $method)
  242. {
  243. $connection = $migration->getConnection();
  244. // Now that we have the connections we can resolve it and pretend to run the
  245. // queries against the database returning the array of raw SQL statements
  246. // that would get fired against the database system for this migration.
  247. $db = $this->resolveConnection($connection);
  248. return $db->pretend(function () use ($migration, $method) {
  249. $migration->$method();
  250. });
  251. }
  252. /**
  253. * Resolve a migration instance from a file.
  254. *
  255. * @param string $file
  256. * @return object
  257. */
  258. public function resolve($file)
  259. {
  260. $file = implode('_', array_slice(explode('_', $file), 4));
  261. $class = studly_case($file);
  262. return new $class;
  263. }
  264. /**
  265. * Raise a note event for the migrator.
  266. *
  267. * @param string $message
  268. * @return void
  269. */
  270. protected function note($message)
  271. {
  272. $this->notes[] = $message;
  273. }
  274. /**
  275. * Get the notes for the last operation.
  276. *
  277. * @return array
  278. */
  279. public function getNotes()
  280. {
  281. return $this->notes;
  282. }
  283. /**
  284. * Resolve the database connection instance.
  285. *
  286. * @param string $connection
  287. * @return \Illuminate\Database\Connection
  288. */
  289. public function resolveConnection($connection)
  290. {
  291. return $this->resolver->connection($connection);
  292. }
  293. /**
  294. * Set the default connection name.
  295. *
  296. * @param string $name
  297. * @return void
  298. */
  299. public function setConnection($name)
  300. {
  301. if (!is_null($name)) {
  302. $this->resolver->setDefaultConnection($name);
  303. }
  304. $this->repository->setSource($name);
  305. $this->connection = $name;
  306. }
  307. /**
  308. * Get the migration repository instance.
  309. *
  310. * @return \Illuminate\Database\Migrations\MigrationRepositoryInterface
  311. */
  312. public function getRepository()
  313. {
  314. return $this->repository;
  315. }
  316. /**
  317. * Determine if the migration repository exists.
  318. *
  319. * @return bool
  320. */
  321. public function repositoryExists()
  322. {
  323. return $this->repository->repositoryExists();
  324. }
  325. /**
  326. * Get the file system instance.
  327. *
  328. * @return \Illuminate\Filesystem\Filesystem
  329. */
  330. public function getFilesystem()
  331. {
  332. return $this->files;
  333. }
  334. }