From da9474e9a63937a59f2c8c0f0b3d8ce065d381b6 Mon Sep 17 00:00:00 2001 From: AdrienPoupa Date: Tue, 8 Dec 2020 08:53:30 -0500 Subject: [PATCH 1/2] Add new shouldExecute method to prevent a migration or seed from being executed --- docs/en/migrations.rst | 8 ++ docs/en/seeding.rst | 8 ++ src/Phinx/Migration/AbstractMigration.php | 14 +++ src/Phinx/Migration/Manager.php | 94 +++++++++++++++---- src/Phinx/Migration/MigrationInterface.php | 11 +++ src/Phinx/Seed/AbstractSeed.php | 14 +++ src/Phinx/Seed/SeedInterface.php | 11 +++ tests/Phinx/Migration/ManagerTest.php | 42 +++++++++ .../_files/seeds/UserSeederNotExecuted.php | 29 ++++++ ...207205056_should_not_execute_migration.php | 17 ++++ ...0201207205057_should_execute_migration.php | 17 ++++ 11 files changed, 246 insertions(+), 19 deletions(-) create mode 100644 tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php create mode 100644 tests/Phinx/Migration/_files/should_execute/20201207205056_should_not_execute_migration.php create mode 100644 tests/Phinx/Migration/_files/should_execute/20201207205057_should_execute_migration.php diff --git a/docs/en/migrations.rst b/docs/en/migrations.rst index d2e2b7587..40e4a5807 100644 --- a/docs/en/migrations.rst +++ b/docs/en/migrations.rst @@ -158,6 +158,14 @@ The ``init()`` method is run by Phinx before the migration methods if it exists. This can be used for setting common class properties that are then used within the migration methods. +The Should Execute Method +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``shouldExecute()`` method is run by Phinx before executing the migration. +This can be used to prevent the migration from being executed at this time. It always +returns true by default. You can override it in your custom ``AbstractMigration`` +implementation. + Executing Queries ----------------- diff --git a/docs/en/seeding.rst b/docs/en/seeding.rst index 9569b9cc6..8ae28db1d 100644 --- a/docs/en/seeding.rst +++ b/docs/en/seeding.rst @@ -75,6 +75,14 @@ The Init Method The ``init()`` method is run by Phinx before the run method if it exists. This can be used to initialize properties of the Seed class before using run. +The Should Execute Method +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``shouldExecute()`` method is run by Phinx before executing the seed. +This can be used to prevent the seed from being executed at this time. It always +returns true by default. You can override it in your custom ``AbstractSeed`` +implementation. + Foreign Key Dependencies ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/Phinx/Migration/AbstractMigration.php b/src/Phinx/Migration/AbstractMigration.php index cf4798cab..1b968aabd 100644 --- a/src/Phinx/Migration/AbstractMigration.php +++ b/src/Phinx/Migration/AbstractMigration.php @@ -336,4 +336,18 @@ public function postFlightCheck() } } } + + /** + * Checks to see if the migration should be executed. + * + * Returns true by default. + * + * You can use this to prevent a migration from executing. + * + * @return bool + */ + public function shouldExecute() + { + return true; + } } diff --git a/src/Phinx/Migration/Manager.php b/src/Phinx/Migration/Manager.php index b74165204..5229ec3da 100644 --- a/src/Phinx/Migration/Manager.php +++ b/src/Phinx/Migration/Manager.php @@ -371,22 +371,25 @@ public function migrate($environment, $version = null, $fake = false) public function executeMigration($name, MigrationInterface $migration, $direction = MigrationInterface::UP, $fake = false) { $this->getOutput()->writeln(''); - $this->getOutput()->writeln( - ' ==' . - ' ' . $migration->getVersion() . ' ' . $migration->getName() . ':' . - ' ' . ($direction === MigrationInterface::UP ? 'migrating' : 'reverting') . '' - ); + + // Skip the migration if it should not be executed + if (!$migration->shouldExecute()) { + $this->printMigrationStatus($migration, 'skipped'); + + return; + } + + $this->printMigrationStatus($migration, ($direction === MigrationInterface::UP ? 'migrating' : 'reverting')); // Execute the migration and log the time elapsed. $start = microtime(true); $this->getEnvironment($name)->executeMigration($migration, $direction, $fake); $end = microtime(true); - $this->getOutput()->writeln( - ' ==' . - ' ' . $migration->getVersion() . ' ' . $migration->getName() . ':' . - ' ' . ($direction === MigrationInterface::UP ? 'migrated' : 'reverted') . - ' ' . sprintf('%.4fs', $end - $start) . '' + $this->printMigrationStatus( + $migration, + ($direction === MigrationInterface::UP ? 'migrated' : 'reverted'), + sprintf('%.4fs', $end - $start) ); } @@ -395,28 +398,81 @@ public function executeMigration($name, MigrationInterface $migration, $directio * * @param string $name Environment Name * @param \Phinx\Seed\SeedInterface $seed Seed - * * @return void */ public function executeSeed($name, SeedInterface $seed) { $this->getOutput()->writeln(''); - $this->getOutput()->writeln( - ' ==' . - ' ' . $seed->getName() . ':' . - ' seeding' - ); + + // Skip the seed if it should not be executed + if (!$seed->shouldExecute()) { + $this->printSeedStatus($seed, 'skipped'); + + return; + } + + $this->printSeedStatus($seed, 'seeding'); // Execute the seeder and log the time elapsed. $start = microtime(true); $this->getEnvironment($name)->executeSeed($seed); $end = microtime(true); + $this->printSeedStatus( + $seed, + 'seeded', + sprintf('%.4fs', $end - $start) + ); + } + + /** + * Print Migration Status + * + * @param \Phinx\Migration\MigrationInterface $migration Migration + * @param string $status Status of the migration + * @param string|null $duration Duration the migration took the be executed + * @return void + */ + protected function printMigrationStatus(MigrationInterface $migration, $status, $duration = null) + { + $this->printStatusOutput( + $migration->getVersion() . ' ' . $migration->getName(), + $status, + $duration + ); + } + + /** + * Print Seed Status + * + * @param \Phinx\Seed\SeedInterface $seed Seed + * @param string $status Status of the seed + * @param string|null $duration Duration the seed took the be executed + * @return void + */ + protected function printSeedStatus(SeedInterface $seed, $status, $duration = null) + { + $this->printStatusOutput( + $seed->getName(), + $status, + $duration + ); + } + + /** + * Print Status in Output + * + * @param string $name Name of the migration or seed + * @param string $status Status of the migration or seed + * @param string|null $duration Duration the migration or seed took the be executed + * @return void + */ + protected function printStatusOutput($name, $status, $duration = null) + { $this->getOutput()->writeln( ' ==' . - ' ' . $seed->getName() . ':' . - ' seeded' . - ' ' . sprintf('%.4fs', $end - $start) . '' + ' ' . $name . ':' . + ' ' . $status . ' ' . $duration . '' ); } diff --git a/src/Phinx/Migration/MigrationInterface.php b/src/Phinx/Migration/MigrationInterface.php index 69f8cd3be..90cdfdca0 100644 --- a/src/Phinx/Migration/MigrationInterface.php +++ b/src/Phinx/Migration/MigrationInterface.php @@ -265,4 +265,15 @@ public function preFlightCheck(); * @return void */ public function postFlightCheck(); + + /** + * Checks to see if the migration should be executed. + * + * Returns true by default. + * + * You can use this to prevent a migration from executing. + * + * @return bool + */ + public function shouldExecute(); } diff --git a/src/Phinx/Seed/AbstractSeed.php b/src/Phinx/Seed/AbstractSeed.php index ee259f4c0..f9ed25737 100644 --- a/src/Phinx/Seed/AbstractSeed.php +++ b/src/Phinx/Seed/AbstractSeed.php @@ -184,4 +184,18 @@ public function table($tableName, $options = []) { return new Table($tableName, $options, $this->getAdapter()); } + + /** + * Checks to see if the seed should be executed. + * + * Returns true by default. + * + * You can use this to prevent a seed from executing. + * + * @return bool + */ + public function shouldExecute() + { + return true; + } } diff --git a/src/Phinx/Seed/SeedInterface.php b/src/Phinx/Seed/SeedInterface.php index 1d3ba89f6..95ddf8944 100644 --- a/src/Phinx/Seed/SeedInterface.php +++ b/src/Phinx/Seed/SeedInterface.php @@ -161,4 +161,15 @@ public function hasTable($tableName); * @return \Phinx\Db\Table */ public function table($tableName, $options); + + /** + * Checks to see if the seed should be executed. + * + * Returns true by default. + * + * You can use this to prevent a seed from executing. + * + * @return bool + */ + public function shouldExecute(); } diff --git a/tests/Phinx/Migration/ManagerTest.php b/tests/Phinx/Migration/ManagerTest.php index e2a3c5426..6b5c36a34 100644 --- a/tests/Phinx/Migration/ManagerTest.php +++ b/tests/Phinx/Migration/ManagerTest.php @@ -5460,6 +5460,19 @@ public function testOrderSeeds() $this->assertInstanceOf('PostSeeder', $seeds[2]); } + public function testSeedWillNotBeExecuted() + { + // stub environment + $envStub = $this->getMockBuilder('\Phinx\Migration\Manager\Environment') + ->setConstructorArgs(['mockenv', []]) + ->getMock(); + $this->manager->setEnvironments(['mockenv' => $envStub]); + $this->manager->seed('mockenv', 'UserSeederNotExecuted'); + rewind($this->manager->getOutput()->getStream()); + $output = stream_get_contents($this->manager->getOutput()->getStream()); + $this->assertStringContainsString('skipped', $output); + } + public function testGettingInputObject() { $migrations = $this->manager->getMigrations('mockenv'); @@ -6067,6 +6080,35 @@ public function testInvalidVersionBreakpoint() $outputStr = stream_get_contents($this->manager->getOutput()->getStream()); $this->assertEquals("warning 20120133235330 is not a valid version", trim($outputStr)); } + + public function testMigrationWillNotBeExecuted() + { + if (!defined('MYSQL_DB_CONFIG')) { + $this->markTestSkipped('Mysql tests disabled.'); + } + $configArray = $this->getConfigArray(); + $adapter = $this->manager->getEnvironment('production')->getAdapter(); + + // override the migrations directory to use the should execute migrations + $configArray['paths']['migrations'] = $this->getCorrectedPath(__DIR__ . '/_files/should_execute'); + $config = new Config($configArray); + + // ensure the database is empty + $adapter->dropDatabase(MYSQL_DB_CONFIG['name']); + $adapter->createDatabase(MYSQL_DB_CONFIG['name']); + $adapter->disconnect(); + + // Run the migration with shouldExecute returning false: the table should not be created + $this->manager->setConfig($config); + $this->manager->migrate('production', '20201207205056'); + + $this->assertFalse($adapter->hasTable('info')); + + // Run the migration with shouldExecute returning true: the table should be created + $this->manager->migrate('production', '20201207205057'); + + $this->assertTrue($adapter->hasTable('info')); + } } /** diff --git a/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php b/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php new file mode 100644 index 000000000..1bb65c543 --- /dev/null +++ b/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php @@ -0,0 +1,29 @@ + 'foo', + 'created' => date('Y-m-d H:i:s'), + ], + [ + 'name' => 'bar', + 'created' => date('Y-m-d H:i:s'), + ], + ]; + + $users = $this->table('users'); + $users->insert($data) + ->save(); + } + + public function shouldExecute() + { + return false; + } +} diff --git a/tests/Phinx/Migration/_files/should_execute/20201207205056_should_not_execute_migration.php b/tests/Phinx/Migration/_files/should_execute/20201207205056_should_not_execute_migration.php new file mode 100644 index 000000000..46cd76564 --- /dev/null +++ b/tests/Phinx/Migration/_files/should_execute/20201207205056_should_not_execute_migration.php @@ -0,0 +1,17 @@ +table('info')->create(); + } + + public function shouldExecute() + { + return false; + } +} diff --git a/tests/Phinx/Migration/_files/should_execute/20201207205057_should_execute_migration.php b/tests/Phinx/Migration/_files/should_execute/20201207205057_should_execute_migration.php new file mode 100644 index 000000000..cf118136e --- /dev/null +++ b/tests/Phinx/Migration/_files/should_execute/20201207205057_should_execute_migration.php @@ -0,0 +1,17 @@ +table('info')->create(); + } + + public function shouldExecute() + { + return true; + } +} From 71f1eff6390cb3231c14331910f325c6d45bf573 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 8 Dec 2020 14:03:49 +0000 Subject: [PATCH 2/2] Fixing style errors. --- tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php | 1 + .../20201207205056_should_not_execute_migration.php | 1 + .../should_execute/20201207205057_should_execute_migration.php | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php b/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php index 1bb65c543..c0d0da050 100644 --- a/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php +++ b/tests/Phinx/Migration/_files/seeds/UserSeederNotExecuted.php @@ -1,4 +1,5 @@