files = $files; $this->repository = $repository; $this->schemaBuilder = $connection->getSchemaBuilder(); // Workaround for https://github.com/laravel/framework/issues/1186 $connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); } /** * Run the outstanding migrations at a given path. * * @param string $path * @param Extension $extension * @return void */ public function run($path, Extension $extension = null) { $files = $this->getMigrationFiles($path); $ran = $this->repository->getRan($extension ? $extension->getId() : null); $migrations = array_diff($files, $ran); $this->runMigrationList($path, $migrations, $extension); } /** * Run an array of migrations. * * @param string $path * @param array $migrations * @param Extension $extension * @return void */ public function runMigrationList($path, $migrations, Extension $extension = null) { // First we will just make sure that there are any migrations to run. If there // aren't, we will just make a note of it to the developer so they're aware // that all of the migrations have been run against this database system. if (count($migrations) == 0) { $this->note('Nothing to migrate.'); return; } // Once we have the array of migrations, we will spin through them and run the // migrations "up" so the changes are made to the databases. We'll then log // that the migration was run so we don't repeat it next time we execute. foreach ($migrations as $file) { $this->runUp($path, $file, $extension); } } /** * Run "up" a migration instance. * * @param string $path * @param string $file * @param string $path * @param Extension $extension * @return void */ protected function runUp($path, $file, Extension $extension = null) { $migration = $this->resolve($path, $file); $this->runClosureMigration($migration); // Once we have run a migrations class, we will log that it was run in this // repository so that we don't try to run it next time we do a migration // in the application. A migration repository keeps the migrate order. $this->repository->log($file, $extension ? $extension->getId() : null); $this->note("Migrated: $file"); } /** * Rolls all of the currently applied migrations back. * * @param string $path * @param Extension $extension * @return int */ public function reset($path, Extension $extension = null) { $migrations = array_reverse($this->repository->getRan( $extension ? $extension->getId() : null )); $count = count($migrations); if ($count === 0) { $this->note('Nothing to rollback.'); } else { foreach ($migrations as $migration) { $this->runDown($path, $migration, $extension); } } return $count; } /** * Run "down" a migration instance. * * @param string $path * @param string $file * @param string $path * @param Extension $extension * @return void */ protected function runDown($path, $file, Extension $extension = null) { $migration = $this->resolve($path, $file); $this->runClosureMigration($migration, 'down'); // Once we have successfully run the migration "down" we will remove it from // the migration repository so it will be considered to have not been run // by the application then will be able to fire by any later operation. $this->repository->delete($file, $extension ? $extension->getId() : null); $this->note("Rolled back: $file"); } /** * Runs a closure migration based on the migrate direction. * * @param $migration * @param string $direction * @throws Exception */ protected function runClosureMigration($migration, $direction = 'up') { if (is_array($migration) && array_key_exists($direction, $migration)) { call_user_func($migration[$direction], $this->schemaBuilder); } else { throw new Exception('Migration file should contain an array with up/down.'); } } /** * Get all of the migration files in a given path. * * @param string $path * @return array */ public function getMigrationFiles($path) { $files = $this->files->glob($path.'/*_*.php'); if ($files === false) { return []; } $files = array_map(function ($file) { return str_replace('.php', '', basename($file)); }, $files); // Once we have all of the formatted file names we will sort them and since // they all start with a timestamp this should give us the migrations in // the order they were actually created by the application developers. sort($files); return $files; } /** * Resolve a migration instance from a file. * * @param string $path * @param string $file * @return array */ public function resolve($path, $file) { $migration = "$path/$file.php"; if ($this->files->exists($migration)) { return $this->files->getRequire($migration); } } /** * Set the output implementation that should be used by the console. * * @param OutputInterface $output * @return $this */ public function setOutput(OutputInterface $output) { $this->output = $output; return $this; } /** * Write a note to the conosle's output. * * @param string $message * @return void */ protected function note($message) { if ($this->output) { $this->output->writeln($message); } } /** * Get the migration repository instance. * * @return MigrationRepositoryInterface */ public function getRepository() { return $this->repository; } /** * Determine if the migration repository exists. * * @return bool */ public function repositoryExists() { return $this->repository->repositoryExists(); } /** * Get the file system instance. * * @return \Illuminate\Filesystem\Filesystem */ public function getFilesystem() { return $this->files; } }