From 950fa663d452c2a3e79f0162bbe19529f6bad2c7 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 08:56:43 -0500 Subject: [PATCH 1/7] Allow usage of mongodb extension with MongoAdapter This patch addresses #138 and #145, with the following approach: - alcaeus/mongo-php-adapter is suggested when using PHP 7 or ext/mongodb. It is not required by default, as installing it conflicts with ext/mongo. - In classes that use `MongoClient`, tests are done for: - Presence of either ext/mongo or ext/mongodb - Presence of the MongoClient class - MongoClient >= 1.4.1 - Travis CI is setup to enable ext/mongodb when testing against hhvm or PHP 7, and ext/mongo for all other versions. When ext/mongodb is installed, it also adds alcaeus/mongo-php-adapter as a development requirement. - Updates the `mongo.application.config.php` test asset to add `Zend\Router` as a module when it is present. Tests now pass against all versions. --- .travis.yml | 4 ++ composer.json | 3 ++ composer.lock | 2 +- src/Adapter/MongoAdapter.php | 9 ++-- .../AuthControllerWithMongoAdapterTest.php | 43 +++++++++++++------ test/Factory/MongoAdapterFactoryTest.php | 18 ++++++-- test/TestAsset/mongo.application.config.php | 31 +++++++------ 7 files changed, 77 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index c631daf..6b02d95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,10 +54,14 @@ notifications: before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi + - if [[ $TRAVIS_PHP_VERSION == '7' ]]; then echo "extension = mongodb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi + - if [[ $TRAVIS_PHP_VERSION == 'hhvm' ]]; then echo "extension = mongodb.so" >> /etc/hhvm/php.ini ; fi + - if [[ $TRAVIS_PHP_VERSION != '7' && $TRAVIS_PHP_VERSION != 'hhvm' ]]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi - travis_retry composer self-update - chmod -R +rwX test/TestAsset install: + - if [[ $TRAVIS_PHP_VERSION != '7' && $TRAVIS_PHP_VERSION != 'hhvm' ]]; then composer require --dev $COMPOSER_ARGS alcaeus/mongo-php-adapter ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - travis_retry composer install $COMPOSER_ARGS diff --git a/composer.json b/composer.json index 6a3d8cf..d631b4f 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,9 @@ "zendframework/zend-serializer": "^2.8", "zendframework/zend-test": "^2.6.1 || ^3.0.1" }, + "suggest": { + "alcaeus/mongo-php-adapter": "^1.0.5, if you are using ext/mongodb and wish to use the MongoAdapter for OAuth2 credential storage." + }, "autoload": { "psr-4": { "ZF\\OAuth2\\": "src/" diff --git a/composer.lock b/composer.lock index 6cb8299..8e7993a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "79245d982fa13c78378aa62d4d9995c0", + "hash": "8b3de83ffe9f5472dde021837257fc13", "content-hash": "b30b519e713ba722c3bf7a97a2d4cc17", "packages": [ { diff --git a/src/Adapter/MongoAdapter.php b/src/Adapter/MongoAdapter.php index 441f2de..1da3870 100644 --- a/src/Adapter/MongoAdapter.php +++ b/src/Adapter/MongoAdapter.php @@ -89,12 +89,15 @@ protected function verifyHash($check, $hash) public function __construct($connection, $config = []) { // @codeCoverageIgnoreStart - if (!extension_loaded('mongo') - || ! class_exists('MongoClient') + $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') ) { throw new Exception\RuntimeException( - 'The Mongo Driver v1.4.1 required for this adapter to work' + 'The MongoAdapter requires either the Mongo Driver v1.4.1 or ' + . 'ext/mongodb + the alcaeus/mongo-php-adapter package (which provides ' + . 'backwards compatibility for ext/mongo classes)' ); } // @codeCoverageIgnoreEnd diff --git a/test/Controller/AuthControllerWithMongoAdapterTest.php b/test/Controller/AuthControllerWithMongoAdapterTest.php index 9b23350..c2291ff 100644 --- a/test/Controller/AuthControllerWithMongoAdapterTest.php +++ b/test/Controller/AuthControllerWithMongoAdapterTest.php @@ -6,19 +6,42 @@ namespace ZFTest\OAuth2\Controller; +use MongoClient; +use MongoConnectionException; +use MongoDB; use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase; class AuthControllerWithMongoAdapterTest extends AbstractHttpControllerTestCase { /** - * @var \MongoDB + * @var MongoDB */ protected $db; + /** + * Default data to insert in database. + * + * Defined here to prevent "cannot pass by reference" issues when using + * alcaeus/mongo-php-adapter (as that library accepts a reference for the + * first argument, and unassigned arrays fail that). + * + * @var array + */ + protected $defaultData = [ + 'client_id' => 'testclient', + 'client_secret' => '$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2', + 'redirect_uri' => '/oauth/receivecode', + 'grant_types' => null, + ]; + public function setUp() { - if (!extension_loaded('mongo')) { - $this->markTestSkipped('The Mongo extension is not available.'); + $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + || ! class_exists(MongoClient::class) + || version_compare(MongoClient::VERSION, '1.4.1', '<') + ) { + $this->markTestSkipped('ext/mongo ^1.4.1 or ext/mongodb + alcaeus/mongo-php-adapter is not available.'); } $this->setApplicationConfig(include __DIR__ . '/../TestAsset/mongo.application.config.php'); @@ -26,24 +49,20 @@ public function setUp() parent::setUp(); try { - $client = new \MongoClient("mongodb://127.0.0.1:27017"); - } catch (\MongoConnectionException $e) { + $client = new MongoClient("mongodb://127.0.0.1:27017"); + } catch (MongoConnectionException $e) { $this->markTestSkipped($e->getMessage()); } + $this->db = $client->selectDB('zf_oauth2_test'); - $this->db->oauth_clients->insert([ - 'client_id' => 'testclient', - 'client_secret' => '$2y$14$f3qml4G2hG6sxM26VMq.geDYbsS089IBtVJ7DlD05BoViS9PFykE2', - 'redirect_uri' => '/oauth/receivecode', - 'grant_types' => null - ]); + $this->db->oauth_clients->insert($this->defaultData); $this->getApplicationServiceLocator()->setService('MongoDB', $this->db); } public function tearDown() { - if ($this->db instanceof \MongoDB) { + if ($this->db instanceof MongoDB) { $this->db->drop(); } diff --git a/test/Factory/MongoAdapterFactoryTest.php b/test/Factory/MongoAdapterFactoryTest.php index f4adb49..43d768e 100644 --- a/test/Factory/MongoAdapterFactoryTest.php +++ b/test/Factory/MongoAdapterFactoryTest.php @@ -6,6 +6,8 @@ namespace ZFTest\OAuth2\Factory; +use MongoClient; +use MongoDB; use ReflectionObject; use Zend\ServiceManager\ServiceManager; use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase; @@ -25,8 +27,12 @@ class MongoAdapterFactoryTest extends AbstractHttpControllerTestCase protected function setUp() { - if (!extension_loaded('mongo')) { - $this->markTestSkipped('The Mongo extension is not available.'); + $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + || ! class_exists(MongoClient::class) + || version_compare(MongoClient::VERSION, '1.4.1', '<') + ) { + $this->markTestSkipped('ext/mongo or ext/mongodb + alcaeus/mongo-php-adapter is not available.'); } $this->factory = new MongoAdapterFactory(); @@ -81,7 +87,9 @@ public function testInstanceCreatedWithMongoDbInServiceLocator() ], ], ]); - $mock = $this->getMock('\MongoDB', [], [], '', false); + $mock = $this->getMockBuilder(MongoDB::class, [], [], '', false) + ->disableOriginalConstructor() + ->getMock(); $this->services->setService('testdb', $mock); $adapter = $this->factory->createService($this->services); @@ -100,7 +108,9 @@ public function testCanPassAdapterConfigurationWhenCreatingInstance() ], ], ]); - $mock = $this->getMock('\MongoDB', [], [], '', false); + $mock = $this->getMockBuilder(MongoDB::class, [], [], '', false) + ->disableOriginalConstructor() + ->getMock(); $this->services->setService('testdb', $mock); $adapter = $this->factory->createService($this->services); diff --git a/test/TestAsset/mongo.application.config.php b/test/TestAsset/mongo.application.config.php index d083cc2..2d86fbb 100644 --- a/test/TestAsset/mongo.application.config.php +++ b/test/TestAsset/mongo.application.config.php @@ -1,28 +1,33 @@ array( - 'ZF\ContentNegotiation', - 'ZF\OAuth2' - ), + 'modules' => $modules, // These are various options for the listeners attached to the ModuleManager - 'module_listener_options' => array( + 'module_listener_options' => [ // This should be an array of paths in which modules reside. // If a string key is provided, the listener will consider that a module // namespace, the value of that key the specific path to that module's // Module class. - 'module_paths' => array( + 'module_paths' => [ __DIR__ . '/../../../../..', __DIR__ . '/../../../../../vendor', - ), + ], // An array of paths from which to glob configuration files after // modules are loaded. These effectively override configuration // provided by modules themselves. Paths may use GLOB_BRACE notation. - 'config_glob_paths' => array( + 'config_glob_paths' => [ __DIR__ . '/autoload_mongo/{,*.}{global,local}.php', - ), - - ), -); + ], + ], +]; From e7a6883ba9d2d7633cc1784109912284c7a4ae92 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 09:23:12 -0500 Subject: [PATCH 2/7] Fix how mongodb extension and optional compat package are injected/installed --- .travis.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6b02d95..1c4c348 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,13 +29,16 @@ matrix: - php: 7 env: - DEPS=lowest + - EXT_MONGODB=true - php: 7 env: - DEPS=locked + - EXT_MONGODB=true - CS_CHECK=true - php: 7 env: - DEPS=latest + - EXT_MONGODB=true - php: hhvm env: - DEPS=lowest @@ -44,6 +47,7 @@ matrix: - DEPS=locked - php: hhvm env: + - EXT_MONGODB=true - DEPS=latest allow_failures: - php: hhvm @@ -54,17 +58,19 @@ notifications: before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - - if [[ $TRAVIS_PHP_VERSION == '7' ]]; then echo "extension = mongodb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi - - if [[ $TRAVIS_PHP_VERSION == 'hhvm' ]]; then echo "extension = mongodb.so" >> /etc/hhvm/php.ini ; fi - - if [[ $TRAVIS_PHP_VERSION != '7' && $TRAVIS_PHP_VERSION != 'hhvm' ]]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi + - if [[ $EXT_MONGODB == 'true' && $TRAVIS_PHP_VERSION == '7' ]]; then echo "extension = mongodb.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi + - if [[ $EXT_MONGODB == 'true' && $TRAVIS_PHP_VERSION == 'hhvm' ]]; then echo "extension = mongodb.so" >> /etc/hhvm/php.ini ; fi + - if [[ $EXT_MONGODB != 'true' && $TRAVIS_PHP_VERSION != 'hhvm' ]]; then echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; fi + - if [[ $EXT_MONGODB != 'true' && $TRAVIS_PHP_VERSION == 'hhvm' ]]; then echo "extension = mongo.so" >> /etc/hhvm/php.ini ; fi - travis_retry composer self-update - chmod -R +rwX test/TestAsset install: - - if [[ $TRAVIS_PHP_VERSION != '7' && $TRAVIS_PHP_VERSION != 'hhvm' ]]; then composer require --dev $COMPOSER_ARGS alcaeus/mongo-php-adapter ; fi + - if [[ $EXT_MONGODB == 'true' ]]; then composer require --dev $COMPOSER_ARGS alcaeus/mongo-php-adapter ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - travis_retry composer install $COMPOSER_ARGS + - php -m - composer show script: From 4e9f1cbed8c8862c4e3d158c1f679880885a25c4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 09:28:41 -0500 Subject: [PATCH 3/7] php -m hangs on hhvm --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c4c348..a51d5c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,7 +70,7 @@ install: - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - travis_retry composer install $COMPOSER_ARGS - - php -m + - if [[ $TRAVIS_PHP_VERSION != 'hhvm' ]]; then php -m ; fi - composer show script: From f0c2bea0baaa6b0c738a856aeca36403c6c05504 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 09:35:17 -0500 Subject: [PATCH 4/7] HHVM supports both ext/mongo and ext/mongodb --- src/Adapter/MongoAdapter.php | 2 +- test/Controller/AuthControllerWithMongoAdapterTest.php | 2 +- test/Factory/MongoAdapterFactoryTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Adapter/MongoAdapter.php b/src/Adapter/MongoAdapter.php index 1da3870..6887653 100644 --- a/src/Adapter/MongoAdapter.php +++ b/src/Adapter/MongoAdapter.php @@ -89,7 +89,7 @@ protected function verifyHash($check, $hash) public function __construct($connection, $config = []) { // @codeCoverageIgnoreStart - $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') diff --git a/test/Controller/AuthControllerWithMongoAdapterTest.php b/test/Controller/AuthControllerWithMongoAdapterTest.php index c2291ff..3698386 100644 --- a/test/Controller/AuthControllerWithMongoAdapterTest.php +++ b/test/Controller/AuthControllerWithMongoAdapterTest.php @@ -36,7 +36,7 @@ class AuthControllerWithMongoAdapterTest extends AbstractHttpControllerTestCase public function setUp() { - $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') diff --git a/test/Factory/MongoAdapterFactoryTest.php b/test/Factory/MongoAdapterFactoryTest.php index 43d768e..256fae4 100644 --- a/test/Factory/MongoAdapterFactoryTest.php +++ b/test/Factory/MongoAdapterFactoryTest.php @@ -27,7 +27,7 @@ class MongoAdapterFactoryTest extends AbstractHttpControllerTestCase protected function setUp() { - $useMongoDb = defined('HHVM_VERSION') || version_compare(PHP_VERSION, '7.0', '>='); + $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') From 16d7c07135e20729d45e92650fbda54480aa1d23 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 09:38:45 -0500 Subject: [PATCH 5/7] Do not use version checking for extension determination - Just check that one or the other extension is installed. --- src/Adapter/MongoAdapter.php | 3 +-- test/Controller/AuthControllerWithMongoAdapterTest.php | 3 +-- test/Factory/MongoAdapterFactoryTest.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Adapter/MongoAdapter.php b/src/Adapter/MongoAdapter.php index 6887653..1c22960 100644 --- a/src/Adapter/MongoAdapter.php +++ b/src/Adapter/MongoAdapter.php @@ -89,8 +89,7 @@ protected function verifyHash($check, $hash) public function __construct($connection, $config = []) { // @codeCoverageIgnoreStart - $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); - if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + if (! (extension_loaded('mongodb') || extension_loaded('mongo')) || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') ) { diff --git a/test/Controller/AuthControllerWithMongoAdapterTest.php b/test/Controller/AuthControllerWithMongoAdapterTest.php index 3698386..9c3b607 100644 --- a/test/Controller/AuthControllerWithMongoAdapterTest.php +++ b/test/Controller/AuthControllerWithMongoAdapterTest.php @@ -36,8 +36,7 @@ class AuthControllerWithMongoAdapterTest extends AbstractHttpControllerTestCase public function setUp() { - $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); - if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + if (! (extension_loaded('mongodb') || extension_loaded('mongo')) || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') ) { diff --git a/test/Factory/MongoAdapterFactoryTest.php b/test/Factory/MongoAdapterFactoryTest.php index 256fae4..b8fb008 100644 --- a/test/Factory/MongoAdapterFactoryTest.php +++ b/test/Factory/MongoAdapterFactoryTest.php @@ -27,8 +27,7 @@ class MongoAdapterFactoryTest extends AbstractHttpControllerTestCase protected function setUp() { - $useMongoDb = version_compare(PHP_VERSION, '7.0', '>='); - if (! extension_loaded($useMongoDb ? 'mongodb' : 'mongo') + if (! (extension_loaded('mongodb') || extension_loaded('mongo')) || ! class_exists(MongoClient::class) || version_compare(MongoClient::VERSION, '1.4.1', '<') ) { From 59186110891f79f79748bf7a91328683ff22c8b1 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sat, 9 Jul 2016 10:42:13 -0500 Subject: [PATCH 6/7] Added verbiage to installation instructions about compat package --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf74256..8bcf409 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,15 @@ You can install using: $ composer require zfcampus/zf-oauth2 ``` -You should also add the following modules to your application's configuration: +If you are using ext/mongodb, you will also need to install a compatibility +package: + +```bash +$ composer require alcaeus/mongo-php-adapter +``` + +Finally, you will need to add the following modules to your application's +configuration: ```php 'modules' => [ From 12ea56109a3e0835e1f0e4a351549cb9469f28dc Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Sun, 10 Jul 2016 18:09:18 -0500 Subject: [PATCH 7/7] Added CHANGELOG for #149 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d82aeba..f518844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file, in reverse ### Added +- [#149](https://github.com/zfcampus/zf-oauth2/pull/149) adds support for usage + of ext/mongodb with `ZF\OAuth2\Adapter\MongoAdapter`; users will need to also + install a compatibility package to do so: + `composer require alcaeus/mongo-php-adapter` - [#141](https://github.com/zfcampus/zf-oauth2/pull/141) and [#148](https://github.com/zfcampus/zf-oauth2/pull/148) update the component to allow usage with v3 releases of Zend Framework components on which it depends,