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

/Streaming-Safe-for-Kids/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php

https://gitlab.com/rocs/Streaming-Safe-for-Kids
PHP | 527 lines | 220 code | 84 blank | 223 comment | 13 complexity | f89bf3869a0b796f7ab1ee9300878382 MD5 | raw file
  1. <?php
  2. namespace Illuminate\Database\Migrations;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Support\Str;
  5. use Illuminate\Support\Collection;
  6. use Illuminate\Filesystem\Filesystem;
  7. use Illuminate\Database\ConnectionResolverInterface as Resolver;
  8. class Migrator
  9. {
  10. /**
  11. * The migration repository implementation.
  12. *
  13. * @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
  14. */
  15. protected $repository;
  16. /**
  17. * The filesystem instance.
  18. *
  19. * @var \Illuminate\Filesystem\Filesystem
  20. */
  21. protected $files;
  22. /**
  23. * The connection resolver instance.
  24. *
  25. * @var \Illuminate\Database\ConnectionResolverInterface
  26. */
  27. protected $resolver;
  28. /**
  29. * The name of the default connection.
  30. *
  31. * @var string
  32. */
  33. protected $connection;
  34. /**
  35. * The notes for the current operation.
  36. *
  37. * @var array
  38. */
  39. protected $notes = [];
  40. /**
  41. * The paths to all of the migration files.
  42. *
  43. * @var array
  44. */
  45. protected $paths = [];
  46. /**
  47. * Create a new migrator instance.
  48. *
  49. * @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
  50. * @param \Illuminate\Database\ConnectionResolverInterface $resolver
  51. * @param \Illuminate\Filesystem\Filesystem $files
  52. * @return void
  53. */
  54. public function __construct(MigrationRepositoryInterface $repository,
  55. Resolver $resolver,
  56. Filesystem $files)
  57. {
  58. $this->files = $files;
  59. $this->resolver = $resolver;
  60. $this->repository = $repository;
  61. }
  62. /**
  63. * Run the outstanding migrations at a given path.
  64. *
  65. * @param array|string $paths
  66. * @param array $options
  67. * @return array
  68. */
  69. public function run($paths = [], array $options = [])
  70. {
  71. $this->notes = [];
  72. $files = $this->getMigrationFiles($paths);
  73. // Once we grab all of the migration files for the path, we will compare them
  74. // against the migrations that have already been run for this package then
  75. // run each of the outstanding migrations against a database connection.
  76. $ran = $this->repository->getRan();
  77. $migrations = Collection::make($files)
  78. ->reject(function ($file) use ($ran) {
  79. return in_array($this->getMigrationName($file), $ran);
  80. })->values()->all();
  81. $this->requireFiles($migrations);
  82. $this->runMigrationList($migrations, $options);
  83. return $migrations;
  84. }
  85. /**
  86. * Run an array of migrations.
  87. *
  88. * @param array $migrations
  89. * @param array $options
  90. * @return void
  91. */
  92. public function runMigrationList($migrations, array $options = [])
  93. {
  94. // First we will just make sure that there are any migrations to run. If there
  95. // aren't, we will just make a note of it to the developer so they're aware
  96. // that all of the migrations have been run against this database system.
  97. if (count($migrations) == 0) {
  98. $this->note('<info>Nothing to migrate.</info>');
  99. return;
  100. }
  101. $batch = $this->repository->getNextBatchNumber();
  102. $pretend = Arr::get($options, 'pretend', false);
  103. $step = Arr::get($options, 'step', false);
  104. // Once we have the array of migrations, we will spin through them and run the
  105. // migrations "up" so the changes are made to the databases. We'll then log
  106. // that the migration was run so we don't repeat it next time we execute.
  107. foreach ($migrations as $file) {
  108. $this->runUp($file, $batch, $pretend);
  109. // If we are stepping through the migrations, then we will increment the
  110. // batch value for each individual migration that is run. That way we
  111. // can run "artisan migrate:rollback" and undo them one at a time.
  112. if ($step) {
  113. $batch++;
  114. }
  115. }
  116. }
  117. /**
  118. * Run "up" a migration instance.
  119. *
  120. * @param string $file
  121. * @param int $batch
  122. * @param bool $pretend
  123. * @return void
  124. */
  125. protected function runUp($file, $batch, $pretend)
  126. {
  127. $file = $this->getMigrationName($file);
  128. // First we will resolve a "real" instance of the migration class from this
  129. // migration file name. Once we have the instances we can run the actual
  130. // command such as "up" or "down", or we can just simulate the action.
  131. $migration = $this->resolve($file);
  132. if ($pretend) {
  133. return $this->pretendToRun($migration, 'up');
  134. }
  135. $this->runMigration($migration, 'up');
  136. // Once we have run a migrations class, we will log that it was run in this
  137. // repository so that we don't try to run it next time we do a migration
  138. // in the application. A migration repository keeps the migrate order.
  139. $this->repository->log($file, $batch);
  140. $this->note("<info>Migrated:</info> {$file}");
  141. }
  142. /**
  143. * Rollback the last migration operation.
  144. *
  145. * @param array|string $paths
  146. * @param array $options
  147. * @return array
  148. */
  149. public function rollback($paths = [], array $options = [])
  150. {
  151. $this->notes = [];
  152. $rolledBack = [];
  153. // We want to pull in the last batch of migrations that ran on the previous
  154. // migration operation. We'll then reverse those migrations and run each
  155. // of them "down" to reverse the last migration "operation" which ran.
  156. if (($steps = Arr::get($options, 'step', 0)) > 0) {
  157. $migrations = $this->repository->getMigrations($steps);
  158. } else {
  159. $migrations = $this->repository->getLast();
  160. }
  161. $count = count($migrations);
  162. $files = $this->getMigrationFiles($paths);
  163. if ($count === 0) {
  164. $this->note('<info>Nothing to rollback.</info>');
  165. } else {
  166. // Next we will run through all of the migrations and call the "down" method
  167. // which will reverse each migration in order. This getLast method on the
  168. // repository already returns these migration's names in reverse order.
  169. $this->requireFiles($files);
  170. foreach ($migrations as $migration) {
  171. $migration = (object) $migration;
  172. $rolledBack[] = $files[$migration->migration];
  173. $this->runDown(
  174. $files[$migration->migration],
  175. $migration, Arr::get($options, 'pretend', false)
  176. );
  177. }
  178. }
  179. return $rolledBack;
  180. }
  181. /**
  182. * Rolls all of the currently applied migrations back.
  183. *
  184. * @param array|string $paths
  185. * @param bool $pretend
  186. * @return array
  187. */
  188. public function reset($paths = [], $pretend = false)
  189. {
  190. $this->notes = [];
  191. $rolledBack = [];
  192. $files = $this->getMigrationFiles($paths);
  193. // Next, we will reverse the migration list so we can run them back in the
  194. // correct order for resetting this database. This will allow us to get
  195. // the database back into its "empty" state ready for the migrations.
  196. $migrations = array_reverse($this->repository->getRan());
  197. $count = count($migrations);
  198. if ($count === 0) {
  199. $this->note('<info>Nothing to rollback.</info>');
  200. } else {
  201. $this->requireFiles($files);
  202. // Next we will run through all of the migrations and call the "down" method
  203. // which will reverse each migration in order. This will get the database
  204. // back to its original "empty" state and will be ready for migrations.
  205. foreach ($migrations as $migration) {
  206. $rolledBack[] = $files[$migration];
  207. $this->runDown($files[$migration], (object) ['migration' => $migration], $pretend);
  208. }
  209. }
  210. return $rolledBack;
  211. }
  212. /**
  213. * Run "down" a migration instance.
  214. *
  215. * @param string $file
  216. * @param object $migration
  217. * @param bool $pretend
  218. * @return void
  219. */
  220. protected function runDown($file, $migration, $pretend)
  221. {
  222. $file = $this->getMigrationName($file);
  223. // First we will get the file name of the migration so we can resolve out an
  224. // instance of the migration. Once we get an instance we can either run a
  225. // pretend execution of the migration or we can run the real migration.
  226. $instance = $this->resolve($file);
  227. if ($pretend) {
  228. return $this->pretendToRun($instance, 'down');
  229. }
  230. $this->runMigration($instance, 'down');
  231. // Once we have successfully run the migration "down" we will remove it from
  232. // the migration repository so it will be considered to have not been run
  233. // by the application then will be able to fire by any later operation.
  234. $this->repository->delete($migration);
  235. $this->note("<info>Rolled back:</info> {$file}");
  236. }
  237. /**
  238. * Get all of the migration files in a given path.
  239. *
  240. * @param string|array $paths
  241. * @return array
  242. */
  243. public function getMigrationFiles($paths)
  244. {
  245. return Collection::make($paths)->flatMap(function ($path) {
  246. return $this->files->glob($path.'/*_*.php');
  247. })->filter()->sortBy(function ($file) {
  248. return $this->getMigrationName($file);
  249. })->values()->keyBy(function ($file) {
  250. return $this->getMigrationName($file);
  251. })->all();
  252. }
  253. /**
  254. * Require in all the migration files in a given path.
  255. *
  256. * @param array $files
  257. * @return void
  258. */
  259. public function requireFiles(array $files)
  260. {
  261. foreach ($files as $file) {
  262. $this->files->requireOnce($file);
  263. }
  264. }
  265. /**
  266. * Pretend to run the migrations.
  267. *
  268. * @param object $migration
  269. * @param string $method
  270. * @return void
  271. */
  272. protected function pretendToRun($migration, $method)
  273. {
  274. foreach ($this->getQueries($migration, $method) as $query) {
  275. $name = get_class($migration);
  276. $this->note("<info>{$name}:</info> {$query['query']}");
  277. }
  278. }
  279. /**
  280. * Get all of the queries that would be run for a migration.
  281. *
  282. * @param object $migration
  283. * @param string $method
  284. * @return array
  285. */
  286. protected function getQueries($migration, $method)
  287. {
  288. $connection = $migration->getConnection();
  289. // Now that we have the connections we can resolve it and pretend to run the
  290. // queries against the database returning the array of raw SQL statements
  291. // that would get fired against the database system for this migration.
  292. $db = $this->resolveConnection($connection);
  293. return $db->pretend(function () use ($migration, $method) {
  294. $migration->$method();
  295. });
  296. }
  297. /**
  298. * Run a migration inside a transaction if the database supports it.
  299. *
  300. * @param object $migration
  301. * @param string $method
  302. * @return void
  303. */
  304. protected function runMigration($migration, $method)
  305. {
  306. $name = $migration->getConnection();
  307. $connection = $this->resolveConnection($name);
  308. $callback = function () use ($migration, $method) {
  309. $migration->$method();
  310. };
  311. $grammar = $this->getSchemaGrammar($connection);
  312. $grammar->supportsSchemaTransactions()
  313. ? $connection->transaction($callback)
  314. : $callback();
  315. }
  316. /**
  317. * Get the schema grammar out of a migration connection.
  318. *
  319. * @param \Illuminate\Database\Connection $connection
  320. * @return \Illuminate\Database\Schema\Grammars\Grammar
  321. */
  322. protected function getSchemaGrammar($connection)
  323. {
  324. if (is_null($grammar = $connection->getSchemaGrammar())) {
  325. $connection->useDefaultSchemaGrammar();
  326. $grammar = $connection->getSchemaGrammar();
  327. }
  328. return $grammar;
  329. }
  330. /**
  331. * Resolve a migration instance from a file.
  332. *
  333. * @param string $file
  334. * @return object
  335. */
  336. public function resolve($file)
  337. {
  338. $class = Str::studly(implode('_', array_slice(explode('_', $file), 4)));
  339. return new $class;
  340. }
  341. /**
  342. * Get the name of the migration.
  343. *
  344. * @param string $path
  345. * @return string
  346. */
  347. public function getMigrationName($path)
  348. {
  349. return str_replace('.php', '', basename($path));
  350. }
  351. /**
  352. * Raise a note event for the migrator.
  353. *
  354. * @param string $message
  355. * @return void
  356. */
  357. protected function note($message)
  358. {
  359. $this->notes[] = $message;
  360. }
  361. /**
  362. * Get the notes for the last operation.
  363. *
  364. * @return array
  365. */
  366. public function getNotes()
  367. {
  368. return $this->notes;
  369. }
  370. /**
  371. * Resolve the database connection instance.
  372. *
  373. * @param string $connection
  374. * @return \Illuminate\Database\Connection
  375. */
  376. public function resolveConnection($connection)
  377. {
  378. return $this->resolver->connection($connection);
  379. }
  380. /**
  381. * Register a custom migration path.
  382. *
  383. * These path will not automatically be applied.
  384. *
  385. * @param string $path
  386. * @return void
  387. */
  388. public function path($path)
  389. {
  390. $this->paths[] = $path;
  391. $this->paths = array_unique($this->paths);
  392. }
  393. /**
  394. * Get all of the custom migration paths.
  395. *
  396. * @return array
  397. */
  398. public function paths()
  399. {
  400. return $this->paths;
  401. }
  402. /**
  403. * Set the default connection name.
  404. *
  405. * @param string $name
  406. * @return void
  407. */
  408. public function setConnection($name)
  409. {
  410. if (! is_null($name)) {
  411. $this->resolver->setDefaultConnection($name);
  412. }
  413. $this->repository->setSource($name);
  414. $this->connection = $name;
  415. }
  416. /**
  417. * Get the migration repository instance.
  418. *
  419. * @return \Illuminate\Database\Migrations\MigrationRepositoryInterface
  420. */
  421. public function getRepository()
  422. {
  423. return $this->repository;
  424. }
  425. /**
  426. * Determine if the migration repository exists.
  427. *
  428. * @return bool
  429. */
  430. public function repositoryExists()
  431. {
  432. return $this->repository->repositoryExists();
  433. }
  434. /**
  435. * Get the file system instance.
  436. *
  437. * @return \Illuminate\Filesystem\Filesystem
  438. */
  439. public function getFilesystem()
  440. {
  441. return $this->files;
  442. }
  443. }