From b51636ed62b64856a4bbff5c1710c5b08d9e8860 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 17:24:38 +0900 Subject: [PATCH 1/6] NamedPdoModule support replication --- src/NamedPdoModule.php | 58 ++++++++++++++++++++--- tests/Fake/FakeNamedReplicationModule.php | 18 +++++++ tests/NamedPdoModuleTest.php | 20 ++++++++ 3 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 tests/Fake/FakeNamedReplicationModule.php diff --git a/src/NamedPdoModule.php b/src/NamedPdoModule.php index 14fc988..73e394b 100644 --- a/src/NamedPdoModule.php +++ b/src/NamedPdoModule.php @@ -2,12 +2,15 @@ namespace Ray\AuraSqlModule; +use Aura\Sql\ConnectionLocator; use Aura\Sql\ExtendedPdo; use Aura\Sql\ExtendedPdoInterface; use Ray\Di\AbstractModule; class NamedPdoModule extends AbstractModule { + const PARSE_PDO_DSN_REGEX = '/(.*?)\:(host|server)=.*?;(.*)/i'; + /** * @var string */ @@ -26,20 +29,25 @@ class NamedPdoModule extends AbstractModule /** * @var string */ - private $pass; + private $password; + /** + * @var string + */ + private $slave; /** * @param string $qualifer * @param string $dsn * @param string $user * @param string $pass */ - public function __construct($qualifer, $dsn, $user = '', $pass = '') + public function __construct($qualifer, $dsn, $user = '', $pass = '', $slave = '') { $this->qualifer = $qualifer; $this->dsn = $dsn; $this->user = $user; - $this->pass = $pass; + $this->password = $pass; + $this->slave = $slave; parent::__construct(); } @@ -48,10 +56,11 @@ public function __construct($qualifer, $dsn, $user = '', $pass = '') */ protected function configure() { - $this->bindNamedPdo($this->qualifer, $this->dsn, $this->user, $this->pass); + $this->slave ? $this->configureMasterSlaveDsn($this->qualifer, $this->dsn, $this->user, $this->password, $this->slave) + : $this->configureSingleDsn($this->qualifer, $this->dsn, $this->user, $this->password); } - private function bindNamedPdo($qualifer, $dsn, $user, $pass) + private function configureSingleDsn($qualifer, $dsn, $user, $password) { $this->bind(ExtendedPdoInterface::class) ->annotatedWith($qualifer) @@ -61,6 +70,43 @@ private function bindNamedPdo($qualifer, $dsn, $user, $pass) ); $this->bind()->annotatedWith("{$qualifer}_dsn")->toInstance($dsn); $this->bind()->annotatedWith("{$qualifer}_username")->toInstance($user); - $this->bind()->annotatedWith("{$qualifer}_password")->toInstance($pass); + $this->bind()->annotatedWith("{$qualifer}_password")->toInstance($password); + } + + private function configureMasterSlaveDsn($qualifer, $dsn, $user, $password, $slaveList) + { + $locator = new ConnectionLocator(); + $locator->setWrite('master', new Connection($dsn, $user, $password)); + $i = 1; + $slaves = explode(',', $slaveList); + foreach ($slaves as $slave) { + $slaveDsn = $this->changeHost($dsn, $slave); + $name = 'slave' . (string) $i++; + $locator->setRead($name, new Connection($slaveDsn, $user, $password)); + } + $this->install(new AuraSqlReplicationModule($locator, $qualifer)); + } + + /** + * @param string $dsn + * @param string $host + * + * @return string + */ + private function changeHost($dsn, $host) + { + preg_match(self::PARSE_PDO_DSN_REGEX, $dsn, $parts); + if (empty($parts)) { + return $dsn; + } +// [ +// 0 => 'mysql:host=localhost;port=3307;dbname=testdb', +// 1 => 'mysql', +// 2 => 'host', +// 3 => 'port=3307;dbname=testdb' +// ] + $dsn = sprintf('%s:%s=%s;%s', $parts[1], $parts[2], $host, $parts[3]); + + return $dsn; } } diff --git a/tests/Fake/FakeNamedReplicationModule.php b/tests/Fake/FakeNamedReplicationModule.php new file mode 100644 index 0000000..8afe5d4 --- /dev/null +++ b/tests/Fake/FakeNamedReplicationModule.php @@ -0,0 +1,18 @@ +install(new NamedPdoModule('log_db', 'mysql:host=localhost;dbname=db', $user, $password, $slave)); + } +} diff --git a/tests/NamedPdoModuleTest.php b/tests/NamedPdoModuleTest.php index ad54f7d..9d925ef 100644 --- a/tests/NamedPdoModuleTest.php +++ b/tests/NamedPdoModuleTest.php @@ -23,4 +23,24 @@ public function testFakeName() $this->assertInstanceOf(ExtendedPdo::class, $fakeName->pdoAnno); $this->assertInstanceOf(ExtendedPdo::class, $fakeName->pdoSetterInject); } + + public function testReplicationMaster() + { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $qualifer = 'log_db'; + $instance = (new Injector(new FakeNamedReplicationModule, $_ENV['TMP_DIR']))->getInstance(ExtendedPdoInterface::class, $qualifer); + $this->assertInstanceOf(ExtendedPdo::class, $instance); + /* @var $instance ExtendedPdo */ + $this->assertSame('mysql:host=localhost;dbname=db', $instance->getDsn()); + } + + public function testReplicationSlave() + { + $_SERVER['REQUEST_METHOD'] = 'GET'; + $qualifer = 'log_db'; + $instance = (new Injector(new FakeNamedReplicationModule, $_ENV['TMP_DIR']))->getInstance(ExtendedPdoInterface::class, $qualifer); + $this->assertInstanceOf(ExtendedPdo::class, $instance); + /* @var $instance ExtendedPdo */ + $this->assertContains('mysql:host=slave', $instance->getDsn()); + } } From ffb7dd3eeb2abb6d5e3423fcf86fbf0c68ab26f2 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 17:29:53 +0900 Subject: [PATCH 2/6] fix phpcs --- src/Pagerfanta/AuraSqlQueryPager.php | 1 + src/TransactionalInterceptor.php | 1 + tests/AuraSqlReplicationModuleTest.php | 4 ++++ tests/Pagerfanta/AuraSqlQueryAdapterTest.php | 1 + 4 files changed, 7 insertions(+) diff --git a/src/Pagerfanta/AuraSqlQueryPager.php b/src/Pagerfanta/AuraSqlQueryPager.php index 312492a..5b8cbeb 100644 --- a/src/Pagerfanta/AuraSqlQueryPager.php +++ b/src/Pagerfanta/AuraSqlQueryPager.php @@ -83,6 +83,7 @@ public function offsetGet($page) foreach (array_keys($select->getCols()) as $key) { $select->removeCol($key); } + return $select->cols(['COUNT(*) AS total_results'])->limit(1); }; $pagerfanta = new Pagerfanta(new AuraSqlQueryAdapter($this->pdo, $this->select, $countQueryBuilderModifier)); diff --git a/src/TransactionalInterceptor.php b/src/TransactionalInterceptor.php index a1a167f..df07d1f 100644 --- a/src/TransactionalInterceptor.php +++ b/src/TransactionalInterceptor.php @@ -46,6 +46,7 @@ public function invoke(MethodInvocation $invocation) * @param string $prop the name of pdo property * * @return \Pdo + * * @throws InvalidTransactionalPropertyException */ private function beginTransaction($object, $prop) diff --git a/tests/AuraSqlReplicationModuleTest.php b/tests/AuraSqlReplicationModuleTest.php index b79dcf2..67f05bd 100644 --- a/tests/AuraSqlReplicationModuleTest.php +++ b/tests/AuraSqlReplicationModuleTest.php @@ -42,6 +42,7 @@ public function connectionProvider() */ public function testLocatorSlave(ConnectionLocator $locator, ExtendedPdo $masterPdo, ExtendedPdo $slavePdo) { + unset($masterPdo); $_SERVER['REQUEST_METHOD'] = 'GET'; /* @var $model FakeRepModel */ $model = (new Injector(new AuraSqlReplicationModule($locator), $_ENV['TMP_DIR']))->getInstance(FakeRepModel::class); @@ -54,6 +55,7 @@ public function testLocatorSlave(ConnectionLocator $locator, ExtendedPdo $master */ public function testLocatorMaster(ConnectionLocator $locator, ExtendedPdo $masterPdo, ExtendedPdo $slavePdo) { + unset($slavePdo); $_SERVER['REQUEST_METHOD'] = 'POST'; /* @var $model FakeRepModel */ $model = (new Injector(new AuraSqlReplicationModule($locator), $_ENV['TMP_DIR']))->getInstance(FakeRepModel::class); @@ -66,6 +68,8 @@ public function testLocatorMaster(ConnectionLocator $locator, ExtendedPdo $maste */ public function testLocatorMasterWithQualifer(ConnectionLocator $locator, ExtendedPdo $masterPdo, ExtendedPdo $slavePdo) { + unset($masterPdo); + unset($slavePdo); $_SERVER['REQUEST_METHOD'] = 'POST'; /* @var $db1Master ExtendedPdo */ /* @var $db2Master ExtendedPdo */ diff --git a/tests/Pagerfanta/AuraSqlQueryAdapterTest.php b/tests/Pagerfanta/AuraSqlQueryAdapterTest.php index ba016c2..8d8d72f 100644 --- a/tests/Pagerfanta/AuraSqlQueryAdapterTest.php +++ b/tests/Pagerfanta/AuraSqlQueryAdapterTest.php @@ -76,6 +76,7 @@ private function createAdapterToTestGetNbResults() foreach (array_keys($select->getCols()) as $key) { $select->removeCol($key); } + return $select->cols(['COUNT(*) AS total_results'])->limit(1); }; From 2e0e4e816de2a5860ddce9c6933c533ef4453d04 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 17:30:04 +0900 Subject: [PATCH 3/6] fix phpdoc --- src/AuraSqlReplicationDbProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AuraSqlReplicationDbProvider.php b/src/AuraSqlReplicationDbProvider.php index 542dfa4..759ceff 100644 --- a/src/AuraSqlReplicationDbProvider.php +++ b/src/AuraSqlReplicationDbProvider.php @@ -24,7 +24,7 @@ class AuraSqlReplicationDbProvider implements ProviderInterface, SetContextInter private $connectionLocator; /** - * @param ConnectionLocatorInterface $connectionLocator + * @param InjectorInterface $injector */ public function __construct(InjectorInterface $injector) { From 38e3cab824ca42f25f9e8e24c4592e7b6142a275 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 17:30:12 +0900 Subject: [PATCH 4/6] add composer scripts --- composer.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/composer.json b/composer.json index 99c449b..cc29612 100644 --- a/composer.json +++ b/composer.json @@ -30,5 +30,17 @@ "tests/Fake/" ] } + }, + "scripts": { + "test": [ + "phpmd src text ./phpmd.xml", + "phpcs src tests", + "phpunit" + ], + "cs-fix": [ + "php-cs-fixer fix --config-file=./.php_cs", + "phpcbf src" + ], + "clean": "rm -rf var/tmp/* var/log/* tests/tmp/*" } } From 763b3e93a60801a53eb0ae2593f806a03f8459de Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 17:46:43 +0900 Subject: [PATCH 5/6] update .travis.yml --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0fedd1..d5c6a9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,8 @@ before_script: - if [ -z "$dependencies" ]; then composer install; fi; - if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest; fi; script: - - if [ "$TRAVIS_PHP_VERSION" != "7.1" ]; then phpunit; fi - - if [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then phpunit --coverage-text --coverage-clover=coverage.clover; fi + - if [ "$TRAVIS_PHP_VERSION" == "hhvm" ]; then phpunit; fi + - if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then phpunit --coverage-text --coverage-clover=coverage.clover; fi after_script: - wget https://scrutinizer-ci.com/ocular.phar - - if [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi + - if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi From 2eb69b1da9178f100ec3f5d1510bb5848061398f Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Tue, 7 Mar 2017 18:31:53 +0900 Subject: [PATCH 6/6] test coverage 100% --- src/AuraSqlConnectionInterceptor.php | 5 +- src/AuraSqlModule.php | 8 +--- src/AuraSqlProvider.php | 53 ---------------------- src/NamedPdoModule.php | 8 +--- src/Pagerfanta/AuraSqlQueryPager.php | 3 -- tests/AuraSqlModuleTest.php | 7 +++ tests/Fake/FakeNamedQualifierModule.php | 16 +++++++ tests/Fake/FakeQualifierModule.php | 16 +++++++ tests/NamedPdoModuleTest.php | 8 ++++ tests/Pagerfanta/AuraSqlQueryPagerTest.php | 8 ++++ 10 files changed, 58 insertions(+), 74 deletions(-) delete mode 100644 src/AuraSqlProvider.php create mode 100644 tests/Fake/FakeNamedQualifierModule.php create mode 100644 tests/Fake/FakeQualifierModule.php diff --git a/src/AuraSqlConnectionInterceptor.php b/src/AuraSqlConnectionInterceptor.php index ec416cc..3477ca0 100644 --- a/src/AuraSqlConnectionInterceptor.php +++ b/src/AuraSqlConnectionInterceptor.php @@ -71,10 +71,7 @@ private function getConnection(MethodInvocation $invocation) if (in_array($methodName, $this->readsMethods)) { return $this->connectionLocator->getRead(); } - if (in_array($methodName, $this->writeMethods)) { - return $this->connectionLocator->getWrite(); - } - return $this->connectionLocator->getDefault(); + return $this->connectionLocator->getWrite(); } } diff --git a/src/AuraSqlModule.php b/src/AuraSqlModule.php index bdb177c..808de17 100644 --- a/src/AuraSqlModule.php +++ b/src/AuraSqlModule.php @@ -98,15 +98,9 @@ private function configureMasterSlaveDsn() private function changeHost($dsn, $host) { preg_match(self::PARSE_PDO_DSN_REGEX, $dsn, $parts); - if (empty($parts)) { + if (! $parts) { return $dsn; } -// [ -// 0 => 'mysql:host=localhost;port=3307;dbname=testdb', -// 1 => 'mysql', -// 2 => 'host', -// 3 => 'port=3307;dbname=testdb' -// ] $dsn = sprintf('%s:%s=%s;%s', $parts[1], $parts[2], $host, $parts[3]); return $dsn; diff --git a/src/AuraSqlProvider.php b/src/AuraSqlProvider.php deleted file mode 100644 index 936ab62..0000000 --- a/src/AuraSqlProvider.php +++ /dev/null @@ -1,53 +0,0 @@ -dsn, $this->user, $this->password) = $config; - } - - /** - * {@inheritdoc} - */ - public function get() - { - $pdo = new ExtendedPdo( - $this->dsn, - $this->user, - $this->password - ); - - return $pdo; - } -} diff --git a/src/NamedPdoModule.php b/src/NamedPdoModule.php index 73e394b..fa11b5b 100644 --- a/src/NamedPdoModule.php +++ b/src/NamedPdoModule.php @@ -96,15 +96,9 @@ private function configureMasterSlaveDsn($qualifer, $dsn, $user, $password, $sla private function changeHost($dsn, $host) { preg_match(self::PARSE_PDO_DSN_REGEX, $dsn, $parts); - if (empty($parts)) { + if (! $parts) { return $dsn; } -// [ -// 0 => 'mysql:host=localhost;port=3307;dbname=testdb', -// 1 => 'mysql', -// 2 => 'host', -// 3 => 'port=3307;dbname=testdb' -// ] $dsn = sprintf('%s:%s=%s;%s', $parts[1], $parts[2], $host, $parts[3]); return $dsn; diff --git a/src/Pagerfanta/AuraSqlQueryPager.php b/src/Pagerfanta/AuraSqlQueryPager.php index 5b8cbeb..de33e68 100644 --- a/src/Pagerfanta/AuraSqlQueryPager.php +++ b/src/Pagerfanta/AuraSqlQueryPager.php @@ -77,9 +77,6 @@ public function offsetGet($page) } $countQueryBuilderModifier = function (SelectInterface $select) { - if (!$select instanceof Select) { - throw new NotInitialized(); - } foreach (array_keys($select->getCols()) as $key) { $select->removeCol($key); } diff --git a/tests/AuraSqlModuleTest.php b/tests/AuraSqlModuleTest.php index 5dda38a..56bdb77 100644 --- a/tests/AuraSqlModuleTest.php +++ b/tests/AuraSqlModuleTest.php @@ -33,4 +33,11 @@ public function testSlaveModule() $dsn = $read->getDsn(); $this->assertContains($dsn, ['mysql:host=slave1;dbname=testdb', 'mysql:host=slave2;dbname=testdb']); } + + public function testNoHost() + { + $instance = (new Injector(new FakeQualifierModule, $_ENV['TMP_DIR']))->getInstance(ExtendedPdoInterface::class); + /* @var $instance ExtendedPdo */ + $this->assertSame('sqlite::memory:', $instance->getDsn()); + } } diff --git a/tests/Fake/FakeNamedQualifierModule.php b/tests/Fake/FakeNamedQualifierModule.php new file mode 100644 index 0000000..886fbd2 --- /dev/null +++ b/tests/Fake/FakeNamedQualifierModule.php @@ -0,0 +1,16 @@ +install(new NamedPdoModule('log_db', 'sqlite::memory:', '', '', 'slave1')); + } +} diff --git a/tests/Fake/FakeQualifierModule.php b/tests/Fake/FakeQualifierModule.php new file mode 100644 index 0000000..33373e1 --- /dev/null +++ b/tests/Fake/FakeQualifierModule.php @@ -0,0 +1,16 @@ +install(new AuraSqlModule('sqlite::memory:', '', '', 'slave1')); + } +} diff --git a/tests/NamedPdoModuleTest.php b/tests/NamedPdoModuleTest.php index 9d925ef..d0ab1ca 100644 --- a/tests/NamedPdoModuleTest.php +++ b/tests/NamedPdoModuleTest.php @@ -43,4 +43,12 @@ public function testReplicationSlave() /* @var $instance ExtendedPdo */ $this->assertContains('mysql:host=slave', $instance->getDsn()); } + + public function testNoHost() + { + $qualifer = 'log_db'; + $instance = (new Injector(new FakeNamedQualifierModule, $_ENV['TMP_DIR']))->getInstance(ExtendedPdoInterface::class, $qualifer); + /* @var $instance ExtendedPdo */ + $this->assertSame('sqlite::memory:', $instance->getDsn()); + } } diff --git a/tests/Pagerfanta/AuraSqlQueryPagerTest.php b/tests/Pagerfanta/AuraSqlQueryPagerTest.php index 8e5e37a..e79602a 100644 --- a/tests/Pagerfanta/AuraSqlQueryPagerTest.php +++ b/tests/Pagerfanta/AuraSqlQueryPagerTest.php @@ -56,4 +56,12 @@ public function testOffsetGet() $expected = [['username' => 'Jon Doe']]; $this->assertSame($expected, $post->data); } + + public function estOffsetGetWithoutInit() + { + $this->select = $this->qf->newSelect(); + $this->select->cols(['p.username'])->from('posts as p'); + $pager = new AuraSqlQueryPager(new DefaultView, []); + $post = $pager[2]; + } }