PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

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