Skip to content

Commit

Permalink
Fix the builds
Browse files Browse the repository at this point in the history
For SQLite, we disable some of the foreign key management feature as some of them are not secure and break the database schema cohesion (see the #321 thread for more details)
  • Loading branch information
HavokInspiration committed Jul 29, 2017
1 parent 5607ce9 commit 12fc74e
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 43 deletions.
11 changes: 11 additions & 0 deletions src/CakeAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
4 changes: 2 additions & 2 deletions src/Command/Seed.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
class Seed extends SeedRun
{

use CommandTrait;
use ConfigurationTrait {
use CommandTrait {
execute as parentExecute;
}
use ConfigurationTrait;
use EventDispatcherTrait;

/**
Expand Down
14 changes: 14 additions & 0 deletions src/Migrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
20 changes: 20 additions & 0 deletions src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
160 changes: 160 additions & 0 deletions tests/CommandTester.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php
/**
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/

namespace Migrations\Test;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Complete override of the Symfony class needed to have a charged instance of the output object used in the tests.
* The output object used should be the one of the command.
*/
class CommandTester
{
private $command;
private $input;
private $output;
private $inputs = array();
private $statusCode;

/**
* Constructor.
*
* @param Command $command A Command instance to test
*/
public function __construct(Command $command)
{
$this->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;
}
}
2 changes: 1 addition & 1 deletion tests/TestCase/Command/CreateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 7 additions & 7 deletions tests/TestCase/Command/DumpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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)) {
Expand Down
6 changes: 4 additions & 2 deletions tests/TestCase/Command/MarkMigratedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand All @@ -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);
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
Loading

0 comments on commit 12fc74e

Please sign in to comment.