From 63168482e11b6f26682d450ce13b2e583f4daa07 Mon Sep 17 00:00:00 2001 From: David Simon Date: Wed, 26 Nov 2014 10:21:49 -0500 Subject: [PATCH 1/4] Loading sqlite fixtures into mysql --- Command/LoadFixtureCommand.php | 6 ++++ Fixture/CachedSqliteFixture.php | 50 +++++++++++++++++++++++++++++++-- composer.json | 3 +- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Command/LoadFixtureCommand.php b/Command/LoadFixtureCommand.php index 25c1238..8b3e471 100644 --- a/Command/LoadFixtureCommand.php +++ b/Command/LoadFixtureCommand.php @@ -23,6 +23,12 @@ protected function execute(InputInterface $input, OutputInterface $output) { $container = $this->getApplication()->getKernel()->getContainer(); + if ($container->get('kernel')->getEnvironment() == 'prod') { + throw new \RuntimeException( + "You may not load fixture data into a production environment" + ); + } + $cls = $input->getArgument('fixtureClass'); if (is_null($cls)) { $cls = $container->getParameter('ac_web_services.default_fixture_class'); diff --git a/Fixture/CachedSqliteFixture.php b/Fixture/CachedSqliteFixture.php index ff663c4..2564e95 100644 --- a/Fixture/CachedSqliteFixture.php +++ b/Fixture/CachedSqliteFixture.php @@ -5,6 +5,8 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\PDOConnection; use Doctrine\DBAL\Driver\PDOSqlite\Driver as SqliteDriver; +use Doctrine\DBAL\Driver\PDOMySql\Driver as MySqlDriver; +use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\SqliteSchemaManager; use Doctrine\DBAL\Migrations\Version; @@ -12,6 +14,7 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo; use \Mockery as m; +use \Functional as F; abstract class CachedSqliteFixture extends CachedFixture { @@ -24,8 +27,18 @@ final protected function loadImpl($container) { $mainEM = $container->get('doctrine')->getManager(); $conn = $mainEM->getConnection(); - if (!$conn->getDatabasePlatform() instanceof SqlitePlatform) { - throw new \RuntimeException("Cannot load sqlite fixture into non-sqlite database"); + $platform = $conn->getDatabasePlatform(); + if ($platform instanceof MySqlPlatform) { + print "\nAbout to overwrite MySQL database! If you're sure, type \"yes\":\n"; + $line = fgets(STDIN); + if ($line == "yes\n") { + return $this->overwriteMysqlData($mainEM); + } else { + print "Fixture load cancelled.\n"; + return; + } + } elseif (!($platform instanceof SqlitePlatform)) { + throw new \RuntimeException("Cannot load fixture into this SQL database type"); } if (!is_dir(".tmp")) { @@ -50,6 +63,39 @@ final protected function getFixtureObjectManager() return $this->templateEM; } + private function overwriteMysqlData($mainEM) + { + $fileMigs = F\map($this->migrationCodeFiles(), function($filename) { + if (preg_match("#Version(\d+).php$#", $filename, $matches)) { + return $matches[1]; + } else { + throw new \RuntimeException("Invalid migration file $filename"); + } + }); + + $conn = $mainEM->getConnection(); + $dbMigs = F\pluck($conn->fetchAll("SELECT * FROM migration_versions"), 'version'); + sort($dbMigs); + + if ($fileMigs !== $dbMigs) { + throw new \RuntimeException("MySQL database needs to be migrated first"); + } + + $conn->query('SET FOREIGN_KEY_CHECKS=0'); + $tables = F\map($conn->fetchAll("SHOW TABLES"), function ($row) { + return F\first($row); + }); + foreach ($tables as $tableName) { + if ($tableName == 'migration_versions') { continue; } + $conn->executeUpdate($conn->getDatabasePlatform()->getTruncateTableSql($tableName)); + } + $conn->query('SET FOREIGN_KEY_CHECKS=1'); + + $this->templateEM = $mainEM; + $this->execFixture(); + $this->templateEM = null; + } + private function setupSchemaTemplate() { $schemaSource = ""; diff --git a/composer.json b/composer.json index 5dc0b69..f01e07a 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "jms/serializer": "~0.15.0", "willdurand/negotiation": "~1.2", "mockery/mockery": "~0.9", - "fzaninotto/faker": "~1.3" + "fzaninotto/faker": "~1.3", + "lstrojny/functional-php": "*" }, "require-dev": { "symfony/symfony": "~2.2", From 214db2f03391bc7bc8d85c8a20a77df560d96e90 Mon Sep 17 00:00:00 2001 From: David Simon Date: Wed, 26 Nov 2014 10:33:52 -0500 Subject: [PATCH 2/4] Minor fixes to TestCase::callApi --- TestCase.php | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/TestCase.php b/TestCase.php index 4d066e0..4566be1 100644 --- a/TestCase.php +++ b/TestCase.php @@ -101,31 +101,36 @@ protected function callApi($method, $uri, $options = []) $client->request($method, $uri, $params, $files, $server, $content, $changeHist); $response = $client->getResponse(); - if (!isset($options['expectedCode'])) { + if (!array_key_exists('expectedCode', $options)) { $options['expectedCode'] = 200; } if (!is_null($options['expectedCode'])) { if ($response->getStatusCode() != $options['expectedCode']) { $msg = "Expected status code " . $options['expectedCode'] . - ", got " . $response->getStatusCode(); + ", got " . $response->getStatusCode() . ".\n"; if ($response->headers->get('Content-Type') == "application/json") { - $msg .= ". JSON content of invalid response:\n"; $content = json_decode($response->getContent(), true); - - # Clean up the stack trace if there is one - if (isset($content['exception']) && isset($content['exception']['trace'])) { - $content['exception']['trace'] = - $this->cleanTrace($content['exception']['trace']); - } - - $result = var_export($content, true); - if (strlen($result) > 20*1024) { - $result = substr($result, 0, 20*1024); - $result .= "\n.......\n......."; + if (is_null($content)) { + $msg .= "Response content (unparseable JSON):\n$result"; + } else { + $msg .= "JSON content of invalid response:\n"; + # Clean up the stack trace if there is one + if (isset($content['exception']) && isset($content['exception']['trace'])) { + $content['exception']['trace'] = + $this->cleanTrace($content['exception']['trace']); + } + + $result = var_export($content, true); + if (strlen($result) > 20*1024) { + $result = substr($result, 0, 20*1024); + $result .= "\n.......\n......."; + } + $msg .= "$result\n"; } - $msg .= "$result\n"; + } else { + $msg .= "Response content (first 16K):\n" . substr($result, 0, 1024*16); } - $this->fail($msg); + $this->fail(trim($msg)); } } From ca2d34599fe0b54f695688b5f396c738f9f68710 Mon Sep 17 00:00:00 2001 From: David Simon Date: Wed, 26 Nov 2014 10:56:53 -0500 Subject: [PATCH 3/4] Notify bishop about travis activity --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5af8940..3854bb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ -#generally copied from https://github.com/nelmio/NelmioApiDocBundle/blob/master/.travis.yml +notifications: + webhooks: http://ac-dev-bishop.herokuapp.com/bishop/travisci/general + on_start: true language: php From 49f6ab38dc6105e40724315421f37b0e894d1de6 Mon Sep 17 00:00:00 2001 From: David Simon Date: Wed, 26 Nov 2014 10:58:43 -0500 Subject: [PATCH 4/4] Fixed functional-php dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f01e07a..2709f30 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "willdurand/negotiation": "~1.2", "mockery/mockery": "~0.9", "fzaninotto/faker": "~1.3", - "lstrojny/functional-php": "*" + "lstrojny/functional-php": "*@dev" }, "require-dev": { "symfony/symfony": "~2.2",