diff --git a/src/CakeAdapter.php b/src/CakeAdapter.php index 25a9c5e0..9379515a 100644 --- a/src/CakeAdapter.php +++ b/src/CakeAdapter.php @@ -79,6 +79,17 @@ public function getConnection() return $this->adapter->getConnection(); } + /** + * Gets the database PDO connection object. + * + * @param \PDO $connection Connection + * @return AdapterInterface + */ + public function setConnection($connection) + { + return $this->adapter->setConnection($connection); + } + /** * Gets the CakePHP Connection object. * diff --git a/src/Command/Seed.php b/src/Command/Seed.php index 90360399..31f063ec 100644 --- a/src/Command/Seed.php +++ b/src/Command/Seed.php @@ -21,10 +21,10 @@ class Seed extends SeedRun { - use CommandTrait; - use ConfigurationTrait { + use CommandTrait { execute as parentExecute; } + use ConfigurationTrait; use EventDispatcherTrait; /** diff --git a/src/Migrations.php b/src/Migrations.php index 9c5f98ee..a37d1f16 100644 --- a/src/Migrations.php +++ b/src/Migrations.php @@ -14,6 +14,7 @@ use Cake\Datasource\ConnectionManager; use Phinx\Config\Config; use Phinx\Config\ConfigInterface; +use Phinx\Migration\Manager; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\NullOutput; @@ -288,11 +289,24 @@ protected function run($method, $params, $input) $seedPath = array_pop($seedPaths); } + if ($this->manager instanceof Manager) { + $pdo = $this->manager->getEnvironment('default') + ->getAdapter() + ->getConnection(); + } + $this->setInput($input); $newConfig = $this->getConfig(true); $manager = $this->getManager($newConfig); $manager->setInput($input); + + if (isset($pdo)) { + $this->manager->getEnvironment('default') + ->getAdapter() + ->setConnection($pdo); + } + $newMigrationPaths = $newConfig->getMigrationPaths(); if (isset($migrationPath) && array_pop($newMigrationPaths) !== $migrationPath) { $manager->resetMigrations(); diff --git a/src/Table.php b/src/Table.php index c7708be8..7eeccf10 100644 --- a/src/Table.php +++ b/src/Table.php @@ -98,10 +98,30 @@ public function create() */ public function update() { + if ($this->getAdapter()->getAdapterType() == 'sqlite') { + $this->foreignKeys = []; + } + parent::update(); TableRegistry::clear(); } + /** + * {@inheritDoc} + * + * We disable foreign key deletion for the SQLite adapter as SQLite does not support the feature natively and the + * process implemented by Phinx has serious side-effects (for instance it rename FK references in existing tables + * which breaks the database schema cohesion). + */ + public function dropForeignKey($columns, $constraint = null) + { + if ($this->getAdapter()->getAdapterType() == 'sqlite') { + return $this; + } + + return parent::dropForeignKey($columns, $constraint); + } + /** * This method is called in case a primary key was defined using the addPrimaryKey() method. * It currently does something only if using SQLite. diff --git a/tests/CommandTester.php b/tests/CommandTester.php new file mode 100644 index 00000000..6a7f2df8 --- /dev/null +++ b/tests/CommandTester.php @@ -0,0 +1,160 @@ +command = $command; + } + + /** + * Executes the command. + * + * Available execution options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * + * @param array $input An array of command arguments and options + * @param array $options An array of execution options + * + * @return int The command exit code + */ + public function execute(array $input, array $options = array()) + { + // set the command name automatically if the application requires + // this argument and no command name was passed + if (!isset($input['command']) + && (null !== $application = $this->command->getApplication()) + && $application->getDefinition()->hasArgument('command') + ) { + $input = array_merge(array('command' => $this->command->getName()), $input); + } + + $this->input = new ArrayInput($input); + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + } + + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + // This is where the magic does its magic : we use the output object of the command. + $this->output = $this->command->getManager()->getOutput(); + $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false); + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + + return $this->statusCode = $this->command->run($this->input, $this->output); + } + + /** + * Gets the display returned by the last execution of the command. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string The display + */ + public function getDisplay($normalize = false) + { + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the command. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } + + /** + * Gets the status code returned by the last execution of the application. + * + * @return int The status code + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * Sets the user inputs. + * + * @param array An array of strings representing each input + * passed to the command input stream. + * + * @return CommandTester + */ + public function setInputs(array $inputs) + { + $this->inputs = $inputs; + + return $this; + } + + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + fwrite($stream, implode(PHP_EOL, $inputs)); + rewind($stream); + + return $stream; + } +} diff --git a/tests/TestCase/Command/CreateTest.php b/tests/TestCase/Command/CreateTest.php index 0973db46..1bdfe155 100644 --- a/tests/TestCase/Command/CreateTest.php +++ b/tests/TestCase/Command/CreateTest.php @@ -119,7 +119,7 @@ protected function getCommandTester($params) $manager = new CakeManager($this->command->getConfig(), $input, $this->streamOutput); $manager->getEnvironment('default')->getAdapter()->setConnection($this->Connection->driver()->connection()); $this->command->setManager($manager); - $commandTester = new CommandTester($this->command); + $commandTester = new \Migrations\Test\CommandTester($this->command); return $commandTester; } diff --git a/tests/TestCase/Command/DumpTest.php b/tests/TestCase/Command/DumpTest.php index e6b3bfef..03971614 100644 --- a/tests/TestCase/Command/DumpTest.php +++ b/tests/TestCase/Command/DumpTest.php @@ -71,6 +71,7 @@ public function setUp() parent::setUp(); $this->Connection = ConnectionManager::get('test'); + $this->pdo = $this->Connection->driver()->connection(); $application = new MigrationsDispatcher('testing'); $this->command = $application->find('dump'); $this->streamOutput = new StreamOutput(fopen('php://memory', 'w', false)); @@ -85,6 +86,9 @@ public function setUp() public function tearDown() { parent::tearDown(); + $this->Connection->driver()->connection($this->pdo); + $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); + $this->Connection->execute('DROP TABLE IF EXISTS numbers'); unset($this->Connection, $this->command, $this->streamOutput); } @@ -159,16 +163,12 @@ public function testExecuteTables() */ protected function getCommandTester($params) { - if (!$this->Connection->driver()->isConnected()) { - $this->Connection->driver()->connect(); - } - $input = new ArrayInput($params, $this->command->getDefinition()); $this->command->setInput($input); $manager = new CakeManager($this->command->getConfig(), $input, $this->streamOutput); - $manager->getEnvironment('default')->getAdapter()->setConnection($this->Connection->driver()->connection()); + $manager->getEnvironment('default')->getAdapter()->setConnection($this->pdo); $this->command->setManager($manager); - $commandTester = new CommandTester($this->command); + $commandTester = new \Migrations\Test\CommandTester($this->command); return $commandTester; } @@ -190,7 +190,7 @@ protected function getMigrations() ->getManager($this->command->getConfig()) ->getEnvironment('default') ->getAdapter() - ->setConnection($this->Connection->driver()->connection()); + ->setConnection($this->pdo); $tables = (new Collection($this->Connection))->listTables(); if (in_array('phinxlog', $tables)) { diff --git a/tests/TestCase/Command/MarkMigratedTest.php b/tests/TestCase/Command/MarkMigratedTest.php index b626f187..ac844b5c 100644 --- a/tests/TestCase/Command/MarkMigratedTest.php +++ b/tests/TestCase/Command/MarkMigratedTest.php @@ -62,6 +62,7 @@ public function setUp() parent::setUp(); $this->Connection = ConnectionManager::get('test'); + $this->pdo = $this->Connection->driver()->connection(); $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); $this->Connection->execute('DROP TABLE IF EXISTS numbers'); @@ -78,6 +79,7 @@ public function setUp() public function tearDown() { parent::tearDown(); + $this->Connection->driver()->connection($this->pdo); $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); $this->Connection->execute('DROP TABLE IF EXISTS numbers'); unset($this->Connection, $this->commandTester, $this->command); @@ -113,7 +115,7 @@ public function testExecute() $this->assertEquals('20150704160200', $result[0]['version']); $this->assertEquals('20150724233100', $result[1]['version']); $this->assertEquals('20150826191400', $result[2]['version']); - + $this->commandTester->execute([ 'command' => $this->command->getName(), '--connection' => 'test', @@ -157,7 +159,7 @@ public function testExecute() $application = new MigrationsDispatcher('testing'); $buggyCommand = $application->find('mark_migrated'); $buggyCommand->setManager($manager); - $buggyCommandTester = new CommandTester($buggyCommand); + $buggyCommandTester = new \Migrations\Test\CommandTester($buggyCommand); $buggyCommandTester->execute([ 'command' => $this->command->getName(), '--connection' => 'test', diff --git a/tests/TestCase/Command/SeedTest.php b/tests/TestCase/Command/SeedTest.php index cfa0458e..f1795082 100644 --- a/tests/TestCase/Command/SeedTest.php +++ b/tests/TestCase/Command/SeedTest.php @@ -20,7 +20,6 @@ use Migrations\MigrationsDispatcher; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Tester\CommandTester; /** * SeedTest class @@ -67,6 +66,7 @@ public function setUp() parent::setUp(); $this->Connection = ConnectionManager::get('test'); + $this->pdo = $this->Connection->driver()->connection(); $application = new MigrationsDispatcher('testing'); $this->command = $application->find('seed'); $this->streamOutput = new StreamOutput(fopen('php://memory', 'w', false)); @@ -80,6 +80,9 @@ public function setUp() public function tearDown() { parent::tearDown(); + $this->Connection->driver()->connection($this->pdo); + $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); + $this->Connection->execute('DROP TABLE IF EXISTS numbers'); unset($this->Connection, $this->command, $this->streamOutput); } @@ -187,7 +190,7 @@ public function testExecuteWrongCustomParams() ]); $display = $this->getDisplayFromOutput(); - $this->assertEmpty($display); + $this->assertTextNotContains('seeded', $display); $migrations->rollback(['target' => 0]); } @@ -230,16 +233,12 @@ public function testExecuteSeedCallingOtherSeeders() */ protected function getCommandTester($params) { - if (!$this->Connection->driver()->isConnected()) { - $this->Connection->driver()->connect(); - } - $input = new ArrayInput($params, $this->command->getDefinition()); $this->command->setInput($input); $manager = new CakeManager($this->command->getConfig(), $input, $this->streamOutput); - $manager->getEnvironment('default')->getAdapter()->setConnection($this->Connection->driver()->connection()); + $manager->getEnvironment('default')->getAdapter()->setConnection($this->pdo); $this->command->setManager($manager); - $commandTester = new CommandTester($this->command); + $commandTester = new \Migrations\Test\CommandTester($this->command); return $commandTester; } @@ -261,22 +260,13 @@ protected function getMigrations() ->getManager($this->command->getConfig()) ->getEnvironment('default') ->getAdapter() - ->setConnection($this->Connection->driver()->connection()); - - $tables = (new Collection($this->Connection))->listTables(); - if (in_array('phinxlog', $tables)) { - $ormTable = TableRegistry::get('phinxlog', ['connection' => $this->Connection]); - $query = $this->Connection->driver()->schemaDialect()->truncateTableSql($ormTable->schema()); - foreach ($query as $stmt) { - $this->Connection->execute($stmt); - } - } + ->setConnection($this->pdo); return $migrations; } /** - * Extract the content that was stored in self::$streamOutput. + * Extract the content that was stored in self::$output. * * @return string */ diff --git a/tests/TestCase/Command/StatusTest.php b/tests/TestCase/Command/StatusTest.php index 3b571ba3..c9f33501 100644 --- a/tests/TestCase/Command/StatusTest.php +++ b/tests/TestCase/Command/StatusTest.php @@ -74,6 +74,7 @@ public function setUp() parent::setUp(); $this->Connection = ConnectionManager::get('test'); + $this->pdo = $this->Connection->driver()->connection(); $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); $this->Connection->execute('DROP TABLE IF EXISTS numbers'); @@ -90,6 +91,7 @@ public function setUp() public function tearDown() { parent::tearDown(); + $this->Connection->driver()->connection($this->pdo); $this->Connection->execute('DROP TABLE IF EXISTS phinxlog'); $this->Connection->execute('DROP TABLE IF EXISTS numbers'); unset($this->Connection, $this->command, $this->streamOutput); @@ -220,9 +222,9 @@ protected function getCommandTester($params) $input = new ArrayInput($params, $this->command->getDefinition()); $this->command->setInput($input); $manager = new CakeManager($this->command->getConfig(), $input, $this->streamOutput); - $manager->getEnvironment('default')->getAdapter()->setConnection($this->Connection->driver()->connection()); + $manager->getEnvironment('default')->getAdapter()->setConnection($this->pdo); $this->command->setManager($manager); - $commandTester = new CommandTester($this->command); + $commandTester = new \Migrations\Test\CommandTester($this->command); return $commandTester; } @@ -244,16 +246,7 @@ protected function getMigrations() ->getManager($this->command->getConfig()) ->getEnvironment('default') ->getAdapter() - ->setConnection($this->Connection->driver()->connection()); - - $tables = (new Collection($this->Connection))->listTables(); - if (in_array('phinxlog', $tables)) { - $ormTable = TableRegistry::get('phinxlog', ['connection' => $this->Connection]); - $query = $this->Connection->driver()->schemaDialect()->truncateTableSql($ormTable->schema()); - foreach ($query as $stmt) { - $this->Connection->execute($stmt); - } - } + ->setConnection($this->pdo); return $migrations; }