Beispiel #1
0
 public function handle(InputInterface $input, OutputInterface $output)
 {
     $registry = BaseOrm::getRegistry();
     $loader = new Loader();
     $issues = $loader->detectConflicts();
     if (!empty($issues)) {
         $message = 'The following migrations seem to indicate they are both the latest migration :' . PHP_EOL;
         $message .= ' %s ' . PHP_EOL;
         $output->writeln(sprintf($message, Tools::stringify($issues)));
         return;
     }
     if ($input->getOption('no-interaction')) {
         $asker = NonInteractiveAsker::createObject($input, $output);
     } else {
         $asker = InteractiveAsker::createObject($input, $output);
     }
     $autodetector = new AutoDetector($loader->getProjectState(), ProjectState::fromApps($registry), $asker);
     $changes = $autodetector->getChanges($loader->graph);
     if (empty($changes)) {
         $output->writeln('No changes were detected');
         return;
     }
     if ($input->getOption('dry-run')) {
         $output->writeln('<info>Migrations :</info>');
         /** @var $migration Migration */
         foreach ($changes as $migration) {
             $output->writeln('  -- ' . $migration->getName());
         }
         return;
     }
     $this->_writeMigrations($changes, $input, $output);
 }
Beispiel #2
0
 /**
  * Does the actual alteration of the model table.
  *
  * @param SchemaEditor $schemaEditor
  * @param ProjectState $fromState
  * @param ProjectState $toState
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 private function _alterModelTable($schemaEditor, $fromState, $toState)
 {
     $toModel = $toState->getRegistry()->getModel($this->name);
     if ($this->allowMigrateModel($schemaEditor->connection, $toModel)) {
         $fromModel = $fromState->getRegistry()->getModel($this->name);
         $schemaEditor->alterDbTable($toModel, $fromModel->meta->dbTable, $toModel->meta->dbTable);
         // Rename M2M fields whose name is based on this model's db_table
         /** @var $newField ManyToManyField */
         /* @var $oldField ManyToManyField */
         foreach ($toModel->meta->localManyToMany as $newName => $newField) {
             foreach ($fromModel->meta->localManyToMany as $oldName => $oldField) {
                 if ($newName === $oldName) {
                     $schemaEditor->alterDbTable($newField->relation->through, $oldField->relation->through->meta->dbTable, $newField->relation->through->meta->dbTable);
                 }
             }
         }
     }
 }
Beispiel #3
0
 public function handle(InputInterface $input, OutputInterface $output)
 {
     $name = $input->getArgument('migration_name');
     if ($input->getOption('fake')) {
         $fake = true;
     } else {
         $fake = false;
     }
     $connection = BaseOrm::getDbConnection();
     $registry = BaseOrm::getRegistry();
     $executor = Executor::createObject($connection);
     // target migrations to act on
     if (!empty($name)) {
         if ($name == 'zero') {
             $targets = [$name];
         } else {
             $targets = $executor->loader->getMigrationByPrefix($name);
         }
     } else {
         $targets = $executor->loader->graph->getLeafNodes();
     }
     // get migration plan
     $plan = $executor->getMigrationPlan($targets);
     BaseOrm::signalDispatch('powerorm.migration.pre_migrate', $this);
     $output->writeln('<comment>Running migrations:</comment>');
     if (empty($plan)) {
         $output->writeln('  No migrations to apply.');
         if ($input->getOption('no-interaction')) {
             $asker = NonInteractiveAsker::createObject($input, $output);
         } else {
             $asker = InteractiveAsker::createObject($input, $output);
         }
         //detect if we need to make migrations
         $auto_detector = new AutoDetector($executor->loader->getProjectState(), ProjectState::fromApps($registry), $asker);
         $changes = $auto_detector->getChanges($executor->loader->graph);
         if (!empty($changes)) {
             $output->writeln('<warning>  Your models have changes that are not yet reflected ' . "in a migration, and so won't be applied.</warning>");
             $output->writeln("<warning>  Run 'php pmanager.php makemigrations' to make new " . "migrations, and then re-run 'php pmanager.php migrate' to apply them.</warning>");
         }
     } else {
         // migrate
         $executor->migrate($targets, $plan, $fake);
     }
     BaseOrm::signalDispatch('powerorm.migration.post_migrate', $this);
 }
Beispiel #4
0
 /**
  * Takes a ProjectState and returns a new one with the migration's operations applied to it.
  *
  * Preserves the original object state by default and will return a mutated state from a copy.
  *
  * @param ProjectState $state
  * @param bool|true    $preserveState
  *
  * @return mixed
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public function updateState($state, $preserveState = true)
 {
     $newState = $state;
     if ($preserveState) {
         $newState = $state->deepClone();
     }
     /** @var $operation Operation */
     foreach ($this->operations as $operation) {
         $operation->updateState($newState);
     }
     return $newState;
 }
Beispiel #5
0
 /**
  * Create ProjectState based on migrations on disk.
  *
  * @return ProjectState
  *
  * @throws NodeNotFoundError
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public function getState()
 {
     $leaves = $this->getLeafNodes();
     $state = ProjectState::createObject();
     if (empty($leaves)) {
         return $state;
     }
     // from the leave go up its family tree though its parents and ancestors until we get to the root_node.
     // this way we get the full lineage we need to follow to get to this leaf from root_node to leaf_node
     // we use this lineage to apply migrations in database
     $lineage = [];
     foreach ($leaves as $leaf) {
         // get lineage
         $lineage_members = $this->getAncestryTree($leaf);
         foreach ($lineage_members as $i => $l_member) {
             if (in_array($l_member, $lineage)) {
                 continue;
             }
             $lineage[] = $l_member;
         }
     }
     // use the lineage to update the project state based on the migrations.
     /* @var $migration Migration */
     foreach ($lineage as $member) {
         $migration = $this->nodes[$member];
         $state = $migration->updateState($state);
     }
     return $state;
 }
Beispiel #6
0
 /**
  * Migrates the database up to the given targets.
  *
  * @param $targets
  * @param $plan
  * @param $fake
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public function migrate($targets, $plan, $fake)
 {
     if (empty($plan)) {
         $plan = $this->getMigrationPlan($targets);
     }
     $migrationsToRun = $this->getMigrationsFromPlan($plan);
     // the full plan that would be executed if we to run on a new database
     $fullPlan = $this->getMigrationsFromPlan($this->getMigrationPlan($this->loader->graph->getLeafNodes(), true));
     // Holds all states right before a migration is applied
     // if the migration is being run.
     $states = [];
     $state = ProjectState::createObject();
     //Phase 1 -- create all project states before a migration is (un)applied
     /** @var $migration Migration */
     foreach ($fullPlan as $migName => $migration) {
         // we use the migration to mutate state
         // after we mutate we remove the migration from the $migrationsToRun list.
         // so if we get to a point where we dont have any more $migrationsToRun break
         // this is to avoid any further mutations by other migrations not in the list.
         if (empty($migrationsToRun)) {
             break;
         }
         $run = ArrayHelper::hasKey($migrationsToRun, $migName);
         if ($run) {
             $states[$migName] = $state->deepClone();
             unset($migrationsToRun[$migName]);
         }
         // $run will be false if the migration is not in the $migrationsToRun list
         // so there is not need to preserve state else if its in the list we need to  we will get a new state object
         // that has been altered by the migration.
         // we do this because we need the object stored in the states array in the condition it was right before
         // the migration was applied.
         // remember in PHP objects are passed by reference.
         $state = $migration->updateState($state, $run);
     }
     // Phase 2 -- Run the migrations
     foreach ($plan as $mName => $migrationMeta) {
         if ($migrationMeta['unapply']) {
             $this->unApplyMigration($states[$mName], $migrationMeta['migration'], $fake);
         } else {
             $this->applyMigration($states[$mName], $migrationMeta['migration'], $fake);
         }
     }
 }
Beispiel #7
0
 /**
  * Does the actual field alteration.
  *
  * @param SchemaEditor $schemaEditor
  * @param ProjectState $fromState
  * @param ProjectState $toState
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 private function _alterField($schemaEditor, $fromState, $toState)
 {
     $toModel = $toState->getRegistry()->getModel($this->modelName);
     if ($this->allowMigrateModel($schemaEditor->connection, $toModel)) {
         $fromModel = $fromState->getRegistry()->getModel($this->modelName);
         $fromField = $fromModel->meta->getField($this->name);
         $toField = $toModel->meta->getField($this->name);
         if (false === $this->preserveDefault) {
             $toField->default = $this->field->default;
         }
         $schemaEditor->alterField($fromModel, $fromField, $toField);
         if (false === $this->preserveDefault) {
             $toField->default = NOT_PROVIDED;
         }
     }
 }