From adea7a0306a93c0ca84ccc082e10eb0746959bb3 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Tue, 2 Feb 2016 16:10:46 -0800 Subject: [PATCH 001/150] Send the default value back to LD --- src/LaunchDarkly/LDClient.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 7de5252ef..daaf850a9 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -90,17 +90,17 @@ public function toggle($key, $user, $default = false) { $flag = $this->_toggle($key, $user); if (is_null($flag)) { - $this->_sendFlagRequestEvent($key, $user, $default); + $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; } else { - $this->_sendFlagRequestEvent($key, $user, $flag); + $this->_sendFlagRequestEvent($key, $user, $flag, $default); return $flag; } } catch (\Exception $e) { error_log("LaunchDarkly caught $e"); try { - $this->_sendFlagRequestEvent($key, $user, $default); + $this->_sendFlagRequestEvent($key, $user, $default, $default); } catch (\Exception $e) { error_log("LaunchDarkly caught $e"); @@ -178,7 +178,7 @@ public function identify($user) { * @param $user LDUser * @param $value mixed */ - protected function _sendFlagRequestEvent($key, $user, $value) { + protected function _sendFlagRequestEvent($key, $user, $value, $default) { if ($this->isOffline() || !$this->_events) { return; } @@ -189,6 +189,7 @@ protected function _sendFlagRequestEvent($key, $user, $value) { $event['kind'] = "feature"; $event['creationDate'] = round(microtime(1) * 1000); $event['key'] = $key; + $event['default'] = $default; $this->_eventProcessor->enqueue($event); } From daec6855d9f9708b6462b49c45c2c114b175f219 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Mon, 8 Feb 2016 10:40:11 -0800 Subject: [PATCH 002/150] Split events_uri into a different configuration parameter --- composer.lock | 358 +++++++++++++++++----------- src/LaunchDarkly/EventProcessor.php | 6 +- 2 files changed, 227 insertions(+), 137 deletions(-) diff --git a/composer.lock b/composer.lock index eff0ac1bc..1de9bc0cc 100644 --- a/composer.lock +++ b/composer.lock @@ -9,16 +9,16 @@ "packages": [ { "name": "doctrine/cache", - "version": "v1.4.2", + "version": "v1.5.4", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca" + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/8c434000f420ade76a07c64cbe08ca47e5c101ca", - "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca", + "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", "shasum": "" }, "require": { @@ -39,8 +39,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Cache\\": "lib/" + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -75,7 +75,7 @@ "cache", "caching" ], - "time": "2015-08-31 12:36:41" + "time": "2015-12-19 05:03:47" }, { "name": "guzzlehttp/cache-subscriber", @@ -945,20 +945,20 @@ }, { "name": "justinrainbow/json-schema", - "version": "1.5.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe" + "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", - "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341", + "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.29" }, "require-dev": { "json-schema/json-schema-test-suite": "1.1.0", @@ -971,7 +971,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -1007,7 +1007,7 @@ "json", "schema" ], - "time": "2015-09-08 22:28:04" + "time": "2016-01-25 15:43:01" }, { "name": "kherge/version", @@ -2118,28 +2118,28 @@ }, { "name": "sebastian/diff", - "version": "1.3.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -2162,24 +2162,24 @@ } ], "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff" ], - "time": "2015-02-22 15:13:53" + "time": "2015-12-08 07:14:41" }, { "name": "sebastian/environment", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" + "reference": "6e7133793a8e5a5714a551a8324337374be209df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", + "reference": "6e7133793a8e5a5714a551a8324337374be209df", "shasum": "" }, "require": { @@ -2216,7 +2216,7 @@ "environment", "hhvm" ], - "time": "2015-08-03 06:14:51" + "time": "2015-12-02 08:37:27" }, { "name": "sebastian/exporter", @@ -2286,16 +2286,16 @@ }, { "name": "sebastian/recursion-context", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", "shasum": "" }, "require": { @@ -2335,7 +2335,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21 08:04:50" + "time": "2015-11-11 19:50:13" }, { "name": "sebastian/version", @@ -2374,20 +2374,20 @@ }, { "name": "seld/jsonlint", - "version": "1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4" + "reference": "66834d3e3566bb5798db7294619388786ae99394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/863ae85c6d3ef60ca49cb12bd051c4a0648c40c4", - "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394", + "reference": "66834d3e3566bb5798db7294619388786ae99394", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^5.3 || ^7.0" }, "bin": [ "bin/jsonlint" @@ -2416,36 +2416,39 @@ "parser", "validator" ], - "time": "2015-01-04 21:18:15" + "time": "2015-11-21 02:21:41" }, { "name": "symfony/config", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "831f88908b51b9ce945f5e6f402931d1ac544423" + "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/831f88908b51b9ce945f5e6f402931d1ac544423", - "reference": "831f88908b51b9ce945f5e6f402931d1ac544423", + "url": "https://api.github.com/repos/symfony/config/zipball/41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", + "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/filesystem": "~2.3" + "symfony/filesystem": "~2.3|~3.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Config\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2463,29 +2466,30 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-10-11 09:39:48" + "time": "2016-01-03 15:33:41" }, { "name": "symfony/console", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5efd632294c8320ea52492db22292ff853a43766" + "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5efd632294c8320ea52492db22292ff853a43766", - "reference": "5efd632294c8320ea52492db22292ff853a43766", + "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d", + "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/process": "~2.1" + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/process": "~2.1|~3.0.0" }, "suggest": { "psr/log": "For using the console logger", @@ -2495,13 +2499,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2519,20 +2526,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-10-20 14:38:46" + "time": "2016-01-14 08:33:16" }, { "name": "symfony/event-dispatcher", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8" + "reference": "ee278f7c851533e58ca307f66305ccb9188aceda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87a5db5ea887763fa3a31a5471b512ff1596d9b8", - "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ee278f7c851533e58ca307f66305ccb9188aceda", + "reference": "ee278f7c851533e58ca307f66305ccb9188aceda", "shasum": "" }, "require": { @@ -2540,10 +2547,10 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/stopwatch": "~2.3" + "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" }, "suggest": { "symfony/dependency-injection": "", @@ -2552,13 +2559,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2576,20 +2586,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2015-10-11 09:39:48" + "time": "2016-01-13 10:28:07" }, { "name": "symfony/filesystem", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "56fd6df73be859323ff97418d97edc1d756df6df" + "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/56fd6df73be859323ff97418d97edc1d756df6df", - "reference": "56fd6df73be859323ff97418d97edc1d756df6df", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", "shasum": "" }, "require": { @@ -2598,13 +2608,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2622,20 +2635,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-10-18 20:23:18" + "time": "2016-01-13 10:28:07" }, { "name": "symfony/finder", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d" + "reference": "c90fabdd97e431ee19b6383999cf35334dff27da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d", - "reference": "2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d", + "url": "https://api.github.com/repos/symfony/finder/zipball/c90fabdd97e431ee19b6383999cf35334dff27da", + "reference": "c90fabdd97e431ee19b6383999cf35334dff27da", "shasum": "" }, "require": { @@ -2644,13 +2657,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2668,20 +2684,79 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2015-10-11 09:39:48" + "time": "2016-01-14 08:26:52" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "1289d16209491b584839022f29257ad859b8532d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", + "reference": "1289d16209491b584839022f29257ad859b8532d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-01-20 09:13:37" }, { "name": "symfony/process", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4a959dd4e19c2c5d7512689413921e0a74386ec7" + "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4a959dd4e19c2c5d7512689413921e0a74386ec7", - "reference": "4a959dd4e19c2c5d7512689413921e0a74386ec7", + "url": "https://api.github.com/repos/symfony/process/zipball/6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac", + "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac", "shasum": "" }, "require": { @@ -2690,13 +2765,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2714,20 +2792,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-10-23 14:47:27" + "time": "2016-01-06 09:59:23" }, { "name": "symfony/stopwatch", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "f8ab957c17e4b85a73c4df03bdf94ee597f2bd55" + "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f8ab957c17e4b85a73c4df03bdf94ee597f2bd55", - "reference": "f8ab957c17e4b85a73c4df03bdf94ee597f2bd55", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e3bc8e2a984f4382690a438c8bb650f3ffd71e73", + "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73", "shasum": "" }, "require": { @@ -2736,13 +2814,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2760,33 +2841,34 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2015-10-12 12:42:24" + "time": "2016-01-03 15:33:41" }, { "name": "symfony/translation", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6ccd9289ec1c71d01a49d83480de3b5293ce30c8" + "reference": "bc0b666903944858f4ffec01c4e50c63e5c276c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6ccd9289ec1c71d01a49d83480de3b5293ce30c8", - "reference": "6ccd9289ec1c71d01a49d83480de3b5293ce30c8", + "url": "https://api.github.com/repos/symfony/translation/zipball/bc0b666903944858f4ffec01c4e50c63e5c276c0", + "reference": "bc0b666903944858f4ffec01c4e50c63e5c276c0", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "symfony/config": "<2.7" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.7", - "symfony/intl": "~2.4", - "symfony/yaml": "~2.2" + "symfony/config": "~2.8", + "symfony/intl": "~2.4|~3.0.0", + "symfony/yaml": "~2.2|~3.0.0" }, "suggest": { "psr/log": "To use logging capability in translator", @@ -2796,13 +2878,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2820,37 +2905,36 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2015-10-27 15:38:06" + "time": "2016-01-03 15:33:41" }, { "name": "symfony/validator", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "df9021e689aa3d08367881e7f8917219fabe5e64" + "reference": "7a325d73cb492d244d9107406fe40650ac070a04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/df9021e689aa3d08367881e7f8917219fabe5e64", - "reference": "df9021e689aa3d08367881e7f8917219fabe5e64", + "url": "https://api.github.com/repos/symfony/validator/zipball/7a325d73cb492d244d9107406fe40650ac070a04", + "reference": "7a325d73cb492d244d9107406fe40650ac070a04", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/translation": "~2.4" + "symfony/translation": "~2.4|~3.0.0" }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", - "doctrine/common": "~2.3", "egulias/email-validator": "~1.2,>=1.2.1", - "symfony/config": "~2.2", - "symfony/expression-language": "~2.4", - "symfony/http-foundation": "~2.1", - "symfony/intl": "~2.4", - "symfony/property-access": "~2.3", - "symfony/yaml": "~2.0,>=2.0.5" + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.1|~3.0.0", + "symfony/intl": "~2.4|~3.0.0", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", @@ -2866,13 +2950,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Validator\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2890,20 +2977,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2015-10-18 20:23:18" + "time": "2016-01-12 17:46:01" }, { "name": "symfony/yaml", - "version": "v2.7.6", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "eca9019c88fbe250164affd107bc8057771f3f4d" + "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/eca9019c88fbe250164affd107bc8057771f3f4d", - "reference": "eca9019c88fbe250164affd107bc8057771f3f4d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8", "shasum": "" }, "require": { @@ -2912,13 +2999,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2936,20 +3026,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-10-11 09:39:48" + "time": "2016-01-13 10:28:07" }, { "name": "twig/twig", - "version": "v1.22.3", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "ebfc36b7e77b0c1175afe30459cf943010245540" + "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ebfc36b7e77b0c1175afe30459cf943010245540", - "reference": "ebfc36b7e77b0c1175afe30459cf943010245540", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", + "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", "shasum": "" }, "require": { @@ -2962,7 +3052,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.22-dev" + "dev-master": "1.24-dev" } }, "autoload": { @@ -2997,7 +3087,7 @@ "keywords": [ "templating" ], - "time": "2015-10-13 07:07:02" + "time": "2016-01-25 21:22:18" }, { "name": "zendframework/zend-cache", diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index e5f04c390..66272e85e 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -16,13 +16,13 @@ class EventProcessor { public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; - if (!isset($options['base_uri'])) { - $this->_host = 'app.launchdarkly.com'; + if (!isset($options['events_uri'])) { + $this->_host = 'events.launchdarkly.com'; $this->_port = 443; $this->_ssl = true; } else { - $url = parse_url($options['base_uri']); + $url = parse_url($options['events_uri']); $this->_host = $url['host']; $this->_ssl = $url['scheme'] === 'https'; if (isset($url['port'])) { From 034300cbe4784ae55af72a7b837f4540febedcf5 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Mon, 8 Feb 2016 10:46:03 -0800 Subject: [PATCH 003/150] The events URI should point to /bulk, not /api/events/bulk --- src/LaunchDarkly/EventProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index 66272e85e..cf107d7e7 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -77,7 +77,7 @@ private function createArgs($payload) { $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; $args.= " -H 'Accept: application/json'"; $args.= " -d " . escapeshellarg($payload); - $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . "/api/events/bulk"); + $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . "/bulk"); return $args; } From a1a09c1abfd7ae2ee76d3293565186db3ecc99cd Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Mon, 8 Feb 2016 16:10:07 -0800 Subject: [PATCH 004/150] Allow paths to be specified for custom events URIs --- src/LaunchDarkly/EventProcessor.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index cf107d7e7..88dc0956c 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -20,9 +20,10 @@ public function __construct($apiKey, $options = array()) { $this->_host = 'events.launchdarkly.com'; $this->_port = 443; $this->_ssl = true; + $this->_path = ''; } else { - $url = parse_url($options['events_uri']); + $url = parse_url(rtrim($options['events_uri'],'/')); $this->_host = $url['host']; $this->_ssl = $url['scheme'] === 'https'; if (isset($url['port'])) { @@ -31,6 +32,12 @@ public function __construct($apiKey, $options = array()) { else { $this->_port = $this->_ssl ? 443 : 80; } + if (isset($url['path'])) { + $this->_path = $url['path']; + } + else { + $this->_path = ''; + } } $this->_capacity = $options['capacity']; @@ -77,7 +84,7 @@ private function createArgs($payload) { $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; $args.= " -H 'Accept: application/json'"; $args.= " -d " . escapeshellarg($payload); - $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . "/bulk"); + $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . $this->_path . "/bulk"); return $args; } From 6e2ee66100c134f273c110521b6bbedde6807f87 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Mon, 8 Feb 2016 17:25:43 -0800 Subject: [PATCH 005/150] Bump version to 0.7.0 --- VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index a0a15177f..bcaffe19b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.3 \ No newline at end of file +0.7.0 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index daaf850a9..a2d8c14af 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -8,7 +8,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '0.6.3'; + const VERSION = '0.7.0'; protected $_apiKey; protected $_baseUri; From 9182785da7f546a7c38f0a60fa076c741e40f995 Mon Sep 17 00:00:00 2001 From: Patrick Kaeding Date: Mon, 8 Feb 2016 20:25:16 -0800 Subject: [PATCH 006/150] bumped sdk --- composer.json | 3 ++- composer.lock | 17 ++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 8090c70d0..f0eef6480 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "require": { "php": ">=5.4", "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*" + "guzzlehttp/cache-subscriber": "0.1.*", + "launchdarkly/launchdarkly-php": "0.7.*" }, "require-dev": { "phpunit/phpunit": "4.3.*", diff --git a/composer.lock b/composer.lock index 1de9bc0cc..05de2c4d8 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "064d02ddae1114a6ecb771b0500ceccb", - "content-hash": "6d07711fd3a9d3fb5009b02b6a8cafee", + "hash": "1a469242ab4b6f3280894b37d7bda462", "packages": [ { "name": "doctrine/cache", @@ -672,12 +671,12 @@ "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/php-json.git", + "url": "https://github.com/herrera-io/php-json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "url": "https://api.github.com/repos/herrera-io/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, @@ -733,12 +732,12 @@ "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/php-phar-update.git", + "url": "https://github.com/herrera-io/php-phar-update.git", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", + "url": "https://api.github.com/repos/herrera-io/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "shasum": "" }, @@ -1014,12 +1013,12 @@ "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/Version.git", + "url": "https://github.com/kherge-unmaintained/Version.git", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", + "url": "https://api.github.com/repos/kherge-unmaintained/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "shasum": "" }, From 46983adda44dc0be7a39143c476bfa3c68709936 Mon Sep 17 00:00:00 2001 From: Patrick Kaeding Date: Mon, 8 Feb 2016 20:28:25 -0800 Subject: [PATCH 007/150] Revert "bumped sdk" This reverts commit 9182785da7f546a7c38f0a60fa076c741e40f995. --- composer.json | 3 +-- composer.lock | 17 +++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index f0eef6480..8090c70d0 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,7 @@ "require": { "php": ">=5.4", "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*", - "launchdarkly/launchdarkly-php": "0.7.*" + "guzzlehttp/cache-subscriber": "0.1.*" }, "require-dev": { "phpunit/phpunit": "4.3.*", diff --git a/composer.lock b/composer.lock index 05de2c4d8..1de9bc0cc 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,11 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1a469242ab4b6f3280894b37d7bda462", + "hash": "064d02ddae1114a6ecb771b0500ceccb", + "content-hash": "6d07711fd3a9d3fb5009b02b6a8cafee", "packages": [ { "name": "doctrine/cache", @@ -671,12 +672,12 @@ "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/herrera-io/php-json.git", + "url": "https://github.com/kherge-abandoned/php-json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/herrera-io/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, @@ -732,12 +733,12 @@ "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/herrera-io/php-phar-update.git", + "url": "https://github.com/kherge-abandoned/php-phar-update.git", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/herrera-io/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", + "url": "https://api.github.com/repos/kherge-abandoned/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "shasum": "" }, @@ -1013,12 +1014,12 @@ "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/kherge-unmaintained/Version.git", + "url": "https://github.com/kherge-abandoned/Version.git", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-unmaintained/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", + "url": "https://api.github.com/repos/kherge-abandoned/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "shasum": "" }, From 77d491bda8579d5d23cc2a048f0aa985f87b51ad Mon Sep 17 00:00:00 2001 From: richardmiller Date: Fri, 17 Jun 2016 12:00:32 +0100 Subject: [PATCH 008/150] Make Guzzle 5 a suggestion not a requirement --- README.md | 31 ++ composer.json | 12 +- composer.lock | 1351 ++++++++++++++++++++++++++----------------------- 3 files changed, 751 insertions(+), 643 deletions(-) diff --git a/README.md b/README.md index 677a39bc5..aec68a969 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Quick setup 0. Install the PHP SDK with [Composer](https://getcomposer.org/) php composer.phar require launchdarkly/launchdarkly-php + php composer.phar require "guzzlehttp/guzzle:5.*" + php composer.phar require "guzzlehttp/cache-subscriber:0.1.*" 1. After installing, require Composer's autoloader: @@ -34,6 +36,35 @@ Your first feature flag # the code to run if the feature is off } +Fetching flags +-------------- + +There are two approaches to fetching the flag rules from LaunchDarkly: + +* Making HTTP requests (using Guzzle) +* Setting up the [ld-daemon](https://github.com/launchdarkly/ld-daemon) to store the flags in Redis + +Using Guzzle +============ + +To use Guzzle it must be required as a dependency: + + php composer.phar require "guzzlehttp/guzzle:5.*" + php composer.phar require "guzzlehttp/cache-subscriber:0.1.*" + +It will then be used as the default way of fetching flags. + +Using Redis +=========== + +1. Require Predis as a dependency: + + php composer.phar require "predis/predis:1.0.*" + +2. Create the LDClient with the Redis feature requester as an option: + + $client = new LaunchDarkly\LDClient("your_api_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester']); + Learn more ----------- diff --git a/composer.json b/composer.json index 8090c70d0..3175a5cca 100644 --- a/composer.json +++ b/composer.json @@ -14,17 +14,19 @@ } ], "require": { - "php": ">=5.4", - "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*" + "php": ">=5.4" }, "require-dev": { "phpunit/phpunit": "4.3.*", "phpdocumentor/phpdocumentor": "2.*", - "predis/predis": "1.0.*" + "predis/predis": "1.0.*", + "guzzlehttp/guzzle": "5.*", + "guzzlehttp/cache-subscriber": "0.1.*" }, "suggested": { - "predis/predis": "1.0.*" + "predis/predis": "1.0.*", + "guzzlehttp/guzzle": "5.*", + "guzzlehttp/cache-subscriber": "0.1.*" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 1de9bc0cc..f2ede33d4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,43 +4,49 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "064d02ddae1114a6ecb771b0500ceccb", - "content-hash": "6d07711fd3a9d3fb5009b02b6a8cafee", - "packages": [ + "hash": "f5a8595175eee678f39a2da140508c08", + "content-hash": "e6826e132ec2fb5f3078914e11b6a5ff", + "packages": [], + "packages-dev": [ { - "name": "doctrine/cache", - "version": "v1.5.4", + "name": "cilex/cilex", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" + "url": "https://github.com/Cilex/Cilex.git", + "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "url": "https://api.github.com/repos/Cilex/Cilex/zipball/7acd965a609a56d0345e8b6071c261fbdb926cb5", + "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5", "shasum": "" }, "require": { - "php": ">=5.3.2" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" + "cilex/console-service-provider": "1.*", + "php": ">=5.3.3", + "pimple/pimple": "~1.0", + "symfony/finder": "~2.1", + "symfony/process": "~2.1" }, "require-dev": { - "phpunit/phpunit": ">=3.7", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" + "phpunit/phpunit": "3.7.*", + "symfony/validator": "~2.1" + }, + "suggest": { + "monolog/monolog": ">=1.0.0", + "symfony/validator": ">=1.0.0", + "symfony/yaml": ">=1.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + "psr-0": { + "Cilex": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -49,65 +55,50 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" } ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", + "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components", + "homepage": "http://cilex.github.com", "keywords": [ - "cache", - "caching" + "cli", + "microframework" ], - "time": "2015-12-19 05:03:47" + "time": "2014-03-29 14:03:13" }, { - "name": "guzzlehttp/cache-subscriber", - "version": "0.1.0", + "name": "cilex/console-service-provider", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/guzzle/cache-subscriber.git", - "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858" + "url": "https://github.com/Cilex/console-service-provider.git", + "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/cache-subscriber/zipball/ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", - "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", + "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/25ee3d1875243d38e1a3448ff94bdf944f70d24e", + "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e", "shasum": "" }, "require": { - "doctrine/cache": "~1.3", - "guzzlehttp/guzzle": "~5.0", - "php": ">=5.4.0" + "php": ">=5.3.3", + "pimple/pimple": "1.*@dev", + "symfony/console": "~2.1" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "cilex/cilex": "1.*@dev", + "silex/silex": "1.*@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.1-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-4": { - "GuzzleHttp\\Subscriber\\Cache\\": "src" + "psr-0": { + "Cilex\\Provider\\Console": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -116,112 +107,83 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" } ], - "description": "Guzzle HTTP cache subscriber", - "homepage": "http://guzzlephp.org/", + "description": "Console Service Provider", "keywords": [ - "Guzzle", - "cache" + "cilex", + "console", + "pimple", + "service-provider", + "silex" ], - "time": "2014-10-29 21:06:25" + "time": "2012-12-19 10:50:58" }, { - "name": "guzzlehttp/guzzle", - "version": "5.3.0", + "name": "container-interop/container-interop", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", "shasum": "" }, - "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\": "src/" + "Interop\\Container\\": "src/Interop/Container/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2015-05-20 03:47:55" + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" }, { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", + "name": "doctrine/annotations", + "version": "v1.2.7", "source": { "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + "url": "https://github.com/doctrine/annotations.git", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "shasum": "" }, "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" + "doctrine/lexer": "1.*", + "php": ">=5.3.2" }, "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" + "doctrine/cache": "1.*", + "phpunit/phpunit": "4.*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { - "psr-4": { - "GuzzleHttp\\Ring\\": "src/" + "psr-0": { + "Doctrine\\Common\\Annotations\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -230,43 +192,69 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2015-08-31 12:32:49" }, { - "name": "guzzlehttp/streams", - "version": "3.0.0", + "name": "doctrine/cache", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + "url": "https://github.com/doctrine/cache.git", + "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6", + "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "~5.5|~7.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8|~5.0", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Stream\\": "src/" + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -275,49 +263,68 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "Guzzle", - "stream" + "cache", + "caching" ], - "time": "2014-10-12 19:18:40" + "time": "2015-12-31 16:37:02" }, { - "name": "react/promise", - "version": "v2.2.1", + "name": "doctrine/instantiator", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -325,54 +332,45 @@ ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2015-07-03 13:48:55" - } - ], - "packages-dev": [ + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, { - "name": "cilex/cilex", - "version": "1.1.0", + "name": "doctrine/lexer", + "version": "v1.0.1", "source": { "type": "git", - "url": "https://github.com/Cilex/Cilex.git", - "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5" + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Cilex/Cilex/zipball/7acd965a609a56d0345e8b6071c261fbdb926cb5", - "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { - "cilex/console-service-provider": "1.*", - "php": ">=5.3.3", - "pimple/pimple": "~1.0", - "symfony/finder": "~2.1", - "symfony/process": "~2.1" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*", - "symfony/validator": "~2.1" - }, - "suggest": { - "monolog/monolog": ">=1.0.0", - "symfony/validator": ">=1.0.0", - "symfony/yaml": ">=1.0.0" + "php": ">=5.3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-0": { - "Cilex": "src/" + "Doctrine\\Common\\Lexer\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -381,50 +379,44 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components", - "homepage": "http://cilex.github.com", + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "cli", - "microframework" + "lexer", + "parser" ], - "time": "2014-03-29 14:03:13" + "time": "2014-09-09 13:34:57" }, { - "name": "cilex/console-service-provider", - "version": "1.0.0", + "name": "erusev/parsedown", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/Cilex/console-service-provider.git", - "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e" + "url": "https://github.com/erusev/parsedown.git", + "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/25ee3d1875243d38e1a3448ff94bdf944f70d24e", - "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", + "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", "shasum": "" }, - "require": { - "php": ">=5.3.3", - "pimple/pimple": "1.*@dev", - "symfony/console": "~2.1" - }, - "require-dev": { - "cilex/cilex": "1.*@dev", - "silex/silex": "1.*@dev" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "psr-0": { - "Cilex\\Provider\\Console": "src" + "Parsedown": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -433,56 +425,50 @@ ], "authors": [ { - "name": "Beau Simensen", - "email": "beau@dflydev.com", - "homepage": "http://beausimensen.com" - }, - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" } ], - "description": "Console Service Provider", + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", "keywords": [ - "cilex", - "console", - "pimple", - "service-provider", - "silex" + "markdown", + "parser" ], - "time": "2012-12-19 10:50:58" + "time": "2015-10-04 16:44:32" }, { - "name": "doctrine/annotations", - "version": "v1.2.7", + "name": "guzzlehttp/cache-subscriber", + "version": "0.1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" + "url": "https://github.com/guzzle/cache-subscriber.git", + "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "url": "https://api.github.com/repos/guzzle/cache-subscriber/zipball/ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", + "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": ">=5.3.2" + "doctrine/cache": "~1.3", + "guzzlehttp/guzzle": "~5.0", + "php": ">=5.4.0" }, "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "4.*" + "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "0.1-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Annotations\\": "lib/" + "psr-4": { + "GuzzleHttp\\Subscriber\\Cache\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -491,68 +477,51 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", + "description": "Guzzle HTTP cache subscriber", + "homepage": "http://guzzlephp.org/", "keywords": [ - "annotations", - "docblock", - "parser" + "Guzzle", + "cache" ], - "time": "2015-08-31 12:32:49" + "time": "2014-10-29 21:06:25" }, { - "name": "doctrine/instantiator", - "version": "1.0.5", + "name": "guzzlehttp/guzzle", + "version": "5.3.0", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "guzzlehttp/ringphp": "^1.1", + "php": ">=5.4.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -561,45 +530,59 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", "keywords": [ - "constructor", - "instantiate" + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" ], - "time": "2015-06-14 21:17:01" + "time": "2015-05-20 03:47:55" }, { - "name": "doctrine/lexer", - "version": "v1.0.1", + "name": "guzzlehttp/ringphp", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", "shasum": "" }, "require": { - "php": ">=5.3.2" + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -608,44 +591,43 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09 13:34:57" + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-05-20 03:37:09" }, { - "name": "erusev/parsedown", - "version": "1.6.0", + "name": "guzzlehttp/streams", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", "shasum": "" }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, "autoload": { - "psr-0": { - "Parsedown": "" + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -654,18 +636,18 @@ ], "authors": [ { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", "keywords": [ - "markdown", - "parser" + "Guzzle", + "stream" ], - "time": "2015-10-04 16:44:32" + "time": "2014-10-12 19:18:40" }, { "name": "herrera-io/json", @@ -714,8 +696,7 @@ { "name": "Kevin Herrera", "email": "kevin@herrera.io", - "homepage": "http://kevin.herrera.io/", - "role": "Developer" + "homepage": "http://kevin.herrera.io" } ], "description": "A library for simplifying JSON linting and validation.", @@ -774,8 +755,7 @@ { "name": "Kevin Herrera", "email": "kevin@herrera.io", - "homepage": "http://kevin.herrera.io/", - "role": "Developer" + "homepage": "http://kevin.herrera.io" } ], "description": "A library for self-updating Phars.", @@ -875,36 +855,41 @@ }, { "name": "jms/serializer", - "version": "0.16.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "c8a171357ca92b6706e395c757f334902d430ea9" + "reference": "fe13a1f993ea3456e195b7820692f2eb2b6bbb48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/c8a171357ca92b6706e395c757f334902d430ea9", - "reference": "c8a171357ca92b6706e395c757f334902d430ea9", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/fe13a1f993ea3456e195b7820692f2eb2b6bbb48", + "reference": "fe13a1f993ea3456e195b7820692f2eb2b6bbb48", "shasum": "" }, "require": { "doctrine/annotations": "1.*", + "doctrine/instantiator": "~1.0.3", "jms/metadata": "~1.1", "jms/parser-lib": "1.*", - "php": ">=5.3.2", + "php": ">=5.4.0", "phpcollection/phpcollection": "~0.1" }, + "conflict": { + "twig/twig": "<1.12" + }, "require-dev": { "doctrine/orm": "~2.1", "doctrine/phpcr-odm": "~1.0.1", "jackalope/jackalope-doctrine-dbal": "1.0.*", + "phpunit/phpunit": "~4.0", "propel/propel1": "~1.7", "symfony/filesystem": "2.*", "symfony/form": "~2.1", "symfony/translation": "~2.0", "symfony/validator": "~2.0", "symfony/yaml": "2.*", - "twig/twig": ">=1.8,<2.0-dev" + "twig/twig": "~1.12|~2.0" }, "suggest": { "symfony/yaml": "Required if you'd like to serialize data to YAML format." @@ -912,7 +897,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.15-dev" + "dev-master": "1.1-dev" } }, "autoload": { @@ -926,10 +911,8 @@ ], "authors": [ { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" } ], "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", @@ -941,7 +924,7 @@ "serialization", "xml" ], - "time": "2014-03-18 08:39:00" + "time": "2015-10-27 09:24:41" }, { "name": "justinrainbow/json-schema", @@ -1044,8 +1027,7 @@ "authors": [ { "name": "Kevin Herrera", - "email": "me@kevingh.com", - "homepage": "http://www.kevingh.com/" + "email": "me@kevingh.com" } ], "description": "A parsing and comparison library for semantic versioning.", @@ -1054,16 +1036,16 @@ }, { "name": "monolog/monolog", - "version": "1.17.2", + "version": "1.19.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24" + "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bee7f0dc9c3e0b69a6039697533dca1e845c8c24", - "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf", + "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf", "shasum": "" }, "require": { @@ -1078,13 +1060,13 @@ "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", - "swiftmailer/swiftmailer": "~5.3", - "videlalvaro/php-amqplib": "~2.4" + "swiftmailer/swiftmailer": "~5.3" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", @@ -1092,16 +1074,17 @@ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.16.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1127,36 +1110,36 @@ "logging", "psr-3" ], - "time": "2015-10-14 12:51:02" + "time": "2016-04-12 18:29:35" }, { "name": "nikic/php-parser", - "version": "v0.9.5", + "version": "v1.4.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb" + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.2" + "php": ">=5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.9-dev" + "dev-master": "1.4-dev" } }, "autoload": { - "psr-0": { - "PHPParser": "lib/" - } + "files": [ + "lib/bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1172,7 +1155,7 @@ "parser", "php" ], - "time": "2014-07-23 18:24:17" + "time": "2015-09-19 14:15:08" }, { "name": "phpcollection/phpcollection", @@ -1269,23 +1252,23 @@ }, { "name": "phpdocumentor/graphviz", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/GraphViz.git", - "reference": "aa243118c8a055fc853c02802e8503c5435862f7" + "reference": "a906a90a9f230535f25ea31caf81b2323956283f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/aa243118c8a055fc853c02802e8503c5435862f7", - "reference": "aa243118c8a055fc853c02802e8503c5435862f7", + "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/a906a90a9f230535f25ea31caf81b2323956283f", + "reference": "a906a90a9f230535f25ea31caf81b2323956283f", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~3.7" + "phpunit/phpunit": "~4.0" }, "type": "library", "autoload": { @@ -1306,32 +1289,32 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2014-07-19 06:52:59" + "time": "2016-02-02 13:00:08" }, { "name": "phpdocumentor/phpdocumentor", - "version": "v2.8.5", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/phpDocumentor2.git", - "reference": "adfb4affa80e8cc0134616f2d2d264dd25c243eb" + "reference": "be607da0eef9b9249c43c5b4820d25d631c73667" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/adfb4affa80e8cc0134616f2d2d264dd25c243eb", - "reference": "adfb4affa80e8cc0134616f2d2d264dd25c243eb", + "url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/be607da0eef9b9249c43c5b4820d25d631c73667", + "reference": "be607da0eef9b9249c43c5b4820d25d631c73667", "shasum": "" }, "require": { "cilex/cilex": "~1.0", "erusev/parsedown": "~1.0", "herrera-io/phar-update": "1.0.3", - "jms/serializer": "~0.12", + "jms/serializer": ">=0.12", "monolog/monolog": "~1.6", "php": ">=5.3.3", "phpdocumentor/fileset": "~1.0", "phpdocumentor/graphviz": "~1.0", - "phpdocumentor/reflection": "~1.0", + "phpdocumentor/reflection": "^3.0", "phpdocumentor/reflection-docblock": "~2.0", "symfony/config": "~2.3", "symfony/console": "~2.3", @@ -1395,24 +1378,24 @@ "documentation", "phpdoc" ], - "time": "2015-07-28 06:36:40" + "time": "2016-05-22 09:50:56" }, { "name": "phpdocumentor/reflection", - "version": "1.0.7", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Reflection.git", - "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372" + "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/fc40c3f604ac2287eb5c314174d5109b2c699372", - "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", + "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", "shasum": "" }, "require": { - "nikic/php-parser": "~0.9.4", + "nikic/php-parser": "^1.0", "php": ">=5.3.3", "phpdocumentor/reflection-docblock": "~2.0", "psr/log": "~1.0" @@ -1449,7 +1432,7 @@ "reflection", "static analysis" ], - "time": "2014-11-14 11:43:04" + "time": "2016-05-21 08:42:32" }, { "name": "phpdocumentor/reflection-docblock", @@ -1700,21 +1683,24 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -1737,7 +1723,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", @@ -1966,23 +1952,23 @@ }, { "name": "predis/predis", - "version": "v1.0.3", + "version": "v1.0.4", "source": { "type": "git", "url": "https://github.com/nrk/predis.git", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04" + "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/84060b9034d756b4d79641667d7f9efe1aeb8e04", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04", + "url": "https://api.github.com/repos/nrk/predis/zipball/9ead747663bb1b1ae017dfa0d152aca87792b42f", + "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f", "shasum": "" }, "require": { "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8" }, "suggest": { "ext-curl": "Allows access to Webdis when paired with phpiredis", @@ -2005,14 +1991,14 @@ "homepage": "http://clorophilla.net" } ], - "description": "Flexible and feature-complete PHP client library for Redis", + "description": "Flexible and feature-complete Redis client for PHP and HHVM", "homepage": "http://github.com/nrk/predis", "keywords": [ "nosql", "predis", "redis" ], - "time": "2015-07-30 18:34:15" + "time": "2016-05-30 15:25:52" }, { "name": "psr/log", @@ -2052,6 +2038,50 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "react/promise", + "version": "v2.4.1", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8025426794f1944de806618671d4fa476dc7626f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8025426794f1944de806618671d4fa476dc7626f", + "reference": "8025426794f1944de806618671d4fa476dc7626f", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "time": "2016-05-03 17:50:52" + }, { "name": "sebastian/comparator", "version": "1.2.0", @@ -2170,16 +2200,16 @@ }, { "name": "sebastian/environment", - "version": "1.3.3", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e7133793a8e5a5714a551a8324337374be209df" + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", - "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", "shasum": "" }, "require": { @@ -2216,20 +2246,20 @@ "environment", "hhvm" ], - "time": "2015-12-02 08:37:27" + "time": "2016-05-17 03:18:57" }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { @@ -2237,12 +2267,13 @@ "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -2282,7 +2313,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2016-06-17 09:04:28" }, { "name": "sebastian/recursion-context", @@ -2420,22 +2451,25 @@ }, { "name": "symfony/config", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74" + "reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", - "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74", + "url": "https://api.github.com/repos/symfony/config/zipball/a2edd59c2163c65747fc3f35d132b5a39266bd05", + "reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05", "shasum": "" }, "require": { "php": ">=5.3.9", "symfony/filesystem": "~2.3|~3.0.0" }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, "type": "library", "extra": { "branch-alias": { @@ -2466,20 +2500,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:33:41" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/console", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d" + "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d", - "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d", + "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", + "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", "shasum": "" }, "require": { @@ -2526,20 +2560,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-01-14 08:33:16" + "time": "2016-06-06 15:06:25" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda" + "reference": "2a6b8713f8bdb582058cfda463527f195b066110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ee278f7c851533e58ca307f66305ccb9188aceda", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110", + "reference": "2a6b8713f8bdb582058cfda463527f195b066110", "shasum": "" }, "require": { @@ -2586,29 +2620,29 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/filesystem", - "version": "v2.8.2", + "version": "v3.0.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c" + "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/74fec3511b62cb934b64bce1d96f06fffa4beafd", + "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2635,20 +2669,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-04-12 18:09:53" }, { "name": "symfony/finder", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "c90fabdd97e431ee19b6383999cf35334dff27da" + "reference": "3ec095fab1800222732ca522a95dce8fa124007b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/c90fabdd97e431ee19b6383999cf35334dff27da", - "reference": "c90fabdd97e431ee19b6383999cf35334dff27da", + "url": "https://api.github.com/repos/symfony/finder/zipball/3ec095fab1800222732ca522a95dce8fa124007b", + "reference": "3ec095fab1800222732ca522a95dce8fa124007b", "shasum": "" }, "require": { @@ -2684,20 +2718,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-01-14 08:26:52" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -2709,7 +2743,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2743,20 +2777,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/process", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac" + "reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac", - "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac", + "url": "https://api.github.com/repos/symfony/process/zipball/115347d00c342198cdc52a7bd8bc15b5ab43500c", + "reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c", "shasum": "" }, "require": { @@ -2792,20 +2826,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-01-06 09:59:23" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/stopwatch", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73" + "reference": "5e628055488bcc42dbace3af65be435d094e37e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e3bc8e2a984f4382690a438c8bb650f3ffd71e73", - "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5e628055488bcc42dbace3af65be435d094e37e4", + "reference": "5e628055488bcc42dbace3af65be435d094e37e4", "shasum": "" }, "require": { @@ -2841,34 +2875,34 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:33:41" + "time": "2016-06-06 11:11:27" }, { "name": "symfony/translation", - "version": "v2.8.2", + "version": "v3.0.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "bc0b666903944858f4ffec01c4e50c63e5c276c0" + "reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bc0b666903944858f4ffec01c4e50c63e5c276c0", - "reference": "bc0b666903944858f4ffec01c4e50c63e5c276c0", + "url": "https://api.github.com/repos/symfony/translation/zipball/2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7", + "reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7", "shasum": "" }, "require": { - "php": ">=5.3.9", + "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/config": "<2.7" + "symfony/config": "<2.8" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8", - "symfony/intl": "~2.4|~3.0.0", - "symfony/yaml": "~2.2|~3.0.0" + "symfony/config": "~2.8|~3.0", + "symfony/intl": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" }, "suggest": { "psr/log": "To use logging capability in translator", @@ -2878,7 +2912,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2905,24 +2939,25 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:33:41" + "time": "2016-06-06 11:33:26" }, { "name": "symfony/validator", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "7a325d73cb492d244d9107406fe40650ac070a04" + "reference": "4c8f9fd8e2150dbc4745ef13378e690588365df0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/7a325d73cb492d244d9107406fe40650ac070a04", - "reference": "7a325d73cb492d244d9107406fe40650ac070a04", + "url": "https://api.github.com/repos/symfony/validator/zipball/4c8f9fd8e2150dbc4745ef13378e690588365df0", + "reference": "4c8f9fd8e2150dbc4745ef13378e690588365df0", "shasum": "" }, "require": { "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0", "symfony/translation": "~2.4|~3.0.0" }, "require-dev": { @@ -2932,7 +2967,7 @@ "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/http-foundation": "~2.1|~3.0.0", - "symfony/intl": "~2.4|~3.0.0", + "symfony/intl": "~2.7.4|~2.8|~3.0.0", "symfony/property-access": "~2.3|~3.0.0", "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" }, @@ -2977,20 +3012,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-01-12 17:46:01" + "time": "2016-04-14 08:48:44" }, { "name": "symfony/yaml", - "version": "v2.8.2", + "version": "v2.8.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8" + "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/34c8a4b51e751e7ea869b8262f883d008a2b81b8", - "reference": "34c8a4b51e751e7ea869b8262f883d008a2b81b8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34", + "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34", "shasum": "" }, "require": { @@ -3026,20 +3061,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-06-06 11:11:27" }, { "name": "twig/twig", - "version": "v1.24.0", + "version": "v1.24.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8" + "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", - "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512", + "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512", "shasum": "" }, "require": { @@ -3087,40 +3122,45 @@ "keywords": [ "templating" ], - "time": "2016-01-25 21:22:18" + "time": "2016-05-30 09:11:59" }, { "name": "zendframework/zend-cache", - "version": "2.5.1", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-cache.git", - "reference": "5999e5a03f7dcf82abbbe67eea74da641f959684" + "reference": "2c68def8f96ce842d2f2a9a69e2f3508c2f5312d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/5999e5a03f7dcf82abbbe67eea74da641f959684", - "reference": "5999e5a03f7dcf82abbbe67eea74da641f959684", + "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/2c68def8f96ce842d2f2a9a69e2f3508c2f5312d", + "reference": "2c68def8f96ce842d2f2a9a69e2f3508c2f5312d", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-eventmanager": "~2.5", - "zendframework/zend-serializer": "~2.5", - "zendframework/zend-servicemanager": "~2.5", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0", - "zendframework/zend-session": "~2.5" + "phpbench/phpbench": "^0.10.0", + "phpunit/phpunit": "^4.5", + "zendframework/zend-serializer": "^2.6", + "zendframework/zend-session": "^2.6.2" }, "suggest": { - "ext-apc": "APC >= 3.1.6 to use the APC storage adapter", + "ext-apc": "APC or compatible extension, to use the APC storage adapter", + "ext-apcu": "APCU >= 5.1.0, to use the APCu storage adapter", "ext-dba": "DBA, to use the DBA storage adapter", + "ext-memcache": "Memcache >= 2.0.0 to use the Memcache storage adapter", "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter", "ext-mongo": "Mongo, to use MongoDb storage adapter", + "ext-redis": "Redis, to use Redis storage adapter", "ext-wincache": "WinCache, to use the WinCache storage adapter", + "ext-xcache": "XCache, to use the XCache storage adapter", "mongofill/mongofill": "Alternative to ext-mongo - a pure PHP implementation designed as a drop in replacement", "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-session": "Zend\\Session component" @@ -3128,8 +3168,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\Cache", + "config-provider": "Zend\\Cache\\ConfigProvider" } }, "autoload": { @@ -3147,34 +3191,33 @@ "cache", "zf2" ], - "time": "2015-06-03 15:31:59" + "time": "2016-05-12 21:47:55" }, { "name": "zendframework/zend-config", - "version": "2.5.1", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-config.git", - "reference": "ec49b1df1bdd9772df09dc2f612fbfc279bf4c27" + "reference": "2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-config/zipball/ec49b1df1bdd9772df09dc2f612fbfc279bf4c27", - "reference": "ec49b1df1bdd9772df09dc2f612fbfc279bf4c27", + "url": "https://api.github.com/repos/zendframework/zend-config/zipball/2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d", + "reference": "2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-filter": "~2.5", - "zendframework/zend-i18n": "~2.5", - "zendframework/zend-json": "~2.5", - "zendframework/zend-mvc": "~2.5", - "zendframework/zend-servicemanager": "~2.5" + "zendframework/zend-filter": "^2.6", + "zendframework/zend-i18n": "^2.5", + "zendframework/zend-json": "^2.6.1", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { "zendframework/zend-filter": "Zend\\Filter component", @@ -3185,8 +3228,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" } }, "autoload": { @@ -3204,35 +3247,41 @@ "config", "zf2" ], - "time": "2015-06-03 15:32:00" + "time": "2016-02-04 23:01:10" }, { "name": "zendframework/zend-eventmanager", - "version": "2.5.1", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "d94a16039144936f107f906896349900fd634443" + "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/d94a16039144936f107f906896349900fd634443", - "reference": "d94a16039144936f107f906896349900fd634443", + "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/5c80bdee0e952be112dcec0968bad770082c3a6e", + "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0" + "athletic/athletic": "^0.1", + "container-interop/container-interop": "^1.1.0", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^2.0", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0" + }, + "suggest": { + "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -3244,52 +3293,57 @@ "license": [ "BSD-3-Clause" ], + "description": "Trigger and listen to events within a PHP application", "homepage": "https://github.com/zendframework/zend-eventmanager", "keywords": [ + "event", "eventmanager", + "events", "zf2" ], - "time": "2015-06-03 15:32:01" + "time": "2016-02-18 20:53:00" }, { "name": "zendframework/zend-filter", - "version": "2.5.1", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-filter.git", - "reference": "93e6990a198e6cdd811064083acac4693f4b29ae" + "reference": "84c50246428efb0a1e52868e162dab3e149d5b80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/93e6990a198e6cdd811064083acac4693f4b29ae", - "reference": "93e6990a198e6cdd811064083acac4693f4b29ae", + "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/84c50246428efb0a1e52868e162dab3e149d5b80", + "reference": "84c50246428efb0a1e52868e162dab3e149d5b80", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", + "pear/archive_tar": "^1.4", "phpunit/phpunit": "~4.0", - "zendframework/zend-config": "~2.5", - "zendframework/zend-crypt": "~2.5", - "zendframework/zend-i18n": "~2.5", - "zendframework/zend-loader": "~2.5", - "zendframework/zend-servicemanager": "~2.5", - "zendframework/zend-uri": "~2.5" + "zendframework/zend-crypt": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-uri": "^2.5" }, "suggest": { - "zendframework/zend-crypt": "Zend\\Crypt component", - "zendframework/zend-i18n": "Zend\\I18n component", - "zendframework/zend-servicemanager": "Zend\\ServiceManager component", - "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter" + "zendframework/zend-crypt": "Zend\\Crypt component, for encryption filters", + "zendframework/zend-i18n": "Zend\\I18n component for filters depending on i18n functionality", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for using the filter chain functionality", + "zendframework/zend-uri": "Zend\\Uri component, for the UriNormalize filter" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\Filter", + "config-provider": "Zend\\Filter\\ConfigProvider" } }, "autoload": { @@ -3307,210 +3361,226 @@ "filter", "zf2" ], - "time": "2015-06-03 15:32:01" + "time": "2016-04-18 18:32:43" }, { - "name": "zendframework/zend-i18n", - "version": "2.5.1", + "name": "zendframework/zend-hydrator", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-i18n.git", - "reference": "509271eb7947e4aabebfc376104179cffea42696" + "url": "https://github.com/zendframework/zend-hydrator.git", + "reference": "22652e1661a5a10b3f564cf7824a2206cf5a4a65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/509271eb7947e4aabebfc376104179cffea42696", - "reference": "509271eb7947e4aabebfc376104179cffea42696", + "url": "https://api.github.com/repos/zendframework/zend-hydrator/zipball/22652e1661a5a10b3f564cf7824a2206cf5a4a65", + "reference": "22652e1661a5a10b3f564cf7824a2206cf5a4a65", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-cache": "~2.5", - "zendframework/zend-config": "~2.5", - "zendframework/zend-eventmanager": "~2.5", - "zendframework/zend-filter": "~2.5", - "zendframework/zend-servicemanager": "~2.5", - "zendframework/zend-validator": "~2.5", - "zendframework/zend-view": "~2.5" + "squizlabs/php_codesniffer": "^2.0@dev", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-inputfilter": "^2.6", + "zendframework/zend-serializer": "^2.6.1", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { - "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", - "zendframework/zend-cache": "Zend\\Cache component", - "zendframework/zend-config": "Zend\\Config component", - "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", - "zendframework/zend-filter": "You should install this package to use the provided filters", - "zendframework/zend-resources": "Translation resources", - "zendframework/zend-servicemanager": "Zend\\ServiceManager component", - "zendframework/zend-validator": "You should install this package to use the provided validators", - "zendframework/zend-view": "You should install this package to use the provided view helpers" + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, to support aggregate hydrator usage", + "zendframework/zend-filter": "^2.6, to support naming strategy hydrator usage", + "zendframework/zend-serializer": "^2.6.1, to use the SerializableStrategy", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, to support hydrator plugin manager usage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-release-1.0": "1.0-dev", + "dev-release-1.1": "1.1-dev", + "dev-master": "2.0-dev", + "dev-develop": "2.1-dev" } }, "autoload": { "psr-4": { - "Zend\\I18n\\": "src/" + "Zend\\Hydrator\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-i18n", + "homepage": "https://github.com/zendframework/zend-hydrator", "keywords": [ - "i18n", + "hydrator", "zf2" ], - "time": "2015-06-03 15:32:01" + "time": "2016-02-18 22:38:26" }, { - "name": "zendframework/zend-json", - "version": "2.5.1", + "name": "zendframework/zend-i18n", + "version": "2.7.3", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-json.git", - "reference": "c74eaf17d2dd37dc1e964be8dfde05706a821ebc" + "url": "https://github.com/zendframework/zend-i18n.git", + "reference": "b2db0d8246a865c659f93199f90f5fc2cd2f3cd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/c74eaf17d2dd37dc1e964be8dfde05706a821ebc", - "reference": "c74eaf17d2dd37dc1e964be8dfde05706a821ebc", + "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/b2db0d8246a865c659f93199f90f5fc2cd2f3cd8", + "reference": "b2db0d8246a865c659f93199f90f5fc2cd2f3cd8", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-http": "~2.5", - "zendframework/zend-server": "~2.5", - "zendframework/zendxml": "~1.0" + "zendframework/zend-cache": "^2.6.1", + "zendframework/zend-config": "^2.6", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0", + "zendframework/zend-filter": "^2.6.1", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-validator": "^2.6", + "zendframework/zend-view": "^2.6.3" }, "suggest": { - "zendframework/zend-http": "Zend\\Http component", - "zendframework/zend-server": "Zend\\Server component", - "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", + "zendframework/zend-cache": "Zend\\Cache component", + "zendframework/zend-config": "Zend\\Config component", + "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", + "zendframework/zend-filter": "You should install this package to use the provided filters", + "zendframework/zend-i18n-resources": "Translation resources", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component", + "zendframework/zend-validator": "You should install this package to use the provided validators", + "zendframework/zend-view": "You should install this package to use the provided view helpers" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\I18n", + "config-provider": "Zend\\I18n\\ConfigProvider" } }, "autoload": { "psr-4": { - "Zend\\Json\\": "src/" + "Zend\\I18n\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", - "homepage": "https://github.com/zendframework/zend-json", + "homepage": "https://github.com/zendframework/zend-i18n", "keywords": [ - "json", + "i18n", "zf2" ], - "time": "2015-06-03 15:32:01" + "time": "2016-06-07 21:08:30" }, { - "name": "zendframework/zend-math", - "version": "2.5.1", + "name": "zendframework/zend-json", + "version": "2.6.1", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-math.git", - "reference": "9f02a1ac4d3374d3332c80f9215deec9c71558fc" + "url": "https://github.com/zendframework/zend-json.git", + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-math/zipball/9f02a1ac4d3374d3332c80f9215deec9c71558fc", - "reference": "9f02a1ac4d3374d3332c80f9215deec9c71558fc", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", "shasum": "" }, "require": { - "php": ">=5.3.23" + "php": "^5.5 || ^7.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", - "ircmaxell/random-lib": "~1.1", "phpunit/phpunit": "~4.0", - "zendframework/zend-servicemanager": "~2.5" + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-server": "^2.6.1", + "zendframework/zend-stdlib": "^2.5 || ^3.0", + "zendframework/zendxml": "^1.0.2" }, "suggest": { - "ext-bcmath": "If using the bcmath functionality", - "ext-gmp": "If using the gmp functionality", - "ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable", - "zendframework/zend-servicemanager": ">= current version, if using the BigInteger::factory functionality" + "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", + "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", + "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", + "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" } }, "autoload": { "psr-4": { - "Zend\\Math\\": "src/" + "Zend\\Json\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-math", + "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", + "homepage": "https://github.com/zendframework/zend-json", "keywords": [ - "math", + "json", "zf2" ], - "time": "2015-06-03 15:32:02" + "time": "2016-02-04 21:20:26" }, { "name": "zendframework/zend-serializer", - "version": "2.5.1", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "b7208eb17dc4a4fb3a660b85e6c4af035eeed40c" + "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/b7208eb17dc4a4fb3a660b85e6c4af035eeed40c", - "reference": "b7208eb17dc4a4fb3a660b85e6c4af035eeed40c", + "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/95385c2342fc335d5164eb95ac3ca230aa51223b", + "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b", "shasum": "" }, "require": { - "php": ">=5.3.23", - "zendframework/zend-json": "~2.5", - "zendframework/zend-math": "~2.5", - "zendframework/zend-stdlib": "~2.5" + "php": "^5.5 || ^7.0", + "zendframework/zend-json": "^2.5", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0", - "zendframework/zend-servicemanager": "~2.5" + "phpunit/phpunit": "^4.5", + "zendframework/zend-math": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { + "zendframework/zend-math": "(^2.6) To support Python Pickle serialization", "zendframework/zend-servicemanager": "To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\Serializer", + "config-provider": "Zend\\Serializer\\ConfigProvider" } }, "autoload": { @@ -3528,26 +3598,28 @@ "serializer", "zf2" ], - "time": "2015-06-03 15:32:02" + "time": "2016-05-11 16:05:56" }, { "name": "zendframework/zend-servicemanager", - "version": "2.5.1", + "version": "2.7.6", "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", - "reference": "3b22c403e351d92526c642cba0bd810bc22e1c56" + "reference": "a6db4d13b9141fccce5dcb553df0295d6ad7d477" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/3b22c403e351d92526c642cba0bd810bc22e1c56", - "reference": "3b22c403e351d92526c642cba0bd810bc22e1c56", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/a6db4d13b9141fccce5dcb553df0295d6ad7d477", + "reference": "a6db4d13b9141fccce5dcb553df0295d6ad7d477", "shasum": "" }, "require": { - "php": ">=5.3.23" + "container-interop/container-interop": "~1.0", + "php": "^5.5 || ^7.0" }, "require-dev": { + "athletic/athletic": "dev-master", "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "zendframework/zend-di": "~2.5", @@ -3560,8 +3632,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.7-dev", + "dev-develop": "3.0-dev" } }, "autoload": { @@ -3578,26 +3650,28 @@ "servicemanager", "zf2" ], - "time": "2015-06-03 15:32:02" + "time": "2016-04-27 19:07:40" }, { "name": "zendframework/zend-stdlib", - "version": "2.5.1", + "version": "2.7.7", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae" + "reference": "0e44eb46788f65e09e077eb7f44d2659143bcc1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cc8e90a60dd5d44b9730b77d07b97550091da1ae", - "reference": "cc8e90a60dd5d44b9730b77d07b97550091da1ae", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/0e44eb46788f65e09e077eb7f44d2659143bcc1f", + "reference": "0e44eb46788f65e09e077eb7f44d2659143bcc1f", "shasum": "" }, "require": { - "php": ">=5.3.23" + "php": "^5.5 || ^7.0", + "zendframework/zend-hydrator": "~1.1" }, "require-dev": { + "athletic/athletic": "~0.1", "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "zendframework/zend-config": "~2.5", @@ -3616,8 +3690,9 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-release-2.7": "2.7-dev", + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -3634,7 +3709,7 @@ "stdlib", "zf2" ], - "time": "2015-06-03 15:32:03" + "time": "2016-04-12 21:17:31" }, { "name": "zetacomponents/base", From b696bed9d46065157c2b01f60d7afca2698b8164 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 09:52:21 +0100 Subject: [PATCH 009/150] Increase minimum PHP version to 5.5 --- composer.json | 2 +- composer.lock | 57 +++++++++++++++++++++++---------------------------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/composer.json b/composer.json index 3175a5cca..26a3e6cbc 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": ">=5.4" + "php": ">=5.5" }, "require-dev": { "phpunit/phpunit": "4.3.*", diff --git a/composer.lock b/composer.lock index f2ede33d4..bfffec6d8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f5a8595175eee678f39a2da140508c08", - "content-hash": "e6826e132ec2fb5f3078914e11b6a5ff", + "hash": "8447a4d78290846b80eb345bef044bcc", + "content-hash": "0181f320c92ccfc7bee8cb65eb4ac84f", "packages": [], "packages-dev": [ { @@ -3490,40 +3490,35 @@ }, { "name": "zendframework/zend-json", - "version": "2.6.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-http": "^2.5.4", - "zendframework/zend-server": "^2.6.1", - "zendframework/zend-stdlib": "^2.5 || ^3.0", - "zendframework/zendxml": "^1.0.2" + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "suggest": { - "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", - "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", - "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", - "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev", - "dev-develop": "2.7-dev" + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -3541,42 +3536,42 @@ "json", "zf2" ], - "time": "2016-02-04 21:20:26" + "time": "2016-04-01 02:34:00" }, { "name": "zendframework/zend-serializer", - "version": "2.7.2", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b" + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/95385c2342fc335d5164eb95ac3ca230aa51223b", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b", + "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/ff74ea020f5f90866eb28365327e9bc765a61a6e", + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "zendframework/zend-json": "^2.5", + "php": "^5.6 || ^7.0", + "zendframework/zend-json": "^2.5 || ^3.0", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "^4.5", + "squizlabs/php_codesniffer": "^2.3.1", "zendframework/zend-math": "^2.6", "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { - "zendframework/zend-math": "(^2.6) To support Python Pickle serialization", - "zendframework/zend-servicemanager": "To support plugin manager support" + "zendframework/zend-math": "(^2.6 || ^3.0) To support Python Pickle serialization", + "zendframework/zend-servicemanager": "(^2.7.5 || ^3.0.3) To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev", - "dev-develop": "2.8-dev" + "dev-master": "2.8-dev", + "dev-develop": "2.9-dev" }, "zf": { "component": "Zend\\Serializer", @@ -3598,7 +3593,7 @@ "serializer", "zf2" ], - "time": "2016-05-11 16:05:56" + "time": "2016-06-21 17:01:55" }, { "name": "zendframework/zend-servicemanager", @@ -3832,7 +3827,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.4" + "php": ">=5.5" }, "platform-dev": [] } From 51cf2e6e363423e8361e716e9be10687d991902c Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 09:57:42 +0100 Subject: [PATCH 010/150] Use php 5.5.36 for circleci --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 77aae221c..cd4feda0d 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: php: - version: 5.4.37 + version: 5.5.36 test: override: From 4000f3711bad6f7623860bdd98f2225d863552d7 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 10:41:34 +0100 Subject: [PATCH 011/150] Use a supported version of php 5.5 for circleci --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index cd4feda0d..7347245d3 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: php: - version: 5.5.36 + version: 5.5.21 test: override: From a0a8ca4a79a31d07d219af0edd76acb156f8e6f9 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 10:59:27 +0100 Subject: [PATCH 012/150] Fix zend-serializer version to 2.7.* to avoid php 5.6 requirement --- composer.json | 3 ++- composer.lock | 55 ++++++++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/composer.json b/composer.json index 26a3e6cbc..619920a78 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*" + "guzzlehttp/cache-subscriber": "0.1.*", + "zendframework/zend-serializer": "2.7.*" }, "suggested": { "predis/predis": "1.0.*", diff --git a/composer.lock b/composer.lock index bfffec6d8..f39545b62 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8447a4d78290846b80eb345bef044bcc", - "content-hash": "0181f320c92ccfc7bee8cb65eb4ac84f", + "hash": "8e26de8025132073d145955629729e1f", + "content-hash": "d5cb0a55912cef78c91c89c53e3e414a", "packages": [], "packages-dev": [ { @@ -3490,35 +3490,40 @@ }, { "name": "zendframework/zend-json", - "version": "3.0.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", - "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "^2.3", - "zendframework/zend-stdlib": "^2.7 || ^3.0" + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-server": "^2.6.1", + "zendframework/zend-stdlib": "^2.5 || ^3.0", + "zendframework/zendxml": "^1.0.2" }, "suggest": { - "zendframework/zend-json-server": "For implementing JSON-RPC servers", - "zendframework/zend-xml2json": "For converting XML documents to JSON" + "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", + "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", + "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", + "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev", - "dev-develop": "3.1-dev" + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" } }, "autoload": { @@ -3536,42 +3541,42 @@ "json", "zf2" ], - "time": "2016-04-01 02:34:00" + "time": "2016-02-04 21:20:26" }, { "name": "zendframework/zend-serializer", - "version": "2.8.0", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e" + "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/ff74ea020f5f90866eb28365327e9bc765a61a6e", - "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e", + "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/95385c2342fc335d5164eb95ac3ca230aa51223b", + "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "zendframework/zend-json": "^2.5 || ^3.0", + "php": "^5.5 || ^7.0", + "zendframework/zend-json": "^2.5", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "^4.5", - "squizlabs/php_codesniffer": "^2.3.1", "zendframework/zend-math": "^2.6", "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { - "zendframework/zend-math": "(^2.6 || ^3.0) To support Python Pickle serialization", - "zendframework/zend-servicemanager": "(^2.7.5 || ^3.0.3) To support plugin manager support" + "zendframework/zend-math": "(^2.6) To support Python Pickle serialization", + "zendframework/zend-servicemanager": "To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev", - "dev-develop": "2.9-dev" + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" }, "zf": { "component": "Zend\\Serializer", @@ -3593,7 +3598,7 @@ "serializer", "zf2" ], - "time": "2016-06-21 17:01:55" + "time": "2016-05-11 16:05:56" }, { "name": "zendframework/zend-servicemanager", From bbc7bb0935bdccc42e6e0dd8878be35ae4c834c7 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 12:37:46 +0100 Subject: [PATCH 013/150] Add missing property declaration --- src/LaunchDarkly/GuzzleFeatureRequester.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index c6f41bce5..b8a144afe 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -6,6 +6,9 @@ use \GuzzleHttp\Subscriber\Cache\CacheSubscriber; class GuzzleFeatureRequester implements FeatureRequester { + + private $_client; + function __construct($baseUri, $apiKey, $options) { $this->_client = new Client(array( 'base_url' => $baseUri, From 656bc91bfab5fb26e447484aa6a91528c247c755 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 14 Jul 2016 11:13:28 +0100 Subject: [PATCH 014/150] Update to latest stable phpunit Conflicts: composer.lock Conflicts: composer.lock --- composer.json | 2 +- composer.lock | 544 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 426 insertions(+), 120 deletions(-) diff --git a/composer.json b/composer.json index 619920a78..8c480f33d 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "4.3.*", + "phpunit/phpunit": "5.4.*", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "guzzlehttp/guzzle": "5.*", diff --git a/composer.lock b/composer.lock index f39545b62..225917718 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8e26de8025132073d145955629729e1f", - "content-hash": "d5cb0a55912cef78c91c89c53e3e414a", + "hash": "533cfcae075fafcc50bf6802045e3774", + "content-hash": "147e48629bec68e213283c6a8eec9778", "packages": [], "packages-dev": [ { @@ -1036,16 +1036,16 @@ }, { "name": "monolog/monolog", - "version": "1.19.0", + "version": "1.20.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf" + "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf", - "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037", + "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037", "shasum": "" }, "require": { @@ -1064,8 +1064,8 @@ "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", - "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", "swiftmailer/swiftmailer": "~5.3" }, "suggest": { @@ -1077,9 +1077,9 @@ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", - "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" }, "type": "library", "extra": { @@ -1110,7 +1110,49 @@ "logging", "psr-3" ], - "time": "2016-04-12 18:29:35" + "time": "2016-07-02 14:02:10" + }, + { + "name": "myclabs/deep-copy", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "a8773992b362b58498eed24bf85005f363c34771" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a8773992b362b58498eed24bf85005f363c34771", + "reference": "a8773992b362b58498eed24bf85005f363c34771", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2015-11-20 12:04:31" }, { "name": "nikic/php-parser", @@ -1533,41 +1575,104 @@ ], "time": "2015-07-25 16:39:46" }, + { + "name": "phpspec/prophecy", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-06-07 08:13:47" + }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/900370c81280cc0d942ffbc5912d80464eaee7e9", + "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": "^5.6 || ^7.0", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "sebastian/version": "~1.0|~2.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.2.1", + "ext-xdebug": ">=2.4.0", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -1593,35 +1698,37 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2016-06-03 05:03:56" }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -1638,7 +1745,7 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", @@ -1776,16 +1883,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.3.5", + "version": "5.4.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2dab9d593997db4abcf58d0daf798eb4e9cecfe1" + "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2dab9d593997db4abcf58d0daf798eb4e9cecfe1", - "reference": "2dab9d593997db4abcf58d0daf798eb4e9cecfe1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", + "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", "shasum": "" }, "require": { @@ -1794,18 +1901,26 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": "~2.0", - "phpunit/php-file-iterator": "~1.3.2", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "^4.0", + "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.0", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.0", - "sebastian/exporter": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3 || ^2.0", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/object-enumerator": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" }, "suggest": { "phpunit/php-invoker": "~1.1" @@ -1816,7 +1931,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.3.x-dev" + "dev-master": "5.4.x-dev" } }, "autoload": { @@ -1825,10 +1940,6 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -1840,36 +1951,39 @@ } ], "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2014-11-11 10:11:09" + "time": "2016-06-16 06:01:15" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "b13d0d9426ced06958bd32104653526a6c998a52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/b13d0d9426ced06958bd32104653526a6c998a52", + "reference": "b13d0d9426ced06958bd32104653526a6c998a52", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-soap": "*" @@ -1877,7 +1991,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -1902,7 +2016,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2016-06-12 07:37:26" }, { "name": "pimple/pimple", @@ -2082,6 +2196,51 @@ "description": "A lightweight implementation of CommonJS Promises/A for PHP", "time": "2016-05-03 17:50:52" }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" + }, { "name": "sebastian/comparator", "version": "1.2.0", @@ -2315,6 +2474,103 @@ ], "time": "2016-06-17 09:04:28" }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-01-28 13:25:10" + }, { "name": "sebastian/recursion-context", "version": "1.0.2", @@ -2368,21 +2624,71 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2015-11-11 19:50:13" }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", "shasum": "" }, + "require": { + "php": ">=5.6" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2401,7 +2707,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2016-02-04 12:56:52" }, { "name": "seld/jsonlint", @@ -2451,16 +2757,16 @@ }, { "name": "symfony/config", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05" + "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/a2edd59c2163c65747fc3f35d132b5a39266bd05", - "reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05", + "url": "https://api.github.com/repos/symfony/config/zipball/0926e69411eba491803dbafb9f1f233e2ced58d0", + "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0", "shasum": "" }, "require": { @@ -2500,20 +2806,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:31:50" }, { "name": "symfony/console", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3" + "reference": "c392a6ec72f2122748032c2ad6870420561ffcfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", - "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", + "url": "https://api.github.com/repos/symfony/console/zipball/c392a6ec72f2122748032c2ad6870420561ffcfa", + "reference": "c392a6ec72f2122748032c2ad6870420561ffcfa", "shasum": "" }, "require": { @@ -2560,20 +2866,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-06-06 15:06:25" + "time": "2016-06-29 07:02:14" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "2a6b8713f8bdb582058cfda463527f195b066110" + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110", - "reference": "2a6b8713f8bdb582058cfda463527f195b066110", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9", "shasum": "" }, "require": { @@ -2620,20 +2926,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/filesystem", - "version": "v3.0.7", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd" + "reference": "a108b1d603ccb52addb5da9b14a3ba259f8b3db0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/74fec3511b62cb934b64bce1d96f06fffa4beafd", - "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/a108b1d603ccb52addb5da9b14a3ba259f8b3db0", + "reference": "a108b1d603ccb52addb5da9b14a3ba259f8b3db0", "shasum": "" }, "require": { @@ -2669,20 +2975,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-04-12 18:09:53" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/finder", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "3ec095fab1800222732ca522a95dce8fa124007b" + "reference": "bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3ec095fab1800222732ca522a95dce8fa124007b", - "reference": "3ec095fab1800222732ca522a95dce8fa124007b", + "url": "https://api.github.com/repos/symfony/finder/zipball/bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d", + "reference": "bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d", "shasum": "" }, "require": { @@ -2718,7 +3024,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/polyfill-mbstring", @@ -2781,16 +3087,16 @@ }, { "name": "symfony/process", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c" + "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/115347d00c342198cdc52a7bd8bc15b5ab43500c", - "reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c", + "url": "https://api.github.com/repos/symfony/process/zipball/89f33c16796415ccfd8bb3cf8d520cbb79899bfe", + "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe", "shasum": "" }, "require": { @@ -2826,20 +3132,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/stopwatch", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "5e628055488bcc42dbace3af65be435d094e37e4" + "reference": "35bae476693150728b0eb51647faac82faf9aaca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5e628055488bcc42dbace3af65be435d094e37e4", - "reference": "5e628055488bcc42dbace3af65be435d094e37e4", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/35bae476693150728b0eb51647faac82faf9aaca", + "reference": "35bae476693150728b0eb51647faac82faf9aaca", "shasum": "" }, "require": { @@ -2875,20 +3181,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/translation", - "version": "v3.0.7", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7" + "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7", - "reference": "2b0aacaa613c0ec1ad8046f972d8abdcb19c1db7", + "url": "https://api.github.com/repos/symfony/translation/zipball/6bf844e1ee3c820c012386c10427a5c67bbefec8", + "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8", "shasum": "" }, "require": { @@ -2939,20 +3245,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:33:26" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/validator", - "version": "v2.8.7", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "4c8f9fd8e2150dbc4745ef13378e690588365df0" + "reference": "366674c28bf7a107a8bce280c668bac40aeb090e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/4c8f9fd8e2150dbc4745ef13378e690588365df0", - "reference": "4c8f9fd8e2150dbc4745ef13378e690588365df0", + "url": "https://api.github.com/repos/symfony/validator/zipball/366674c28bf7a107a8bce280c668bac40aeb090e", + "reference": "366674c28bf7a107a8bce280c668bac40aeb090e", "shasum": "" }, "require": { @@ -3012,29 +3318,29 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-04-14 08:48:44" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/yaml", - "version": "v2.8.7", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34" + "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34", - "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", + "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -3061,7 +3367,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2016-06-29 05:41:56" }, { "name": "twig/twig", From 3349a3b813a85a76f7a71106963ba480308148d9 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 23 Jun 2016 14:22:13 +0100 Subject: [PATCH 015/150] Check that FeatureRequester class in options is valid --- src/LaunchDarkly/LDClient.php | 4 ++++ tests/LDClientTest.php | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index a2d8c14af..d93491361 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -64,6 +64,10 @@ public function __construct($apiKey, $options = array()) { } else { $featureRequesterClass = '\\LaunchDarkly\\GuzzleFeatureRequester'; } + + if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { + throw new \InvalidArgumentException; + } $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $apiKey, $options); } diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 56b7da442..fdd0300bb 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -1,6 +1,7 @@ assertEquals(0, sizeof($queue)); } + + public function testOnlyValidFeatureRequester() { + $this->expectException(InvalidArgumentException::class); + new LDClient("BOGUS_API_KEY", ['feature_requester_class' => 'stdClass']); + } } From b88163c5d691faf1a1e874e56d03a704eca9d375 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 14 Jul 2016 11:22:56 +0100 Subject: [PATCH 016/150] Downgrade to phpunit 5.3.5 as 5.4.* requires php >= 5.6 --- composer.json | 2 +- composer.lock | 62 +++++++++++++++++++++++---------------------------- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/composer.json b/composer.json index 8c480f33d..404f38a12 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "5.4.*", + "phpunit/phpunit": "5.3.5", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "guzzlehttp/guzzle": "5.*", diff --git a/composer.lock b/composer.lock index 225917718..db17c7e25 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "533cfcae075fafcc50bf6802045e3774", - "content-hash": "147e48629bec68e213283c6a8eec9778", + "hash": "abba774082cc7640f83a6f3fe2168ab0", + "content-hash": "4839b3b7b7a51bf0d4e62c5377ad1474", "packages": [], "packages-dev": [ { @@ -1639,16 +1639,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "4.0.0", + "version": "3.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9" + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/900370c81280cc0d942ffbc5912d80464eaee7e9", - "reference": "900370c81280cc0d942ffbc5912d80464eaee7e9", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/44cd8e3930e431658d1a5de7d282d5cb37837fd5", + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5", "shasum": "" }, "require": { @@ -1662,7 +1662,7 @@ }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-dom": "*", @@ -1672,7 +1672,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "3.3.x-dev" } }, "autoload": { @@ -1698,7 +1698,7 @@ "testing", "xunit" ], - "time": "2016-06-03 05:03:56" + "time": "2016-05-27 16:24:29" }, { "name": "phpunit/php-file-iterator", @@ -1883,16 +1883,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.4.6", + "version": "5.3.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59" + "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", - "reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08c513bfcab57f3dd72f5214c1c3940439fae7fe", + "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe", "shasum": "" }, "require": { @@ -1904,14 +1904,14 @@ "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0", + "phpunit/php-code-coverage": ">=3.3.0,<4.0.0", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", + "phpunit/phpunit-mock-objects": ">=3.1.0,<3.2.0", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", + "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/object-enumerator": "~1.0", @@ -1919,9 +1919,6 @@ "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" - }, "suggest": { "phpunit/php-invoker": "~1.1" }, @@ -1931,7 +1928,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.4.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -1957,33 +1954,30 @@ "testing", "xunit" ], - "time": "2016-06-16 06:01:15" + "time": "2016-06-03 09:42:56" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.2.3", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "b13d0d9426ced06958bd32104653526a6c998a52" + "reference": "151c96874bff6fe61a25039df60e776613a61489" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/b13d0d9426ced06958bd32104653526a6c998a52", - "reference": "b13d0d9426ced06958bd32104653526a6c998a52", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489", + "reference": "151c96874bff6fe61a25039df60e776613a61489", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "php": ">=5.6", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-soap": "*" @@ -1991,7 +1985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -2016,7 +2010,7 @@ "mock", "xunit" ], - "time": "2016-06-12 07:37:26" + "time": "2016-04-20 14:39:26" }, { "name": "pimple/pimple", From b7810f3e9d12960df0030b967b76aacd1b1e14a3 Mon Sep 17 00:00:00 2001 From: richardmiller Date: Thu, 14 Jul 2016 12:28:47 +0100 Subject: [PATCH 017/150] Downgrade phpunit to 4.8.26 to allow for PHP 5.3 --- composer.json | 2 +- composer.lock | 259 ++++++----------------------------------- tests/LDClientTest.php | 2 +- 3 files changed, 38 insertions(+), 225 deletions(-) diff --git a/composer.json b/composer.json index 404f38a12..4f4d8af27 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "5.3.5", + "phpunit/phpunit": "4.8.26", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "guzzlehttp/guzzle": "5.*", diff --git a/composer.lock b/composer.lock index db17c7e25..e0b727b02 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "abba774082cc7640f83a6f3fe2168ab0", - "content-hash": "4839b3b7b7a51bf0d4e62c5377ad1474", + "hash": "0871703de19487d877517617eb99d4bd", + "content-hash": "b83833be7e74086c2399be31c969a806", "packages": [], "packages-dev": [ { @@ -1112,48 +1112,6 @@ ], "time": "2016-07-02 14:02:10" }, - { - "name": "myclabs/deep-copy", - "version": "1.5.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "a8773992b362b58498eed24bf85005f363c34771" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a8773992b362b58498eed24bf85005f363c34771", - "reference": "a8773992b362b58498eed24bf85005f363c34771", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2015-11-20 12:04:31" - }, { "name": "nikic/php-parser", "version": "v1.4.1", @@ -1639,40 +1597,39 @@ }, { "name": "phpunit/php-code-coverage", - "version": "3.3.3", + "version": "2.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5" + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/44cd8e3930e431658d1a5de7d282d5cb37837fd5", - "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", + "php": ">=5.3.3", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "^1.4.2", - "sebastian/code-unit-reverse-lookup": "~1.0", + "phpunit/php-token-stream": "~1.3", "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0|~2.0" + "sebastian/version": "~1.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~5" + "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.4.0", + "ext-xdebug": ">=2.2.1", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { @@ -1698,7 +1655,7 @@ "testing", "xunit" ], - "time": "2016-05-27 16:24:29" + "time": "2015-10-06 15:47:00" }, { "name": "phpunit/php-file-iterator", @@ -1883,16 +1840,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.3.5", + "version": "4.8.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe" + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08c513bfcab57f3dd72f5214c1c3940439fae7fe", - "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74", + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74", "shasum": "" }, "require": { @@ -1901,22 +1858,19 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", + "php": ">=5.3.3", "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": ">=3.3.0,<4.0.0", + "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": ">=3.1.0,<3.2.0", + "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", + "sebastian/version": "~1.0", "symfony/yaml": "~2.1|~3.0" }, "suggest": { @@ -1928,7 +1882,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { @@ -1954,30 +1908,30 @@ "testing", "xunit" ], - "time": "2016-06-03 09:42:56" + "time": "2016-05-17 03:09:28" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.1.3", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "151c96874bff6fe61a25039df60e776613a61489" + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489", - "reference": "151c96874bff6fe61a25039df60e776613a61489", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.6", + "php": ">=5.3.3", "phpunit/php-text-template": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" @@ -1985,7 +1939,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "2.3.x-dev" } }, "autoload": { @@ -2010,7 +1964,7 @@ "mock", "xunit" ], - "time": "2016-04-20 14:39:26" + "time": "2015-10-02 06:51:40" }, { "name": "pimple/pimple", @@ -2190,51 +2144,6 @@ "description": "A lightweight implementation of CommonJS Promises/A for PHP", "time": "2016-05-03 17:50:52" }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "phpunit/phpunit": "~5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" - }, { "name": "sebastian/comparator", "version": "1.2.0", @@ -2519,52 +2428,6 @@ ], "time": "2015-10-12 03:26:01" }, - { - "name": "sebastian/object-enumerator", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", - "shasum": "" - }, - "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "~5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" - }, { "name": "sebastian/recursion-context", "version": "1.0.2", @@ -2618,71 +2481,21 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2015-11-11 19:50:13" }, - { - "name": "sebastian/resource-operations", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" - }, { "name": "sebastian/version", - "version": "2.0.0", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, - "require": { - "php": ">=5.6" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -2701,7 +2514,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-02-04 12:56:52" + "time": "2015-06-21 13:59:46" }, { "name": "seld/jsonlint", diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index fdd0300bb..42f86ee06 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -69,7 +69,7 @@ public function testToggleEventsOff() { } public function testOnlyValidFeatureRequester() { - $this->expectException(InvalidArgumentException::class); + $this->setExpectedException(InvalidArgumentException::class); new LDClient("BOGUS_API_KEY", ['feature_requester_class' => 'stdClass']); } } From 1b2e675a15121520bdd67e8e4256e0f7eb0fe65d Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 22 Jul 2016 11:19:55 -0700 Subject: [PATCH 018/150] Update Guzzle, change http client cache --- composer.json | 8 +- composer.lock | 377 +++++++++----------- src/LaunchDarkly/GuzzleFeatureRequester.php | 15 +- src/LaunchDarkly/LDClient.php | 1 - 4 files changed, 184 insertions(+), 217 deletions(-) diff --git a/composer.json b/composer.json index 4f4d8af27..4c7336196 100644 --- a/composer.json +++ b/composer.json @@ -20,14 +20,14 @@ "phpunit/phpunit": "4.8.26", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", - "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*", + "guzzlehttp/guzzle": "6.2.1", + "kevinrob/guzzle-cache-middleware": "1.4.1", "zendframework/zend-serializer": "2.7.*" }, "suggested": { "predis/predis": "1.0.*", - "guzzlehttp/guzzle": "5.*", - "guzzlehttp/cache-subscriber": "0.1.*" + "guzzlehttp/guzzle": "6.2.1", + "kevinrob/guzzle-cache-middleware": "1.4.1" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index e0b727b02..6c8573a58 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0871703de19487d877517617eb99d4bd", - "content-hash": "b83833be7e74086c2399be31c969a806", + "hash": "debb1b5eecfb098fb376ae687fbfc780", + "content-hash": "8864ddd9f30426e5308dbd6fc2c94f1c", "packages": [], "packages-dev": [ { @@ -221,76 +221,6 @@ ], "time": "2015-08-31 12:32:49" }, - { - "name": "doctrine/cache", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6", - "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6", - "shasum": "" - }, - "require": { - "php": "~5.5|~7.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2015-12-31 16:37:02" - }, { "name": "doctrine/instantiator", "version": "1.0.5", @@ -438,75 +368,24 @@ ], "time": "2015-10-04 16:44:32" }, - { - "name": "guzzlehttp/cache-subscriber", - "version": "0.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/cache-subscriber.git", - "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/cache-subscriber/zipball/ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", - "reference": "ecb903f6e11b5ca9f2cdbc460e2e68deea9e8858", - "shasum": "" - }, - "require": { - "doctrine/cache": "~1.3", - "guzzlehttp/guzzle": "~5.0", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.1-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Subscriber\\Cache\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle HTTP cache subscriber", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "cache" - ], - "time": "2014-10-29 21:06:25" - }, { "name": "guzzlehttp/guzzle", - "version": "5.3.0", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", "shasum": "" }, "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" }, "require-dev": { "ext-curl": "*", @@ -516,10 +395,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "6.2-dev" } }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\": "src/" } @@ -535,7 +417,7 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "description": "Guzzle is a PHP HTTP client library", "homepage": "http://guzzlephp.org/", "keywords": [ "client", @@ -546,44 +428,41 @@ "rest", "web service" ], - "time": "2015-05-20 03:47:55" + "time": "2016-07-15 17:22:37" }, { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", + "name": "guzzlehttp/promises", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", "shasum": "" }, "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" + "php": ">=5.5.0" }, "require-dev": { - "ext-curl": "*", "phpunit/phpunit": "~4.0" }, - "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Ring\\": "src/" - } + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -596,25 +475,32 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" }, { - "name": "guzzlehttp/streams", - "version": "3.0.0", + "name": "guzzlehttp/psr7", + "version": "1.3.1", "source": { "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" }, "require-dev": { "phpunit/phpunit": "~4.0" @@ -622,13 +508,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Stream\\": "src/" - } + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -641,13 +530,14 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", + "description": "PSR-7 message implementation", "keywords": [ - "Guzzle", - "stream" + "http", + "message", + "stream", + "uri" ], - "time": "2014-10-12 19:18:40" + "time": "2016-06-24 23:00:38" }, { "name": "herrera-io/json", @@ -992,6 +882,84 @@ ], "time": "2016-01-25 15:43:01" }, + { + "name": "kevinrob/guzzle-cache-middleware", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", + "reference": "f30ded404c296d50820670489d718a04634b6789" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", + "reference": "f30ded404c296d50820670489d718a04634b6789", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "cache/array-adapter": "^0.4", + "doctrine/cache": "^1.0", + "guzzlehttp/guzzle": "^6.0", + "illuminate/cache": "^5.0", + "league/flysystem": "^1.0", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/cache": "^1.0" + }, + "suggest": { + "doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)", + "guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)", + "laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage", + "league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage", + "psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage" + }, + "type": "library", + "autoload": { + "psr-4": { + "Kevinrob\\GuzzleCache\\": [ + "src/", + "tests/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Robatel", + "email": "kevinrob2@gmail.com", + "homepage": "https://github.com/Kevinrob" + } + ], + "description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)", + "homepage": "https://github.com/Kevinrob/guzzle-cache-middleware", + "keywords": [ + "Etag", + "Flysystem", + "Guzzle", + "cache", + "cache-control", + "doctrine", + "expiration", + "guzzle6", + "handler", + "http", + "http 1.1", + "middleware", + "performance", + "php", + "promise", + "psr6", + "psr7", + "rfc7234", + "validation" + ], + "time": "2016-06-17 08:34:36" + }, { "name": "kherge/version", "version": "1.0.1", @@ -2063,23 +2031,31 @@ "time": "2016-05-30 15:25:52" }, { - "name": "psr/log", - "version": "1.0.0", + "name": "psr/http-message", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2092,44 +2068,36 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", + "description": "Common interface for HTTP messages", "keywords": [ - "log", + "http", + "http-message", "psr", - "psr-3" + "psr-7", + "request", + "response" ], - "time": "2012-12-21 11:40:51" + "time": "2015-05-04 20:22:00" }, { - "name": "react/promise", - "version": "v2.4.1", + "name": "psr/log", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "8025426794f1944de806618671d4fa476dc7626f" + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8025426794f1944de806618671d4fa476dc7626f", - "reference": "8025426794f1944de806618671d4fa476dc7626f", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", "shasum": "" }, - "require": { - "php": ">=5.4.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "psr-0": { + "Psr\\Log\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2137,12 +2105,17 @@ ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2016-05-03 17:50:52" + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" }, { "name": "sebastian/comparator", diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index b8a144afe..de605e4b2 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -3,15 +3,19 @@ use GuzzleHttp\Client; use \GuzzleHttp\Exception\BadResponseException; -use \GuzzleHttp\Subscriber\Cache\CacheSubscriber; +use GuzzleHttp\HandlerStack; +use Kevinrob\GuzzleCache\CacheMiddleware; class GuzzleFeatureRequester implements FeatureRequester { private $_client; function __construct($baseUri, $apiKey, $options) { + $stack = HandlerStack::create(); + $stack->push(new CacheMiddleware(), 'cache'); $this->_client = new Client(array( 'base_url' => $baseUri, + 'handler' => $stack, 'defaults' => array( 'headers' => array( 'Authorization' => "api_key {$apiKey}", @@ -23,15 +27,6 @@ function __construct($baseUri, $apiKey, $options) { 'connect_timeout' => $options['connect_timeout'] ) )); - - if (!isset($options['cache_storage'])) { - $csOptions = array('validate' => false); - } - else { - $csOptions = array('storage' => $options['cache_storage'], 'validate' => false); - } - - CacheSubscriber::attach($this->_client, $csOptions); } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index d93491361..c03c6bae9 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -29,7 +29,6 @@ class LDClient { * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 - * - cache_storage: An optional GuzzleHttp\Subscriber\Cache\CacheStorageInterface. Defaults to an in-memory cache. */ public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; From c967b316300a5c4ec45a7414d138b65c20a8d19c Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 22 Jul 2016 12:19:42 -0700 Subject: [PATCH 019/150] wip --- composer.json | 1 + composer.lock | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4c7336196..9a983bc51 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "launchdarkly/launchdarkly-php", + "version": "dev", "description": "Official LaunchDarkly SDK for PHP", "keywords": [ "launchdarkly", diff --git a/composer.lock b/composer.lock index 6c8573a58..7f22d0d12 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "debb1b5eecfb098fb376ae687fbfc780", - "content-hash": "8864ddd9f30426e5308dbd6fc2c94f1c", + "hash": "cdc57b7146b3596bffddfbf0158834bf", + "content-hash": "a4a7f410e26085652dfeed1aba37bf45", "packages": [], "packages-dev": [ { From 4ad38ed01585f9a5ff164332a6f1d1785ee101d7 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 10:43:31 -0700 Subject: [PATCH 020/150] FeatureRequester works with Guzzle 6, but no caching yet --- src/LaunchDarkly/GuzzleFeatureRequester.php | 55 ++++++++++++--------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index de605e4b2..9907b003b 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -1,32 +1,36 @@ push(new CacheMiddleware(), 'cache'); - $this->_client = new Client(array( - 'base_url' => $baseUri, - 'handler' => $stack, - 'defaults' => array( - 'headers' => array( - 'Authorization' => "api_key {$apiKey}", - 'Content-Type' => 'application/json', - 'User-Agent' => 'PHPClient/' . LDClient::VERSION - ), - 'debug' => false, - 'timeout' => $options['timeout'], - 'connect_timeout' => $options['connect_timeout'] - ) - )); + function __construct($baseUri, $apiKey, $options) + { + $this->_baseUri = $baseUri; + error_log("uri: $baseUri"); +// $stack = HandlerStack::create(); +// $stack->push(new CacheMiddleware(), 'cache'); + + $this->_defaults = array( + 'headers' => array( + 'Authorization' => "api_key {$apiKey}", + 'Content-Type' => 'application/json', + 'User-Agent' => 'PHPClient/' . LDClient::VERSION + ), + 'timeout' => $options['timeout'], + 'connect_timeout' => $options['connect_timeout'] + ); + + $this->_client = new Client(); } @@ -36,10 +40,15 @@ function __construct($baseUri, $apiKey, $options) { * @param $key string feature key * @return array|null The decoded JSON feature data, or null if missing */ - public function get($key) { + public function get($key) + { try { - $response = $this->_client->get("/api/eval/features/$key"); - return $response->json(); + $uri = $this->_baseUri . "/api/eval/features/$key"; + error_log($uri); + $response = $this->_client->get($uri, $this->_defaults); + $body = $response->getBody(); + error_log($body); + return json_decode($body, true); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); error_log("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); From 1f3576010f3853f1fefd6e695032554b624294c6 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 11:38:25 -0700 Subject: [PATCH 021/150] [wip] add cache --- src/LaunchDarkly/GuzzleFeatureRequester.php | 8 +++----- src/LaunchDarkly/LDClient.php | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 9907b003b..e412db11f 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -8,7 +8,6 @@ class GuzzleFeatureRequester implements FeatureRequester { - private $_client; private $_baseUri; private $_defaults; @@ -17,8 +16,8 @@ function __construct($baseUri, $apiKey, $options) { $this->_baseUri = $baseUri; error_log("uri: $baseUri"); -// $stack = HandlerStack::create(); -// $stack->push(new CacheMiddleware(), 'cache'); + $stack = HandlerStack::create(); + $stack->push(new CacheMiddleware(isset($options['cache_strategy']) ? $options['cache_strategy'] : null, 'cache')); $this->_defaults = array( 'headers' => array( @@ -30,7 +29,7 @@ function __construct($baseUri, $apiKey, $options) 'connect_timeout' => $options['connect_timeout'] ); - $this->_client = new Client(); + $this->_client = new Client(['handler' => $stack, 'debug' => true]); } @@ -44,7 +43,6 @@ public function get($key) { try { $uri = $this->_baseUri . "/api/eval/features/$key"; - error_log($uri); $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); error_log($body); diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index c03c6bae9..45a772292 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -29,6 +29,7 @@ class LDClient { * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 + * - cache_strategy: An optional Kevinrob\GuzzleCache\Strategy\CacheStrategyInterface. Defaults to an in-memory cache. */ public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; From 826a5fac2bc8fe3dcb05ee5279b2bb85f9d734af Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 12:19:26 -0700 Subject: [PATCH 022/150] New http client caching works. --- src/LaunchDarkly/GuzzleFeatureRequester.php | 13 ++++++------- src/LaunchDarkly/LDClient.php | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index e412db11f..a53385e67 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -1,10 +1,11 @@ _baseUri = $baseUri; error_log("uri: $baseUri"); $stack = HandlerStack::create(); - $stack->push(new CacheMiddleware(isset($options['cache_strategy']) ? $options['cache_strategy'] : null, 'cache')); + $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); $this->_defaults = array( 'headers' => array( @@ -28,8 +29,7 @@ function __construct($baseUri, $apiKey, $options) 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ); - - $this->_client = new Client(['handler' => $stack, 'debug' => true]); + $this->_client = new Client(['handler' => $stack, 'debug' => false]); } @@ -45,7 +45,6 @@ public function get($key) $uri = $this->_baseUri . "/api/eval/features/$key"; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); - error_log($body); return json_decode($body, true); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 45a772292..0ae568258 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -29,7 +29,7 @@ class LDClient { * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 - * - cache_strategy: An optional Kevinrob\GuzzleCache\Strategy\CacheStrategyInterface. Defaults to an in-memory cache. + * - cache: An optional Kevinrob\GuzzleCache\Strategy\CacheStorageInterface. Defaults to an in-memory cache. */ public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; From a15a47d658495c52f6cf0bf9dc9f0faa2730d091 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 12:21:23 -0700 Subject: [PATCH 023/150] remove dev version --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 9a983bc51..4c7336196 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,5 @@ { "name": "launchdarkly/launchdarkly-php", - "version": "dev", "description": "Official LaunchDarkly SDK for PHP", "keywords": [ "launchdarkly", From 8912139b8fa7ab0dafa6f44144eb46ffb605ab20 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 12:39:29 -0700 Subject: [PATCH 024/150] Update version --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 0ae568258..6b38f25f6 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -8,7 +8,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '0.7.0'; + const VERSION = '1.0.0'; protected $_apiKey; protected $_baseUri; From 10a60c83c47a0d88bf745da7fe6a476ebc345931 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 12:40:30 -0700 Subject: [PATCH 025/150] Update version in other place --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bcaffe19b..afaf360d3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.0 \ No newline at end of file +1.0.0 \ No newline at end of file From 428e36c6e82369ca0531fba5be9c2c17721ac1e8 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 13:27:48 -0700 Subject: [PATCH 026/150] maybe a no-op. --- composer.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index 7f22d0d12..6c8573a58 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "cdc57b7146b3596bffddfbf0158834bf", - "content-hash": "a4a7f410e26085652dfeed1aba37bf45", + "hash": "debb1b5eecfb098fb376ae687fbfc780", + "content-hash": "8864ddd9f30426e5308dbd6fc2c94f1c", "packages": [], "packages-dev": [ { From 1f34437cb099461bacc57020f14ab441a329757d Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 13:30:36 -0700 Subject: [PATCH 027/150] make guzzle required --- composer.json | 10 +- composer.lock | 709 +++++++++++++++++++++++++------------------------- 2 files changed, 359 insertions(+), 360 deletions(-) diff --git a/composer.json b/composer.json index 4c7336196..074b0844d 100644 --- a/composer.json +++ b/composer.json @@ -14,20 +14,18 @@ } ], "require": { - "php": ">=5.5" + "php": ">=5.5", + "guzzlehttp/guzzle": "6.2.1", + "kevinrob/guzzle-cache-middleware": "1.4.1" }, "require-dev": { "phpunit/phpunit": "4.8.26", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", - "guzzlehttp/guzzle": "6.2.1", - "kevinrob/guzzle-cache-middleware": "1.4.1", "zendframework/zend-serializer": "2.7.*" }, "suggested": { - "predis/predis": "1.0.*", - "guzzlehttp/guzzle": "6.2.1", - "kevinrob/guzzle-cache-middleware": "1.4.1" + "predis/predis": "1.0.*" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 6c8573a58..5d5a59033 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,308 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "debb1b5eecfb098fb376ae687fbfc780", - "content-hash": "8864ddd9f30426e5308dbd6fc2c94f1c", - "packages": [], + "hash": "5eedb482e4771e6654320cd7e4eeba75", + "content-hash": "a86b9bdc4496a0675fcc918a7f92b585", + "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-07-15 17:22:37" + }, + { + "name": "guzzlehttp/promises", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-06-24 23:00:38" + }, + { + "name": "kevinrob/guzzle-cache-middleware", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", + "reference": "f30ded404c296d50820670489d718a04634b6789" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", + "reference": "f30ded404c296d50820670489d718a04634b6789", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "cache/array-adapter": "^0.4", + "doctrine/cache": "^1.0", + "guzzlehttp/guzzle": "^6.0", + "illuminate/cache": "^5.0", + "league/flysystem": "^1.0", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/cache": "^1.0" + }, + "suggest": { + "doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)", + "guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)", + "laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage", + "league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage", + "psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage" + }, + "type": "library", + "autoload": { + "psr-4": { + "Kevinrob\\GuzzleCache\\": [ + "src/", + "tests/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Robatel", + "email": "kevinrob2@gmail.com", + "homepage": "https://github.com/Kevinrob" + } + ], + "description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)", + "homepage": "https://github.com/Kevinrob/guzzle-cache-middleware", + "keywords": [ + "Etag", + "Flysystem", + "Guzzle", + "cache", + "cache-control", + "doctrine", + "expiration", + "guzzle6", + "handler", + "http", + "http 1.1", + "middleware", + "performance", + "php", + "promise", + "psr6", + "psr7", + "rfc7234", + "validation" + ], + "time": "2016-06-17 08:34:36" + }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + } + ], "packages-dev": [ { "name": "cilex/cilex", @@ -248,162 +547,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14 21:17:01" - }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09 13:34:57" - }, - { - "name": "erusev/parsedown", - "version": "1.6.0", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ], - "time": "2015-10-04 16:44:32" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.2.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.3.1", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { - "GuzzleHttp\\": "src/" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -412,57 +561,46 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" + "constructor", + "instantiate" ], - "time": "2016-07-15 17:22:37" + "time": "2015-06-14 21:17:01" }, { - "name": "guzzlehttp/promises", - "version": "1.2.0", + "name": "doctrine/lexer", + "version": "v1.0.1", "source": { "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" + "php": ">=5.3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -470,54 +608,45 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Guzzle promises library", + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "promise" + "lexer", + "parser" ], - "time": "2016-05-18 16:56:05" + "time": "2014-09-09 13:34:57" }, { - "name": "guzzlehttp/psr7", - "version": "1.3.1", + "name": "erusev/parsedown", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + "url": "https://github.com/erusev/parsedown.git", + "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", + "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", "shasum": "" }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "psr-0": { + "Parsedown": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -525,19 +654,18 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" } ], - "description": "PSR-7 message implementation", + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", "keywords": [ - "http", - "message", - "stream", - "uri" + "markdown", + "parser" ], - "time": "2016-06-24 23:00:38" + "time": "2015-10-04 16:44:32" }, { "name": "herrera-io/json", @@ -882,84 +1010,6 @@ ], "time": "2016-01-25 15:43:01" }, - { - "name": "kevinrob/guzzle-cache-middleware", - "version": "v1.4.1", - "source": { - "type": "git", - "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", - "reference": "f30ded404c296d50820670489d718a04634b6789" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", - "reference": "f30ded404c296d50820670489d718a04634b6789", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "cache/array-adapter": "^0.4", - "doctrine/cache": "^1.0", - "guzzlehttp/guzzle": "^6.0", - "illuminate/cache": "^5.0", - "league/flysystem": "^1.0", - "phpunit/phpunit": "^4.0 || ^5.0", - "psr/cache": "^1.0" - }, - "suggest": { - "doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)", - "guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)", - "laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage", - "league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage", - "psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage" - }, - "type": "library", - "autoload": { - "psr-4": { - "Kevinrob\\GuzzleCache\\": [ - "src/", - "tests/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kevin Robatel", - "email": "kevinrob2@gmail.com", - "homepage": "https://github.com/Kevinrob" - } - ], - "description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)", - "homepage": "https://github.com/Kevinrob/guzzle-cache-middleware", - "keywords": [ - "Etag", - "Flysystem", - "Guzzle", - "cache", - "cache-control", - "doctrine", - "expiration", - "guzzle6", - "handler", - "http", - "http 1.1", - "middleware", - "performance", - "php", - "promise", - "psr6", - "psr7", - "rfc7234", - "validation" - ], - "time": "2016-06-17 08:34:36" - }, { "name": "kherge/version", "version": "1.0.1", @@ -2030,55 +2080,6 @@ ], "time": "2016-05-30 15:25:52" }, - { - "name": "psr/http-message", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2015-05-04 20:22:00" - }, { "name": "psr/log", "version": "1.0.0", From 132453ac800bee07da9a327a7c93a7ca47bd2d89 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 13:56:00 -0700 Subject: [PATCH 028/150] Make guzzle optional. Update README. --- README.md | 8 +- composer.json | 6 +- composer.lock | 305 +------------------------------------------------- 3 files changed, 10 insertions(+), 309 deletions(-) diff --git a/README.md b/README.md index aec68a969..325158603 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Quick setup 0. Install the PHP SDK with [Composer](https://getcomposer.org/) php composer.phar require launchdarkly/launchdarkly-php - php composer.phar require "guzzlehttp/guzzle:5.*" - php composer.phar require "guzzlehttp/cache-subscriber:0.1.*" + php composer.phar require "guzzlehttp/guzzle:6.2.1" + php composer.phar require "kevinrob/guzzle-cache-middleware": "1.4.1" 1. After installing, require Composer's autoloader: @@ -49,8 +49,8 @@ Using Guzzle To use Guzzle it must be required as a dependency: - php composer.phar require "guzzlehttp/guzzle:5.*" - php composer.phar require "guzzlehttp/cache-subscriber:0.1.*" + php composer.phar require "guzzlehttp/guzzle:6.2.1" + php composer.phar require "kevinrob/guzzle-cache-middleware": "1.4.1" It will then be used as the default way of fetching flags. diff --git a/composer.json b/composer.json index 074b0844d..17682be3c 100644 --- a/composer.json +++ b/composer.json @@ -14,9 +14,7 @@ } ], "require": { - "php": ">=5.5", - "guzzlehttp/guzzle": "6.2.1", - "kevinrob/guzzle-cache-middleware": "1.4.1" + "php": ">=5.5" }, "require-dev": { "phpunit/phpunit": "4.8.26", @@ -25,6 +23,8 @@ "zendframework/zend-serializer": "2.7.*" }, "suggested": { + "guzzlehttp/guzzle": "6.2.1", + "kevinrob/guzzle-cache-middleware": "1.4.1", "predis/predis": "1.0.*" }, "autoload": { diff --git a/composer.lock b/composer.lock index 5d5a59033..f6e81cf7e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,308 +4,9 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "5eedb482e4771e6654320cd7e4eeba75", - "content-hash": "a86b9bdc4496a0675fcc918a7f92b585", - "packages": [ - { - "name": "guzzlehttp/guzzle", - "version": "6.2.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.3.1", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2016-07-15 17:22:37" - }, - { - "name": "guzzlehttp/promises", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-05-18 16:56:05" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "PSR-7 message implementation", - "keywords": [ - "http", - "message", - "stream", - "uri" - ], - "time": "2016-06-24 23:00:38" - }, - { - "name": "kevinrob/guzzle-cache-middleware", - "version": "v1.4.1", - "source": { - "type": "git", - "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", - "reference": "f30ded404c296d50820670489d718a04634b6789" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", - "reference": "f30ded404c296d50820670489d718a04634b6789", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "cache/array-adapter": "^0.4", - "doctrine/cache": "^1.0", - "guzzlehttp/guzzle": "^6.0", - "illuminate/cache": "^5.0", - "league/flysystem": "^1.0", - "phpunit/phpunit": "^4.0 || ^5.0", - "psr/cache": "^1.0" - }, - "suggest": { - "doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)", - "guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)", - "laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage", - "league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage", - "psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage" - }, - "type": "library", - "autoload": { - "psr-4": { - "Kevinrob\\GuzzleCache\\": [ - "src/", - "tests/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kevin Robatel", - "email": "kevinrob2@gmail.com", - "homepage": "https://github.com/Kevinrob" - } - ], - "description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)", - "homepage": "https://github.com/Kevinrob/guzzle-cache-middleware", - "keywords": [ - "Etag", - "Flysystem", - "Guzzle", - "cache", - "cache-control", - "doctrine", - "expiration", - "guzzle6", - "handler", - "http", - "http 1.1", - "middleware", - "performance", - "php", - "promise", - "psr6", - "psr7", - "rfc7234", - "validation" - ], - "time": "2016-06-17 08:34:36" - }, - { - "name": "psr/http-message", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2015-05-04 20:22:00" - } - ], + "hash": "81f0f2d66e4ac270e2d713a8e40e372c", + "content-hash": "a8e4c5c74e80e417f21fefadd2b259e8", + "packages": [], "packages-dev": [ { "name": "cilex/cilex", From 5cfbc9c250a181d6aa85c899776e56e5779b27bb Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 13:58:10 -0700 Subject: [PATCH 029/150] Add dev requirements --- composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/composer.json b/composer.json index 17682be3c..0329dee7e 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,8 @@ "php": ">=5.5" }, "require-dev": { + "guzzlehttp/guzzle": "6.2.1", + "kevinrob/guzzle-cache-middleware": "1.4.1", "phpunit/phpunit": "4.8.26", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", From a903193745927a6b0411d6824d3218336c8e2ad6 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Sat, 23 Jul 2016 14:03:33 -0700 Subject: [PATCH 030/150] composer update --- composer.lock | 302 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 300 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index f6e81cf7e..87ffb3aaf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "81f0f2d66e4ac270e2d713a8e40e372c", - "content-hash": "a8e4c5c74e80e417f21fefadd2b259e8", + "hash": "cf5c4602f9f9aff086005edc75728d0f", + "content-hash": "f09e942238b22b8ef39b297cd1808ee6", "packages": [], "packages-dev": [ { @@ -368,6 +368,177 @@ ], "time": "2015-10-04 16:44:32" }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-07-15 17:22:37" + }, + { + "name": "guzzlehttp/promises", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-06-24 23:00:38" + }, { "name": "herrera-io/json", "version": "1.0.3", @@ -711,6 +882,84 @@ ], "time": "2016-01-25 15:43:01" }, + { + "name": "kevinrob/guzzle-cache-middleware", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", + "reference": "f30ded404c296d50820670489d718a04634b6789" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", + "reference": "f30ded404c296d50820670489d718a04634b6789", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "cache/array-adapter": "^0.4", + "doctrine/cache": "^1.0", + "guzzlehttp/guzzle": "^6.0", + "illuminate/cache": "^5.0", + "league/flysystem": "^1.0", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/cache": "^1.0" + }, + "suggest": { + "doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)", + "guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)", + "laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage", + "league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage", + "psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage" + }, + "type": "library", + "autoload": { + "psr-4": { + "Kevinrob\\GuzzleCache\\": [ + "src/", + "tests/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Robatel", + "email": "kevinrob2@gmail.com", + "homepage": "https://github.com/Kevinrob" + } + ], + "description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)", + "homepage": "https://github.com/Kevinrob/guzzle-cache-middleware", + "keywords": [ + "Etag", + "Flysystem", + "Guzzle", + "cache", + "cache-control", + "doctrine", + "expiration", + "guzzle6", + "handler", + "http", + "http 1.1", + "middleware", + "performance", + "php", + "promise", + "psr6", + "psr7", + "rfc7234", + "validation" + ], + "time": "2016-06-17 08:34:36" + }, { "name": "kherge/version", "version": "1.0.1", @@ -1781,6 +2030,55 @@ ], "time": "2016-05-30 15:25:52" }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, { "name": "psr/log", "version": "1.0.0", From dc4ee02e221b4587f25a3377cda339a8896aabcf Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 28 Jul 2016 14:51:46 -0600 Subject: [PATCH 031/150] [wip] V2 data model + evaluation start. --- src/LaunchDarkly/EvaluationException.php | 22 + src/LaunchDarkly/FeatureFlag.php | 510 ++++++++++++++++++++ src/LaunchDarkly/FeatureRequester.php | 2 +- src/LaunchDarkly/GuzzleFeatureRequester.php | 7 +- src/LaunchDarkly/LDClient.php | 62 ++- src/LaunchDarkly/LDUser.php | 58 ++- src/LaunchDarkly/Operator.php | 71 +++ tests/FeatureFlagTest.php | 156 ++++++ 8 files changed, 846 insertions(+), 42 deletions(-) create mode 100644 src/LaunchDarkly/EvaluationException.php create mode 100644 src/LaunchDarkly/FeatureFlag.php create mode 100644 src/LaunchDarkly/Operator.php create mode 100644 tests/FeatureFlagTest.php diff --git a/src/LaunchDarkly/EvaluationException.php b/src/LaunchDarkly/EvaluationException.php new file mode 100644 index 000000000..5980b667a --- /dev/null +++ b/src/LaunchDarkly/EvaluationException.php @@ -0,0 +1,22 @@ +_key = $key; + $this->_version = $version; + $this->_on = $on; + $this->_prerequisites = $prerequisites; + $this->_salt = $salt; + $this->_targets = $targets; + $this->_rules = $rules; + $this->_fallthrough = $fallthrough; + $this->_offVariation = $offVariation; + $this->_variations = $variations; + $this->_deleted = $deleted; + } + + public static function decode($v) { + return new FeatureFlag( + $v['key'], + $v['version'], + $v['on'], + array_map(Prerequisite::getDecoder(), $v['prerequisites']), + $v['salt'], + array_map(Target::getDecoder(), $v['targets']), + array_map(Rule::getDecoder(), $v['rules']), + call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), + $v['offVariation'], + $v['variations'], + $v['deleted']); + } + + public function isOn() { + return $this->_on; + } + + /** + * @param $user LDUser + * @param $featureRequester FeatureRequester + * @return mixed|null + */ + public function evaluate($user, $featureRequester) { + $prereqEvents = array(); + $value = $this->_evaluate($user, $featureRequester, $prereqEvents); + return $value; + } + + /** + * @param $user LDUser + * @param $featureRequester FeatureRequester + * @param $events + * @return mixed|null + */ + private function _evaluate($user, $featureRequester, $events) { + $prereqOk = true; + if ($this->_prerequisites != null) { + foreach ($this->_prerequisites as $prereq) { + try { + $prereqFeatureFlag = $featureRequester->get($prereq->getKey()); + if ($prereqFeatureFlag == null) { + return null; + } else if ($prereqFeatureFlag->isOn()) { + $prereqEvalResult = $prereqFeatureFlag->evaluate($user, $featureRequester); + $variation = $prereqFeatureFlag->getVariation($prereq->getVariation()); + if ($prereqEvalResult == null || $variation == null || $prereqEvalResult != $variation) { + $prereqOk = false; + } + } else { + $prereqOk = false; + } + } catch (EvaluationException $e) { + $prereqOk = false; + } + //TODO: Add event. + } + } + if ($prereqOk) { + return $this->getVariation($this->evaluateIndex($user)); + } + } + + /** + * @param $user LDUser + * @return int|null + */ + private function evaluateIndex($user) { + // Check to see if targets match + if ($this->_targets != null) { + foreach ($this->_targets as $target) { + foreach ($target->getValues() as $value) { + if ($value == $user->getKey()) { + return $target->getVariation(); + } + } + } + } + // Now walk through the rules and see if any match + if ($this->_rules != null) { + foreach ($this->_rules as $rule) { + if ($rule->matchesUser($user)) { + return $rule->variationIndexForUser($user, $this->_key, $this->_salt); + } + } + } + // Walk through the fallthrough and see if it matches + return $this->_fallthrough->variationIndexForUser($user, $this->_key, $this->_salt); + + } + + private function getVariation($index) { + // If the supplied index is null, then rules didn't match, and we want to return + // the off variation + if (!isset($index)) { + return null; + } + // If the index doesn't refer to a valid variation, that's an unexpected exception and we will + // return the default variation + if ($index >= count($this->_variations)) { + throw new EvaluationException("Invalid Index"); + } else { + return $this->_variations[$index]; + } + } + + public function getOffVariationValue() { + if ($this->_offVariation == null) { + return null; + } + if ($this->_offVariation >= count($this->_variations)) { + throw new EvaluationException("Invalid offVariation index"); + } + return $this->_variations[$this->_offVariation]; + } +} + +class VariationOrRollout { + private static $LONG_SCALE = 0xFFFFFFFFFFFFFFF; + + /** @var int */ + private $_variation = null; + /** @var Rollout */ + private $_rollout = null; + + protected function __construct($variation, $rollout) { + $this->_variation = $variation; + $this->_rollout = $rollout; + } + + public static function getDecoder() { + return function ($v) { + return new VariationOrRollout( + isset($v['variation']) ? $v['variation'] : null, + isset($v['rollout']) ? $v['rollout'] : null); + }; + } + + /** + * @return int + */ + public function getVariation() { + return $this->_variation; + } + + /** + * @return Rollout + */ + public function getRollout() { + return $this->_rollout; + } + + /** + * @param $user LDUser + * @param $_key string + * @param $_salt string + * @return int|null + */ + public function variationIndexForUser($user, $_key, $_salt) { + if ($this->_variation != null) { + return $this->_variation; + } else if ($this->_rollout != null) { + $bucketBy = $this->_rollout->getBucketBy() == null ? "key" : $this->_rollout->getBucketBy(); + $bucket = $this->bucketUser($user, $_key, $bucketBy, $_salt); + $sum = 0.0; + foreach ($this->_rollout->getVariations() as $wv) { + $sum += $wv->getWeight() / 100000.0; + if ($bucket < $sum) { + return $wv->getVariation(); + } + } + } + return null; + } + + /** + * @param $user LDUser + * @param $_key string + * @param $attr string + * @param $_salt string + * @return float + */ + private function bucketUser($user, $_key, $attr, $_salt) { + $userValue = $user->getValueForEvaluation($attr); + $idHash = null; + if ($userValue != null) { + if (is_string($userValue)) { + $idHash = $userValue; + if ($user->getSecondary() != null) { + $idHash = $idHash . "." . $user->getSecondary(); + } + $hash = substr(sha1($_key . "." . $_salt . "." . $idHash), 0, 15); + $longVal = base_convert($hash, 16, 10); + $result = $longVal / self::$LONG_SCALE; + + return $result; + } + } + return 0.0; + } +} + +class Clause { + private $_attribute = null; + private $_op = null; + private $_values = array(); + private $_negate = false; + + private function __construct($attribute, $op, array $values, $negate) { + $this->_attribute = $attribute; + $this->_op = $op; + $this->_values = $values; + $this->_negate = $negate; + } + + public static function getDecoder() { + return function ($v) { + return new Clause($v['attribute'], $v['op'], $v['values'], $v['negate']); + }; + } + + /** + * @param $user LDUser + * @return bool + */ + public function matchesUser($user) { + $userValue = $user->getValueForEvaluation($this->_attribute); + if ($userValue == null) { + return false; + } + if (is_array($userValue)) { + foreach ($userValue as $element) { + if ($this->matchAny($userValue)) { + return $this->_maybeNegate(true); + } + } + return $this->maybeNegate(false); + } else { + return $this->maybeNegate($this->matchAny($userValue)); + } + } + + /** + * @return null + */ + public function getAttribute() { + return $this->_attribute; + } + + /** + * @return null + */ + public function getOp() { + return $this->_op; + } + + /** + * @return array + */ + public function getValues() { + return $this->_values; + } + + /** + * @return boolean + */ + public function isNegate() { + return $this->_negate; + } + + /** + * @param $userValue + * @return bool + */ + private function matchAny($userValue) { + foreach ($this->_values as $v) { + if (Operator::apply($this->_op, $userValue, $v)) { + return true; + } + } + return false; + } + + private function _maybeNegate($b) { + if ($this->_negate) { + return !$b; + } else { + return $b; + } + } +} + +class Rule extends VariationOrRollout { + /** @var Clause[] */ + private $_clauses = array(); + + protected function __construct($variation, $rollout, array $clauses) { + parent::__construct($variation, $rollout); + $this->_clauses = $clauses; + } + + public static function getDecoder() { + return function ($v) { + return new Rule( + isset($v['variation']) ? $v['variation'] : null, + isset($v['rollout']) ? $v['rollout'] : null, + array_map(Clause::getDecoder(), $v['clauses'])); + }; + } + + /** + * @param $user LDUser + * @return bool + */ + public function matchesUser($user) { + foreach ($this->_clauses as $clause) { + if (!$clause->matchesUser($user)) { + return false; + } + } + return true; + } + + /** + * @return Clause[] + */ + public function getClauses() { + return $this->_clauses; + } +} + +class WeightedVariation { + /** @var int */ + private $_variation = null; + /** @var int */ + private $_weight = null; + + private function __construct($variation, $weight) { + $this->_variation = $variation; + $this->_weight = $weight; + } + + public static function getDecoder() { + return function ($v) { + return new WeightedVariation($v['variation'], $v['weight']); + }; + } + + /** + * @return int + */ + public function getVariation() { + return $this->_variation; + } + + /** + * @return int + */ + public function getWeight() { + return $this->_weight; + } +} + +class Target { + /** @var string[] */ + private $_values = array(); + /** @var int */ + private $_variation = null; + + protected function __construct(array $values, $variation) { + $this->_values = $values; + $this->_variation = $variation; + } + + public static function getDecoder() { + return function ($v) { + return new Target($v['values'], $v['variation']); + }; + } + + /** + * @return \string[] + */ + public function getValues() { + return $this->_values; + } + + /** + * @return int + */ + public function getVariation() { + return $this->_variation; + } +} + +class Prerequisite { + /** @var string */ + private $_key = null; + /** @var int */ + private $_variation = null; + + protected function __construct($key, $variation) { + $this->_key = $key; + $this->_variation = $variation; + } + + public static function getDecoder() { + return function ($v) { + return new Prerequisite($v['key'], $v['variation']); + }; + } + + /** + * @return string + */ + public function getKey() { + return $this->_key; + } + + /** + * @return int + */ + public function getVariation() { + return $this->_variation; + } +} + +class Rollout { + /** @var WeightedVariation[] */ + private $_variations = array(); + /** @var string */ + private $_bucketBy = null; + + protected function __construct(array $variations, $bucketBy) { + $this->_variations = $variations; + $this->_bucketBy = $bucketBy; + } + + public static function getDecoder() { + return function ($v) { + return new Rollout($v['variations'], $v['bucketBy']); + }; + } + + /** + * @return WeightedVariation[] + */ + public function getVariations() { + return $this->_variations; + } + + /** + * @return string + */ + public function getBucketBy() { + return $this->_bucketBy; + } +} diff --git a/src/LaunchDarkly/FeatureRequester.php b/src/LaunchDarkly/FeatureRequester.php index f330dba76..25a7c9186 100644 --- a/src/LaunchDarkly/FeatureRequester.php +++ b/src/LaunchDarkly/FeatureRequester.php @@ -7,7 +7,7 @@ interface FeatureRequester { * Gets feature data from a likely cached store * * @param $key string feature key - * @return array|null The decoded JSON feature data, or null if missing + * @return FeatureFlag|null The decoded FeatureFlag, or null if missing */ public function get($key); } \ No newline at end of file diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index a53385e67..d1c29458b 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -16,7 +16,6 @@ class GuzzleFeatureRequester implements FeatureRequester function __construct($baseUri, $apiKey, $options) { $this->_baseUri = $baseUri; - error_log("uri: $baseUri"); $stack = HandlerStack::create(); $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); @@ -37,15 +36,15 @@ function __construct($baseUri, $apiKey, $options) * Gets feature data from a likely cached store * * @param $key string feature key - * @return array|null The decoded JSON feature data, or null if missing + * @return FeatureFlag|null The decoded FeatureFlag, or null if missing */ public function get($key) { try { - $uri = $this->_baseUri . "/api/eval/features/$key"; + $uri = $this->_baseUri . "/sdk/latest-flags/" . $key; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); - return json_decode($body, true); + return FeatureFlag::decode(json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); error_log("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 6b38f25f6..c440e26a0 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -24,8 +24,8 @@ class LDClient { /** * Creates a new client instance that connects to LaunchDarkly. * - * @param string $apiKey The API key for your account - * @param array $options Client configuration settings + * @param string $apiKey The API key for your account + * @param array $options Client configuration settings * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 @@ -35,8 +35,7 @@ public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; if (!isset($options['base_uri'])) { $this->_baseUri = self::DEFAULT_BASE_URI; - } - else { + } else { $this->_baseUri = rtrim($options['base_uri'], '/'); } if (isset($options['events'])) { @@ -75,15 +74,15 @@ public function getFlag($key, $user, $default = false) { return $this->toggle($key, $user, $default); } - /** - * Calculates the value of a feature flag for a given user. - * - * @param string $key The unique key for the feature flag - * @param LDUser $user The end user requesting the flag - * @param boolean $default The default value of the flag - * - * @return boolean Whether or not the flag should be enabled, or `default` if the flag is disabled in the LaunchDarkly control panel - */ + /** + * Calculates the value of a feature flag for a given user. + * + * @param string $key The unique key for the feature flag + * @param LDUser $user The end user requesting the flag + * @param boolean $default The default value of the flag + * + * @return boolean Whether or not the flag should be enabled, or `default` if the flag is disabled in the LaunchDarkly control panel + */ public function toggle($key, $user, $default = false) { if ($this->_offline) { return $default; @@ -91,22 +90,36 @@ public function toggle($key, $user, $default = false) { try { $default = $this->_get_default($key, $default); - $flag = $this->_toggle($key, $user); + if (is_null($user) || strlen($user['key']) == 0) { + $this->_sendFlagRequestEvent($key, $user, $default, $default); + return $default; + } + $flag = $this->_featureRequester->get($key); +// $flag = $this->_get_flag($key, $user); if (is_null($flag)) { $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; + } else if ($flag->isOn()) { + $result = $flag->evaluate($user, $this->_featureRequester); + if (!$this->_offline) { + //TODO: send prereq events + } + if ($result != null) { + $this->_sendFlagRequestEvent($key, $user, $result, $default); + return $result; + } } - else { - $this->_sendFlagRequestEvent($key, $user, $flag, $default); - return $flag; + $offVariation = $flag->getOffVariationValue(); + if ($offVariation != null) { + $this->_sendFlagRequestEvent($key, $user, $offVariation, $default); + return $offVariation; } } catch (\Exception $e) { error_log("LaunchDarkly caught $e"); try { - $this->_sendFlagRequestEvent($key, $user, $default, $default); - } - catch (\Exception $e) { + $this->_sendFlagRequestEvent($key, $user, $default, $default); + } catch (\Exception $e) { error_log("LaunchDarkly caught $e"); } return $default; @@ -174,7 +187,7 @@ public function identify($user) { $event['kind'] = "identify"; $event['creationDate'] = round(microtime(1) * 1000); $event['key'] = $user->getKey(); - $this->_eventProcessor->enqueue($event); + $this->_eventProcessor->enqueue($event); } /** @@ -194,10 +207,10 @@ protected function _sendFlagRequestEvent($key, $user, $value, $default) { $event['creationDate'] = round(microtime(1) * 1000); $event['key'] = $key; $event['default'] = $default; - $this->_eventProcessor->enqueue($event); + $this->_eventProcessor->enqueue($event); } - protected function _toggle($key, $user) { + protected function _get_flag($key, $user) { try { $data = $this->_featureRequester->get($key); if ($data == null) { @@ -229,8 +242,7 @@ protected static function _decode($json, $user) { $targets = array_map($makeTarget, $ts); if (isset($v['userTarget'])) { return new Variation($v['value'], $v['weight'], $targets, $makeTarget($v['userTarget'])); - } - else { + } else { return new Variation($v['value'], $v['weight'], $targets, null); } }; diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index fb6ea96cb..02c806e0c 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -20,19 +20,19 @@ class LDUser { protected $_custom = array(); /** - * @param string $key Unique key for the user. For authenticated users, this may be a username or e-mail address. For anonymous users, this could be an IP address or session ID. - * @param string|null $secondary An optional secondary identifier - * @param string|null $ip The user's IP address (optional) - * @param string|null $country The user's country, as an ISO 3166-1 alpha-2 code (e.g. 'US') (optional) - * @param string|null $email The user's e-mail address (optional) - * @param string|null $name The user's full name (optional) - * @param string|null $avatar A URL pointing to the user's avatar image (optional) - * @param string|null $firstName The user's first name (optional) - * @param string|null $lastName The user's last name (optional) + * @param string $key Unique key for the user. For authenticated users, this may be a username or e-mail address. For anonymous users, this could be an IP address or session ID. + * @param string|null $secondary An optional secondary identifier + * @param string|null $ip The user's IP address (optional) + * @param string|null $country The user's country, as an ISO 3166-1 alpha-2 code (e.g. 'US') (optional) + * @param string|null $email The user's e-mail address (optional) + * @param string|null $name The user's full name (optional) + * @param string|null $avatar A URL pointing to the user's avatar image (optional) + * @param string|null $firstName The user's first name (optional) + * @param string|null $lastName The user's last name (optional) * @param boolean|null $anonymous Whether this is an anonymous user - * @param array|null $custom Other custom attributes that can be used to create custom rules + * @param array|null $custom Other custom attributes that can be used to create custom rules */ - public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName= null, $anonymous = null, $custom = array()) { + public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array()) { $this->_key = strval($key); $this->_secondary = $secondary; $this->_ip = $ip; @@ -46,6 +46,40 @@ public function __construct($key, $secondary = null, $ip = null, $country = null $this->_custom = $custom; } + public function getValueForEvaluation($attr) { + switch ($attr) { + case "key": + return $this->getKey(); + case "secondary": //not available for evaluation. + return null; + case "ip": + return $this->getIP(); + case "country": + return $this->getCountry(); + case "email": + return $this->getEmail(); + case "name": + return $this->getName(); + case "avatar": + return $this->getAvatar(); + case "firstName": + return $this->getFirstName(); + case "lastName": + return $this->getLastName(); + case "anonymous": + return $this->getAnonymous(); + default: + $custom = $this->getCustom(); + if (is_null($custom)) { + return null; + } + if (!array_key_exists($attr, $custom)) { + return null; + } + return $custom[$attr]; + } + } + public function getCountry() { return $this->_country; } @@ -122,7 +156,7 @@ public function toJSON() { } if (isset($this->_anonymous)) { $json['anonymous'] = $this->_anonymous; - } + } return $json; } } diff --git a/src/LaunchDarkly/Operator.php b/src/LaunchDarkly/Operator.php new file mode 100644 index 000000000..eb0ca25d2 --- /dev/null +++ b/src/LaunchDarkly/Operator.php @@ -0,0 +1,71 @@ + $c; + } + break; + case "greaterThanOrEqual": + if (is_numeric($u) && is_numeric($c)) { + return $u >= $c; + } + break; + case "before": + break; + case "after": + break; + } + } finally { + return false; + } + } +} \ No newline at end of file diff --git a/tests/FeatureFlagTest.php b/tests/FeatureFlagTest.php new file mode 100644 index 000000000..3d084f047 --- /dev/null +++ b/tests/FeatureFlagTest.php @@ -0,0 +1,156 @@ + Date: Thu, 28 Jul 2016 16:44:21 -0600 Subject: [PATCH 032/150] [wip] V2 data model + evaluation start. --- src/LaunchDarkly/FeatureFlag.php | 2 +- src/LaunchDarkly/LDClient.php | 2 +- .../{Operator.php => Operators.php} | 57 ++++++++++++++++++- tests/OperatorsTest.php | 22 +++++++ 4 files changed, 80 insertions(+), 3 deletions(-) rename src/LaunchDarkly/{Operator.php => Operators.php} (57%) create mode 100644 tests/OperatorsTest.php diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 545ed451a..95e4cc9ca 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -326,7 +326,7 @@ public function isNegate() { */ private function matchAny($userValue) { foreach ($this->_values as $v) { - if (Operator::apply($this->_op, $userValue, $v)) { + if (Operators::apply($this->_op, $userValue, $v)) { return true; } } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index c440e26a0..6d21233b1 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -90,7 +90,7 @@ public function toggle($key, $user, $default = false) { try { $default = $this->_get_default($key, $default); - if (is_null($user) || strlen($user['key']) == 0) { + if (is_null($user) || strlen($user->getKey()) == 0) { $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; } diff --git a/src/LaunchDarkly/Operator.php b/src/LaunchDarkly/Operators.php similarity index 57% rename from src/LaunchDarkly/Operator.php rename to src/LaunchDarkly/Operators.php index eb0ca25d2..a747c0911 100644 --- a/src/LaunchDarkly/Operator.php +++ b/src/LaunchDarkly/Operators.php @@ -1,7 +1,12 @@ $cTime; + } + } break; } } finally { return false; } } + + /** + * @param $in + * @return null|int|float + */ + public static function parseTime($in) { + if (is_numeric($in)) { + return $in; + } + + if ($in instanceof DateTime) { + return self::dateTimeToUnixMillis($in); + } + + if (is_string($in)) { + try { + $dateTime = new DateTime($in); + return self::dateTimeToUnixMillis($dateTime); + } catch (Exception $e) { + error_log("LaunchDarkly: Could not parse timestamp: " . $in); + return null; + } + } + return null; + } + + /** + * @param $dateTime DateTime + * @return int + */ + private static function dateTimeToUnixMillis($dateTime) { + $timeStampSeconds = (int)$dateTime->getTimeStamp(); + $timestampMicros = $dateTime->format('u'); + return $timeStampSeconds * 1000 + (int)($timestampMicros / 1000); + } + } \ No newline at end of file diff --git a/tests/OperatorsTest.php b/tests/OperatorsTest.php new file mode 100644 index 000000000..383c3220e --- /dev/null +++ b/tests/OperatorsTest.php @@ -0,0 +1,22 @@ +assertEquals(0, Operators::parseTime(0)); + $this->assertEquals(100, Operators::parseTime(100)); + $this->assertEquals(100, Operators::parseTime(100)); + $this->assertEquals(1000, Operators::parseTime("1970-01-01T00:00:01Z")); + $this->assertEquals(1001, Operators::parseTime("1970-01-01T00:00:01.001Z")); + + + $this->assertEquals(null, Operators::parseTime("NOT A REAL TIMESTAMP")); + $this->assertEquals(null, Operators::parseTime([])); + + } +} \ No newline at end of file From 02f4118e15c4c59098178ef49e674f42433442ac Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 13:16:39 -0700 Subject: [PATCH 033/150] [wip] V2 eval works. --- src/LaunchDarkly/FeatureFlag.php | 45 ++++++++++++++++++++------------ src/LaunchDarkly/LDClient.php | 16 +++++++----- src/LaunchDarkly/Operators.php | 24 ++++++++++++----- tests/OperatorsTest.php | 37 ++++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 32 deletions(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 95e4cc9ca..993dc03bf 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -96,7 +96,7 @@ private function _evaluate($user, $featureRequester, $events) { } else if ($prereqFeatureFlag->isOn()) { $prereqEvalResult = $prereqFeatureFlag->evaluate($user, $featureRequester); $variation = $prereqFeatureFlag->getVariation($prereq->getVariation()); - if ($prereqEvalResult == null || $variation == null || $prereqEvalResult != $variation) { + if ($prereqEvalResult === null || $variation === null || $prereqEvalResult !== $variation) { $prereqOk = false; } } else { @@ -111,6 +111,7 @@ private function _evaluate($user, $featureRequester, $events) { if ($prereqOk) { return $this->getVariation($this->evaluateIndex($user)); } + return null; } /** @@ -122,7 +123,7 @@ private function evaluateIndex($user) { if ($this->_targets != null) { foreach ($this->_targets as $target) { foreach ($target->getValues() as $value) { - if ($value == $user->getKey()) { + if ($value === $user->getKey()) { return $target->getVariation(); } } @@ -138,7 +139,6 @@ private function evaluateIndex($user) { } // Walk through the fallthrough and see if it matches return $this->_fallthrough->variationIndexForUser($user, $this->_key, $this->_salt); - } private function getVariation($index) { @@ -157,7 +157,7 @@ private function getVariation($index) { } public function getOffVariationValue() { - if ($this->_offVariation == null) { + if ($this->_offVariation === null) { return null; } if ($this->_offVariation >= count($this->_variations)) { @@ -184,7 +184,7 @@ public static function getDecoder() { return function ($v) { return new VariationOrRollout( isset($v['variation']) ? $v['variation'] : null, - isset($v['rollout']) ? $v['rollout'] : null); + isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null); }; } @@ -209,10 +209,11 @@ public function getRollout() { * @return int|null */ public function variationIndexForUser($user, $_key, $_salt) { - if ($this->_variation != null) { + if ($this->_variation !== null) { + error_log("Returning: $this->_variation"); return $this->_variation; - } else if ($this->_rollout != null) { - $bucketBy = $this->_rollout->getBucketBy() == null ? "key" : $this->_rollout->getBucketBy(); + } else if ($this->_rollout !== null) { + $bucketBy = $this->_rollout->getBucketBy() === null ? "key" : $this->_rollout->getBucketBy(); $bucket = $this->bucketUser($user, $_key, $bucketBy, $_salt); $sum = 0.0; foreach ($this->_rollout->getVariations() as $wv) { @@ -222,6 +223,7 @@ public function variationIndexForUser($user, $_key, $_salt) { } } } + error_log("both fallthrough and variation are null!!"); return null; } @@ -238,7 +240,7 @@ private function bucketUser($user, $_key, $attr, $_salt) { if ($userValue != null) { if (is_string($userValue)) { $idHash = $userValue; - if ($user->getSecondary() != null) { + if ($user->getSecondary() !== null) { $idHash = $idHash . "." . $user->getSecondary(); } $hash = substr(sha1($_key . "." . $_salt . "." . $idHash), 0, 15); @@ -277,18 +279,22 @@ public static function getDecoder() { */ public function matchesUser($user) { $userValue = $user->getValueForEvaluation($this->_attribute); - if ($userValue == null) { +// error_log("user value: $userValue"); + if ($userValue === null) { + error_log("null user value"); return false; } if (is_array($userValue)) { + error_log("uservalue is array"); foreach ($userValue as $element) { - if ($this->matchAny($userValue)) { + if ($this->matchAny($element)) { return $this->_maybeNegate(true); } } - return $this->maybeNegate(false); + return $this->_maybeNegate(false); } else { - return $this->maybeNegate($this->matchAny($userValue)); + error_log("else..."); + return $this->_maybeNegate($this->matchAny($userValue)); } } @@ -326,7 +332,10 @@ public function isNegate() { */ private function matchAny($userValue) { foreach ($this->_values as $v) { - if (Operators::apply($this->_op, $userValue, $v)) { + $result = Operators::apply($this->_op, $userValue, $v); + error_log("clause.matchany operator result for v: $v $result"); + if ($result) { + error_log("true for $userValue"); return true; } } @@ -355,7 +364,7 @@ public static function getDecoder() { return function ($v) { return new Rule( isset($v['variation']) ? $v['variation'] : null, - isset($v['rollout']) ? $v['rollout'] : null, + isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null, array_map(Clause::getDecoder(), $v['clauses'])); }; } @@ -367,9 +376,11 @@ public static function getDecoder() { public function matchesUser($user) { foreach ($this->_clauses as $clause) { if (!$clause->matchesUser($user)) { + error_log("false from rule.matchesuser with attr: " . $clause->getAttribute()); return false; } } + error_log("true from rule.matchesuser"); return true; } @@ -490,7 +501,9 @@ protected function __construct(array $variations, $bucketBy) { public static function getDecoder() { return function ($v) { - return new Rollout($v['variations'], $v['bucketBy']); + return new Rollout( + array_map(WeightedVariation::getDecoder(), $v['variations']), + isset($v['bucketBy']) ? $v['bucketBy'] : null); }; } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 6d21233b1..8fd7f3f5b 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -81,7 +81,7 @@ public function getFlag($key, $user, $default = false) { * @param LDUser $user The end user requesting the flag * @param boolean $default The default value of the flag * - * @return boolean Whether or not the flag should be enabled, or `default` if the flag is disabled in the LaunchDarkly control panel + * @return mixed Whether or not the flag should be enabled, or `default` */ public function toggle($key, $user, $default = false) { if ($this->_offline) { @@ -101,11 +101,13 @@ public function toggle($key, $user, $default = false) { $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; } else if ($flag->isOn()) { + error_log("got a flag and it's on"); $result = $flag->evaluate($user, $this->_featureRequester); if (!$this->_offline) { //TODO: send prereq events } if ($result != null) { +// error_log("result: $result"); $this->_sendFlagRequestEvent($key, $user, $result, $default); return $result; } @@ -117,13 +119,13 @@ public function toggle($key, $user, $default = false) { } } catch (\Exception $e) { error_log("LaunchDarkly caught $e"); - try { - $this->_sendFlagRequestEvent($key, $user, $default, $default); - } catch (\Exception $e) { - error_log("LaunchDarkly caught $e"); - } - return $default; } + try { + $this->_sendFlagRequestEvent($key, $user, $default, $default); + } catch (\Exception $e) { + error_log("LaunchDarkly caught $e"); + } + return $default; } /** diff --git a/src/LaunchDarkly/Operators.php b/src/LaunchDarkly/Operators.php index a747c0911..21ed43510 100644 --- a/src/LaunchDarkly/Operators.php +++ b/src/LaunchDarkly/Operators.php @@ -14,29 +14,38 @@ class Operators { * @return bool */ public static function apply($op, $u, $c) { + error_log("apply with op: $op u: $u c: $c"); try { - if ($u == null || $c == null) { + if ($u === null || $c === null) { + error_log("one or both are null"); return false; } switch ($op) { case "in": - if ($u == $c) { + error_log("in with u: $u and c: $c"); + if ($u === $c) { + error_log("returning true from in op"); return true; } + if (is_numeric($u) && is_numeric($c)) { + return $u == $c; + } break; case "endsWith": if (is_string($u) && is_string($c)) { - return substr_compare($u, $c, strlen($c)) === 0; + return $c === "" || (($temp = strlen($u) - strlen($c)) >= 0 && strpos($u, $c, $temp) !== false); } break; case "startsWith": if (is_string($u) && is_string($c)) { - return substr_compare($u, $c, -strlen($c)) === 0; + return strpos($u, $c) === 0; } break; case "matches": if (is_string($u) && is_string($c)) { - return preg_match($c, $u) == 1; + error_log("u: $u c: $c"); + //PHP can do subpatterns, but everything needs to be wrapped in an outer (): + return preg_match("($c)", $u) === 1; } break; case "contains": @@ -83,9 +92,10 @@ public static function apply($op, $u, $c) { } break; } - } finally { - return false; + } catch (Exception $e) { + //TODO: log warning } + return false; } /** diff --git a/tests/OperatorsTest.php b/tests/OperatorsTest.php index 383c3220e..15e04e8da 100644 --- a/tests/OperatorsTest.php +++ b/tests/OperatorsTest.php @@ -7,7 +7,41 @@ class OperatorsTest extends \PHPUnit_Framework_TestCase { - public function testDefaultCtor() { + public function testIn() { + $this->assertTrue(Operators::apply("in", "A string to match", "A string to match")); + $this->assertFalse(Operators::apply("in", "A string to match", true)); + $this->assertTrue(Operators::apply("in", 34, 34)); + $this->assertTrue(Operators::apply("in", 34, 34.0)); + $this->assertFalse(Operators::apply("in", 34, true)); + $this->assertTrue(Operators::apply("in", false, false)); + $this->assertTrue(Operators::apply("in", true, true)); + $this->assertFalse(Operators::apply("in", true, false)); + $this->assertFalse(Operators::apply("in", false, true)); + + } + + public function testStartsWith() { + $this->assertTrue(Operators::apply("startsWith", "start", "start")); + $this->assertTrue(Operators::apply("startsWith", "start plus more", "start")); + $this->assertFalse(Operators::apply("startsWith", "does not contain", "start")); + $this->assertFalse(Operators::apply("startsWith", "does not start with", "start")); + } + + public function testEndsWith() { + $this->assertTrue(Operators::apply("endsWith", "end", "end")); + $this->assertTrue(Operators::apply("endsWith", "something somethingend", "end")); + $this->assertFalse(Operators::apply("endsWith", "does not contain", "end")); + $this->assertFalse(Operators::apply("endsWith", "does not end with", "end")); + } + + public function testMatches() { + $this->assertTrue(Operators::apply("matches", "anything", ".*")); + $this->assertTrue(Operators::apply("matches", "darn", "(\\W|^)(baloney|darn|drat|fooey|gosh\\sdarnit|heck)(\\W|$)")); + } + + + + public function testParseTime() { $this->assertEquals(0, Operators::parseTime(0)); $this->assertEquals(100, Operators::parseTime(100)); $this->assertEquals(100, Operators::parseTime(100)); @@ -17,6 +51,5 @@ public function testDefaultCtor() { $this->assertEquals(null, Operators::parseTime("NOT A REAL TIMESTAMP")); $this->assertEquals(null, Operators::parseTime([])); - } } \ No newline at end of file From 5b9defde96977fd3a6ae8679cf51f7117cfa80b0 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 13:32:20 -0700 Subject: [PATCH 034/150] [wip] Move some things out of big file. --- src/LaunchDarkly/Clause.php | 99 +++++++++++ src/LaunchDarkly/FeatureFlag.php | 225 ------------------------ src/LaunchDarkly/Rule.php | 50 ++++++ src/LaunchDarkly/VariationOrRollout.php | 91 ++++++++++ 4 files changed, 240 insertions(+), 225 deletions(-) create mode 100644 src/LaunchDarkly/Clause.php create mode 100644 src/LaunchDarkly/Rule.php create mode 100644 src/LaunchDarkly/VariationOrRollout.php diff --git a/src/LaunchDarkly/Clause.php b/src/LaunchDarkly/Clause.php new file mode 100644 index 000000000..dd7d61c0d --- /dev/null +++ b/src/LaunchDarkly/Clause.php @@ -0,0 +1,99 @@ +_attribute = $attribute; + $this->_op = $op; + $this->_values = $values; + $this->_negate = $negate; + } + + public static function getDecoder() { + return function ($v) { + return new Clause($v['attribute'], $v['op'], $v['values'], $v['negate']); + }; + } + + /** + * @param $user LDUser + * @return bool + */ + public function matchesUser($user) { + $userValue = $user->getValueForEvaluation($this->_attribute); + if ($userValue === null) { + error_log("null user value"); + return false; + } + if (is_array($userValue)) { + error_log("uservalue is array"); + foreach ($userValue as $element) { + if ($this->matchAny($element)) { + return $this->_maybeNegate(true); + } + } + return $this->_maybeNegate(false); + } else { + error_log("else..."); + return $this->_maybeNegate($this->matchAny($userValue)); + } + } + + /** + * @return null + */ + public function getAttribute() { + return $this->_attribute; + } + + /** + * @return null + */ + public function getOp() { + return $this->_op; + } + + /** + * @return array + */ + public function getValues() { + return $this->_values; + } + + /** + * @return boolean + */ + public function isNegate() { + return $this->_negate; + } + + /** + * @param $userValue + * @return bool + */ + private function matchAny($userValue) { + foreach ($this->_values as $v) { + $result = Operators::apply($this->_op, $userValue, $v); + error_log("clause.matchany operator result for v: $v $result"); + if ($result) { + error_log("true for $userValue"); + return true; + } + } + return false; + } + + private function _maybeNegate($b) { + if ($this->_negate) { + return !$b; + } else { + return $b; + } + } +} \ No newline at end of file diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 993dc03bf..bf884aeec 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -167,231 +167,6 @@ public function getOffVariationValue() { } } -class VariationOrRollout { - private static $LONG_SCALE = 0xFFFFFFFFFFFFFFF; - - /** @var int */ - private $_variation = null; - /** @var Rollout */ - private $_rollout = null; - - protected function __construct($variation, $rollout) { - $this->_variation = $variation; - $this->_rollout = $rollout; - } - - public static function getDecoder() { - return function ($v) { - return new VariationOrRollout( - isset($v['variation']) ? $v['variation'] : null, - isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null); - }; - } - - /** - * @return int - */ - public function getVariation() { - return $this->_variation; - } - - /** - * @return Rollout - */ - public function getRollout() { - return $this->_rollout; - } - - /** - * @param $user LDUser - * @param $_key string - * @param $_salt string - * @return int|null - */ - public function variationIndexForUser($user, $_key, $_salt) { - if ($this->_variation !== null) { - error_log("Returning: $this->_variation"); - return $this->_variation; - } else if ($this->_rollout !== null) { - $bucketBy = $this->_rollout->getBucketBy() === null ? "key" : $this->_rollout->getBucketBy(); - $bucket = $this->bucketUser($user, $_key, $bucketBy, $_salt); - $sum = 0.0; - foreach ($this->_rollout->getVariations() as $wv) { - $sum += $wv->getWeight() / 100000.0; - if ($bucket < $sum) { - return $wv->getVariation(); - } - } - } - error_log("both fallthrough and variation are null!!"); - return null; - } - - /** - * @param $user LDUser - * @param $_key string - * @param $attr string - * @param $_salt string - * @return float - */ - private function bucketUser($user, $_key, $attr, $_salt) { - $userValue = $user->getValueForEvaluation($attr); - $idHash = null; - if ($userValue != null) { - if (is_string($userValue)) { - $idHash = $userValue; - if ($user->getSecondary() !== null) { - $idHash = $idHash . "." . $user->getSecondary(); - } - $hash = substr(sha1($_key . "." . $_salt . "." . $idHash), 0, 15); - $longVal = base_convert($hash, 16, 10); - $result = $longVal / self::$LONG_SCALE; - - return $result; - } - } - return 0.0; - } -} - -class Clause { - private $_attribute = null; - private $_op = null; - private $_values = array(); - private $_negate = false; - - private function __construct($attribute, $op, array $values, $negate) { - $this->_attribute = $attribute; - $this->_op = $op; - $this->_values = $values; - $this->_negate = $negate; - } - - public static function getDecoder() { - return function ($v) { - return new Clause($v['attribute'], $v['op'], $v['values'], $v['negate']); - }; - } - - /** - * @param $user LDUser - * @return bool - */ - public function matchesUser($user) { - $userValue = $user->getValueForEvaluation($this->_attribute); -// error_log("user value: $userValue"); - if ($userValue === null) { - error_log("null user value"); - return false; - } - if (is_array($userValue)) { - error_log("uservalue is array"); - foreach ($userValue as $element) { - if ($this->matchAny($element)) { - return $this->_maybeNegate(true); - } - } - return $this->_maybeNegate(false); - } else { - error_log("else..."); - return $this->_maybeNegate($this->matchAny($userValue)); - } - } - - /** - * @return null - */ - public function getAttribute() { - return $this->_attribute; - } - - /** - * @return null - */ - public function getOp() { - return $this->_op; - } - - /** - * @return array - */ - public function getValues() { - return $this->_values; - } - - /** - * @return boolean - */ - public function isNegate() { - return $this->_negate; - } - - /** - * @param $userValue - * @return bool - */ - private function matchAny($userValue) { - foreach ($this->_values as $v) { - $result = Operators::apply($this->_op, $userValue, $v); - error_log("clause.matchany operator result for v: $v $result"); - if ($result) { - error_log("true for $userValue"); - return true; - } - } - return false; - } - - private function _maybeNegate($b) { - if ($this->_negate) { - return !$b; - } else { - return $b; - } - } -} - -class Rule extends VariationOrRollout { - /** @var Clause[] */ - private $_clauses = array(); - - protected function __construct($variation, $rollout, array $clauses) { - parent::__construct($variation, $rollout); - $this->_clauses = $clauses; - } - - public static function getDecoder() { - return function ($v) { - return new Rule( - isset($v['variation']) ? $v['variation'] : null, - isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null, - array_map(Clause::getDecoder(), $v['clauses'])); - }; - } - - /** - * @param $user LDUser - * @return bool - */ - public function matchesUser($user) { - foreach ($this->_clauses as $clause) { - if (!$clause->matchesUser($user)) { - error_log("false from rule.matchesuser with attr: " . $clause->getAttribute()); - return false; - } - } - error_log("true from rule.matchesuser"); - return true; - } - - /** - * @return Clause[] - */ - public function getClauses() { - return $this->_clauses; - } -} - class WeightedVariation { /** @var int */ private $_variation = null; diff --git a/src/LaunchDarkly/Rule.php b/src/LaunchDarkly/Rule.php new file mode 100644 index 000000000..326229168 --- /dev/null +++ b/src/LaunchDarkly/Rule.php @@ -0,0 +1,50 @@ +_clauses = $clauses; + } + + public static function getDecoder() { + return function ($v) { + return new Rule( + isset($v['variation']) ? $v['variation'] : null, + isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null, + array_map(Clause::getDecoder(), $v['clauses'])); + }; + } + + /** + * @param $user LDUser + * @return bool + */ + public function matchesUser($user) { + foreach ($this->_clauses as $clause) { + if (!$clause->matchesUser($user)) { + error_log("false from rule.matchesuser with attr: " . $clause->getAttribute()); + return false; + } + } + error_log("true from rule.matchesuser"); + return true; + } + + /** + * @return Clause[] + */ + public function getClauses() { + return $this->_clauses; + } +} \ No newline at end of file diff --git a/src/LaunchDarkly/VariationOrRollout.php b/src/LaunchDarkly/VariationOrRollout.php new file mode 100644 index 000000000..7a6511e6d --- /dev/null +++ b/src/LaunchDarkly/VariationOrRollout.php @@ -0,0 +1,91 @@ +_variation = $variation; + $this->_rollout = $rollout; + } + + public static function getDecoder() { + return function ($v) { + return new VariationOrRollout( + isset($v['variation']) ? $v['variation'] : null, + isset($v['rollout']) ? call_user_func(Rollout::getDecoder(), $v['rollout']) : null); + }; + } + + /** + * @return int + */ + public function getVariation() { + return $this->_variation; + } + + /** + * @return Rollout + */ + public function getRollout() { + return $this->_rollout; + } + + /** + * @param $user LDUser + * @param $_key string + * @param $_salt string + * @return int|null + */ + public function variationIndexForUser($user, $_key, $_salt) { + if ($this->_variation !== null) { + error_log("Returning: $this->_variation"); + return $this->_variation; + } else if ($this->_rollout !== null) { + $bucketBy = $this->_rollout->getBucketBy() === null ? "key" : $this->_rollout->getBucketBy(); + $bucket = $this->bucketUser($user, $_key, $bucketBy, $_salt); + $sum = 0.0; + foreach ($this->_rollout->getVariations() as $wv) { + $sum += $wv->getWeight() / 100000.0; + if ($bucket < $sum) { + return $wv->getVariation(); + } + } + } + error_log("both fallthrough and variation are null!!"); + return null; + } + + /** + * @param $user LDUser + * @param $_key string + * @param $attr string + * @param $_salt string + * @return float + */ + private function bucketUser($user, $_key, $attr, $_salt) { + $userValue = $user->getValueForEvaluation($attr); + $idHash = null; + if ($userValue != null) { + if (is_string($userValue)) { + $idHash = $userValue; + if ($user->getSecondary() !== null) { + $idHash = $idHash . "." . $user->getSecondary(); + } + $hash = substr(sha1($_key . "." . $_salt . "." . $idHash), 0, 15); + $longVal = base_convert($hash, 16, 10); + $result = $longVal / self::$LONG_SCALE; + + return $result; + } + } + return 0.0; + } +} \ No newline at end of file From 2ce8d58961b6f5aa2aa5c49aed6198b072f44a3c Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 13:51:58 -0700 Subject: [PATCH 035/150] [wip] v2 events work ok- but not prereqs. --- src/LaunchDarkly/FeatureFlag.php | 7 +++++++ src/LaunchDarkly/LDClient.php | 15 +++++++++++---- src/LaunchDarkly/LDUser.php | 2 +- src/LaunchDarkly/Operators.php | 15 ++------------- src/LaunchDarkly/Util.php | 20 ++++++++++++++++++++ 5 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 src/LaunchDarkly/Util.php diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index bf884aeec..00073e505 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -165,6 +165,13 @@ public function getOffVariationValue() { } return $this->_variations[$this->_offVariation]; } + + /** + * @return int + */ + public function getVersion() { + return $this->_version; + } } class WeightedVariation { diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 8fd7f3f5b..09beb0e11 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -1,6 +1,8 @@ _sendFlagRequestEvent($key, $user, $result, $default); + $this->_sendFlagRequestEvent($key, $user, $result, $default, $flag->getVersion()); return $result; } } $offVariation = $flag->getOffVariationValue(); if ($offVariation != null) { - $this->_sendFlagRequestEvent($key, $user, $offVariation, $default); + $this->_sendFlagRequestEvent($key, $user, $offVariation, $default, $flag->getVersion()); return $offVariation; } } catch (\Exception $e) { @@ -196,8 +198,11 @@ public function identify($user) { * @param $key string * @param $user LDUser * @param $value mixed + * @param $default + * @param $version int | null + * @param string | null $prereqOf */ - protected function _sendFlagRequestEvent($key, $user, $value, $default) { + protected function _sendFlagRequestEvent($key, $user, $value, $default, $version = null, $prereqOf = null) { if ($this->isOffline() || !$this->_events) { return; } @@ -206,9 +211,11 @@ protected function _sendFlagRequestEvent($key, $user, $value, $default) { $event['user'] = $user->toJSON(); $event['value'] = $value; $event['kind'] = "feature"; - $event['creationDate'] = round(microtime(1) * 1000); + $event['creationDate'] = Util::dateTimeToUnixMillis(new DateTime('now', new DateTimeZone("UTC"))); $event['key'] = $key; $event['default'] = $default; + $event['version'] = $version; + $event['prereqOf'] = $prereqOf; $this->_eventProcessor->enqueue($event); } diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index 02c806e0c..933fb6121 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -33,7 +33,7 @@ class LDUser { * @param array|null $custom Other custom attributes that can be used to create custom rules */ public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array()) { - $this->_key = strval($key); + $this->_key = $key; $this->_secondary = $secondary; $this->_ip = $ip; $this->_country = $country; diff --git a/src/LaunchDarkly/Operators.php b/src/LaunchDarkly/Operators.php index 21ed43510..1f2ca9266 100644 --- a/src/LaunchDarkly/Operators.php +++ b/src/LaunchDarkly/Operators.php @@ -108,13 +108,13 @@ public static function parseTime($in) { } if ($in instanceof DateTime) { - return self::dateTimeToUnixMillis($in); + return Util::dateTimeToUnixMillis($in); } if (is_string($in)) { try { $dateTime = new DateTime($in); - return self::dateTimeToUnixMillis($dateTime); + return Util::dateTimeToUnixMillis($dateTime); } catch (Exception $e) { error_log("LaunchDarkly: Could not parse timestamp: " . $in); return null; @@ -122,15 +122,4 @@ public static function parseTime($in) { } return null; } - - /** - * @param $dateTime DateTime - * @return int - */ - private static function dateTimeToUnixMillis($dateTime) { - $timeStampSeconds = (int)$dateTime->getTimeStamp(); - $timestampMicros = $dateTime->format('u'); - return $timeStampSeconds * 1000 + (int)($timestampMicros / 1000); - } - } \ No newline at end of file diff --git a/src/LaunchDarkly/Util.php b/src/LaunchDarkly/Util.php new file mode 100644 index 000000000..d4a08ed7f --- /dev/null +++ b/src/LaunchDarkly/Util.php @@ -0,0 +1,20 @@ +getTimeStamp(); + $timestampMicros = $dateTime->format('u'); + return $timeStampSeconds * 1000 + (int)($timestampMicros / 1000); + } + +} \ No newline at end of file From 100d34dff62e8d90eadc90439b65c84d47fec007 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 14:28:13 -0700 Subject: [PATCH 036/150] [wip] v2 events work ok including prereqs. --- src/LaunchDarkly/FeatureFlag.php | 48 ++++++++++++++++++++++++++++---- src/LaunchDarkly/LDClient.php | 26 ++++++----------- src/LaunchDarkly/Util.php | 22 +++++++++++++++ 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 00073e505..78be4e6cd 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -71,12 +71,12 @@ public function isOn() { /** * @param $user LDUser * @param $featureRequester FeatureRequester - * @return mixed|null + * @return EvalResult|null */ public function evaluate($user, $featureRequester) { $prereqEvents = array(); $value = $this->_evaluate($user, $featureRequester, $prereqEvents); - return $value; + return new EvalResult($value, $prereqEvents); } /** @@ -85,16 +85,17 @@ public function evaluate($user, $featureRequester) { * @param $events * @return mixed|null */ - private function _evaluate($user, $featureRequester, $events) { + private function _evaluate($user, $featureRequester, &$events) { $prereqOk = true; if ($this->_prerequisites != null) { foreach ($this->_prerequisites as $prereq) { try { + $prereqEvalResult = null; $prereqFeatureFlag = $featureRequester->get($prereq->getKey()); if ($prereqFeatureFlag == null) { return null; } else if ($prereqFeatureFlag->isOn()) { - $prereqEvalResult = $prereqFeatureFlag->evaluate($user, $featureRequester); + $prereqEvalResult = $prereqFeatureFlag->_evaluate($user, $featureRequester, $events); $variation = $prereqFeatureFlag->getVariation($prereq->getVariation()); if ($prereqEvalResult === null || $variation === null || $prereqEvalResult !== $variation) { $prereqOk = false; @@ -102,10 +103,10 @@ private function _evaluate($user, $featureRequester, $events) { } else { $prereqOk = false; } + array_push($events, Util::newFeatureRequestEvent($prereqFeatureFlag->getKey(), $user, $prereqEvalResult, null, $prereqFeatureFlag->getVersion(), $this->_key)); } catch (EvaluationException $e) { $prereqOk = false; } - //TODO: Add event. } } if ($prereqOk) { @@ -172,6 +173,43 @@ public function getOffVariationValue() { public function getVersion() { return $this->_version; } + + /** + * @return string + */ + public function getKey() { + return $this->_key; + } +} + +class EvalResult { + private $_value = null; + /** @var array */ + private $_prerequisiteEvents = []; + + /** + * EvalResult constructor. + * @param null $value + * @param array $prerequisiteEvents + */ + public function __construct($value, array $prerequisiteEvents) { + $this->_value = $value; + $this->_prerequisiteEvents = $prerequisiteEvents; + } + + /** + * @return null + */ + public function getValue() { + return $this->_value; + } + + /** + * @return array + */ + public function getPrerequisiteEvents() { + return $this->_prerequisiteEvents; + } } class WeightedVariation { diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 09beb0e11..04aa48c67 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -105,13 +105,15 @@ public function toggle($key, $user, $default = false) { } else if ($flag->isOn()) { error_log("got a flag and it's on"); $result = $flag->evaluate($user, $this->_featureRequester); - if (!$this->_offline) { - //TODO: send prereq events + if (!$this->isOffline() && $this->_events) { + foreach ($result->getPrerequisiteEvents() as $e) { + error_log("enqueueing prereq event..."); + $this->_eventProcessor->enqueue($e); + } } - if ($result != null) { -// error_log("result: $result"); - $this->_sendFlagRequestEvent($key, $user, $result, $default, $flag->getVersion()); - return $result; + if ($result->getValue() != null) { + $this->_sendFlagRequestEvent($key, $user, $result->getValue(), $default, $flag->getVersion()); + return $result->getValue(); } } $offVariation = $flag->getOffVariationValue(); @@ -206,17 +208,7 @@ protected function _sendFlagRequestEvent($key, $user, $value, $default, $version if ($this->isOffline() || !$this->_events) { return; } - - $event = array(); - $event['user'] = $user->toJSON(); - $event['value'] = $value; - $event['kind'] = "feature"; - $event['creationDate'] = Util::dateTimeToUnixMillis(new DateTime('now', new DateTimeZone("UTC"))); - $event['key'] = $key; - $event['default'] = $default; - $event['version'] = $version; - $event['prereqOf'] = $prereqOf; - $this->_eventProcessor->enqueue($event); + $this->_eventProcessor->enqueue(Util::newFeatureRequestEvent($key, $user, $value, $default, $version, $prereqOf)); } protected function _get_flag($key, $user) { diff --git a/src/LaunchDarkly/Util.php b/src/LaunchDarkly/Util.php index d4a08ed7f..a1a38cd75 100644 --- a/src/LaunchDarkly/Util.php +++ b/src/LaunchDarkly/Util.php @@ -4,6 +4,7 @@ use DateTime; +use DateTimeZone; class Util { @@ -17,4 +18,25 @@ public static function dateTimeToUnixMillis($dateTime) { return $timeStampSeconds * 1000 + (int)($timestampMicros / 1000); } + /** + * @return int + */ + public static function currentTimeUnixMillis() { + return Util::dateTimeToUnixMillis(new DateTime('now', new DateTimeZone("UTC"))); + } + + + public static function newFeatureRequestEvent($key, $user, $value, $default, $version = null, $prereqOf = null) { + $event = array(); + $event['user'] = $user->toJSON(); + $event['value'] = $value; + $event['kind'] = "feature"; + $event['creationDate'] = Util::currentTimeUnixMillis(); + $event['key'] = $key; + $event['default'] = $default; + $event['version'] = $version; + $event['prereqOf'] = $prereqOf; + return $event; + } + } \ No newline at end of file From 6beeb750cfe3b7c7ef039a3be4f89b079e9f0103 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 15:39:25 -0700 Subject: [PATCH 037/150] Use standard logging interface. Log more/better things --- composer.json | 4 +- composer.lock | 187 ++++++++++---------- src/LaunchDarkly/Clause.php | 7 +- src/LaunchDarkly/FeatureFlag.php | 7 + src/LaunchDarkly/GuzzleFeatureRequester.php | 9 +- src/LaunchDarkly/LDClient.php | 95 +++++----- src/LaunchDarkly/LDDFeatureRequester.php | 17 +- src/LaunchDarkly/Operators.php | 6 - src/LaunchDarkly/Rule.php | 2 - src/LaunchDarkly/VariationOrRollout.php | 3 +- 10 files changed, 173 insertions(+), 164 deletions(-) diff --git a/composer.json b/composer.json index 0329dee7e..afa5ae0f9 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ } ], "require": { - "php": ">=5.5" + "php": ">=5.5", + "psr/log": "1.0.0" }, "require-dev": { "guzzlehttp/guzzle": "6.2.1", @@ -27,6 +28,7 @@ "suggested": { "guzzlehttp/guzzle": "6.2.1", "kevinrob/guzzle-cache-middleware": "1.4.1", + "monolog/monolog": "1.21.0", "predis/predis": "1.0.*" }, "autoload": { diff --git a/composer.lock b/composer.lock index 87ffb3aaf..c07149b50 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,48 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "cf5c4602f9f9aff086005edc75728d0f", - "content-hash": "f09e942238b22b8ef39b297cd1808ee6", - "packages": [], + "hash": "fc1de559a4df16ad00c93dd5c20fcc28", + "content-hash": "a8cf37cf9851938001d2b8babe963b5e", + "packages": [ + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + } + ], "packages-dev": [ { "name": "cilex/cilex", @@ -1004,16 +1043,16 @@ }, { "name": "monolog/monolog", - "version": "1.20.0", + "version": "1.21.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037" + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", "shasum": "" }, "require": { @@ -1078,7 +1117,7 @@ "logging", "psr-3" ], - "time": "2016-07-02 14:02:10" + "time": "2016-07-29 03:23:52" }, { "name": "nikic/php-parser", @@ -2079,44 +2118,6 @@ ], "time": "2015-05-04 20:22:00" }, - { - "name": "psr/log", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2012-12-21 11:40:51" - }, { "name": "sebastian/comparator", "version": "1.2.0", @@ -2537,16 +2538,16 @@ }, { "name": "symfony/config", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0" + "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0926e69411eba491803dbafb9f1f233e2ced58d0", - "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0", + "url": "https://api.github.com/repos/symfony/config/zipball/4275ef5b59f18959df0eee3991e9ca0cc208ffd4", + "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4", "shasum": "" }, "require": { @@ -2586,20 +2587,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:31:50" + "time": "2016-07-26 08:02:44" }, { "name": "symfony/console", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c392a6ec72f2122748032c2ad6870420561ffcfa" + "reference": "36e62335caca8a6e909c5c5bac4a8128149911c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c392a6ec72f2122748032c2ad6870420561ffcfa", - "reference": "c392a6ec72f2122748032c2ad6870420561ffcfa", + "url": "https://api.github.com/repos/symfony/console/zipball/36e62335caca8a6e909c5c5bac4a8128149911c9", + "reference": "36e62335caca8a6e909c5c5bac4a8128149911c9", "shasum": "" }, "require": { @@ -2646,20 +2647,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-06-29 07:02:14" + "time": "2016-07-30 07:20:35" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9" + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9", - "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8", + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8", "shasum": "" }, "require": { @@ -2706,20 +2707,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-28 16:56:28" }, { "name": "symfony/filesystem", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "a108b1d603ccb52addb5da9b14a3ba259f8b3db0" + "reference": "b2da5009d9bacbd91d83486aa1f44c793a8c380d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a108b1d603ccb52addb5da9b14a3ba259f8b3db0", - "reference": "a108b1d603ccb52addb5da9b14a3ba259f8b3db0", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b2da5009d9bacbd91d83486aa1f44c793a8c380d", + "reference": "b2da5009d9bacbd91d83486aa1f44c793a8c380d", "shasum": "" }, "require": { @@ -2755,20 +2756,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:40:00" + "time": "2016-07-20 05:43:46" }, { "name": "symfony/finder", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d" + "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d", - "reference": "bf0506ef4e7778fd3f0f1f141ab5e8c1ef35dd7d", + "url": "https://api.github.com/repos/symfony/finder/zipball/60804d88691e4a73bbbb3035eb1d9f075c5c2c10", + "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10", "shasum": "" }, "require": { @@ -2804,7 +2805,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-26 08:02:44" }, { "name": "symfony/polyfill-mbstring", @@ -2867,16 +2868,16 @@ }, { "name": "symfony/process", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe" + "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/89f33c16796415ccfd8bb3cf8d520cbb79899bfe", - "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe", + "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c", + "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c", "shasum": "" }, "require": { @@ -2912,11 +2913,11 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-28 11:13:19" }, { "name": "symfony/stopwatch", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -2965,16 +2966,16 @@ }, { "name": "symfony/translation", - "version": "v3.0.8", + "version": "v3.0.9", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8" + "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6bf844e1ee3c820c012386c10427a5c67bbefec8", - "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8", + "url": "https://api.github.com/repos/symfony/translation/zipball/eee6c664853fd0576f21ae25725cfffeafe83f26", + "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26", "shasum": "" }, "require": { @@ -3025,20 +3026,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:40:00" + "time": "2016-07-30 07:22:48" }, { "name": "symfony/validator", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "366674c28bf7a107a8bce280c668bac40aeb090e" + "reference": "244ff2a7f0283d1c854abbf17181dbb02c0af95f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/366674c28bf7a107a8bce280c668bac40aeb090e", - "reference": "366674c28bf7a107a8bce280c668bac40aeb090e", + "url": "https://api.github.com/repos/symfony/validator/zipball/244ff2a7f0283d1c854abbf17181dbb02c0af95f", + "reference": "244ff2a7f0283d1c854abbf17181dbb02c0af95f", "shasum": "" }, "require": { @@ -3052,7 +3053,7 @@ "egulias/email-validator": "~1.2,>=1.2.1", "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", - "symfony/http-foundation": "~2.1|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", "symfony/intl": "~2.7.4|~2.8|~3.0.0", "symfony/property-access": "~2.3|~3.0.0", "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" @@ -3098,20 +3099,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-26 08:02:44" }, { "name": "symfony/yaml", - "version": "v3.1.2", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", - "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac", + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac", "shasum": "" }, "require": { @@ -3147,7 +3148,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:41:56" + "time": "2016-07-17 14:02:08" }, { "name": "twig/twig", diff --git a/src/LaunchDarkly/Clause.php b/src/LaunchDarkly/Clause.php index dd7d61c0d..9f4534830 100644 --- a/src/LaunchDarkly/Clause.php +++ b/src/LaunchDarkly/Clause.php @@ -28,11 +28,9 @@ public static function getDecoder() { public function matchesUser($user) { $userValue = $user->getValueForEvaluation($this->_attribute); if ($userValue === null) { - error_log("null user value"); return false; } if (is_array($userValue)) { - error_log("uservalue is array"); foreach ($userValue as $element) { if ($this->matchAny($element)) { return $this->_maybeNegate(true); @@ -40,7 +38,6 @@ public function matchesUser($user) { } return $this->_maybeNegate(false); } else { - error_log("else..."); return $this->_maybeNegate($this->matchAny($userValue)); } } @@ -80,9 +77,7 @@ public function isNegate() { private function matchAny($userValue) { foreach ($this->_values as $v) { $result = Operators::apply($this->_op, $userValue, $v); - error_log("clause.matchany operator result for v: $v $result"); - if ($result) { - error_log("true for $userValue"); + if ($result === true) { return true; } } diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 78be4e6cd..26684e713 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -180,6 +180,13 @@ public function getVersion() { public function getKey() { return $this->_key; } + + /** + * @return boolean + */ + public function isDeleted() { + return $this->_deleted; + } } class EvalResult { diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index d1c29458b..958547a8d 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -6,12 +6,18 @@ use GuzzleHttp\HandlerStack; use Kevinrob\GuzzleCache\CacheMiddleware; use Kevinrob\GuzzleCache\Strategy\PublicCacheStrategy; +use Psr\Log\LoggerInterface; class GuzzleFeatureRequester implements FeatureRequester { + /** @var Client */ private $_client; + /** @var string */ private $_baseUri; + /** @var array */ private $_defaults; + /** @var LoggerInterface */ + private $_logger; function __construct($baseUri, $apiKey, $options) { @@ -28,6 +34,7 @@ function __construct($baseUri, $apiKey, $options) 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ); + $this->_logger = $options['logger']; $this->_client = new Client(['handler' => $stack, 'debug' => false]); } @@ -47,7 +54,7 @@ public function get($key) return FeatureFlag::decode(json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); - error_log("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); + $this->_logger->error("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); return null; } } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 04aa48c67..486835306 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -1,24 +1,32 @@ _baseUri = rtrim($options['base_uri'], '/'); } - if (isset($options['events'])) { - $this->_events = $options['events']; + if (isset($options['send_events'])) { + $this->_send_events = $options['send_events']; } + if (isset($options['offline']) && $options['offline'] === true) { + $this->_offline = true; + $this->_send_events = false; + } + if (isset($options['defaults'])) { $this->_defaults = $options['defaults']; } @@ -58,6 +71,12 @@ public function __construct($apiKey, $options = array()) { $options['capacity'] = 1000; } + if (!isset($options['logger'])) { + $logger = new Logger("LaunchDarkly", [new ErrorLogHandler()]); + $options['logger'] = $logger; + } + $this->_logger = $options['logger']; + $this->_eventProcessor = new EventProcessor($apiKey, $options); if (isset($options['feature_requester_class'])) { @@ -86,28 +105,27 @@ public function getFlag($key, $user, $default = false) { * @return mixed Whether or not the flag should be enabled, or `default` */ public function toggle($key, $user, $default = false) { + $default = $this->_get_default($key, $default); + if ($this->_offline) { return $default; } try { - $default = $this->_get_default($key, $default); - if (is_null($user) || strlen($user->getKey()) == 0) { + if (is_null($user) || strlen($user->getKey()) === 0) { $this->_sendFlagRequestEvent($key, $user, $default, $default); + $this->_logger->warn("Toggle called with null user or null/empty user key! Returning default value"); return $default; } $flag = $this->_featureRequester->get($key); -// $flag = $this->_get_flag($key, $user); if (is_null($flag)) { $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; } else if ($flag->isOn()) { - error_log("got a flag and it's on"); $result = $flag->evaluate($user, $this->_featureRequester); - if (!$this->isOffline() && $this->_events) { + if (!$this->isOffline() && $this->_send_events) { foreach ($result->getPrerequisiteEvents() as $e) { - error_log("enqueueing prereq event..."); $this->_eventProcessor->enqueue($e); } } @@ -122,35 +140,18 @@ public function toggle($key, $user, $default = false) { return $offVariation; } } catch (\Exception $e) { - error_log("LaunchDarkly caught $e"); + $this->_logger->error("Caught $e"); } try { $this->_sendFlagRequestEvent($key, $user, $default, $default); } catch (\Exception $e) { - error_log("LaunchDarkly caught $e"); + $this->_logger->error("Caught $e"); } return $default; } /** - * Puts the LaunchDarkly client in offline mode. - * In offline mode, all calls to `toggle` will return the default value, and `track` will be a no-op. - * - */ - public function setOffline() { - $this->_offline = true; - } - - /** - * Puts the LaunchDarkly client in online mode. - * - */ - public function setOnline() { - $this->_offline = false; - } - - /** - * Returns whether the LaunchDarlkly client is in offline mode. + * Returns whether the LaunchDarkly client is in offline mode. * */ public function isOffline() { @@ -168,11 +169,14 @@ public function track($eventName, $user, $data) { if ($this->isOffline()) { return; } + if (is_null($user) || strlen($user->getKey()) === 0) { + $this->_logger->warn("Track called with null user or null/empty user key!"); + } $event = array(); $event['user'] = $user->toJSON(); $event['kind'] = "custom"; - $event['creationDate'] = round(microtime(1) * 1000); + $event['creationDate'] = Util::currentTimeUnixMillis(); $event['key'] = $eventName; if (isset($data)) { $event['data'] = $data; @@ -187,11 +191,14 @@ public function identify($user) { if ($this->isOffline()) { return; } + if (is_null($user) || strlen($user->getKey()) === 0) { + $this->_logger->warn("Track called with null user or null/empty user key!"); + } $event = array(); $event['user'] = $user->toJSON(); $event['kind'] = "identify"; - $event['creationDate'] = round(microtime(1) * 1000); + $event['creationDate'] = Util::currentTimeUnixMillis(); $event['key'] = $user->getKey(); $this->_eventProcessor->enqueue($event); } @@ -205,26 +212,12 @@ public function identify($user) { * @param string | null $prereqOf */ protected function _sendFlagRequestEvent($key, $user, $value, $default, $version = null, $prereqOf = null) { - if ($this->isOffline() || !$this->_events) { + if ($this->isOffline() || !$this->_send_events) { return; } $this->_eventProcessor->enqueue(Util::newFeatureRequestEvent($key, $user, $value, $default, $version, $prereqOf)); } - protected function _get_flag($key, $user) { - try { - $data = $this->_featureRequester->get($key); - if ($data == null) { - return null; - } - return self::_decode($data, $user); - } catch (Exception $e) { - $msg = $e->getMessage(); - error_log("LDClient::_toggle received error $msg, using default"); - return null; - } - } - protected function _get_default($key, $default) { if (array_key_exists($key, $this->_defaults)) { return $this->_defaults[$key]; diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index 08cdf665b..06fecb7d5 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -2,11 +2,15 @@ namespace LaunchDarkly; +use Psr\Log\LoggerInterface; + class LDDFeatureRequester implements FeatureRequester { protected $_baseUri; protected $_apiKey; protected $_options; protected $_features_key; + /** @var LoggerInterface */ + private $_logger; function __construct($baseUri, $apiKey, $options) { $this->_baseUri = $baseUri; @@ -25,6 +29,8 @@ function __construct($baseUri, $apiKey, $options) { $prefix = $options['redis_prefix']; } $this->_features_key = "$prefix:features"; + $this->_logger = $options['logger']; + } protected function get_connection() { @@ -40,7 +46,7 @@ protected function get_connection() { * Gets feature data from a likely cached store * * @param $key string feature key - * @return array|null The decoded JSON feature data, or null if missing + * @return FeatureFlag|null The decoded JSON feature data, or null if missing */ public function get($key) { $raw = $this->get_from_cache($key); @@ -52,8 +58,15 @@ public function get($key) { } } if ($raw) { - return json_decode($raw, True); + $flag = FeatureFlag::decode(json_decode($raw, True)); + if ($flag->isDeleted()) { + $this->_logger->warning("LDDFeatureRequester: Attempted to get deleted feature with key: " . $key); + return null; + } + return $flag; + } else { + $this->_logger->warning("LDDFeatureRequester: Attempted to get missing feature with key: " . $key); return null; } } diff --git a/src/LaunchDarkly/Operators.php b/src/LaunchDarkly/Operators.php index 1f2ca9266..9c415ebbb 100644 --- a/src/LaunchDarkly/Operators.php +++ b/src/LaunchDarkly/Operators.php @@ -14,17 +14,13 @@ class Operators { * @return bool */ public static function apply($op, $u, $c) { - error_log("apply with op: $op u: $u c: $c"); try { if ($u === null || $c === null) { - error_log("one or both are null"); return false; } switch ($op) { case "in": - error_log("in with u: $u and c: $c"); if ($u === $c) { - error_log("returning true from in op"); return true; } if (is_numeric($u) && is_numeric($c)) { @@ -43,7 +39,6 @@ public static function apply($op, $u, $c) { break; case "matches": if (is_string($u) && is_string($c)) { - error_log("u: $u c: $c"); //PHP can do subpatterns, but everything needs to be wrapped in an outer (): return preg_match("($c)", $u) === 1; } @@ -116,7 +111,6 @@ public static function parseTime($in) { $dateTime = new DateTime($in); return Util::dateTimeToUnixMillis($dateTime); } catch (Exception $e) { - error_log("LaunchDarkly: Could not parse timestamp: " . $in); return null; } } diff --git a/src/LaunchDarkly/Rule.php b/src/LaunchDarkly/Rule.php index 326229168..be9f1778b 100644 --- a/src/LaunchDarkly/Rule.php +++ b/src/LaunchDarkly/Rule.php @@ -33,11 +33,9 @@ public static function getDecoder() { public function matchesUser($user) { foreach ($this->_clauses as $clause) { if (!$clause->matchesUser($user)) { - error_log("false from rule.matchesuser with attr: " . $clause->getAttribute()); return false; } } - error_log("true from rule.matchesuser"); return true; } diff --git a/src/LaunchDarkly/VariationOrRollout.php b/src/LaunchDarkly/VariationOrRollout.php index 7a6511e6d..9e507df6f 100644 --- a/src/LaunchDarkly/VariationOrRollout.php +++ b/src/LaunchDarkly/VariationOrRollout.php @@ -46,7 +46,6 @@ public function getRollout() { */ public function variationIndexForUser($user, $_key, $_salt) { if ($this->_variation !== null) { - error_log("Returning: $this->_variation"); return $this->_variation; } else if ($this->_rollout !== null) { $bucketBy = $this->_rollout->getBucketBy() === null ? "key" : $this->_rollout->getBucketBy(); @@ -59,7 +58,7 @@ public function variationIndexForUser($user, $_key, $_salt) { } } } - error_log("both fallthrough and variation are null!!"); + //TODO: throw exception? return null; } From 35766f377ea5d6c8cefb6f316814a1cf02f208d3 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 16:04:11 -0700 Subject: [PATCH 038/150] Remove v1 code. Other cleanup --- src/LaunchDarkly/EvaluationException.php | 7 -- src/LaunchDarkly/FeatureRep.php | 90 ------------------------ src/LaunchDarkly/LDClient.php | 23 ------ src/LaunchDarkly/LDUser.php | 2 +- src/LaunchDarkly/Operators.php | 3 +- src/LaunchDarkly/Rule.php | 6 -- src/LaunchDarkly/TargetRule.php | 81 --------------------- src/LaunchDarkly/Util.php | 10 ++- src/LaunchDarkly/Variation.php | 55 --------------- tests/FeatureRepTest.php | 89 ----------------------- tests/LDClientTest.php | 15 ---- 11 files changed, 11 insertions(+), 370 deletions(-) delete mode 100644 src/LaunchDarkly/FeatureRep.php delete mode 100644 src/LaunchDarkly/TargetRule.php delete mode 100644 src/LaunchDarkly/Variation.php delete mode 100644 tests/FeatureRepTest.php diff --git a/src/LaunchDarkly/EvaluationException.php b/src/LaunchDarkly/EvaluationException.php index 5980b667a..294688752 100644 --- a/src/LaunchDarkly/EvaluationException.php +++ b/src/LaunchDarkly/EvaluationException.php @@ -1,11 +1,4 @@ _name = $name; - $this->_key = $key; - $this->_salt = $salt; - $this->_on = $on; - $this->_variations = $variations; - } - - /** - * @param $user LDUser - * @return mixed - */ - public function evaluate($user) { - if (!$this->_on || !$user) { - return null; - } - - $param = $this->_get_param($user); - if (is_null($param)) { - return null; - } - else { - foreach ($this->_variations as $variation) { - if ($variation->matchUser($user)) { - return $variation->getValue(); - } - } - - foreach ($this->_variations as $variation) { - if ($variation->matchTarget($user)) { - return $variation->getValue(); - } - } - - $sum = 0.0; - foreach ($this->_variations as $variation) { - $sum += $variation->getWeight() / 100.0; - - if ($param < $sum) { - return $variation->getValue(); - } - } - } - - return null; - } - - /** - * @param $user LDUser - * @return float|null - */ - private function _get_param($user) { - $id_hash = null; - $hash = null; - - if ($user->getKey()) { - $id_hash = $user->getKey(); - } - else { - return null; - } - - if ($user->getSecondary()) { - $id_hash .= "." . $user->getSecondary(); - } - - $hash = substr(sha1($this->_key . "." . $this->_salt . "." . $id_hash), 0, 15); - $longVal = base_convert($hash, 16, 10); - $result = $longVal / self::$LONG_SCALE; - - return $result; - } -} diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 486835306..8107f06cf 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -1,7 +1,6 @@ evaluate($user); - } } diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index 933fb6121..02c806e0c 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -33,7 +33,7 @@ class LDUser { * @param array|null $custom Other custom attributes that can be used to create custom rules */ public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array()) { - $this->_key = $key; + $this->_key = strval($key); $this->_secondary = $secondary; $this->_ip = $ip; $this->_country = $country; diff --git a/src/LaunchDarkly/Operators.php b/src/LaunchDarkly/Operators.php index 9c415ebbb..a491fc932 100644 --- a/src/LaunchDarkly/Operators.php +++ b/src/LaunchDarkly/Operators.php @@ -87,8 +87,7 @@ public static function apply($op, $u, $c) { } break; } - } catch (Exception $e) { - //TODO: log warning + } catch (Exception $ignored) { } return false; } diff --git a/src/LaunchDarkly/Rule.php b/src/LaunchDarkly/Rule.php index be9f1778b..c2ac20d43 100644 --- a/src/LaunchDarkly/Rule.php +++ b/src/LaunchDarkly/Rule.php @@ -1,10 +1,4 @@ _attribute = $attribute; - $this->_operator = $operator; - $this->_values = $values; - } - - public function isKey() { - return $this->_attribute == "key"; - } - - - /** - * @param $user LDUser - * @return bool - */ - public function matchTarget($user) { - $u_value = null; - - switch ($this->_attribute) { - case "key": - $u_value = $user->getKey(); - break; - case "ip": - $u_value = $user->getIP(); - break; - case "country": - $u_value = $user->getCountry(); - break; - case "email": - $u_value = $user->getEmail(); - break; - case "name": - $u_value = $user->getName(); - break; - case "avatar": - $u_value = $user->getAvatar(); - break; - case "firstName": - $u_value = $user->getFirstName(); - break; - case "lastName": - $u_value = $user->getLastName(); - break; - case "anonymous": - $u_value = $user->getAnonymous(); - break; - default: - $custom = $user->getCustom(); - if (is_null($custom)) { - return false; - } - if (!array_key_exists($this->_attribute, $custom)) { - return false; - } - $u_value = $custom[$this->_attribute]; - - if (is_array($u_value)) { - foreach ($u_value as $elt) { - if (in_array($elt, $this->_values)) { - return true; - } - } - return false; - } - break; - } - - return isset($u_value) && in_array($u_value, $this->_values); - } -} \ No newline at end of file diff --git a/src/LaunchDarkly/Util.php b/src/LaunchDarkly/Util.php index a1a38cd75..e1d84897a 100644 --- a/src/LaunchDarkly/Util.php +++ b/src/LaunchDarkly/Util.php @@ -2,7 +2,6 @@ namespace LaunchDarkly; - use DateTime; use DateTimeZone; @@ -26,6 +25,15 @@ public static function currentTimeUnixMillis() { } + /** + * @param $key string + * @param $user LDUser + * @param $value + * @param $default + * @param null $version int | null + * @param null $prereqOf string | null + * @return array + */ public static function newFeatureRequestEvent($key, $user, $value, $default, $version = null, $prereqOf = null) { $event = array(); $event['user'] = $user->toJSON(); diff --git a/src/LaunchDarkly/Variation.php b/src/LaunchDarkly/Variation.php deleted file mode 100644 index 40cdd97a8..000000000 --- a/src/LaunchDarkly/Variation.php +++ /dev/null @@ -1,55 +0,0 @@ -_value = $value; - $this->_weight = $weight; - $this->_targets = $targets; - $this->_userTarget = $userTarget; - } - - /** - * @param $user LDUser - * @return bool - */ - public function matchUser($user) { - if ($this->_userTarget != null) { - return $this->_userTarget->matchTarget($user); - } - return false; - } - - public function matchTarget($user) { - foreach($this->_targets as $target) { - if ($this->_userTarget != null && $target->isKey()) { - continue; - } - if ($target->matchTarget($user)) { - return true; - } - } - return false; - } - - public function getValue() { - return $this->_value; - } - - public function getWeight() { - return $this->_weight; - } -} \ No newline at end of file diff --git a/tests/FeatureRepTest.php b/tests/FeatureRepTest.php deleted file mode 100644 index 16b1f207b..000000000 --- a/tests/FeatureRepTest.php +++ /dev/null @@ -1,89 +0,0 @@ -_simpleFlag = new FeatureRep("Sample flag", "sample.flag", "feefifofum", true, array($trueVariation, $falseVariation)); - $this->_disabledFlag = new FeatureRep("Sample flag", "sample.flag", "feefifofum", false, array($trueVariation, $falseVariation)); - - $userTargetVariation = new Variation(false, 20, array(), $targetUserOn); - - $this->_userTargetFlag = new FeatureRep("Sample flag", "sample.flag", "feefifofum", true, array($trueVariation, $userTargetVariation)); - } - - protected function tearDown() { - parent::tearDown(); - $this->_simpleFlag = null; - } - - public function testFlagForTargetedUserOff() { - $user = new LDUser("targetOff@test.com"); - $b = $this->_simpleFlag->evaluate($user); - $this->assertEquals(false, $b); - } - - public function testFlagForTargetedUserOn() { - $user = new LDUser("targetOn@test.com"); - $b = $this->_simpleFlag->evaluate($user); - $this->assertEquals(true, $b); - } - - public function testFlagForTargetGroupOn() { - $builder = new LDUserBuilder("targetOther@test.com"); - $user = $builder->custom(array("groups" => array("google", "microsoft")))->build(); - $b = $this->_simpleFlag->evaluate($user); - $this->assertEquals(true, $b); - } - - public function testFlagForTargetGroupOff() { - $builder = new LDUserBuilder("targetOther@test.com"); - $user = $builder->custom(array("groups" => array("oracle")))->build(); - $b = $this->_simpleFlag->evaluate($user); - $this->assertEquals(false, $b); - } - - public function testDisabledFlagAlwaysOff() { - $user = new LDUser("targetOn@test.com"); - $b = $this->_disabledFlag->evaluate($user); - $this->assertEquals(null, $b); - } - - public function testUserRuleFlagForTargetUserOff() { - $builder = new LDUserBuilder("targetOff@test.com"); - $user = $builder->build(); - $b = $this->_userTargetFlag->evaluate($user); - $this->assertEquals(false, $b); - } - - public function testFlagForTargetEmailOff() { - $builder = new LDUserBuilder("targetOff@test.com"); - $user = $builder->email("targetEmailOn@test.com")->build(); - $b = $this->_simpleFlag->evaluate($user); - $this->assertEquals(true,$b); - } -} - diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 42f86ee06..50da3c704 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -53,21 +53,6 @@ public function testToggleEvent() { $this->assertEquals(1, sizeof($queue)); } - public function testToggleEventsOff() { - MockFeatureRequester::$val = null; - $client = new LDClient("someKey", array( - 'feature_requester_class' => '\\LaunchDarkly\Tests\\MockFeatureRequester', - 'events' => false - )); - - $builder = new LDUserBuilder(3); - $user = $builder->build(); - $client->toggle('foo', $user, 'argdef'); - $proc = getPrivateField($client, '_eventProcessor'); - $queue = getPrivateField($proc, '_queue'); - $this->assertEquals(0, sizeof($queue)); - } - public function testOnlyValidFeatureRequester() { $this->setExpectedException(InvalidArgumentException::class); new LDClient("BOGUS_API_KEY", ['feature_requester_class' => 'stdClass']); From c191a07abc0fd36aea703807ffce3d8b3b46b4e1 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 16:15:10 -0700 Subject: [PATCH 039/150] update version. --- VERSION | 2 +- tests/FeatureFlagTest.php | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/VERSION b/VERSION index afaf360d3..359a5b952 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0 \ No newline at end of file +2.0.0 \ No newline at end of file diff --git a/tests/FeatureFlagTest.php b/tests/FeatureFlagTest.php index 3d084f047..a81cd11e4 100644 --- a/tests/FeatureFlagTest.php +++ b/tests/FeatureFlagTest.php @@ -2,7 +2,6 @@ namespace LaunchDarkly\Tests; use LaunchDarkly\FeatureFlag; -use LaunchDarkly\LDUser; class FeatureFlagTest extends \PHPUnit_Framework_TestCase { @@ -137,20 +136,9 @@ class FeatureFlagTest extends \PHPUnit_Framework_TestCase { \"deleted\": false }"; - protected function setUp() { - parent::setUp(); - } - - protected function tearDown() { - parent::tearDown(); - } - public function testDecode() { FeatureFlag::decode(\GuzzleHttp\json_decode(FeatureFlagTest::$json1, true)); FeatureFlag::decode(\GuzzleHttp\json_decode(FeatureFlagTest::$json2, true)); - - } - } From efe65f942da81314a6a13160edce7738bea0f75f Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 1 Aug 2016 16:15:46 -0700 Subject: [PATCH 040/150] remove whitespace --- tests/OperatorsTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/OperatorsTest.php b/tests/OperatorsTest.php index 15e04e8da..bb25ed423 100644 --- a/tests/OperatorsTest.php +++ b/tests/OperatorsTest.php @@ -17,7 +17,6 @@ public function testIn() { $this->assertTrue(Operators::apply("in", true, true)); $this->assertFalse(Operators::apply("in", true, false)); $this->assertFalse(Operators::apply("in", false, true)); - } public function testStartsWith() { @@ -39,8 +38,6 @@ public function testMatches() { $this->assertTrue(Operators::apply("matches", "darn", "(\\W|^)(baloney|darn|drat|fooey|gosh\\sdarnit|heck)(\\W|$)")); } - - public function testParseTime() { $this->assertEquals(0, Operators::parseTime(0)); $this->assertEquals(100, Operators::parseTime(100)); From 674dc1b6dc68592a9ceff24d99aa31b42d324af2 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 2 Aug 2016 11:43:40 -0700 Subject: [PATCH 041/150] Address PR comments. Deprecate toggle function. Remove getFlag function --- README.md | 2 +- integration-tests/LDDFeatureRequesterTest.php | 12 +++++----- src/LaunchDarkly/Clause.php | 9 +++++-- src/LaunchDarkly/FeatureFlag.php | 2 ++ src/LaunchDarkly/LDClient.php | 24 ++++++++++++++----- src/LaunchDarkly/VariationOrRollout.php | 9 ++++--- tests/LDClientTest.php | 6 ++--- 7 files changed, 41 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 325158603..33703af20 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Your first feature flag 2. In your application code, use the feature's key to check whether the flag is on for each user: $user = new LaunchDarkly\LDUser("user@test.com"); - if ($client->toggle("your.flag.key", $user)) { + if ($client->variation("your.flag.key", $user)) { # application code to show the feature } else { # the code to run if the feature is off diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 5afeb7a88..602b87717 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -18,9 +18,9 @@ public function testGet() { $user = $builder->build(); $redis->del("launchdarkly:features"); - $this->assertEquals("jim", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("jim", $client->variation('foo', $user, 'jim')); $redis->hset("launchdarkly:features", 'foo', $this->gen_feature("foo", "bar")); - $this->assertEquals("bar", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("bar", $client->variation('foo', $user, 'jim')); } public function testGetApc() { @@ -34,16 +34,16 @@ public function testGetApc() { $user = $builder->build(); $redis->del("launchdarkly:features"); - $this->assertEquals("jim", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("jim", $client->variation('foo', $user, 'jim')); $redis->hset("launchdarkly:features", 'foo', $this->gen_feature("foo", "bar")); - $this->assertEquals("bar", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("bar", $client->variation('foo', $user, 'jim')); # cached value so not updated $redis->hset("launchdarkly:features", 'foo', $this->gen_feature("foo", "baz")); - $this->assertEquals("bar", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("bar", $client->variation('foo', $user, 'jim')); apc_delete("launchdarkly:features.foo"); - $this->assertEquals("baz", $client->toggle('foo', $user, 'jim')); + $this->assertEquals("baz", $client->variation('foo', $user, 'jim')); } private function gen_feature($key, $val) { diff --git a/src/LaunchDarkly/Clause.php b/src/LaunchDarkly/Clause.php index 9f4534830..adf01615e 100644 --- a/src/LaunchDarkly/Clause.php +++ b/src/LaunchDarkly/Clause.php @@ -3,9 +3,13 @@ namespace LaunchDarkly; class Clause { + /** @var string */ private $_attribute = null; + /** @var string */ private $_op = null; + /** @var array */ private $_values = array(); + /** @var bool */ private $_negate = false; private function __construct($attribute, $op, array $values, $negate) { @@ -42,15 +46,16 @@ public function matchesUser($user) { } } + /** - * @return null + * @return string */ public function getAttribute() { return $this->_attribute; } /** - * @return null + * @return string */ public function getOp() { return $this->_op; diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 26684e713..ba70f6106 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -20,7 +20,9 @@ class FeatureFlag { protected $_rules = array(); /** @var VariationOrRollout */ protected $_fallthrough = null; + /** @var int | null */ protected $_offVariation = null; + /** @var array */ protected $_variations = array(); /** @var bool */ protected $_deleted = false; diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 8107f06cf..5e589499a 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -36,9 +36,13 @@ class LDClient { * @param string $apiKey The API key for your account * @param array $options Client configuration settings * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` + * - events_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 * - cache: An optional Kevinrob\GuzzleCache\Strategy\CacheStorageInterface. Defaults to an in-memory cache. + * - send_events: An optional bool that can disable the sending of events to LaunchDarkly. Defaults to false. + * - logger: An optional Psr\Log\LoggerInterface. Defaults to a Monolog\Logger sending all messages to the php error_log. + * - offline: An optional boolean which will disable all network calls and always return the default value. Defaults to false. */ public function __construct($apiKey, $options = array()) { $this->_apiKey = $apiKey; @@ -90,10 +94,6 @@ public function __construct($apiKey, $options = array()) { $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $apiKey, $options); } - public function getFlag($key, $user, $default = false) { - return $this->toggle($key, $user, $default); - } - /** * Calculates the value of a feature flag for a given user. * @@ -101,9 +101,9 @@ public function getFlag($key, $user, $default = false) { * @param LDUser $user The end user requesting the flag * @param boolean $default The default value of the flag * - * @return mixed Whether or not the flag should be enabled, or `default` + * @return mixed The result of the Feature Flag evaluation, or $default if any errors occurred. */ - public function toggle($key, $user, $default = false) { + public function variation($key, $user, $default = false) { $default = $this->_get_default($key, $default); if ($this->_offline) { @@ -149,6 +149,18 @@ public function toggle($key, $user, $default = false) { return $default; } + + /** @deprecated Use variation() instead. + * @param $key + * @param $user + * @param bool $default + * @return mixed + */ + public function toggle($key, $user, $default = false) { + $this->_logger->warning("Deprecated function: toggle() called. Use variation() instead."); + return $this->variation($key, $user, $default); + } + /** * Returns whether the LaunchDarkly client is in offline mode. * diff --git a/src/LaunchDarkly/VariationOrRollout.php b/src/LaunchDarkly/VariationOrRollout.php index 9e507df6f..e1ff63b60 100644 --- a/src/LaunchDarkly/VariationOrRollout.php +++ b/src/LaunchDarkly/VariationOrRollout.php @@ -6,9 +6,9 @@ class VariationOrRollout { private static $LONG_SCALE = 0xFFFFFFFFFFFFFFF; - /** @var int */ + /** @var int | null */ private $_variation = null; - /** @var Rollout */ + /** @var Rollout | null */ private $_rollout = null; protected function __construct($variation, $rollout) { @@ -25,14 +25,14 @@ public static function getDecoder() { } /** - * @return int + * @return int | null */ public function getVariation() { return $this->_variation; } /** - * @return Rollout + * @return Rollout | null */ public function getRollout() { return $this->_rollout; @@ -58,7 +58,6 @@ public function variationIndexForUser($user, $_key, $_salt) { } } } - //TODO: throw exception? return null; } diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 50da3c704..c524bcd20 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -22,7 +22,7 @@ public function testToggleDefault() { $builder = new LDUserBuilder(3); $user = $builder->build(); - $this->assertEquals('argdef', $client->toggle('foo', $user, 'argdef')); + $this->assertEquals('argdef', $client->variation('foo', $user, 'argdef')); } public function testToggleFromArray() { @@ -35,7 +35,7 @@ public function testToggleFromArray() { $builder = new LDUserBuilder(3); $user = $builder->build(); - $this->assertEquals('fromarray', $client->toggle('foo', $user, 'argdef')); + $this->assertEquals('fromarray', $client->variation('foo', $user, 'argdef')); } public function testToggleEvent() { @@ -47,7 +47,7 @@ public function testToggleEvent() { $builder = new LDUserBuilder(3); $user = $builder->build(); - $client->toggle('foo', $user, 'argdef'); + $client->variation('foo', $user, 'argdef'); $proc = getPrivateField($client, '_eventProcessor'); $queue = getPrivateField($proc, '_queue'); $this->assertEquals(1, sizeof($queue)); From f6d923180f2e3f54ddfaaaf9a1cb2995a3d98f88 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 08:45:57 -0700 Subject: [PATCH 042/150] api_key->sdk_key --- README.md | 6 +++--- src/LaunchDarkly/EventProcessor.php | 6 +++--- src/LaunchDarkly/GuzzleFeatureRequester.php | 4 ++-- tests/LDClientTest.php | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 33703af20..063794d81 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ Quick setup require 'vendor/autoload.php'; -2. Create a new LDClient with your API key: +2. Create a new LDClient with your SDK key: - $client = new LaunchDarkly\LDClient("your_api_key"); + $client = new LaunchDarkly\LDClient("your_sdk_key"); Your first feature flag ----------------------- @@ -63,7 +63,7 @@ Using Redis 2. Create the LDClient with the Redis feature requester as an option: - $client = new LaunchDarkly\LDClient("your_api_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester']); + $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester']); Learn more ----------- diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index 88dc0956c..4e2c2ea12 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -6,7 +6,7 @@ */ class EventProcessor { - private $_apiKey; + private $_sdkKey; private $_queue; private $_capacity; private $_timeout; @@ -15,7 +15,7 @@ class EventProcessor { private $_ssl; public function __construct($apiKey, $options = array()) { - $this->_apiKey = $apiKey; + $this->_sdkKey = $apiKey; if (!isset($options['events_uri'])) { $this->_host = 'events.launchdarkly.com'; $this->_port = 443; @@ -80,7 +80,7 @@ private function createArgs($payload) { $scheme = $this->_ssl ? "https://" : "http://"; $args = " -X POST"; $args.= " -H 'Content-Type: application/json'"; - $args.= " -H " . escapeshellarg("Authorization: api_key " . $this->_apiKey); + $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; $args.= " -H 'Accept: application/json'"; $args.= " -d " . escapeshellarg($payload); diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 958547a8d..62f25f0cf 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -19,7 +19,7 @@ class GuzzleFeatureRequester implements FeatureRequester /** @var LoggerInterface */ private $_logger; - function __construct($baseUri, $apiKey, $options) + function __construct($baseUri, $sdkKey, $options) { $this->_baseUri = $baseUri; $stack = HandlerStack::create(); @@ -27,7 +27,7 @@ function __construct($baseUri, $apiKey, $options) $this->_defaults = array( 'headers' => array( - 'Authorization' => "api_key {$apiKey}", + 'Authorization' => $sdkKey, 'Content-Type' => 'application/json', 'User-Agent' => 'PHPClient/' . LDClient::VERSION ), diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index c524bcd20..249bb6afb 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -10,7 +10,7 @@ class LDClientTest extends \PHPUnit_Framework_TestCase { public function testDefaultCtor() { - new LDClient("BOGUS_API_KEY"); + new LDClient("BOGUS_SDK_KEY"); } public function testToggleDefault() { @@ -55,7 +55,7 @@ public function testToggleEvent() { public function testOnlyValidFeatureRequester() { $this->setExpectedException(InvalidArgumentException::class); - new LDClient("BOGUS_API_KEY", ['feature_requester_class' => 'stdClass']); + new LDClient("BOGUS_SDK_KEY", ['feature_requester_class' => 'stdClass']); } } From 2d5aaae7d17c3e19130346c9e7dbfb55572490b0 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 08:59:48 -0700 Subject: [PATCH 043/150] add secure mode hash function --- src/LaunchDarkly/LDClient.php | 27 +++++++++++++++++++-------- tests/LDClientTest.php | 7 +++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 5e589499a..55f8c80e0 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -13,7 +13,7 @@ class LDClient { const VERSION = '2.0.0'; /** @var string */ - protected $_apiKey; + protected $_sdkKey; /** @var string */ protected $_baseUri; /** @var EventProcessor */ @@ -33,10 +33,10 @@ class LDClient { /** * Creates a new client instance that connects to LaunchDarkly. * - * @param string $apiKey The API key for your account + * @param string $sdkKey The SDK key for your account * @param array $options Client configuration settings - * - base_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` - * - events_uri: Base URI of the LaunchDarkly API. Defaults to `DEFAULT_BASE_URI` + * - base_uri: Base URI of the LaunchDarkly API. Defaults to `https://app.launchdarkly.com`. + * - events_uri: Base URI for sending events to LaunchDarkly. Defaults to 'https://events.launchdarkly.com' * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 * - cache: An optional Kevinrob\GuzzleCache\Strategy\CacheStorageInterface. Defaults to an in-memory cache. @@ -44,8 +44,8 @@ class LDClient { * - logger: An optional Psr\Log\LoggerInterface. Defaults to a Monolog\Logger sending all messages to the php error_log. * - offline: An optional boolean which will disable all network calls and always return the default value. Defaults to false. */ - public function __construct($apiKey, $options = array()) { - $this->_apiKey = $apiKey; + public function __construct($sdkKey, $options = array()) { + $this->_sdkKey = $sdkKey; if (!isset($options['base_uri'])) { $this->_baseUri = self::DEFAULT_BASE_URI; } else { @@ -80,7 +80,7 @@ public function __construct($apiKey, $options = array()) { } $this->_logger = $options['logger']; - $this->_eventProcessor = new EventProcessor($apiKey, $options); + $this->_eventProcessor = new EventProcessor($sdkKey, $options); if (isset($options['feature_requester_class'])) { $featureRequesterClass = $options['feature_requester_class']; @@ -91,7 +91,7 @@ public function __construct($apiKey, $options = array()) { if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { throw new \InvalidArgumentException; } - $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $apiKey, $options); + $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $sdkKey, $options); } /** @@ -214,6 +214,17 @@ public function identify($user) { $this->_eventProcessor->enqueue($event); } + /** Generates an HMAC sha256 hash for use in Secure mode: https://github.com/launchdarkly/js-client#secure-mode + * @param $user LDUser + * @return string + */ + public function secureModeHash($user) { + if (is_null($user) || strlen($user->getKey()) === 0) { + return ""; + } + return hash_hmac("sha256", $user->getKey(), $this->_sdkKey, false); + } + /** * @param $key string * @param $user LDUser diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 249bb6afb..81d280b34 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -4,6 +4,7 @@ use InvalidArgumentException; use LaunchDarkly\FeatureRequester; use LaunchDarkly\LDClient; +use LaunchDarkly\LDUser; use LaunchDarkly\LDUserBuilder; @@ -57,6 +58,12 @@ public function testOnlyValidFeatureRequester() { $this->setExpectedException(InvalidArgumentException::class); new LDClient("BOGUS_SDK_KEY", ['feature_requester_class' => 'stdClass']); } + + public function testSecureModeHash() { + $client = new LDClient("secret", ['offline' => true]); + $user = new LDUser("Message"); + $this->assertEquals("aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597", $client->secureModeHash($user)); + } } From b1ea59651023530b1806878b19bb98a1ba6887b2 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 09:54:12 -0700 Subject: [PATCH 044/150] Move all flag eval logic into FeatureFlag class. --- src/LaunchDarkly/FeatureFlag.php | 13 +++++++++++-- src/LaunchDarkly/LDClient.php | 28 +++++++++++++--------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index ba70f6106..98556b0e9 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -77,8 +77,17 @@ public function isOn() { */ public function evaluate($user, $featureRequester) { $prereqEvents = array(); - $value = $this->_evaluate($user, $featureRequester, $prereqEvents); - return new EvalResult($value, $prereqEvents); + if (is_null($user) || strlen($user->getKey()) === 0) { + return new EvalResult(null, $prereqEvents); + } + if ($this->isOn()) { + $result = $this->_evaluate($user, $featureRequester, $prereqEvents); + if ($result != null) { + return new EvalResult($result, $prereqEvents); + } + } + $offVariation = $this->getOffVariationValue(); + return new EvalResult($offVariation, $prereqEvents); } /** diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 55f8c80e0..0c03a3a48 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -113,7 +113,7 @@ public function variation($key, $user, $default = false) { try { if (is_null($user) || strlen($user->getKey()) === 0) { $this->_sendFlagRequestEvent($key, $user, $default, $default); - $this->_logger->warn("Toggle called with null user or null/empty user key! Returning default value"); + $this->_logger->warn("Variation called with null user or null/empty user key! Returning default value"); return $default; } $flag = $this->_featureRequester->get($key); @@ -121,22 +121,16 @@ public function variation($key, $user, $default = false) { if (is_null($flag)) { $this->_sendFlagRequestEvent($key, $user, $default, $default); return $default; - } else if ($flag->isOn()) { - $result = $flag->evaluate($user, $this->_featureRequester); - if (!$this->isOffline() && $this->_send_events) { - foreach ($result->getPrerequisiteEvents() as $e) { - $this->_eventProcessor->enqueue($e); - } - } - if ($result->getValue() != null) { - $this->_sendFlagRequestEvent($key, $user, $result->getValue(), $default, $flag->getVersion()); - return $result->getValue(); + } + $evalResult = $flag->evaluate($user, $this->_featureRequester); + if (!$this->isOffline() && $this->_send_events) { + foreach ($evalResult->getPrerequisiteEvents() as $e) { + $this->_eventProcessor->enqueue($e); } } - $offVariation = $flag->getOffVariationValue(); - if ($offVariation != null) { - $this->_sendFlagRequestEvent($key, $user, $offVariation, $default, $flag->getVersion()); - return $offVariation; + if ($evalResult->getValue() != null) { + $this->_sendFlagRequestEvent($key, $user, $evalResult->getValue(), $default, $flag->getVersion()); + return $evalResult->getValue(); } } catch (\Exception $e) { $this->_logger->error("Caught $e"); @@ -214,6 +208,10 @@ public function identify($user) { $this->_eventProcessor->enqueue($event); } + public function allFlags($user) { + + } + /** Generates an HMAC sha256 hash for use in Secure mode: https://github.com/launchdarkly/js-client#secure-mode * @param $user LDUser * @return string From a569bd255e3e1458aa6471e68eb70a19a0a520fc Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 10:33:25 -0700 Subject: [PATCH 045/150] allFlags --- src/LaunchDarkly/FeatureFlag.php | 34 ++++++++++------- src/LaunchDarkly/FeatureRequester.php | 7 ++++ src/LaunchDarkly/GuzzleFeatureRequester.php | 21 ++++++++++- src/LaunchDarkly/LDClient.php | 42 +++++++++++++++++++++ 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 98556b0e9..55e06d774 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -20,9 +20,9 @@ class FeatureFlag { protected $_rules = array(); /** @var VariationOrRollout */ protected $_fallthrough = null; - /** @var int | null */ + /** @var int | null */ protected $_offVariation = null; - /** @var array */ + /** @var array */ protected $_variations = array(); /** @var bool */ protected $_deleted = false; @@ -51,19 +51,25 @@ protected function __construct($key, $this->_deleted = $deleted; } + public static function getDecoder() { + return function ($v) { + return new FeatureFlag( + $v['key'], + $v['version'], + $v['on'], + array_map(Prerequisite::getDecoder(), $v['prerequisites']), + $v['salt'], + array_map(Target::getDecoder(), $v['targets']), + array_map(Rule::getDecoder(), $v['rules']), + call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), + $v['offVariation'], + $v['variations'], + $v['deleted']); + }; + } + public static function decode($v) { - return new FeatureFlag( - $v['key'], - $v['version'], - $v['on'], - array_map(Prerequisite::getDecoder(), $v['prerequisites']), - $v['salt'], - array_map(Target::getDecoder(), $v['targets']), - array_map(Rule::getDecoder(), $v['rules']), - call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), - $v['offVariation'], - $v['variations'], - $v['deleted']); + return call_user_func(FeatureFlag::getDecoder(), $v); } public function isOn() { diff --git a/src/LaunchDarkly/FeatureRequester.php b/src/LaunchDarkly/FeatureRequester.php index 25a7c9186..618a7136b 100644 --- a/src/LaunchDarkly/FeatureRequester.php +++ b/src/LaunchDarkly/FeatureRequester.php @@ -10,4 +10,11 @@ interface FeatureRequester { * @return FeatureFlag|null The decoded FeatureFlag, or null if missing */ public function get($key); + + /** + * Gets all features from a likely cached store + * + * @return array()|null The decoded FeatureFlags, or null if missing + */ + public function getAll(); } \ No newline at end of file diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 62f25f0cf..23d053ecb 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -10,6 +10,7 @@ class GuzzleFeatureRequester implements FeatureRequester { + const SDK_LATEST_FLAGS = "/sdk/latest-flags"; /** @var Client */ private $_client; /** @var string */ @@ -48,7 +49,7 @@ function __construct($baseUri, $sdkKey, $options) public function get($key) { try { - $uri = $this->_baseUri . "/sdk/latest-flags/" . $key; + $uri = $this->_baseUri . self::SDK_LATEST_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); return FeatureFlag::decode(json_decode($body, true)); @@ -58,4 +59,22 @@ public function get($key) return null; } } + + /** + * Gets all features from a likely cached store + * + * @return array()|null The decoded FeatureFlags, or null if missing + */ + public function getAll() { + try { + $uri = $this->_baseUri . self::SDK_LATEST_FLAGS; + $response = $this->_client->get($uri, $this->_defaults); + $body = $response->getBody(); + return array_map(FeatureFlag::getDecoder(), json_decode($body, true)); + } catch (BadResponseException $e) { + $code = $e->getResponse()->getStatusCode(); + $this->_logger->error("GuzzleFeatureRetriever::getAll received an unexpected HTTP status code $code"); + return null; + } + } } \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 0c03a3a48..7c9155c8a 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -208,8 +208,50 @@ public function identify($user) { $this->_eventProcessor->enqueue($event); } + /** + * Returns a map from feature flag keys to {@code JsonElement} feature flag values for a given user. + * If the result of a flag's evaluation would have returned the default variation, it will have a null entry + * in the map. If the client is offline, has not been initialized, or a null user or user with null/empty user key a {@code null} map will be returned. + * This method will not send analytics events back to LaunchDarkly. + *

+ * The most common use case for this method is to bootstrap a set of client-side feature flags from a back-end service. + * + * @param user the end user requesting the feature flags + * @return a map from feature flag keys to {@code JsonElement} for the specified user + */ + + + + /** Returns an array mapping Feature Flag keys to their evaluated results for a given user. + * + * If the result of a flag's evaluation would have returned the default variation, it will have a null entry. + * If the client is offline, has not been initialized, or a null user or user with null/empty user key, null will be returned. + * This method will not send analytics events back to LaunchDarkly. + *

+ * The most common use case for this method is to bootstrap a set of client-side feature flags from a back-end service. + * + * @param $user LDUser the end user requesting the feature flags + * @return array()|null Mapping of feature flag keys to their evaluated results for $user + */ public function allFlags($user) { + if (is_null($user) || strlen($user->getKey()) === 0) { + $this->_logger->warn("allFlags called with null user or null/empty user key! Returning null"); + return null; + } + $flags = $this->_featureRequester->getAll(); + if ($flags === null) { + return null; + } + + /** + * @param $flag FeatureFlag + * @return array() + */ + $eval = function($flag) use($user) { + return array($flag->getKey() => $flag->evaluate($user, $this->_featureRequester)); + }; + return array_map($eval, $flags); } /** Generates an HMAC sha256 hash for use in Secure mode: https://github.com/launchdarkly/js-client#secure-mode From 98477dee3b34483f71f7368b225b0c96bb2eac19 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 13:32:00 -0700 Subject: [PATCH 046/150] Add allFlags(). --- src/LaunchDarkly/FeatureRequester.php | 2 +- src/LaunchDarkly/LDClient.php | 4 ++-- src/LaunchDarkly/LDDFeatureRequester.php | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/LaunchDarkly/FeatureRequester.php b/src/LaunchDarkly/FeatureRequester.php index 618a7136b..2ce2757b1 100644 --- a/src/LaunchDarkly/FeatureRequester.php +++ b/src/LaunchDarkly/FeatureRequester.php @@ -12,7 +12,7 @@ interface FeatureRequester { public function get($key); /** - * Gets all features from a likely cached store + * Gets all features. * * @return array()|null The decoded FeatureFlags, or null if missing */ diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 7c9155c8a..243e352ae 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -245,10 +245,10 @@ public function allFlags($user) { /** * @param $flag FeatureFlag - * @return array() + * @return mixed|null */ $eval = function($flag) use($user) { - return array($flag->getKey() => $flag->evaluate($user, $this->_featureRequester)); + return $flag->evaluate($user, $this->_featureRequester)->getValue(); }; return array_map($eval, $flags); diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index 06fecb7d5..f163ee90f 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -86,4 +86,28 @@ protected function get_from_cache($key) { * @param $val array The feature data */ protected function store_in_cache($key, $val) {} + + /** + * Gets all features + * + * @return array()|null The decoded FeatureFlags, or null if missing + */ + public function getAll() { + $redis = $this->get_connection(); + $raw = $redis->hgetall($this->_features_key); + if ($raw) { + $allFlags = array_map(FeatureFlag::getDecoder(), json_decode($raw, true)); + /** + * @param $flag FeatureFlag + * @return bool + */ + $isNotDeleted = function ($flag) { + return !$flag->isDeleted(); + }; + return array_filter($allFlags, $isNotDeleted); + } else { + $this->_logger->warning("LDDFeatureRequester: Attempted to get all features, instead got nothing."); + return null; + } + } } \ No newline at end of file From 1d1b3c6ec89cd2d8adab82dba81fb27a7cb55611 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 13:37:51 -0700 Subject: [PATCH 047/150] remove comments --- src/LaunchDarkly/LDClient.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 243e352ae..7c8261ab9 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -208,20 +208,6 @@ public function identify($user) { $this->_eventProcessor->enqueue($event); } - /** - * Returns a map from feature flag keys to {@code JsonElement} feature flag values for a given user. - * If the result of a flag's evaluation would have returned the default variation, it will have a null entry - * in the map. If the client is offline, has not been initialized, or a null user or user with null/empty user key a {@code null} map will be returned. - * This method will not send analytics events back to LaunchDarkly. - *

- * The most common use case for this method is to bootstrap a set of client-side feature flags from a back-end service. - * - * @param user the end user requesting the feature flags - * @return a map from feature flag keys to {@code JsonElement} for the specified user - */ - - - /** Returns an array mapping Feature Flag keys to their evaluated results for a given user. * * If the result of a flag's evaluation would have returned the default variation, it will have a null entry. From 024b16230307e9026b485c767ef24599a5ba4e89 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 4 Aug 2016 13:41:19 -0700 Subject: [PATCH 048/150] add stub method in test class --- tests/LDClientTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 81d280b34..8487e0ca5 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -84,4 +84,8 @@ function __construct($baseurl, $key, $options) { public function get($key) { return self::$val; } + + public function getAll() { + return null; + } } From 329b574b82f6e9d4dc577097067f08bf4b73bde8 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 16:16:30 -0700 Subject: [PATCH 049/150] Allow blank user key in evaluation. --- src/LaunchDarkly/LDClient.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 7c8261ab9..fb1005b31 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -111,11 +111,14 @@ public function variation($key, $user, $default = false) { } try { - if (is_null($user) || strlen($user->getKey()) === 0) { + if (is_null($user) || is_null($user->getKey()) ) { $this->_sendFlagRequestEvent($key, $user, $default, $default); - $this->_logger->warn("Variation called with null user or null/empty user key! Returning default value"); + $this->_logger->warn("Variation called with null user or null user key! Returning default value"); return $default; } + if (strlen($user->getKey()) === 0) { + $this->_logger->warn("User key is blank. Flag evaluation will proceed, but the user will not be stored in LaunchDarkly."); + } $flag = $this->_featureRequester->get($key); if (is_null($flag)) { From f3fe42a27f7b35adf67d2efe12c462810812d8f6 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 18:06:39 -0700 Subject: [PATCH 050/150] Change user key null check --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index fb1005b31..b64885f8b 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -111,7 +111,7 @@ public function variation($key, $user, $default = false) { } try { - if (is_null($user) || is_null($user->getKey()) ) { + if (is_null($user) || $user->getKey() === null ) { $this->_sendFlagRequestEvent($key, $user, $default, $default); $this->_logger->warn("Variation called with null user or null user key! Returning default value"); return $default; From 98e55f10dd03b7354a39119954e62573e0d4ec5e Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 19:59:17 -0700 Subject: [PATCH 051/150] add better check for blank user key --- src/LaunchDarkly/LDClient.php | 6 +++--- src/LaunchDarkly/LDUser.php | 11 ++++++++++- tests/LDUserTest.php | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index b64885f8b..5b351e7a3 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -116,7 +116,7 @@ public function variation($key, $user, $default = false) { $this->_logger->warn("Variation called with null user or null user key! Returning default value"); return $default; } - if (strlen($user->getKey()) === 0) { + if ($user->isKeyBlank()) { $this->_logger->warn("User key is blank. Flag evaluation will proceed, but the user will not be stored in LaunchDarkly."); } $flag = $this->_featureRequester->get($key); @@ -177,7 +177,7 @@ public function track($eventName, $user, $data) { if ($this->isOffline()) { return; } - if (is_null($user) || strlen($user->getKey()) === 0) { + if (is_null($user) || $user->isKeyBlank()) { $this->_logger->warn("Track called with null user or null/empty user key!"); } @@ -199,7 +199,7 @@ public function identify($user) { if ($this->isOffline()) { return; } - if (is_null($user) || strlen($user->getKey()) === 0) { + if (is_null($user) || $user->isKeyBlank()) { $this->_logger->warn("Track called with null user or null/empty user key!"); } diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index 02c806e0c..76aaac5fe 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -33,7 +33,9 @@ class LDUser { * @param array|null $custom Other custom attributes that can be used to create custom rules */ public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array()) { - $this->_key = strval($key); + if ($key !== null) { + $this->_key = strval($key); + } $this->_secondary = $secondary; $this->_ip = $ip; $this->_country = $country; @@ -92,6 +94,9 @@ public function getIP() { return $this->_ip; } + /** + * @return null|string + */ public function getKey() { return $this->_key; } @@ -124,6 +129,10 @@ public function getAnonymous() { return $this->_anonymous; } + public function isKeyBlank() { + return isset($this->_key) && empty($this->_key); + } + public function toJSON() { $json = array("key" => $this->_key); diff --git a/tests/LDUserTest.php b/tests/LDUserTest.php index 106b2a441..df4a47a46 100644 --- a/tests/LDUserTest.php +++ b/tests/LDUserTest.php @@ -100,5 +100,20 @@ public function testLDUserAnonymous() { $this->assertEquals(true, $json['anonymous']); } + + public function testLDUserBlankKey() { + $builder = new LDUserBuilder(""); + $user = $builder->build(); + $this->assertTrue($user->isKeyBlank()); + + $builder = new LDUserBuilder("key"); + $user = $builder->build(); + $this->assertFalse($user->isKeyBlank()); + + $builder = new LDUserBuilder(null); + $user = $builder->build(); + $this->assertFalse($user->isKeyBlank()); + + } } From 87f37d44ed102c187efb0a145ff702152b9ec7a7 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 20:06:03 -0700 Subject: [PATCH 052/150] add better check for blank user key --- src/LaunchDarkly/LDClient.php | 2 +- tests/LDUserTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 5b351e7a3..06725e332 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -111,7 +111,7 @@ public function variation($key, $user, $default = false) { } try { - if (is_null($user) || $user->getKey() === null ) { + if (is_null($user) || is_null($user->getKey())) { $this->_sendFlagRequestEvent($key, $user, $default, $default); $this->_logger->warn("Variation called with null user or null user key! Returning default value"); return $default; diff --git a/tests/LDUserTest.php b/tests/LDUserTest.php index df4a47a46..0dfbb0d01 100644 --- a/tests/LDUserTest.php +++ b/tests/LDUserTest.php @@ -105,6 +105,7 @@ public function testLDUserBlankKey() { $builder = new LDUserBuilder(""); $user = $builder->build(); $this->assertTrue($user->isKeyBlank()); + $this->assertFalse(is_null($user->getKey())); $builder = new LDUserBuilder("key"); $user = $builder->build(); @@ -113,7 +114,6 @@ public function testLDUserBlankKey() { $builder = new LDUserBuilder(null); $user = $builder->build(); $this->assertFalse($user->isKeyBlank()); - } } From cc81f8e9b10a8f2eef4e799ddfb845d6f3fcfaa2 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 20:08:09 -0700 Subject: [PATCH 053/150] add better check for blank user key --- src/LaunchDarkly/FeatureFlag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 55e06d774..b20ced40b 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -83,7 +83,7 @@ public function isOn() { */ public function evaluate($user, $featureRequester) { $prereqEvents = array(); - if (is_null($user) || strlen($user->getKey()) === 0) { + if (is_null($user) || is_null($user->getKey())) { return new EvalResult(null, $prereqEvents); } if ($this->isOn()) { From 392cefcdb5d26a1e52a6946ca4b0a52cae6ecf9e Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Mon, 8 Aug 2016 20:10:06 -0700 Subject: [PATCH 054/150] add better check for blank user key --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 06725e332..5d1dd8305 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -223,7 +223,7 @@ public function identify($user) { * @return array()|null Mapping of feature flag keys to their evaluated results for $user */ public function allFlags($user) { - if (is_null($user) || strlen($user->getKey()) === 0) { + if (is_null($user) || is_null($user->getKey())) { $this->_logger->warn("allFlags called with null user or null/empty user key! Returning null"); return null; } From 88f89d5f29ff2ea3993734fa12479473f906b700 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Tue, 9 Aug 2016 17:01:53 -0700 Subject: [PATCH 055/150] Change log for v2. Update license file --- CHANGELOG.md | 18 ++++++++++++++++++ CONTRIBUTING.md | 4 ++++ LICENSE => LICENSE.txt | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md rename LICENSE => LICENSE.txt (94%) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..2e548727c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Change log + +All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). + +## [2.0.0] - 2016-08-08 +### Added +- Support for multivariate feature flags. In addition to booleans, feature flags can now return numbers, strings, dictionaries, or arrays via the `variation` method. +- New `allFlags` method returns all flag values for a specified user. +- New `secureModeHash` function computes a hash suitable for the new LaunchDarkly JavaScript client's secure mode feature. + +### Changed +- The `FeatureRep` data model has been replaced with `FeatureFlag`. `FeatureFlag` is not generic. + +### Deprecated +- The `toggle` call has been deprecated in favor of `variation`. + +### Removed +- The `getFlag` function has been removed. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..3ec616bd2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing to the LaunchDarkly SDK for PHP +================================================ + +We encourage pull-requests and other contributions from the community. We've also published an [SDK contributor's guide](http://docs.launchdarkly.com/v1.0/docs/sdk-contributors-guide) that provides a detailed explanation of how our SDKs work. \ No newline at end of file diff --git a/LICENSE b/LICENSE.txt similarity index 94% rename from LICENSE rename to LICENSE.txt index b5c790da8..e82de54ed 100644 --- a/LICENSE +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2015 Catamorphic, Co. +Copyright 2016 Catamorphic, Co. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 94727af365db020a08d29c1565a0dd0386ea1e80 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 10 Aug 2016 10:07:31 -0700 Subject: [PATCH 056/150] stop getting latest flags --- src/LaunchDarkly/GuzzleFeatureRequester.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 23d053ecb..68c475302 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -10,7 +10,7 @@ class GuzzleFeatureRequester implements FeatureRequester { - const SDK_LATEST_FLAGS = "/sdk/latest-flags"; + const SDK_FLAGS = "/sdk/flags"; /** @var Client */ private $_client; /** @var string */ @@ -49,7 +49,7 @@ function __construct($baseUri, $sdkKey, $options) public function get($key) { try { - $uri = $this->_baseUri . self::SDK_LATEST_FLAGS . "/" . $key; + $uri = $this->_baseUri . self::SDK_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); return FeatureFlag::decode(json_decode($body, true)); @@ -67,7 +67,7 @@ public function get($key) */ public function getAll() { try { - $uri = $this->_baseUri . self::SDK_LATEST_FLAGS; + $uri = $this->_baseUri . self::SDK_FLAGS; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); return array_map(FeatureFlag::getDecoder(), json_decode($body, true)); From 0a254cfeb4247ac4be0093eebeedb5e83cdf682a Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 10 Aug 2016 10:17:20 -0700 Subject: [PATCH 057/150] stop getting latest flags --- src/LaunchDarkly/GuzzleFeatureRequester.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 68c475302..4c7f25dd0 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -52,6 +52,7 @@ public function get($key) $uri = $this->_baseUri . self::SDK_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); + $this->_logger->info("Got status code: " . $response->getStatusCode() . " with body: " . $response->getBody()); return FeatureFlag::decode(json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); From 5a5fb3ecd4b0357f8de5d73f0b6a7f69fe99a78a Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 10 Aug 2016 10:22:36 -0700 Subject: [PATCH 058/150] Revert log statement --- src/LaunchDarkly/GuzzleFeatureRequester.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 4c7f25dd0..68c475302 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -52,7 +52,6 @@ public function get($key) $uri = $this->_baseUri . self::SDK_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); - $this->_logger->info("Got status code: " . $response->getStatusCode() . " with body: " . $response->getBody()); return FeatureFlag::decode(json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); From e6f45c0f5efab3cbf1c12063e0e6a9fced77eab6 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 12 Aug 2016 09:40:16 -0700 Subject: [PATCH 059/150] when requesting a feature and we get 404: log warning instead of error --- src/LaunchDarkly/GuzzleFeatureRequester.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index 68c475302..c1cc7b419 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -55,7 +55,11 @@ public function get($key) return FeatureFlag::decode(json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); - $this->_logger->error("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); + if ($code == 404) { + $this->_logger->warning("GuzzleFeatureRetriever::get returned 404. Feature flag does not exist for key: " . $key); + } else { + $this->_logger->error("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); + } return null; } } From 0ba48fdafa97eb4fe0d48e92bf765e17a6d40337 Mon Sep 17 00:00:00 2001 From: Justin Baker Date: Thu, 1 Sep 2016 10:03:43 -0700 Subject: [PATCH 060/150] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 063794d81..5a0c2a96f 100644 --- a/README.md +++ b/README.md @@ -68,12 +68,12 @@ Using Redis Learn more ----------- -Check out our [documentation](http://docs.launchdarkly.com) for in-depth instructions on configuring and using LaunchDarkly. You can also head straight to the [complete reference guide for this SDK](http://docs.launchdarkly.com/v1.0/docs/php-sdk-reference). +Check out our [documentation](http://docs.launchdarkly.com) for in-depth instructions on configuring and using LaunchDarkly. You can also head straight to the [complete reference guide for this SDK](http://docs.launchdarkly.com/docs/php-sdk-reference). Contributing ------------ -We encourage pull-requests and other contributions from the community. We've also published an [SDK contributor's guide](http://docs.launchdarkly.com/v1.0/docs/sdk-contributors-guide) that provides a detailed explanation of how our SDKs work. +We encourage pull-requests and other contributions from the community. We've also published an [SDK contributor's guide](http://docs.launchdarkly.com/docs/sdk-contributors-guide) that provides a detailed explanation of how our SDKs work. About LaunchDarkly ----------- From 1a2ceca232c06db054829cadd57cf3ecf99ea6a6 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 8 Nov 2016 08:41:17 -0800 Subject: [PATCH 061/150] Update readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5a0c2a96f..e4fd167a9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ LaunchDarkly SDK for PHP [![Circle CI](https://circleci.com/gh/launchdarkly/php-client.svg?style=svg)](https://circleci.com/gh/launchdarkly/php-client) +Requirements +------------ +1. PHP 5.5 or higher. +1. We strongly suggest you include [monolog](https://packagist.org/packages/monolog/monolog) version 1.21.0 or higher for logging. + Quick setup ----------- From 421933e5a1d619a179d0dd61044d281c736ae7b5 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 8 Nov 2016 09:34:36 -0800 Subject: [PATCH 062/150] Update readme --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e4fd167a9..5e34e14f7 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,21 @@ LaunchDarkly SDK for PHP Requirements ------------ 1. PHP 5.5 or higher. -1. We strongly suggest you include [monolog](https://packagist.org/packages/monolog/monolog) version 1.21.0 or higher for logging. +1. A [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)-compatible logger. We suggest [monolog](https://packagist.org/packages/monolog/monolog) version 1.21.0 or higher. Quick setup ----------- -0. Install the PHP SDK with [Composer](https://getcomposer.org/) +1. Install the PHP SDK and monolog for logging with [Composer](https://getcomposer.org/) php composer.phar require launchdarkly/launchdarkly-php - php composer.phar require "guzzlehttp/guzzle:6.2.1" - php composer.phar require "kevinrob/guzzle-cache-middleware": "1.4.1" + php composer.phar require monolog/monolog:1.21.0 1. After installing, require Composer's autoloader: require 'vendor/autoload.php'; -2. Create a new LDClient with your SDK key: +1. Create a new LDClient with your SDK key: $client = new LaunchDarkly\LDClient("your_sdk_key"); From f6fd57d4299ea7a016b7398a9e6e03b53c1878b0 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 8 Nov 2016 12:41:26 -0800 Subject: [PATCH 063/150] Add monolog dep as required --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index afa5ae0f9..aed5ad7bf 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ } ], "require": { + "monolog/monolog": "1.21.0", "php": ">=5.5", "psr/log": "1.0.0" }, From a6f1f2cde733f326e97e0b8983da5cf0f6d5edd7 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 9 Nov 2016 10:38:47 -0800 Subject: [PATCH 064/150] Bump version to 2.0.1 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e548727c..2880d8dd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.1] - 2016-11-09 +### Added +- Monolog is now a required dependency + ## [2.0.0] - 2016-08-08 ### Added - Support for multivariate feature flags. In addition to booleans, feature flags can now return numbers, strings, dictionaries, or arrays via the `variation` method. diff --git a/VERSION b/VERSION index 359a5b952..10bf840ed 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0 \ No newline at end of file +2.0.1 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 5d1dd8305..507b65ab0 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.0'; + const VERSION = '2.0.1'; /** @var string */ protected $_sdkKey; From 004cc7074178d0bff9baec3e9a63e02e6acd1e93 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 9 Nov 2016 11:42:26 -0800 Subject: [PATCH 065/150] Update Readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 5e34e14f7..deda4e725 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ LaunchDarkly SDK for PHP Requirements ------------ 1. PHP 5.5 or higher. -1. A [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)-compatible logger. We suggest [monolog](https://packagist.org/packages/monolog/monolog) version 1.21.0 or higher. Quick setup ----------- @@ -16,7 +15,6 @@ Quick setup 1. Install the PHP SDK and monolog for logging with [Composer](https://getcomposer.org/) php composer.phar require launchdarkly/launchdarkly-php - php composer.phar require monolog/monolog:1.21.0 1. After installing, require Composer's autoloader: From fa2097d0827998492e923d7a49edcf17e74e6fae Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 28 Nov 2016 19:44:54 +0100 Subject: [PATCH 066/150] Update README.md file Fix compose installation for kevinrob/guzzle-cache-middleware in README.md file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index deda4e725..870458be2 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Using Guzzle To use Guzzle it must be required as a dependency: php composer.phar require "guzzlehttp/guzzle:6.2.1" - php composer.phar require "kevinrob/guzzle-cache-middleware": "1.4.1" + php composer.phar require "kevinrob/guzzle-cache-middleware:1.4.1" It will then be used as the default way of fetching flags. From bb5b79386cc518f4029f9e1456a585012db66e56 Mon Sep 17 00:00:00 2001 From: Justin Baker Date: Wed, 30 Nov 2016 12:36:45 -0800 Subject: [PATCH 067/150] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 870458be2..e9be6ace4 100644 --- a/README.md +++ b/README.md @@ -90,16 +90,16 @@ About LaunchDarkly * [JavaScript] (http://docs.launchdarkly.com/docs/js-sdk-reference "LaunchDarkly JavaScript SDK") * [PHP] (http://docs.launchdarkly.com/docs/php-sdk-reference "LaunchDarkly PHP SDK") * [Python] (http://docs.launchdarkly.com/docs/python-sdk-reference "LaunchDarkly Python SDK") + * [Python Twisted] (http://docs.launchdarkly.com/docs/python-twisted-sdk-reference "LaunchDarkly Python Twisted SDK") * [Go] (http://docs.launchdarkly.com/docs/go-sdk-reference "LaunchDarkly Go SDK") * [Node.JS] (http://docs.launchdarkly.com/docs/node-sdk-reference "LaunchDarkly Node SDK") * [.NET] (http://docs.launchdarkly.com/docs/dotnet-sdk-reference "LaunchDarkly .Net SDK") * [Ruby] (http://docs.launchdarkly.com/docs/ruby-sdk-reference "LaunchDarkly Ruby SDK") - * [Python Twisted] (http://docs.launchdarkly.com/docs/python-twisted "LaunchDarkly Python Twisted SDK") + * [iOS] (http://docs.launchdarkly.com/docs/ios-sdk-reference "LaunchDarkly iOS SDK") + * [Android] (http://docs.launchdarkly.com/docs/android-sdk-reference "LaunchDarkly Android SDK") * Explore LaunchDarkly - * [www.launchdarkly.com] (http://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information + * [launchdarkly.com] (http://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information * [docs.launchdarkly.com] (http://docs.launchdarkly.com/ "LaunchDarkly Documentation") for our documentation and SDKs * [apidocs.launchdarkly.com] (http://apidocs.launchdarkly.com/ "LaunchDarkly API Documentation") for our API documentation * [blog.launchdarkly.com] (http://blog.launchdarkly.com/ "LaunchDarkly Blog Documentation") for the latest product updates - - - + * [Feature Flagging Guide] (https://github.com/launchdarkly/featureflags/ "Feature Flagging Guide") for best practices and strategies From 9579ba41236248dc9ec880e3bcda65220bf19564 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 16 Dec 2016 12:23:03 -0700 Subject: [PATCH 068/150] add phpunit config with a whitelist so that coverage reports can be generated in CI. --- circle.yml | 2 +- phpunit.xml.dist | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 phpunit.xml.dist diff --git a/circle.yml b/circle.yml index 7347245d3..74c6f1d8a 100644 --- a/circle.yml +++ b/circle.yml @@ -4,4 +4,4 @@ machine: test: override: - - vendor/bin/phpunit tests + - vendor/bin/phpunit tests --coverage-text diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..05bb415b5 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,12 @@ + + + + tests + + + + + src + + + \ No newline at end of file From 93b43883d937fbfc37b69d0fbab6e44de97bdc86 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 23 Dec 2016 15:28:07 -0800 Subject: [PATCH 069/150] rename phpunit file --- phpunit.xml.dist => phpunit.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename phpunit.xml.dist => phpunit.xml (100%) diff --git a/phpunit.xml.dist b/phpunit.xml similarity index 100% rename from phpunit.xml.dist rename to phpunit.xml From 09efa548a7d5486bcbf4407973575d0fe96cbb02 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 23 Dec 2016 15:30:40 -0800 Subject: [PATCH 070/150] change php version --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 74c6f1d8a..550389cab 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: php: - version: 5.5.21 + version: 5.6.17 test: override: From 5d724582f9f05b7ba062df431f19ada46dc0b1e5 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 23 Dec 2016 15:36:54 -0800 Subject: [PATCH 071/150] update Readme --- README.md | 5 + composer.lock | 575 ++++++++++++++++++++++++++++---------------------- 2 files changed, 328 insertions(+), 252 deletions(-) diff --git a/README.md b/README.md index e9be6ace4..58fd312b9 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,11 @@ Using Redis $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester']); +Testing +------- + +We run integration tests for all our SDKs using a centralized test harness. This approach gives us the ability to test for consistency across SDKs, as well as test networking behavior in a long-running application. These tests cover each method in the SDK, and verify that event sending, flag evaluation, stream reconnection, and other aspects of the SDK all behave correctly. + Learn more ----------- diff --git a/composer.lock b/composer.lock index c07149b50..c79ee8819 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,87 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fc1de559a4df16ad00c93dd5c20fcc28", - "content-hash": "a8cf37cf9851938001d2b8babe963b5e", + "hash": "cd49540bfcf76434cbb74b1dda2b5d13", + "content-hash": "6a93d29d931b3889657d4aa00eed323f", "packages": [ + { + "name": "monolog/monolog", + "version": "1.21.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "~5.3" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2016-07-29 03:23:52" + }, { "name": "psr/log", "version": "1.0.0", @@ -194,35 +272,35 @@ }, { "name": "doctrine/annotations", - "version": "v1.2.7", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" + "reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/30e07cf03edc3cd3ef579d0dd4dd8c58250799a5", + "reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": ">=5.3.2" + "php": "^5.6 || ^7.0" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "4.*" + "phpunit/phpunit": "^5.6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "1.4.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Annotations\\": "lib/" + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", @@ -258,7 +336,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2016-10-24 11:45:47" }, { "name": "doctrine/instantiator", @@ -370,18 +448,21 @@ }, { "name": "erusev/parsedown", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" + "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", - "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/20ff8bbb57205368b4b42d094642a3e52dac85fb", + "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", "autoload": { "psr-0": { @@ -405,7 +486,7 @@ "markdown", "parser" ], - "time": "2015-10-04 16:44:32" + "time": "2016-11-02 15:56:58" }, { "name": "guzzlehttp/guzzle", @@ -471,28 +552,28 @@ }, { "name": "guzzlehttp/promises", - "version": "1.2.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "shasum": "" }, "require": { "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -518,7 +599,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-12-20 10:07:11" }, { "name": "guzzlehttp/psr7", @@ -697,23 +778,24 @@ }, { "name": "jms/metadata", - "version": "1.5.1", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/metadata.git", - "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/22b72455559a25777cfd28c4ffda81ff7639f353", - "reference": "22b72455559a25777cfd28c4ffda81ff7639f353", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/6a06970a10e0a532fb52d3959547123b84a3b3ab", + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "doctrine/cache": "~1.0" + "doctrine/cache": "~1.0", + "symfony/cache": "~3.1" }, "type": "library", "extra": { @@ -728,14 +810,12 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache" + "Apache-2.0" ], "authors": [ { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" } ], "description": "Class/method/property metadata management in PHP", @@ -745,7 +825,7 @@ "xml", "yaml" ], - "time": "2014-07-12 07:13:19" + "time": "2016-12-05 10:18:33" }, { "name": "jms/parser-lib", @@ -784,40 +864,42 @@ }, { "name": "jms/serializer", - "version": "1.1.0", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "fe13a1f993ea3456e195b7820692f2eb2b6bbb48" + "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/fe13a1f993ea3456e195b7820692f2eb2b6bbb48", - "reference": "fe13a1f993ea3456e195b7820692f2eb2b6bbb48", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f39d8b4660d5cef43b0c3265ce642173d9b2c58b", + "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b", "shasum": "" }, "require": { - "doctrine/annotations": "1.*", - "doctrine/instantiator": "~1.0.3", + "doctrine/annotations": "^1.0", + "doctrine/instantiator": "^1.0.3", "jms/metadata": "~1.1", "jms/parser-lib": "1.*", - "php": ">=5.4.0", - "phpcollection/phpcollection": "~0.1" + "php": ">=5.5.0", + "phpcollection/phpcollection": "~0.1", + "phpoption/phpoption": "^1.1" }, "conflict": { "twig/twig": "<1.12" }, "require-dev": { "doctrine/orm": "~2.1", - "doctrine/phpcr-odm": "~1.0.1", - "jackalope/jackalope-doctrine-dbal": "1.0.*", - "phpunit/phpunit": "~4.0", + "doctrine/phpcr-odm": "^1.3|^2.0", + "ext-pdo_sqlite": "*", + "jackalope/jackalope-doctrine-dbal": "^1.1.5", + "phpunit/phpunit": "^4.8|^5.0", "propel/propel1": "~1.7", - "symfony/filesystem": "2.*", + "symfony/filesystem": "^2.1", "symfony/form": "~2.1", - "symfony/translation": "~2.0", - "symfony/validator": "~2.0", - "symfony/yaml": "2.*", + "symfony/translation": "^2.1", + "symfony/validator": "^2.2", + "symfony/yaml": "^2.1", "twig/twig": "~1.12|~2.0" }, "suggest": { @@ -826,7 +908,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -853,7 +935,7 @@ "serialization", "xml" ], - "time": "2015-10-27 09:24:41" + "time": "2016-11-13 10:20:11" }, { "name": "justinrainbow/json-schema", @@ -1041,84 +1123,6 @@ "homepage": "http://github.com/kherge/Version", "time": "2012-08-16 17:13:03" }, - { - "name": "monolog/monolog", - "version": "1.21.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" - }, - "provide": { - "psr/log-implementation": "1.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^2.4.9", - "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "jakub-onderka/php-parallel-lint": "0.9", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpunit/phpunit": "~4.5", - "phpunit/phpunit-mock-objects": "2.3.0", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "~5.3" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "time": "2016-07-29 03:23:52" - }, { "name": "nikic/php-parser", "version": "v1.4.1", @@ -1166,16 +1170,16 @@ }, { "name": "phpcollection/phpcollection", - "version": "0.4.0", + "version": "0.5.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-collection.git", - "reference": "b8bf55a0a929ca43b01232b36719f176f86c7e83" + "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/b8bf55a0a929ca43b01232b36719f176f86c7e83", - "reference": "b8bf55a0a929ca43b01232b36719f176f86c7e83", + "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", + "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", "shasum": "" }, "require": { @@ -1184,7 +1188,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "0.4-dev" } }, "autoload": { @@ -1198,10 +1202,8 @@ ], "authors": [ { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" } ], "description": "General-Purpose Collection Library for PHP", @@ -1212,7 +1214,7 @@ "sequence", "set" ], - "time": "2014-03-11 13:46:42" + "time": "2015-05-17 12:39:23" }, { "name": "phpdocumentor/fileset", @@ -1542,16 +1544,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.1", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { @@ -1559,10 +1561,11 @@ "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { @@ -1600,7 +1603,7 @@ "spy", "stub" ], - "time": "2016-06-07 08:13:47" + "time": "2016-11-21 14:58:47" }, { "name": "phpunit/php-code-coverage", @@ -1666,16 +1669,16 @@ }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { @@ -1709,7 +1712,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", @@ -1798,16 +1801,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -1843,7 +1846,7 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", @@ -2071,16 +2074,16 @@ }, { "name": "psr/http-message", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { @@ -2108,6 +2111,7 @@ } ], "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ "http", "http-message", @@ -2116,26 +2120,26 @@ "request", "response" ], - "time": "2015-05-04 20:22:00" + "time": "2016-08-06 14:39:51" }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -2180,7 +2184,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -2236,23 +2240,23 @@ }, { "name": "sebastian/environment", - "version": "1.3.7", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { @@ -2282,7 +2286,7 @@ "environment", "hhvm" ], - "time": "2016-05-17 03:18:57" + "time": "2016-08-18 05:49:44" }, { "name": "sebastian/exporter", @@ -2492,16 +2496,16 @@ }, { "name": "seld/jsonlint", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "66834d3e3566bb5798db7294619388786ae99394" + "reference": "19495c181d6d53a0a13414154e52817e3b504189" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394", - "reference": "66834d3e3566bb5798db7294619388786ae99394", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/19495c181d6d53a0a13414154e52817e3b504189", + "reference": "19495c181d6d53a0a13414154e52817e3b504189", "shasum": "" }, "require": { @@ -2534,26 +2538,29 @@ "parser", "validator" ], - "time": "2015-11-21 02:21:41" + "time": "2016-11-14 17:59:58" }, { "name": "symfony/config", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4" + "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4275ef5b59f18959df0eee3991e9ca0cc208ffd4", - "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4", + "url": "https://api.github.com/repos/symfony/config/zipball/b522856007b258f46d5ee35d3b7b235c11e76e86", + "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86", "shasum": "" }, "require": { "php": ">=5.3.9", "symfony/filesystem": "~2.3|~3.0.0" }, + "require-dev": { + "symfony/yaml": "~2.7|~3.0.0" + }, "suggest": { "symfony/yaml": "To use the yaml reference dumper" }, @@ -2587,24 +2594,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-07-26 08:02:44" + "time": "2016-12-10 08:21:45" }, { "name": "symfony/console", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "36e62335caca8a6e909c5c5bac4a8128149911c9" + "reference": "d5643cd095e5e37d31e004bb2606b5dd7e96602f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/36e62335caca8a6e909c5c5bac4a8128149911c9", - "reference": "36e62335caca8a6e909c5c5bac4a8128149911c9", + "url": "https://api.github.com/repos/symfony/console/zipball/d5643cd095e5e37d31e004bb2606b5dd7e96602f", + "reference": "d5643cd095e5e37d31e004bb2606b5dd7e96602f", "shasum": "" }, "require": { "php": ">=5.3.9", + "symfony/debug": "~2.7,>=2.7.2|~3.0.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -2647,20 +2655,77 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:20:35" + "time": "2016-12-06 11:59:35" + }, + { + "name": "symfony/debug", + "version": "v3.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/697c527acd9ea1b2d3efac34d9806bf255278b0a", + "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2016-07-30 07:22:48" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8" + "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8", - "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", + "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", "shasum": "" }, "require": { @@ -2707,7 +2772,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-07-28 16:56:28" + "time": "2016-10-13 01:43:15" }, { "name": "symfony/filesystem", @@ -2760,16 +2825,16 @@ }, { "name": "symfony/finder", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10" + "reference": "c0f10576335743b881ac1ed39d18c0fa66048775" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/60804d88691e4a73bbbb3035eb1d9f075c5c2c10", - "reference": "60804d88691e4a73bbbb3035eb1d9f075c5c2c10", + "url": "https://api.github.com/repos/symfony/finder/zipball/c0f10576335743b881ac1ed39d18c0fa66048775", + "reference": "c0f10576335743b881ac1ed39d18c0fa66048775", "shasum": "" }, "require": { @@ -2805,20 +2870,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-07-26 08:02:44" + "time": "2016-12-13 09:38:12" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "dff51f72b0706335131b00a7f49606168c582594" + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", - "reference": "dff51f72b0706335131b00a7f49606168c582594", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", "shasum": "" }, "require": { @@ -2830,7 +2895,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -2864,20 +2929,20 @@ "portable", "shim" ], - "time": "2016-05-18 14:26:46" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/process", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c" + "reference": "1a1bd056395540d0bc549d39818316513565d278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c", - "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c", + "url": "https://api.github.com/repos/symfony/process/zipball/1a1bd056395540d0bc549d39818316513565d278", + "reference": "1a1bd056395540d0bc549d39818316513565d278", "shasum": "" }, "require": { @@ -2913,11 +2978,11 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-07-28 11:13:19" + "time": "2016-11-24 00:43:03" }, { "name": "symfony/stopwatch", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -3030,16 +3095,16 @@ }, { "name": "symfony/validator", - "version": "v2.8.9", + "version": "v2.8.15", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "244ff2a7f0283d1c854abbf17181dbb02c0af95f" + "reference": "1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/244ff2a7f0283d1c854abbf17181dbb02c0af95f", - "reference": "244ff2a7f0283d1c854abbf17181dbb02c0af95f", + "url": "https://api.github.com/repos/symfony/validator/zipball/1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce", + "reference": "1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce", "shasum": "" }, "require": { @@ -3099,29 +3164,35 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-07-26 08:02:44" + "time": "2016-12-08 15:59:39" }, { "name": "symfony/yaml", - "version": "v3.1.3", + "version": "v3.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "1819adf2066880c7967df7180f4f662b6f0567ac" + "reference": "a7095af4b97a0955f85c8989106c249fa649011f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac", - "reference": "1819adf2066880c7967df7180f4f662b6f0567ac", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", + "reference": "a7095af4b97a0955f85c8989106c249fa649011f", "shasum": "" }, "require": { "php": ">=5.5.9" }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3148,20 +3219,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-07-17 14:02:08" + "time": "2016-12-10 10:07:06" }, { "name": "twig/twig", - "version": "v1.24.1", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512" + "reference": "c6ff71094fde15d12398eaba029434b013dc5e59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512", - "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/c6ff71094fde15d12398eaba029434b013dc5e59", + "reference": "c6ff71094fde15d12398eaba029434b013dc5e59", "shasum": "" }, "require": { @@ -3169,12 +3240,12 @@ }, "require-dev": { "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~3.2@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.24-dev" + "dev-master": "1.30-dev" } }, "autoload": { @@ -3209,20 +3280,20 @@ "keywords": [ "templating" ], - "time": "2016-05-30 09:11:59" + "time": "2016-12-23 11:06:22" }, { "name": "zendframework/zend-cache", - "version": "2.7.1", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/zendframework/zend-cache.git", - "reference": "2c68def8f96ce842d2f2a9a69e2f3508c2f5312d" + "reference": "c98331b96d3b9d9b24cf32d02660602edb34d039" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/2c68def8f96ce842d2f2a9a69e2f3508c2f5312d", - "reference": "2c68def8f96ce842d2f2a9a69e2f3508c2f5312d", + "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/c98331b96d3b9d9b24cf32d02660602edb34d039", + "reference": "c98331b96d3b9d9b24cf32d02660602edb34d039", "shasum": "" }, "require": { @@ -3232,9 +3303,9 @@ "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpbench/phpbench": "^0.10.0", - "phpunit/phpunit": "^4.5", + "phpunit/phpunit": "^4.8", + "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-serializer": "^2.6", "zendframework/zend-session": "^2.6.2" }, @@ -3278,7 +3349,7 @@ "cache", "zf2" ], - "time": "2016-05-12 21:47:55" + "time": "2016-12-16 11:35:47" }, { "name": "zendframework/zend-config", @@ -3338,26 +3409,26 @@ }, { "name": "zendframework/zend-eventmanager", - "version": "3.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e" + "reference": "c3bce7b7d47c54040b9ae51bc55491c72513b75d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/5c80bdee0e952be112dcec0968bad770082c3a6e", - "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e", + "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/c3bce7b7d47c54040b9ae51bc55491c72513b75d", + "reference": "c3bce7b7d47c54040b9ae51bc55491c72513b75d", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0" + "php": "^5.6 || ^7.0" }, "require-dev": { "athletic/athletic": "^0.1", "container-interop/container-interop": "^1.1.0", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "^2.0", + "phpunit/phpunit": "^5.6", + "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-stdlib": "^2.7.3 || ^3.0" }, "suggest": { @@ -3367,8 +3438,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev", - "dev-develop": "3.1-dev" + "dev-master": "3.1-dev", + "dev-develop": "3.2-dev" } }, "autoload": { @@ -3388,7 +3459,7 @@ "events", "zf2" ], - "time": "2016-02-18 20:53:00" + "time": "2016-12-19 21:47:12" }, { "name": "zendframework/zend-filter", @@ -3689,16 +3760,16 @@ }, { "name": "zendframework/zend-servicemanager", - "version": "2.7.6", + "version": "2.7.8", "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", - "reference": "a6db4d13b9141fccce5dcb553df0295d6ad7d477" + "reference": "2ae3b6e4978ec2e9ff52352e661946714ed989f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/a6db4d13b9141fccce5dcb553df0295d6ad7d477", - "reference": "a6db4d13b9141fccce5dcb553df0295d6ad7d477", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/2ae3b6e4978ec2e9ff52352e661946714ed989f9", + "reference": "2ae3b6e4978ec2e9ff52352e661946714ed989f9", "shasum": "" }, "require": { @@ -3737,7 +3808,7 @@ "servicemanager", "zf2" ], - "time": "2016-04-27 19:07:40" + "time": "2016-12-19 19:14:29" }, { "name": "zendframework/zend-stdlib", From 9f75ad29a3d72018617477fb83a938de4a9ddc97 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Sun, 1 Jan 2017 08:35:55 -0700 Subject: [PATCH 072/150] install php55-php71 with docker. run tests after installing minimum and maximum dependency versions allowed by composer config. --- circle.yml | 17 +++++++++++++++++ composer.json | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 550389cab..513e43b0a 100644 --- a/circle.yml +++ b/circle.yml @@ -1,7 +1,24 @@ machine: php: version: 5.6.17 + services: + - docker +dependencies: + pre: + - docker pull php + - docker pull nyanpass/php5.5 test: override: - vendor/bin/phpunit tests --coverage-text + - composer update && vendor/bin/phpunit tests + - composer update --prefer-lowest && vendor/bin/phpunit tests + + - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" + + - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" + + - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" \ No newline at end of file diff --git a/composer.json b/composer.json index aed5ad7bf..357083cc5 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require-dev": { "guzzlehttp/guzzle": "6.2.1", "kevinrob/guzzle-cache-middleware": "1.4.1", - "phpunit/phpunit": "4.8.26", + "phpunit/phpunit": ">=4.8.26 <5.4", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "zendframework/zend-serializer": "2.7.*" From a0deaf3c10f653184690f6419994d0c3c973a8b4 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Wed, 4 Jan 2017 11:48:40 -0800 Subject: [PATCH 073/150] Update version to 2.0.2 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2880d8dd0..f399f6fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.2] - 2017-01-04 +### Changed +- Better handling of null vs false when evaluating. + ## [2.0.1] - 2016-11-09 ### Added - Monolog is now a required dependency diff --git a/VERSION b/VERSION index 10bf840ed..f93ea0ca3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.1 \ No newline at end of file +2.0.2 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 507b65ab0..fd5e1adb1 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.1'; + const VERSION = '2.0.2'; /** @var string */ protected $_sdkKey; From 0a8e34b9a6018bf9c7f7faf9b36c15f175916e92 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Thu, 5 Jan 2017 08:46:10 -0700 Subject: [PATCH 074/150] simplifiy docker build commands. --- circle.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/circle.yml b/circle.yml index 513e43b0a..78b6c1dad 100644 --- a/circle.yml +++ b/circle.yml @@ -14,11 +14,11 @@ test: - composer update && vendor/bin/phpunit tests - composer update --prefer-lowest && vendor/bin/phpunit tests - - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "php -v && php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php --install-dir=/usr/local/bin && cd /php-client && composer.phar update --prefer-lowest && vendor/bin/phpunit" \ No newline at end of file + - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" + - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" \ No newline at end of file From 5d661c28941e3da3f1a3b09d2645ec3fe3f188f1 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 5 Jan 2017 10:32:40 -0800 Subject: [PATCH 075/150] Update to 2.0.3 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/FeatureFlag.php | 2 +- src/LaunchDarkly/LDClient.php | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f399f6fd0..e04e9ca86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.3] - 2017-01-05 +### Changed +- Fixed botched 2.0.2 release: Better handling of null vs false when evaluating. + ## [2.0.2] - 2017-01-04 ### Changed - Better handling of null vs false when evaluating. diff --git a/VERSION b/VERSION index f93ea0ca3..6acdb4428 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.2 \ No newline at end of file +2.0.3 \ No newline at end of file diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index b20ced40b..ff122534d 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -88,7 +88,7 @@ public function evaluate($user, $featureRequester) { } if ($this->isOn()) { $result = $this->_evaluate($user, $featureRequester, $prereqEvents); - if ($result != null) { + if ($result !== null) { return new EvalResult($result, $prereqEvents); } } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index fd5e1adb1..bc4e96ce7 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.2'; + const VERSION = '2.0.3'; /** @var string */ protected $_sdkKey; @@ -131,7 +131,7 @@ public function variation($key, $user, $default = false) { $this->_eventProcessor->enqueue($e); } } - if ($evalResult->getValue() != null) { + if ($evalResult->getValue() !== null) { $this->_sendFlagRequestEvent($key, $user, $evalResult->getValue(), $default, $flag->getVersion()); return $evalResult->getValue(); } From 8a88c3ec6305f1cd1a24e0b39d2ce1acf6b96924 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 6 Jan 2017 08:21:01 -0700 Subject: [PATCH 076/150] add monolog to integration-test composer config. --- integration-tests/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/composer.json b/integration-tests/composer.json index e0cd69628..83541023a 100644 --- a/integration-tests/composer.json +++ b/integration-tests/composer.json @@ -11,6 +11,7 @@ ], "require": { "php": ">=5.3", + "monolog/monolog": "^1.22", "predis/predis": "1.0.*" }, "require-dev": { From 92a2699abe49698e83751c912ad3fa8af041835b Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 20:10:07 -0700 Subject: [PATCH 077/150] refactor integration-test feature-generator to match v2 feature structure, e.g. \LaunchDarkly\Tests\FeatureFlagTest::$json1 and \LaunchDarkly\Tests\FeatureFlagTest::$json2. --- integration-tests/LDDFeatureRequesterTest.php | 61 +++++++++++++++---- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 602b87717..64ac40eaf 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -47,19 +47,54 @@ public function testGetApc() { } private function gen_feature($key, $val) { - $data = << 'Feature ' . $key, + 'key' => $key, + 'kind' => 'flag', + 'salt' => 'Zm9v', + 'on' => true, + 'variations' => [ + $val, + false, + ], + 'commitDate' => '2015-09-08T21:24:16.712Z', + 'creationDate' => '2015-09-08T21:06:16.527Z', + 'version' => 4, + 'prerequisites' => [], + 'targets' => [ + [ + 'values' => [ + $val, + ], + 'variation' => 0, + ], + [ + 'values' => [ + false, + ], + 'variation' => 1, + ], + ], + 'rules' => [], + 'fallthrough' => [ + 'rollout' => [ + 'variations' => [ + [ + 'variation' => 0, + 'weight' => 95000, + ], + [ + 'variation' => 1, + 'weight' => 5000, + ], + ], + ], + ], + 'offVariation' => null, + 'deleted' => false, + ]; + + return \json_encode($data); } } From 66656c714171d19fc029915198ddc5810782f793 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 20:46:17 -0700 Subject: [PATCH 078/150] split vagrant user bootstrap from root bootstrap. provisioner correctly installs php54 with APC, and switches php version. --- integration-tests/Vagrantfile | 1 + integration-tests/bootstrap.sh | 22 --------------------- integration-tests/bootstrap.user.sh | 30 +++++++++++++++++++++++++++++ src/LaunchDarkly/LDClient.php | 2 +- 4 files changed, 32 insertions(+), 23 deletions(-) create mode 100755 integration-tests/bootstrap.user.sh diff --git a/integration-tests/Vagrantfile b/integration-tests/Vagrantfile index ff73f459b..5529ac9d3 100644 --- a/integration-tests/Vagrantfile +++ b/integration-tests/Vagrantfile @@ -17,6 +17,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box_url = "https://vagrantcloud.com/ubuntu/boxes/trusty64" config.vm.provision :shell, path: "bootstrap.sh" + config.vm.provision :shell, path: "bootstrap.user.sh", privileged: false # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index 3e75fe316..786182dfa 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -35,25 +35,3 @@ cat < /home/vagrant/.vimrc set tabstop=4 EOF chown vagrant.vagrant /home/vagrant/.vimrc - -su - vagrant -cd ~vagrant -pwd -curl -s -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew -chmod +x phpbrew -sudo mv phpbrew /usr/bin/phpbrew -phpbrew init -phpbrew known --update -phpbrew update -phpbrew install 5.4.34 +default - -echo "source $HOME/.phpbrew/bashrc" >> /home/vagrant/.bashrc -source $HOME/.bashrc -phpbrew switch php-5.4.34 -phpbrew ext install apc -echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini - - -cd /home/vagrant/project/integration-tests -curl -sS https://getcomposer.org/installer | php -php composer.phar install diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh new file mode 100755 index 000000000..60145cb70 --- /dev/null +++ b/integration-tests/bootstrap.user.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +echo +echo "install phpbrew and php54" +cd ~ +curl -s -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew +chmod +x phpbrew +sudo mv phpbrew /usr/bin/phpbrew +phpbrew init +phpbrew known --update +phpbrew update +phpbrew install 5.4.34 +default + +echo +echo "switch php54" +echo "source $HOME/.phpbrew/bashrc" >> /home/vagrant/.bashrc +source $HOME/.phpbrew/bashrc +phpbrew switch 5.4.34 + +echo +echo "install php54-apc" +phpbrew ext install apc +echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini +echo "date.timezone =UTC" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini + +echo +echo "update project dependencies" +cd /home/vagrant/project/integration-tests +curl -sS https://getcomposer.org/installer | php +php composer.phar update diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index bc4e96ce7..d2f3551f0 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -88,7 +88,7 @@ public function __construct($sdkKey, $options = array()) { $featureRequesterClass = '\\LaunchDarkly\\GuzzleFeatureRequester'; } - if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { + if (!is_a($featureRequesterClass, '\LaunchDarkly\FeatureRequester', true)) { throw new \InvalidArgumentException; } $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $sdkKey, $options); From e0efa74864ffaa35a6beb367428949bfeb0cbc2c Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 18 Jan 2017 21:04:36 -0700 Subject: [PATCH 079/150] add integration tests to CircleCI build. starts redis server on CircleCI and installs apcu extension on php56. add APCU-feature-requester which is the >=php55 version of the <=php54 APC-feature-requester. --- circle.yml | 7 ++++ integration-tests/LDDFeatureRequesterTest.php | 36 +++++++++++++++++++ integration-tests/bootstrap.sh | 4 +++ integration-tests/bootstrap.user.sh | 1 + src/LaunchDarkly/ApcLDDFeatureRequester.php | 27 ++++++++++++-- src/LaunchDarkly/ApcuLDDFeatureRequester.php | 34 ++++++++++++++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/LaunchDarkly/ApcuLDDFeatureRequester.php diff --git a/circle.yml b/circle.yml index 513e43b0a..92e5e7c01 100644 --- a/circle.yml +++ b/circle.yml @@ -2,15 +2,22 @@ machine: php: version: 5.6.17 services: + - redis - docker dependencies: pre: + - yes '' | pecl install -f apcu-4.0.10 + - echo "extension=apcu.so" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini + - echo "apc.enable_cli = 1" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini - docker pull php - docker pull nyanpass/php5.5 test: override: - vendor/bin/phpunit tests --coverage-text + - ln -s vendor integration-tests/vendor + - vendor/bin/phpunit integration-tests/LDDFeatureRequesterTest.php + - composer update && vendor/bin/phpunit tests - composer update --prefer-lowest && vendor/bin/phpunit tests diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 64ac40eaf..47229c861 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -5,6 +5,7 @@ use LaunchDarkly\LDClient; use LaunchDarkly\LDUserBuilder; +use Predis\Client; class LDDFeatureRetrieverTest extends \PHPUnit_Framework_TestCase { @@ -24,6 +25,9 @@ public function testGet() { } public function testGetApc() { + if (!extension_loaded('apc')) { + self::markTestSkipped('Install `apc` extension to run this test.'); + } $redis = new \Predis\Client(array( "scheme" => "tcp", "host" => 'localhost', @@ -46,6 +50,38 @@ public function testGetApc() { $this->assertEquals("baz", $client->variation('foo', $user, 'jim')); } + public function testGetApcu() { + if (!extension_loaded('apcu')) { + self::markTestSkipped('Install `apcu` extension to run this test.'); + } + + $redis = new Client([ + 'scheme' => 'tcp', + 'host' => 'localhost', + 'port' => 6379 + ]); + + $client = new LDClient('BOGUS_API_KEY', [ + 'feature_requester_class' => '\LaunchDarkly\ApcuLDDFeatureRequester', + 'apc_expiration' => 1 + ]); + + $builder = new LDUserBuilder(3); + $user = $builder->build(); + + $redis->del('launchdarkly:features'); + $this->assertEquals('alice', $client->variation('fiz', $user, 'alice')); + $redis->hset('launchdarkly:features', 'fiz', $this->gen_feature('fiz', 'buz')); + $this->assertEquals('buz', $client->variation('fiz', $user, 'alice')); + + # cached value so not updated + $redis->hset('launchdarkly:features', 'fiz', $this->gen_feature('fiz', 'bob')); + $this->assertEquals('buz', $client->variation('fiz', $user, 'alice')); + + \apcu_delete('launchdarkly:features.fiz'); + $this->assertEquals('bob', $client->variation('fiz', $user, 'alice')); + } + private function gen_feature($key, $val) { $data = [ 'name' => 'Feature ' . $key, diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index 786182dfa..81558a836 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -35,3 +35,7 @@ cat < /home/vagrant/.vimrc set tabstop=4 EOF chown vagrant.vagrant /home/vagrant/.vimrc + +# enable APC for php5 CLI +echo "apc.enable_cli = 1" >> /etc/php5/cli/conf.d/20-apcu.ini +php -i | grep apc diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh index 60145cb70..56ff2b07c 100755 --- a/integration-tests/bootstrap.user.sh +++ b/integration-tests/bootstrap.user.sh @@ -21,6 +21,7 @@ echo echo "install php54-apc" phpbrew ext install apc echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini +php -i | grep apc echo "date.timezone =UTC" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini echo diff --git a/src/LaunchDarkly/ApcLDDFeatureRequester.php b/src/LaunchDarkly/ApcLDDFeatureRequester.php index 9ad8e7f82..ad4a36af7 100644 --- a/src/LaunchDarkly/ApcLDDFeatureRequester.php +++ b/src/LaunchDarkly/ApcLDDFeatureRequester.php @@ -4,6 +4,9 @@ /** * Feature requester from an LDD-populated redis, with APC caching + * @deprecated Per the docs (http://php.net/manual/en/intro.apc.php): + * "This extension (APC) is considered unmaintained and dead". + * Install APCu and use \LaunchDarkly\ApcuLDDFeatureRequester instead! * * @package LaunchDarkly */ @@ -18,10 +21,19 @@ function __construct($baseUri, $apiKey, $options) { } } + /** + * @param $key + * @param $success + * @return mixed + */ + protected function fetch($key, &$success = null) + { + return \apc_fetch($key, $success); + } protected function get_from_cache($key) { $key = self::make_cache_key($key); - $enabled = apc_fetch($key); + $enabled = $this->fetch($key); if ($enabled === false) { return null; } @@ -30,8 +42,19 @@ protected function get_from_cache($key) { } } + /** + * @param $key + * @param $var + * @param int $ttl + * @return mixed + */ + protected function add($key, $var, $ttl = 0) + { + return \apc_add($key, $var, $ttl); + } + protected function store_in_cache($key, $val) { - apc_add($this->make_cache_key($key), $val, $this->_expiration); + $this->add($this->make_cache_key($key), $val, $this->_expiration); } private function make_cache_key($name) { diff --git a/src/LaunchDarkly/ApcuLDDFeatureRequester.php b/src/LaunchDarkly/ApcuLDDFeatureRequester.php new file mode 100644 index 000000000..30f2fb2c9 --- /dev/null +++ b/src/LaunchDarkly/ApcuLDDFeatureRequester.php @@ -0,0 +1,34 @@ + Date: Thu, 26 Jan 2017 15:44:17 -0800 Subject: [PATCH 080/150] Relax strict dependency versions --- composer.json | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 357083cc5..779ca090a 100644 --- a/composer.json +++ b/composer.json @@ -14,22 +14,21 @@ } ], "require": { - "monolog/monolog": "1.21.0", + "monolog/monolog": "1.21.*", "php": ">=5.5", - "psr/log": "1.0.0" + "psr/log": "1.0.*" }, "require-dev": { - "guzzlehttp/guzzle": "6.2.1", - "kevinrob/guzzle-cache-middleware": "1.4.1", + "guzzlehttp/guzzle": "^6.2.1", + "kevinrob/guzzle-cache-middleware": "^1.4.1", "phpunit/phpunit": ">=4.8.26 <5.4", "phpdocumentor/phpdocumentor": "2.*", "predis/predis": "1.0.*", "zendframework/zend-serializer": "2.7.*" }, "suggested": { - "guzzlehttp/guzzle": "6.2.1", - "kevinrob/guzzle-cache-middleware": "1.4.1", - "monolog/monolog": "1.21.0", + "guzzlehttp/guzzle": "^6.2.1", + "kevinrob/guzzle-cache-middleware": "^1.4.1", "predis/predis": "1.0.*" }, "autoload": { From 3125691bb38893565014a5ab57f0f9fcad73044d Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 26 Jan 2017 16:23:20 -0800 Subject: [PATCH 081/150] Update version and Changelog for 2.0.4 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e04e9ca86..5cecbcb4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.4] - 2017-01-26 +### Changed +- Made Composer requirements less strict + ## [2.0.3] - 2017-01-05 ### Changed - Fixed botched 2.0.2 release: Better handling of null vs false when evaluating. diff --git a/VERSION b/VERSION index 6acdb4428..26e33797a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.3 \ No newline at end of file +2.0.4 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index bc4e96ce7..3643665cb 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.3'; + const VERSION = '2.0.4'; /** @var string */ protected $_sdkKey; From 6ca5d4bfe006d8eb7a3920d6edeaeaee459e8526 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 31 Jan 2017 11:52:27 -0800 Subject: [PATCH 082/150] Try different monolog version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 779ca090a..3df91cead 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "monolog/monolog": "1.21.*", + "monolog/monolog": "~1.21", "php": ">=5.5", "psr/log": "1.0.*" }, From f497973b0b438f973681aa7ddf5401e00509917f Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 2 Feb 2017 11:14:30 -0800 Subject: [PATCH 083/150] Update bootstrap.sh shell script --- integration-tests/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index 81558a836..c0dbc86f6 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -1,5 +1,5 @@ #!/bin/bash - +set -uxe # init apt-get update 2> /dev/null From 440f7ddc0c0bd0313b4df6193e5690b1a777dc53 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 2 Feb 2017 11:14:58 -0800 Subject: [PATCH 084/150] Update bootstrap-user.sh shell script --- integration-tests/bootstrap.user.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh index 56ff2b07c..b7a0d35af 100755 --- a/integration-tests/bootstrap.user.sh +++ b/integration-tests/bootstrap.user.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -uxe echo echo "install phpbrew and php54" From 0a7bd128544adb5b923d96de30204138d533c90b Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 3 Feb 2017 08:36:47 -0700 Subject: [PATCH 085/150] drop php54 from the integration-test Vagrant VM, as this package officially only supports >=php5.5 --- .gitignore | 2 +- circle.yml | 1 - integration-tests/LDDFeatureRequesterTest.php | 15 +++++----- integration-tests/bootstrap.sh | 2 +- integration-tests/bootstrap.user.sh | 26 +--------------- integration-tests/composer.json | 30 ------------------- src/LaunchDarkly/LDClient.php | 4 +-- tests/LDClientTest.php | 8 ++--- 8 files changed, 17 insertions(+), 71 deletions(-) delete mode 100644 integration-tests/composer.json diff --git a/.gitignore b/.gitignore index 20328172b..f69e4693c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ composer.phar .vagrant integration-tests/vendor -integration-tests/composer.lock +composer.lock diff --git a/circle.yml b/circle.yml index fae9330de..73fa1cac4 100644 --- a/circle.yml +++ b/circle.yml @@ -15,7 +15,6 @@ dependencies: test: override: - vendor/bin/phpunit tests --coverage-text - - ln -s vendor integration-tests/vendor - vendor/bin/phpunit integration-tests/LDDFeatureRequesterTest.php - composer update && vendor/bin/phpunit tests diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 47229c861..3f96cd831 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -1,20 +1,21 @@ "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => '\\LaunchDarkly\\LDDFeatureRequester')); + $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => LDDFeatureRequester::class)); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -28,11 +29,11 @@ public function testGetApc() { if (!extension_loaded('apc')) { self::markTestSkipped('Install `apc` extension to run this test.'); } - $redis = new \Predis\Client(array( + $redis = new Client(array( "scheme" => "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => '\\LaunchDarkly\\ApcLDDFeatureRequester', + $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => ApcLDDFeatureRequester::class, 'apc_expiration' => 1)); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -62,7 +63,7 @@ public function testGetApcu() { ]); $client = new LDClient('BOGUS_API_KEY', [ - 'feature_requester_class' => '\LaunchDarkly\ApcuLDDFeatureRequester', + 'feature_requester_class' => ApcuLDDFeatureRequester::class, 'apc_expiration' => 1 ]); diff --git a/integration-tests/bootstrap.sh b/integration-tests/bootstrap.sh index c0dbc86f6..f3f4ad105 100755 --- a/integration-tests/bootstrap.sh +++ b/integration-tests/bootstrap.sh @@ -21,7 +21,7 @@ apt-get install -y php-apc 2> /dev/null apt-get install -y phpunit 2> /dev/null # phpbrew stuff for 5.4 -apt-get build-dep php5 2> /dev/null +apt-get build-dep -y php5 2> /dev/null apt-get install -y php5 php5-dev php-pear autoconf automake curl build-essential libxslt1-dev re2c libxml2 libxml2-dev php5-cli bison libbz2-dev libreadline-dev 2> /dev/null apt-get install -y libfreetype6 libfreetype6-dev libpng12-0 libpng12-dev libjpeg-dev libjpeg8-dev libjpeg8 libgd-dev libgd3 libxpm4 libltdl7 libltdl-dev 2> /dev/null apt-get install -y libssl-dev openssl 2> /dev/null diff --git a/integration-tests/bootstrap.user.sh b/integration-tests/bootstrap.user.sh index b7a0d35af..fc36f5848 100755 --- a/integration-tests/bootstrap.user.sh +++ b/integration-tests/bootstrap.user.sh @@ -1,32 +1,8 @@ #!/bin/bash set -uxe -echo -echo "install phpbrew and php54" -cd ~ -curl -s -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew -chmod +x phpbrew -sudo mv phpbrew /usr/bin/phpbrew -phpbrew init -phpbrew known --update -phpbrew update -phpbrew install 5.4.34 +default - -echo -echo "switch php54" -echo "source $HOME/.phpbrew/bashrc" >> /home/vagrant/.bashrc -source $HOME/.phpbrew/bashrc -phpbrew switch 5.4.34 - -echo -echo "install php54-apc" -phpbrew ext install apc -echo "apc.enable_cli = 1" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini -php -i | grep apc -echo "date.timezone =UTC" >> ~/.phpbrew/php/php-5.4.34/etc/php.ini - echo echo "update project dependencies" -cd /home/vagrant/project/integration-tests +cd /home/vagrant/project curl -sS https://getcomposer.org/installer | php php composer.phar update diff --git a/integration-tests/composer.json b/integration-tests/composer.json deleted file mode 100644 index 83541023a..000000000 --- a/integration-tests/composer.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "launchdarkly/launchdarkly-php-integration-tests", - "description": "Integration tests", - "homepage": "https://github.com/launchdarkly/php-client", - "license": "Apache-2.0", - "authors": [ - { - "name": "LaunchDarkly ", - "homepage": "http://launchdarkly.com/" - } - ], - "require": { - "php": ">=5.3", - "monolog/monolog": "^1.22", - "predis/predis": "1.0.*" - }, - "require-dev": { - "phpunit/phpunit": "4.3.*" - }, - "autoload": { - "psr-4": { - "": "../src/" - } - }, - "autoload-dev": { - "psr-4": { - "": "." - } - } -} diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 5ee841d0c..ab3d22953 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -85,10 +85,10 @@ public function __construct($sdkKey, $options = array()) { if (isset($options['feature_requester_class'])) { $featureRequesterClass = $options['feature_requester_class']; } else { - $featureRequesterClass = '\\LaunchDarkly\\GuzzleFeatureRequester'; + $featureRequesterClass = GuzzleFeatureRequester::class; } - if (!is_a($featureRequesterClass, '\LaunchDarkly\FeatureRequester', true)) { + if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { throw new \InvalidArgumentException; } $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $sdkKey, $options); diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 8487e0ca5..3a1492962 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -17,7 +17,7 @@ public function testDefaultCtor() { public function testToggleDefault() { MockFeatureRequester::$val = null; $client = new LDClient("someKey", array( - 'feature_requester_class' => '\\LaunchDarkly\Tests\\MockFeatureRequester', + 'feature_requester_class' => MockFeatureRequester::class, 'events' => false )); @@ -29,7 +29,7 @@ public function testToggleDefault() { public function testToggleFromArray() { MockFeatureRequester::$val = null; $client = new LDClient("someKey", array( - 'feature_requester_class' => '\\LaunchDarkly\Tests\\MockFeatureRequester', + 'feature_requester_class' => MockFeatureRequester::class, 'events' => false, 'defaults' => array('foo' => 'fromarray') )); @@ -42,7 +42,7 @@ public function testToggleFromArray() { public function testToggleEvent() { MockFeatureRequester::$val = null; $client = new LDClient("someKey", array( - 'feature_requester_class' => '\\LaunchDarkly\Tests\\MockFeatureRequester', + 'feature_requester_class' => MockFeatureRequester::class, 'events' => true )); @@ -56,7 +56,7 @@ public function testToggleEvent() { public function testOnlyValidFeatureRequester() { $this->setExpectedException(InvalidArgumentException::class); - new LDClient("BOGUS_SDK_KEY", ['feature_requester_class' => 'stdClass']); + new LDClient("BOGUS_SDK_KEY", ['feature_requester_class' => \stdClass::class]); } public function testSecureModeHash() { From 59109b14c541669a9c765ee8255693b1e86f049e Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 3 Feb 2017 14:47:10 -0800 Subject: [PATCH 086/150] Relax monolog version --- composer.json | 2 +- composer.lock | 428 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 313 insertions(+), 117 deletions(-) diff --git a/composer.json b/composer.json index 3df91cead..c357154ee 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "monolog/monolog": "~1.21", + "monolog/monolog": "1.*", "php": ">=5.5", "psr/log": "1.0.*" }, diff --git a/composer.lock b/composer.lock index c79ee8819..6796b4600 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "cd49540bfcf76434cbb74b1dda2b5d13", - "content-hash": "6a93d29d931b3889657d4aa00eed323f", + "hash": "fe2ef61776962bb0e97f4889c939534d", + "content-hash": "12982c87565739e6a9c652a75ee41de6", "packages": [ { "name": "monolog/monolog", - "version": "1.21.0", + "version": "1.22.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" + "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", + "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", "shasum": "" }, "require": { @@ -29,7 +29,7 @@ "psr/log-implementation": "1.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "jakub-onderka/php-parallel-lint": "0.9", @@ -83,26 +83,34 @@ "logging", "psr-3" ], - "time": "2016-07-29 03:23:52" + "time": "2016-11-26 00:15:39" }, { "name": "psr/log", - "version": "1.0.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -116,12 +124,13 @@ } ], "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2016-10-10 12:19:37" } ], "packages-dev": [ @@ -272,16 +281,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.3.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5" + "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/30e07cf03edc3cd3ef579d0dd4dd8c58250799a5", - "reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/bd4461328621bde0ae6b1b2675fbc6aca4ceb558", + "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558", "shasum": "" }, "require": { @@ -336,7 +345,7 @@ "docblock", "parser" ], - "time": "2016-10-24 11:45:47" + "time": "2016-12-30 15:59:45" }, { "name": "doctrine/instantiator", @@ -490,16 +499,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.2.1", + "version": "6.2.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", "shasum": "" }, "require": { @@ -548,7 +557,7 @@ "rest", "web service" ], - "time": "2016-07-15 17:22:37" + "time": "2016-10-08 15:01:37" }, { "name": "guzzlehttp/promises", @@ -1005,16 +1014,16 @@ }, { "name": "kevinrob/guzzle-cache-middleware", - "version": "v1.4.1", + "version": "v1.5.2", "source": { "type": "git", "url": "https://github.com/Kevinrob/guzzle-cache-middleware.git", - "reference": "f30ded404c296d50820670489d718a04634b6789" + "reference": "2893fff87ef9f7f2c669957f5e446beea48d7a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/f30ded404c296d50820670489d718a04634b6789", - "reference": "f30ded404c296d50820670489d718a04634b6789", + "url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/2893fff87ef9f7f2c669957f5e446beea48d7a1d", + "reference": "2893fff87ef9f7f2c669957f5e446beea48d7a1d", "shasum": "" }, "require": { @@ -1079,7 +1088,7 @@ "rfc7234", "validation" ], - "time": "2016-06-17 08:34:36" + "time": "2017-01-16 07:02:13" }, { "name": "kherge/version", @@ -1123,6 +1132,48 @@ "homepage": "http://github.com/kherge/Version", "time": "2012-08-16 17:13:03" }, + { + "name": "myclabs/deep-copy", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-01-26 22:05:40" + }, { "name": "nikic/php-parser", "version": "v1.4.1", @@ -1607,39 +1658,40 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "3.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/44cd8e3930e431658d1a5de7d282d5cb37837fd5", + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": "^5.6 || ^7.0", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "sebastian/version": "~1.0|~2.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.2.1", + "ext-xdebug": ">=2.4.0", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "3.3.x-dev" } }, "autoload": { @@ -1665,7 +1717,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2016-05-27 16:24:29" }, { "name": "phpunit/php-file-iterator", @@ -1850,16 +1902,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.8.26", + "version": "5.3.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74" + "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74", - "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08c513bfcab57f3dd72f5214c1c3940439fae7fe", + "reference": "08c513bfcab57f3dd72f5214c1c3940439fae7fe", "shasum": "" }, "require": { @@ -1868,19 +1920,22 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "php": ">=5.3.3", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", + "phpunit/php-code-coverage": ">=3.3.0,<4.0.0", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", + "phpunit/phpunit-mock-objects": ">=3.1.0,<3.2.0", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", + "sebastian/object-enumerator": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" }, "suggest": { @@ -1892,7 +1947,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -1918,30 +1973,30 @@ "testing", "xunit" ], - "time": "2016-05-17 03:09:28" + "time": "2016-06-03 09:42:56" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "151c96874bff6fe61a25039df60e776613a61489" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489", + "reference": "151c96874bff6fe61a25039df60e776613a61489", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", + "php": ">=5.6", "phpunit/php-text-template": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-soap": "*" @@ -1949,7 +2004,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1974,7 +2029,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2016-04-20 14:39:26" }, { "name": "pimple/pimple", @@ -2122,18 +2177,63 @@ ], "time": "2016-08-06 14:39:51" }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" + }, { "name": "sebastian/comparator", - "version": "1.2.2", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { @@ -2184,7 +2284,7 @@ "compare", "equality" ], - "time": "2016-11-19 09:18:40" + "time": "2017-01-29 09:50:25" }, { "name": "sebastian/diff", @@ -2406,6 +2506,52 @@ ], "time": "2015-10-12 03:26:01" }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-01-28 13:25:10" + }, { "name": "sebastian/recursion-context", "version": "1.0.2", @@ -2459,21 +2605,71 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2015-11-11 19:50:13" }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, + "require": { + "php": ">=5.6" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2492,7 +2688,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2016-10-03 07:35:21" }, { "name": "seld/jsonlint", @@ -2542,16 +2738,16 @@ }, { "name": "symfony/config", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86" + "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/b522856007b258f46d5ee35d3b7b235c11e76e86", - "reference": "b522856007b258f46d5ee35d3b7b235c11e76e86", + "url": "https://api.github.com/repos/symfony/config/zipball/4537f2413348fe271c2c4b09da219ed615d79f9c", + "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c", "shasum": "" }, "require": { @@ -2594,20 +2790,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-12-10 08:21:45" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/console", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d5643cd095e5e37d31e004bb2606b5dd7e96602f" + "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d5643cd095e5e37d31e004bb2606b5dd7e96602f", - "reference": "d5643cd095e5e37d31e004bb2606b5dd7e96602f", + "url": "https://api.github.com/repos/symfony/console/zipball/2e18b8903d9c498ba02e1dfa73f64d4894bb6912", + "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912", "shasum": "" }, "require": { @@ -2655,7 +2851,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-12-06 11:59:35" + "time": "2017-01-08 20:43:03" }, { "name": "symfony/debug", @@ -2716,16 +2912,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934" + "reference": "74877977f90fb9c3e46378d5764217c55f32df34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", - "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74877977f90fb9c3e46378d5764217c55f32df34", + "reference": "74877977f90fb9c3e46378d5764217c55f32df34", "shasum": "" }, "require": { @@ -2772,7 +2968,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-10-13 01:43:15" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/filesystem", @@ -2825,16 +3021,16 @@ }, { "name": "symfony/finder", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "c0f10576335743b881ac1ed39d18c0fa66048775" + "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/c0f10576335743b881ac1ed39d18c0fa66048775", - "reference": "c0f10576335743b881ac1ed39d18c0fa66048775", + "url": "https://api.github.com/repos/symfony/finder/zipball/355fccac526522dc5fca8ecf0e62749a149f3b8b", + "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b", "shasum": "" }, "require": { @@ -2870,7 +3066,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-12-13 09:38:12" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/polyfill-mbstring", @@ -2933,16 +3129,16 @@ }, { "name": "symfony/process", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1a1bd056395540d0bc549d39818316513565d278" + "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1a1bd056395540d0bc549d39818316513565d278", - "reference": "1a1bd056395540d0bc549d39818316513565d278", + "url": "https://api.github.com/repos/symfony/process/zipball/ebb3c2abe0940a703f08e0cbe373f62d97d40231", + "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231", "shasum": "" }, "require": { @@ -2978,20 +3174,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-11-24 00:43:03" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/stopwatch", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "35bae476693150728b0eb51647faac82faf9aaca" + "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/35bae476693150728b0eb51647faac82faf9aaca", - "reference": "35bae476693150728b0eb51647faac82faf9aaca", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e8bb9de52febc4ee9922b33b1f04ba5feed457b8", + "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8", "shasum": "" }, "require": { @@ -3027,7 +3223,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/translation", @@ -3095,16 +3291,16 @@ }, { "name": "symfony/validator", - "version": "v2.8.15", + "version": "v2.8.16", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce" + "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce", - "reference": "1a2bad8d4669f55dc4f9fcd26071b5e78fb37bce", + "url": "https://api.github.com/repos/symfony/validator/zipball/3b1a3188efea75ec7c0419a2568b6e5f82031811", + "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811", "shasum": "" }, "require": { @@ -3164,20 +3360,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-12-08 15:59:39" + "time": "2017-01-12 19:24:25" }, { "name": "symfony/yaml", - "version": "v3.2.1", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a7095af4b97a0955f85c8989106c249fa649011f" + "reference": "50eadbd7926e31842893c957eca362b21592a97d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", - "reference": "a7095af4b97a0955f85c8989106c249fa649011f", + "url": "https://api.github.com/repos/symfony/yaml/zipball/50eadbd7926e31842893c957eca362b21592a97d", + "reference": "50eadbd7926e31842893c957eca362b21592a97d", "shasum": "" }, "require": { @@ -3219,20 +3415,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-12-10 10:07:06" + "time": "2017-01-03 13:51:32" }, { "name": "twig/twig", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "c6ff71094fde15d12398eaba029434b013dc5e59" + "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/c6ff71094fde15d12398eaba029434b013dc5e59", - "reference": "c6ff71094fde15d12398eaba029434b013dc5e59", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddc9e3e20ee9c0b6908f401ac8353635b750eca7", + "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7", "shasum": "" }, "require": { @@ -3240,12 +3436,12 @@ }, "require-dev": { "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.2@dev" + "symfony/phpunit-bridge": "~3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.30-dev" + "dev-master": "1.31-dev" } }, "autoload": { @@ -3280,7 +3476,7 @@ "keywords": [ "templating" ], - "time": "2016-12-23 11:06:22" + "time": "2017-01-11 19:36:15" }, { "name": "zendframework/zend-cache", From fac0b400711cf89029886b3306c72b3b7040641f Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Fri, 3 Feb 2017 14:57:43 -0800 Subject: [PATCH 087/150] Relax monolog version. --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cecbcb4e..215add431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.5] - 2017-02-03 +### Changed +- Made Monolog dependency version less strict + ## [2.0.4] - 2017-01-26 ### Changed - Made Composer requirements less strict diff --git a/VERSION b/VERSION index 26e33797a..b9d2bdfd6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.4 \ No newline at end of file +2.0.5 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 3643665cb..048632ba4 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.4'; + const VERSION = '2.0.5'; /** @var string */ protected $_sdkKey; From 016026cf0151adbc542de78513d2f6ba91662346 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 3 Feb 2017 19:13:19 -0700 Subject: [PATCH 088/150] further loosen composer dependencies, and fix monolog dependency (ErrorHandler was not available until 1.6.0) --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index c357154ee..9293d011e 100644 --- a/composer.json +++ b/composer.json @@ -14,22 +14,22 @@ } ], "require": { - "monolog/monolog": "1.*", + "monolog/monolog": "^1.6", "php": ">=5.5", - "psr/log": "1.0.*" + "psr/log": "^1.0" }, "require-dev": { "guzzlehttp/guzzle": "^6.2.1", "kevinrob/guzzle-cache-middleware": "^1.4.1", "phpunit/phpunit": ">=4.8.26 <5.4", - "phpdocumentor/phpdocumentor": "2.*", - "predis/predis": "1.0.*", - "zendframework/zend-serializer": "2.7.*" + "phpdocumentor/phpdocumentor": "^2.0", + "predis/predis": "^1.0", + "zendframework/zend-serializer": "^2.7" }, "suggested": { "guzzlehttp/guzzle": "^6.2.1", "kevinrob/guzzle-cache-middleware": "^1.4.1", - "predis/predis": "1.0.*" + "predis/predis": "^1.0" }, "autoload": { "psr-4": { From 208b9f80eb077059356885238971019f6e10ca48 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Tue, 7 Feb 2017 11:24:35 -0800 Subject: [PATCH 089/150] Update Changelog, etc for 2.0.6 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 215add431..3c0796fab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.6] - 2017-02-07 +### Changed +- Use minimum versions in composer.json + ## [2.0.5] - 2017-02-03 ### Changed - Made Monolog dependency version less strict diff --git a/VERSION b/VERSION index b9d2bdfd6..703cec9e2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.5 \ No newline at end of file +2.0.6 \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 9e29554b1..5ccc2e316 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.5'; + const VERSION = '2.0.6'; /** @var string */ protected $_sdkKey; From db2d6a2dbcde724f6a2530bdd34e62fd1d83012d Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 17 Feb 2017 11:01:11 -0700 Subject: [PATCH 090/150] fix `WARNING: array_map(): Argument #2 should be an array in vendor/launchdarkly/launchdarkly-php/src/LaunchDarkly/FeatureFlag.php on line 60` where FeatureFlag assumes `prerequisites` will always be an array. in an ld-relay test i see that `prerequisites` can be null so that must be handled here. --- src/LaunchDarkly/FeatureFlag.php | 2 +- tests/FeatureFlagTest.php | 47 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index ff122534d..7aa7ede76 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -57,7 +57,7 @@ public static function getDecoder() { $v['key'], $v['version'], $v['on'], - array_map(Prerequisite::getDecoder(), $v['prerequisites']), + array_map(Prerequisite::getDecoder(), $v['prerequisites'] ?: []), $v['salt'], array_map(Target::getDecoder(), $v['targets']), array_map(Rule::getDecoder(), $v['rules']), diff --git a/tests/FeatureFlagTest.php b/tests/FeatureFlagTest.php index a81cd11e4..faecf0243 100644 --- a/tests/FeatureFlagTest.php +++ b/tests/FeatureFlagTest.php @@ -140,5 +140,52 @@ public function testDecode() { FeatureFlag::decode(\GuzzleHttp\json_decode(FeatureFlagTest::$json1, true)); FeatureFlag::decode(\GuzzleHttp\json_decode(FeatureFlagTest::$json2, true)); } + + public function dataDecodeMulti() + { + return [ + 'null-prerequisites' => [ + [ + 'key' => 'sysops-test', + 'version' => 14, + 'on' => true, + 'prerequisites' => NULL, + 'salt' => 'c3lzb3BzLXRlc3Q=', + 'sel' => '8ed13de1bfb14507ba7e6dde01f3e035', + 'targets' => [ + [ + 'values' => [], + 'variation' => 0, + ], + [ + 'values' => [], + 'variation' => 1, + ], + ], + 'rules' => [], + 'fallthrough' => [ + 'variation' => 0, + ], + 'offVariation' => NULL, + 'variations' => [ + true, + false, + ], + 'deleted' => false, + ] + ], + ]; + } + + /** + * @dataProvider dataDecodeMulti + * @param array $feature + */ + public function testDecodeMulti(array $feature) + { + $featureFlag = FeatureFlag::decode($feature); + + self::assertInstanceOf(FeatureFlag::class, $featureFlag); + } } From a1b745f82231a8c656831eaca515f13fd17dd723 Mon Sep 17 00:00:00 2001 From: Tiago Butzke Date: Wed, 22 Feb 2017 19:56:58 +0100 Subject: [PATCH 091/150] Fixes #67 --- integration-tests/LDDFeatureRequesterTest.php | 52 ++++++++++++++++--- src/LaunchDarkly/LDDFeatureRequester.php | 18 ++++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 3f96cd831..6d41355ed 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -2,6 +2,7 @@ namespace LaunchDarkly\Tests; use LaunchDarkly\LDClient; +use LaunchDarkly\LDUser; use LaunchDarkly\LDUserBuilder; use LaunchDarkly\LDDFeatureRequester; use LaunchDarkly\ApcLDDFeatureRequester; @@ -9,13 +10,14 @@ use LaunchDarkly\ApcuLDDFeatureRequester; class LDDFeatureRetrieverTest extends \PHPUnit_Framework_TestCase { + const API_KEY = 'BOGUS_API_KEY'; public function testGet() { $redis = new Client(array( "scheme" => "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => LDDFeatureRequester::class)); + $client = new LDClient(static::API_KEY, array('feature_requester_class' => LDDFeatureRequester::class)); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -33,7 +35,7 @@ public function testGetApc() { "scheme" => "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient("BOGUS_API_KEY", array('feature_requester_class' => ApcLDDFeatureRequester::class, + $client = new LDClient(static::API_KEY, array('feature_requester_class' => ApcLDDFeatureRequester::class, 'apc_expiration' => 1)); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -55,18 +57,18 @@ public function testGetApcu() { if (!extension_loaded('apcu')) { self::markTestSkipped('Install `apcu` extension to run this test.'); } - + $redis = new Client([ 'scheme' => 'tcp', 'host' => 'localhost', 'port' => 6379 ]); - - $client = new LDClient('BOGUS_API_KEY', [ + + $client = new LDClient(static::API_KEY, [ 'feature_requester_class' => ApcuLDDFeatureRequester::class, 'apc_expiration' => 1 ]); - + $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -83,6 +85,42 @@ public function testGetApcu() { $this->assertEquals('bob', $client->variation('fiz', $user, 'alice')); } + public function testGetAllWithoutFeatures() + { + $redis = new \Predis\Client([ + 'scheme' => 'tcp', + 'host' => 'localhost', + 'port' => 6379, + ]); + $redis->flushall(); + + $client = new LDClient(static::API_KEY, ['feature_requester_class' => LDDFeatureRequester::class]); + $user = new LDUser(static::API_KEY); + $allFlags = $client->allFlags($user); + + $this->assertNull($allFlags); + } + + public function testGetAll() + { + $featureKey = 'foo'; + $featureValue = 'bar'; + + $redis = new \Predis\Client([ + 'scheme' => 'tcp', + 'host' => 'localhost', + 'port' => 6379, + ]); + $client = new LDClient(static::API_KEY, ['feature_requester_class' => LDDFeatureRequester::class]); + $redis->hset('launchdarkly:features', $featureKey, $this->gen_feature($featureKey, $featureValue)); + $user = new LDUser(static::API_KEY); + $allFlags = $client->allFlags($user); + + $this->assertInternalType('array', $allFlags); + $this->assertArrayHasKey($featureKey, $allFlags); + $this->assertEquals($featureValue, $allFlags[$featureKey]); + } + private function gen_feature($key, $val) { $data = [ 'name' => 'Feature ' . $key, @@ -130,7 +168,7 @@ private function gen_feature($key, $val) { 'offVariation' => null, 'deleted' => false, ]; - + return \json_encode($data); } diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index f163ee90f..a043dfa6c 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -96,7 +96,7 @@ public function getAll() { $redis = $this->get_connection(); $raw = $redis->hgetall($this->_features_key); if ($raw) { - $allFlags = array_map(FeatureFlag::getDecoder(), json_decode($raw, true)); + $allFlags = array_map(FeatureFlag::getDecoder(), $this->decodeFeatures($raw)); /** * @param $flag FeatureFlag * @return bool @@ -110,4 +110,18 @@ public function getAll() { return null; } } -} \ No newline at end of file + + /** + * @param array $features + * + * @return array + */ + private function decodeFeatures(array $features) + { + foreach ($features as $featureKey => $feature) { + $features[$featureKey] = json_decode($feature, true); + } + + return $features; + } +} From c1b3bb365e6507fb2399a35155606dc7b6774fa0 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 22 Feb 2017 18:35:20 -0700 Subject: [PATCH 092/150] allow Predis\Client to be overridden via parameter. this will allow consumers to factory their own Client with different Connection backends, Sentinel support, etc. --- src/LaunchDarkly/LDDFeatureRequester.php | 8 +++ tests/LDDFeatureRequesterTest.php | 72 ++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/LDDFeatureRequesterTest.php diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index f163ee90f..a4ce8fd7d 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -2,6 +2,7 @@ namespace LaunchDarkly; +use Predis\ClientInterface; use Psr\Log\LoggerInterface; class LDDFeatureRequester implements FeatureRequester { @@ -33,7 +34,14 @@ function __construct($baseUri, $apiKey, $options) { } + /** + * @return ClientInterface + */ protected function get_connection() { + if (isset($this->_options['predis_client']) && $this->_options['predis_client'] instanceof ClientInterface) { + return $this->_options['predis_client']; + } + /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ return new \Predis\Client(array( "scheme" => "tcp", diff --git a/tests/LDDFeatureRequesterTest.php b/tests/LDDFeatureRequesterTest.php new file mode 100644 index 000000000..97bfcc428 --- /dev/null +++ b/tests/LDDFeatureRequesterTest.php @@ -0,0 +1,72 @@ +logger = new NullLogger(); + + $this->predisClient = $this->getMockBuilder(ClientInterface::class) + ->setMethods(['hget']) + ->getMockForAbstractClass(); + } + + public function testGet() + { + $sut = new LDDFeatureRequester('example.com', 'MyApiKey', [ + 'logger' => $this->logger, + 'predis_client' => $this->predisClient, + ]); + + $this->predisClient->method('hget')->with('launchdarkly:features', 'foo') + ->willReturn(json_encode([ + 'key' => 'foo', + 'version' => 14, + 'on' => true, + 'prerequisites' => [], + 'salt' => 'c3lzb3BzLXRlc3Q=', + 'sel' => '8ed13de1bfb14507ba7e6dde01f3e035', + 'targets' => [ + [ + 'values' => [], + 'variation' => 0, + ], + [ + 'values' => [], + 'variation' => 1, + ], + ], + 'rules' => [], + 'fallthrough' => [ + 'variation' => 0, + ], + 'offVariation' => null, + 'variations' => [ + true, + false, + ], + 'deleted' => false, + ])); + + $featureFlag = $sut->get('foo'); + + self::assertInstanceOf(FeatureFlag::class, $featureFlag); + self::assertTrue($featureFlag->isOn()); + } +} From acc1ac5d1da6dd6dd243fe40793ece5518b509ed Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Thu, 2 Mar 2017 21:20:35 -0700 Subject: [PATCH 093/150] move Predis Client override into constructor (where it belongs), and store a local private connection field so that fallback connections are not created over and over on subsequent feature requests. --- src/LaunchDarkly/LDDFeatureRequester.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index a4ce8fd7d..a44bedc3c 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -12,6 +12,8 @@ class LDDFeatureRequester implements FeatureRequester { protected $_features_key; /** @var LoggerInterface */ private $_logger; + /** @var ClientInterface */ + private $_connection; function __construct($baseUri, $apiKey, $options) { $this->_baseUri = $baseUri; @@ -32,18 +34,21 @@ function __construct($baseUri, $apiKey, $options) { $this->_features_key = "$prefix:features"; $this->_logger = $options['logger']; + if (isset($this->_options['predis_client']) && $this->_options['predis_client'] instanceof ClientInterface) { + $this->_connection = $this->_options['predis_client']; + } } /** * @return ClientInterface */ protected function get_connection() { - if (isset($this->_options['predis_client']) && $this->_options['predis_client'] instanceof ClientInterface) { - return $this->_options['predis_client']; + if ($this->_connection instanceof ClientInterface) { + return $this->_connection; } /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ - return new \Predis\Client(array( + return $this->_connection = new \Predis\Client(array( "scheme" => "tcp", "host" => $this->_options['redis_host'], "port" => $this->_options['redis_port'])); From 63f08c7181fda608ebf993b72ab92ad3c20f5ee0 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Fri, 3 Mar 2017 13:06:28 -0800 Subject: [PATCH 094/150] Release version 2.0.7 --- CHANGELOG.md | 5 +++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c0796fab..76ef3b4f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.0.7] - 2017-03-03 +### Changed +- Removed warning when calling `allFlags` via `LDDFeatureRequester` +- Removed warning when a feature flag's prerequisites happen to be null + ## [2.0.6] - 2017-02-07 ### Changed - Use minimum versions in composer.json diff --git a/VERSION b/VERSION index 703cec9e2..f1547e6d1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.6 \ No newline at end of file +2.0.7 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index db681cc73..c439b7906 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.6'; + const VERSION = '2.0.7'; /** @var string */ protected $_sdkKey; From c1423c41c090bda3a71b8b392e6611529f607320 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Mon, 13 Mar 2017 10:17:36 -0700 Subject: [PATCH 095/150] `warn` is a method on the concrete Logger impl from Monolog. `warning` on the PSR LoggerInterface should be used instead. --- src/LaunchDarkly/LDClient.php | 10 +++++----- tests/LDClientTest.php | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index c439b7906..2fb604cf1 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -24,7 +24,7 @@ class LDClient { protected $_send_events = true; /** @var array|mixed */ protected $_defaults = array(); - /** @var mixed|LoggerInterface */ + /** @var LoggerInterface */ protected $_logger; /** @var FeatureRequester */ @@ -113,11 +113,11 @@ public function variation($key, $user, $default = false) { try { if (is_null($user) || is_null($user->getKey())) { $this->_sendFlagRequestEvent($key, $user, $default, $default); - $this->_logger->warn("Variation called with null user or null user key! Returning default value"); + $this->_logger->warning("Variation called with null user or null user key! Returning default value"); return $default; } if ($user->isKeyBlank()) { - $this->_logger->warn("User key is blank. Flag evaluation will proceed, but the user will not be stored in LaunchDarkly."); + $this->_logger->warning("User key is blank. Flag evaluation will proceed, but the user will not be stored in LaunchDarkly."); } $flag = $this->_featureRequester->get($key); @@ -178,7 +178,7 @@ public function track($eventName, $user, $data) { return; } if (is_null($user) || $user->isKeyBlank()) { - $this->_logger->warn("Track called with null user or null/empty user key!"); + $this->_logger->warning("Track called with null user or null/empty user key!"); } $event = array(); @@ -200,7 +200,7 @@ public function identify($user) { return; } if (is_null($user) || $user->isKeyBlank()) { - $this->_logger->warn("Track called with null user or null/empty user key!"); + $this->_logger->warning("Track called with null user or null/empty user key!"); } $event = array(); diff --git a/tests/LDClientTest.php b/tests/LDClientTest.php index 3a1492962..b4b5d2245 100644 --- a/tests/LDClientTest.php +++ b/tests/LDClientTest.php @@ -6,6 +6,7 @@ use LaunchDarkly\LDClient; use LaunchDarkly\LDUser; use LaunchDarkly\LDUserBuilder; +use Psr\Log\LoggerInterface; class LDClientTest extends \PHPUnit_Framework_TestCase { @@ -64,6 +65,22 @@ public function testSecureModeHash() { $user = new LDUser("Message"); $this->assertEquals("aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597", $client->secureModeHash($user)); } + + public function testLoggerInterfaceWarn() + { + // Use LoggerInterface impl, instead of concreate Logger from Monolog, to demonstrate the problem with `warn`. + $logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); + + $logger->expects(self::atLeastOnce())->method('warning'); + + $client = new LDClient('secret', [ + 'logger' => $logger, + ]); + + $user = new LDUser(''); + + $client->variation('MyFeature', $user); + } } From b0787e570aad691a9fd7e698fc20db9733b7684e Mon Sep 17 00:00:00 2001 From: Jonas Drieghe Date: Tue, 14 Mar 2017 08:52:50 +0100 Subject: [PATCH 096/150] Default was type hinted as boolean but can be anything. --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index c439b7906..78883327d 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -99,7 +99,7 @@ public function __construct($sdkKey, $options = array()) { * * @param string $key The unique key for the feature flag * @param LDUser $user The end user requesting the flag - * @param boolean $default The default value of the flag + * @param mixed $default The default value of the flag * * @return mixed The result of the Feature Flag evaluation, or $default if any errors occurred. */ From 014f3f88d830a1e7407e6033553e6481cceb8059 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Wed, 15 Mar 2017 14:34:31 -0700 Subject: [PATCH 097/150] allow feature-requester to be injected into the client rather than instantiated in the client controller by configurable class name. both are supported. --- src/LaunchDarkly/LDClient.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 78883327d..a0abe7edc 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -82,6 +82,20 @@ public function __construct($sdkKey, $options = array()) { $this->_eventProcessor = new EventProcessor($sdkKey, $options); + $this->_featureRequester = $this->getFeatureRequester($options, $sdkKey); + } + + /** + * @param mixed[] $options + * @param string $sdkKey + * @return FeatureRequester + */ + private function getFeatureRequester(array $options, $sdkKey) + { + if (isset($options['feature_requester']) && $options['feature_requester'] instanceof FeatureRequester) { + return $options['feature_requester']; + } + if (isset($options['feature_requester_class'])) { $featureRequesterClass = $options['feature_requester_class']; } else { @@ -91,7 +105,7 @@ public function __construct($sdkKey, $options = array()) { if (!is_a($featureRequesterClass, FeatureRequester::class, true)) { throw new \InvalidArgumentException; } - $this->_featureRequester = new $featureRequesterClass($this->_baseUri, $sdkKey, $options); + return new $featureRequesterClass($this->_baseUri, $sdkKey, $options); } /** From 06f0dff5cbe618443c7d629f7b58f7da2898dcb2 Mon Sep 17 00:00:00 2001 From: Dan Richelson Date: Thu, 23 Mar 2017 10:43:14 -0700 Subject: [PATCH 098/150] Update Changelog, etc for 2.1.0 --- CHANGELOG.md | 9 ++++++++- VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76ef3b4f2..39d1a5b74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change log -All notable changes to the LaunchDarkly Java SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). + +## [2.1.0] - 2017-03-23 +### Changed +- Allow FeatureRequester to be injected into the client. Thanks @abacaphiliac! +- Allow Predis\Client to be overriden in LDDFeatureRequester. Thanks @abacaphiliac! +- Use logger interface method instead of Monolog method. Thanks @abacaphiliac! +- Improve type hinting for default. Thanks @jdrieghe! ## [2.0.7] - 2017-03-03 ### Changed diff --git a/VERSION b/VERSION index f1547e6d1..7ec1d6db4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.7 +2.1.0 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 861c4fa76..969297864 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.0.7'; + const VERSION = '2.1.0'; /** @var string */ protected $_sdkKey; From 99297ba4a651a522d28b4332a68d3c5c405002a4 Mon Sep 17 00:00:00 2001 From: John Kodumal Date: Mon, 10 Apr 2017 13:14:41 -0700 Subject: [PATCH 099/150] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58fd312b9..6ea969760 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Fetching flags There are two approaches to fetching the flag rules from LaunchDarkly: * Making HTTP requests (using Guzzle) -* Setting up the [ld-daemon](https://github.com/launchdarkly/ld-daemon) to store the flags in Redis +* Setting up the [ld-relay](https://github.com/launchdarkly/ld-relay) to store the flags in Redis Using Guzzle ============ From 30e40beffdb08b28e1cf47a5e2ae84e5b88bf791 Mon Sep 17 00:00:00 2001 From: Idir Ouhab Meskine Date: Mon, 10 Apr 2017 23:58:28 +0200 Subject: [PATCH 100/150] Set target field to empty array whenever is null --- src/LaunchDarkly/FeatureFlag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 7aa7ede76..8d9661f6b 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -59,7 +59,7 @@ public static function getDecoder() { $v['on'], array_map(Prerequisite::getDecoder(), $v['prerequisites'] ?: []), $v['salt'], - array_map(Target::getDecoder(), $v['targets']), + array_map(Target::getDecoder(), $v['targets'] ?: []), array_map(Rule::getDecoder(), $v['rules']), call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), $v['offVariation'], From 7fe97d31f443be0e35488af5251038431853ba02 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Mon, 10 Apr 2017 17:00:15 -0700 Subject: [PATCH 101/150] Ensure that FeatureFlag _rules is non-null --- src/LaunchDarkly/FeatureFlag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 8d9661f6b..c59ca830f 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -60,7 +60,7 @@ public static function getDecoder() { array_map(Prerequisite::getDecoder(), $v['prerequisites'] ?: []), $v['salt'], array_map(Target::getDecoder(), $v['targets'] ?: []), - array_map(Rule::getDecoder(), $v['rules']), + array_map(Rule::getDecoder(), $v['rules'] ?: []), call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), $v['offVariation'], $v['variations'], From f0ff5a9b2bf346d118cc9de96102d6af13b23480 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Tue, 11 Apr 2017 13:29:21 -0700 Subject: [PATCH 102/150] Release version 2.1.1 --- CHANGELOG.md | 7 ++++++- VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39d1a5b74..e3a426cd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.1.1] - 2017-04-11 +### Changed +- Better handling of possibly null targets. Thanks @idirouhab! +- Better handling of possibly null rules. + ## [2.1.0] - 2017-03-23 ### Changed - Allow FeatureRequester to be injected into the client. Thanks @abacaphiliac! @@ -51,4 +56,4 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. - The `toggle` call has been deprecated in favor of `variation`. ### Removed -- The `getFlag` function has been removed. \ No newline at end of file +- The `getFlag` function has been removed. diff --git a/VERSION b/VERSION index 7ec1d6db4..3e3c2f1e5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.0 +2.1.1 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 969297864..f85b602b9 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.1.0'; + const VERSION = '2.1.1'; /** @var string */ protected $_sdkKey; From f348c10e548de8ba60e35a680f8cb412d7094668 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Tue, 11 Apr 2017 13:40:03 -0700 Subject: [PATCH 103/150] Fix markdown in README --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 6ea969760..06ca1c622 100644 --- a/README.md +++ b/README.md @@ -92,19 +92,19 @@ About LaunchDarkly * Grant access to certain features based on user attributes, like payment plan (eg: users on the ‘gold’ plan get access to more features than users in the ‘silver’ plan). Disable parts of your application to facilitate maintenance, without taking everything offline. * LaunchDarkly provides feature flag SDKs for * [Java](http://docs.launchdarkly.com/docs/java-sdk-reference "Java SDK") - * [JavaScript] (http://docs.launchdarkly.com/docs/js-sdk-reference "LaunchDarkly JavaScript SDK") - * [PHP] (http://docs.launchdarkly.com/docs/php-sdk-reference "LaunchDarkly PHP SDK") - * [Python] (http://docs.launchdarkly.com/docs/python-sdk-reference "LaunchDarkly Python SDK") - * [Python Twisted] (http://docs.launchdarkly.com/docs/python-twisted-sdk-reference "LaunchDarkly Python Twisted SDK") - * [Go] (http://docs.launchdarkly.com/docs/go-sdk-reference "LaunchDarkly Go SDK") - * [Node.JS] (http://docs.launchdarkly.com/docs/node-sdk-reference "LaunchDarkly Node SDK") - * [.NET] (http://docs.launchdarkly.com/docs/dotnet-sdk-reference "LaunchDarkly .Net SDK") - * [Ruby] (http://docs.launchdarkly.com/docs/ruby-sdk-reference "LaunchDarkly Ruby SDK") - * [iOS] (http://docs.launchdarkly.com/docs/ios-sdk-reference "LaunchDarkly iOS SDK") - * [Android] (http://docs.launchdarkly.com/docs/android-sdk-reference "LaunchDarkly Android SDK") + * [JavaScript](http://docs.launchdarkly.com/docs/js-sdk-reference "LaunchDarkly JavaScript SDK") + * [PHP](http://docs.launchdarkly.com/docs/php-sdk-reference "LaunchDarkly PHP SDK") + * [Python](http://docs.launchdarkly.com/docs/python-sdk-reference "LaunchDarkly Python SDK") + * [Python Twisted](http://docs.launchdarkly.com/docs/python-twisted-sdk-reference "LaunchDarkly Python Twisted SDK") + * [Go](http://docs.launchdarkly.com/docs/go-sdk-reference "LaunchDarkly Go SDK") + * [Node.JS](http://docs.launchdarkly.com/docs/node-sdk-reference "LaunchDarkly Node SDK") + * [.NET](http://docs.launchdarkly.com/docs/dotnet-sdk-reference "LaunchDarkly .Net SDK") + * [Ruby](http://docs.launchdarkly.com/docs/ruby-sdk-reference "LaunchDarkly Ruby SDK") + * [iOS](http://docs.launchdarkly.com/docs/ios-sdk-reference "LaunchDarkly iOS SDK") + * [Android](http://docs.launchdarkly.com/docs/android-sdk-reference "LaunchDarkly Android SDK") * Explore LaunchDarkly - * [launchdarkly.com] (http://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information - * [docs.launchdarkly.com] (http://docs.launchdarkly.com/ "LaunchDarkly Documentation") for our documentation and SDKs - * [apidocs.launchdarkly.com] (http://apidocs.launchdarkly.com/ "LaunchDarkly API Documentation") for our API documentation - * [blog.launchdarkly.com] (http://blog.launchdarkly.com/ "LaunchDarkly Blog Documentation") for the latest product updates - * [Feature Flagging Guide] (https://github.com/launchdarkly/featureflags/ "Feature Flagging Guide") for best practices and strategies + * [launchdarkly.com](http://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information + * [docs.launchdarkly.com](http://docs.launchdarkly.com/ "LaunchDarkly Documentation") for our documentation and SDKs + * [apidocs.launchdarkly.com](http://apidocs.launchdarkly.com/ "LaunchDarkly API Documentation") for our API documentation + * [blog.launchdarkly.com](http://blog.launchdarkly.com/ "LaunchDarkly Blog Documentation") for the latest product updates + * [Feature Flagging Guide](https://github.com/launchdarkly/featureflags/ "Feature Flagging Guide") for best practices and strategies From 054304c55e6e88cf97509b0c83f544d6178c546e Mon Sep 17 00:00:00 2001 From: Idir Ouhab Meskine Date: Wed, 12 Apr 2017 10:58:21 +0200 Subject: [PATCH 104/150] Ensure that FeatureFlag _variations is non-null --- src/LaunchDarkly/FeatureFlag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index c59ca830f..871b797ed 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -63,7 +63,7 @@ public static function getDecoder() { array_map(Rule::getDecoder(), $v['rules'] ?: []), call_user_func(VariationOrRollout::getDecoder(), $v['fallthrough']), $v['offVariation'], - $v['variations'], + $v['variations'] ?: [], $v['deleted']); }; } From 920eae2ba5c0878cfbb03f842ca7d59a4ea6ab76 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Tue, 25 Apr 2017 16:43:30 -0700 Subject: [PATCH 105/150] =?UTF-8?q?Add=20dependency=20suggestions=20Don?= =?UTF-8?q?=E2=80=99t=20require=20kevinrob/guzzle-cache-middleware=20in=20?= =?UTF-8?q?GuzzleFeatureRequester?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 8 +- composer.lock | 522 +++++++++++--------- src/LaunchDarkly/GuzzleFeatureRequester.php | 19 +- 3 files changed, 313 insertions(+), 236 deletions(-) diff --git a/composer.json b/composer.json index 9293d011e..2ed48998a 100644 --- a/composer.json +++ b/composer.json @@ -26,10 +26,10 @@ "predis/predis": "^1.0", "zendframework/zend-serializer": "^2.7" }, - "suggested": { - "guzzlehttp/guzzle": "^6.2.1", - "kevinrob/guzzle-cache-middleware": "^1.4.1", - "predis/predis": "^1.0" + "suggest": { + "guzzlehttp/guzzle": "(^6.2.1) Required when using the default FeatureRequester", + "kevinrob/guzzle-cache-middleware": "(^1.4.1) Recommended for performance when using the default FeatureRequester", + "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 6796b4600..1e40df487 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fe2ef61776962bb0e97f4889c939534d", - "content-hash": "12982c87565739e6a9c652a75ee41de6", + "content-hash": "ad2c6c29c2c748655900711de6dba807", "packages": [ { "name": "monolog/monolog", - "version": "1.22.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", "shasum": "" }, "require": { @@ -83,7 +82,7 @@ "logging", "psr-3" ], - "time": "2016-11-26 00:15:39" + "time": "2017-03-13T07:08:03+00:00" }, { "name": "psr/log", @@ -130,7 +129,7 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2016-10-10T12:19:37+00:00" } ], "packages-dev": [ @@ -191,7 +190,7 @@ "cli", "microframework" ], - "time": "2014-03-29 14:03:13" + "time": "2014-03-29T14:03:13+00:00" }, { "name": "cilex/console-service-provider", @@ -250,22 +249,25 @@ "service-provider", "silex" ], - "time": "2012-12-19 10:50:58" + "time": "2012-12-19T10:50:58+00:00" }, { "name": "container-interop/container-interop", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/container-interop/container-interop.git", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", "shasum": "" }, + "require": { + "psr/container": "^1.0" + }, "type": "library", "autoload": { "psr-4": { @@ -277,20 +279,21 @@ "MIT" ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "time": "2014-12-30 15:22:37" + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" }, { "name": "doctrine/annotations", - "version": "v1.3.1", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558" + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/bd4461328621bde0ae6b1b2675fbc6aca4ceb558", - "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", "shasum": "" }, "require": { @@ -299,7 +302,7 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.6.1" + "phpunit/phpunit": "^5.7" }, "type": "library", "extra": { @@ -345,7 +348,7 @@ "docblock", "parser" ], - "time": "2016-12-30 15:59:45" + "time": "2017-02-24T16:22:25+00:00" }, { "name": "doctrine/instantiator", @@ -399,7 +402,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "doctrine/lexer", @@ -453,20 +456,20 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "erusev/parsedown", - "version": "1.6.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb" + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/20ff8bbb57205368b4b42d094642a3e52dac85fb", - "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01", + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01", "shasum": "" }, "require": { @@ -495,25 +498,25 @@ "markdown", "parser" ], - "time": "2016-11-02 15:56:58" + "time": "2017-03-29T16:04:15+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.2.2", + "version": "6.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", "shasum": "" }, "require": { "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.3.1", + "guzzlehttp/psr7": "^1.4", "php": ">=5.5" }, "require-dev": { @@ -557,7 +560,7 @@ "rest", "web service" ], - "time": "2016-10-08 15:01:37" + "time": "2017-02-28T22:50:30+00:00" }, { "name": "guzzlehttp/promises", @@ -608,20 +611,20 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.3.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -657,28 +660,35 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" } ], - "description": "PSR-7 message implementation", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "request", + "response", "stream", - "uri" + "uri", + "url" ], - "time": "2016-06-24 23:00:38" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "herrera-io/json", "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/php-json.git", + "url": "https://github.com/kherge-php/json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "url": "https://api.github.com/repos/kherge-php/json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, @@ -726,7 +736,8 @@ "schema", "validate" ], - "time": "2013-10-30 16:51:34" + "abandoned": "kherge/json", + "time": "2013-10-30T16:51:34+00:00" }, { "name": "herrera-io/phar-update", @@ -783,7 +794,8 @@ "phar", "update" ], - "time": "2013-10-30 17:23:01" + "abandoned": true, + "time": "2013-10-30T17:23:01+00:00" }, { "name": "jms/metadata", @@ -834,7 +846,7 @@ "xml", "yaml" ], - "time": "2016-12-05 10:18:33" + "time": "2016-12-05T10:18:33+00:00" }, { "name": "jms/parser-lib", @@ -869,20 +881,20 @@ "Apache2" ], "description": "A library for easily creating recursive-descent parsers.", - "time": "2012-11-18 18:08:43" + "time": "2012-11-18T18:08:43+00:00" }, { "name": "jms/serializer", - "version": "1.4.2", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b" + "reference": "b8683d206e7297f54034f67a877f966c14dc12ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f39d8b4660d5cef43b0c3265ce642173d9b2c58b", - "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/b8683d206e7297f54034f67a877f966c14dc12ea", + "reference": "b8683d206e7297f54034f67a877f966c14dc12ea", "shasum": "" }, "require": { @@ -895,6 +907,7 @@ "phpoption/phpoption": "^1.1" }, "conflict": { + "jms/serializer-bundle": "<1.2.1", "twig/twig": "<1.12" }, "require-dev": { @@ -904,20 +917,23 @@ "jackalope/jackalope-doctrine-dbal": "^1.1.5", "phpunit/phpunit": "^4.8|^5.0", "propel/propel1": "~1.7", + "symfony/expression-language": "^2.6|^3.0", "symfony/filesystem": "^2.1", - "symfony/form": "~2.1", - "symfony/translation": "^2.1", - "symfony/validator": "^2.2", - "symfony/yaml": "^2.1", + "symfony/form": "~2.1|^3.0", + "symfony/translation": "^2.1|^3.0", + "symfony/validator": "^2.2|^3.0", + "symfony/yaml": "^2.1|^3.0", "twig/twig": "~1.12|~2.0" }, "suggest": { + "doctrine/cache": "Required if you like to use cache functionality.", + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", "symfony/yaml": "Required if you'd like to serialize data to YAML format." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -944,7 +960,7 @@ "serialization", "xml" ], - "time": "2016-11-13 10:20:11" + "time": "2017-04-17T15:27:46+00:00" }, { "name": "justinrainbow/json-schema", @@ -1010,7 +1026,7 @@ "json", "schema" ], - "time": "2016-01-25 15:43:01" + "time": "2016-01-25T15:43:01+00:00" }, { "name": "kevinrob/guzzle-cache-middleware", @@ -1088,7 +1104,7 @@ "rfc7234", "validation" ], - "time": "2017-01-16 07:02:13" + "time": "2017-01-16T07:02:13+00:00" }, { "name": "kherge/version", @@ -1130,20 +1146,21 @@ ], "description": "A parsing and comparison library for semantic versioning.", "homepage": "http://github.com/kherge/Version", - "time": "2012-08-16 17:13:03" + "abandoned": true, + "time": "2012-08-16T17:13:03+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", "shasum": "" }, "require": { @@ -1172,7 +1189,7 @@ "object", "object graph" ], - "time": "2017-01-26 22:05:40" + "time": "2017-04-12T18:52:22+00:00" }, { "name": "nikic/php-parser", @@ -1217,7 +1234,7 @@ "parser", "php" ], - "time": "2015-09-19 14:15:08" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "phpcollection/phpcollection", @@ -1265,7 +1282,7 @@ "sequence", "set" ], - "time": "2015-05-17 12:39:23" + "time": "2015-05-17T12:39:23+00:00" }, { "name": "phpdocumentor/fileset", @@ -1308,7 +1325,7 @@ "fileset", "phpdoc" ], - "time": "2013-08-06 21:07:42" + "time": "2013-08-06T21:07:42+00:00" }, { "name": "phpdocumentor/graphviz", @@ -1349,7 +1366,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2016-02-02 13:00:08" + "time": "2016-02-02T13:00:08+00:00" }, { "name": "phpdocumentor/phpdocumentor", @@ -1438,7 +1455,7 @@ "documentation", "phpdoc" ], - "time": "2016-05-22 09:50:56" + "time": "2016-05-22T09:50:56+00:00" }, { "name": "phpdocumentor/reflection", @@ -1492,7 +1509,7 @@ "reflection", "static analysis" ], - "time": "2016-05-21 08:42:32" + "time": "2016-05-21T08:42:32+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -1541,7 +1558,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2015-02-03T12:10:50+00:00" }, { "name": "phpoption/phpoption", @@ -1591,31 +1608,31 @@ "php", "type" ], - "time": "2015-07-25 16:39:46" + "time": "2015-07-25T16:39:46+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -1654,7 +1671,7 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1717,7 +1734,7 @@ "testing", "xunit" ], - "time": "2016-05-27 16:24:29" + "time": "2016-05-27T16:24:29+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1764,7 +1781,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -1805,29 +1822,34 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1849,20 +1871,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -1898,7 +1920,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", @@ -1973,7 +1995,7 @@ "testing", "xunit" ], - "time": "2016-06-03 09:42:56" + "time": "2016-06-03T09:42:56+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -2029,7 +2051,7 @@ "mock", "xunit" ], - "time": "2016-04-20 14:39:26" + "time": "2016-04-20T14:39:26+00:00" }, { "name": "pimple/pimple", @@ -2075,24 +2097,24 @@ "container", "dependency injection" ], - "time": "2013-11-22 08:30:29" + "time": "2013-11-22T08:30:29+00:00" }, { "name": "predis/predis", - "version": "v1.0.4", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/nrk/predis.git", - "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f" + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/9ead747663bb1b1ae017dfa0d152aca87792b42f", - "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.9" }, "require-dev": { "phpunit/phpunit": "~4.8" @@ -2125,7 +2147,56 @@ "predis", "redis" ], - "time": "2016-05-30 15:25:52" + "time": "2016-06-16T16:22:20+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/http-message", @@ -2175,27 +2246,27 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -2220,7 +2291,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -2284,7 +2355,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -2336,7 +2407,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", @@ -2386,7 +2457,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -2453,7 +2524,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -2504,7 +2575,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -2550,20 +2621,20 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" + "time": "2016-01-28T13:25:10+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { @@ -2603,7 +2674,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/resource-operations", @@ -2645,7 +2716,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", @@ -2688,25 +2759,28 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "seld/jsonlint", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "19495c181d6d53a0a13414154e52817e3b504189" + "reference": "791f8c594f300d246cdf01c6b3e1e19611e301d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/19495c181d6d53a0a13414154e52817e3b504189", - "reference": "19495c181d6d53a0a13414154e52817e3b504189", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/791f8c594f300d246cdf01c6b3e1e19611e301d8", + "reference": "791f8c594f300d246cdf01c6b3e1e19611e301d8", "shasum": "" }, "require": { "php": "^5.3 || ^7.0" }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, "bin": [ "bin/jsonlint" ], @@ -2734,20 +2808,20 @@ "parser", "validator" ], - "time": "2016-11-14 17:59:58" + "time": "2017-03-06T16:42:24+00:00" }, { "name": "symfony/config", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c" + "reference": "35b7dfa089d7605eb1fdd46281b3070fb9f38750" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4537f2413348fe271c2c4b09da219ed615d79f9c", - "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c", + "url": "https://api.github.com/repos/symfony/config/zipball/35b7dfa089d7605eb1fdd46281b3070fb9f38750", + "reference": "35b7dfa089d7605eb1fdd46281b3070fb9f38750", "shasum": "" }, "require": { @@ -2790,25 +2864,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-04-04T15:24:26+00:00" }, { "name": "symfony/console", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912" + "reference": "86407ff20855a5eaa2a7219bd815e9c40a88633e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2e18b8903d9c498ba02e1dfa73f64d4894bb6912", - "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912", + "url": "https://api.github.com/repos/symfony/console/zipball/86407ff20855a5eaa2a7219bd815e9c40a88633e", + "reference": "86407ff20855a5eaa2a7219bd815e9c40a88633e", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/debug": "~2.7,>=2.7.2|~3.0.0", + "symfony/debug": "^2.7.2|~3.0.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -2851,7 +2925,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-01-08 20:43:03" + "time": "2017-04-03T20:37:06+00:00" }, { "name": "symfony/debug", @@ -2908,20 +2982,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:22:48" + "time": "2016-07-30T07:22:48+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34" + "reference": "88b65f0ac25355090e524aba4ceb066025df8bd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74877977f90fb9c3e46378d5764217c55f32df34", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/88b65f0ac25355090e524aba4ceb066025df8bd2", + "reference": "88b65f0ac25355090e524aba4ceb066025df8bd2", "shasum": "" }, "require": { @@ -2929,7 +3003,7 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/config": "^2.0.5|~3.0.0", "symfony/dependency-injection": "~2.6|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0" @@ -2968,7 +3042,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-04-03T20:37:06+00:00" }, { "name": "symfony/filesystem", @@ -3017,20 +3091,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-07-20 05:43:46" + "time": "2016-07-20T05:43:46+00:00" }, { "name": "symfony/finder", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b" + "reference": "7131327eb95d86d72039fd1216226c28f36fd02a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/355fccac526522dc5fca8ecf0e62749a149f3b8b", - "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b", + "url": "https://api.github.com/repos/symfony/finder/zipball/7131327eb95d86d72039fd1216226c28f36fd02a", + "reference": "7131327eb95d86d72039fd1216226c28f36fd02a", "shasum": "" }, "require": { @@ -3066,7 +3140,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-03-20T08:46:40+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3125,20 +3199,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/process", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231" + "reference": "41336b20b52f5fd5b42a227e394e673c8071118f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/ebb3c2abe0940a703f08e0cbe373f62d97d40231", - "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231", + "url": "https://api.github.com/repos/symfony/process/zipball/41336b20b52f5fd5b42a227e394e673c8071118f", + "reference": "41336b20b52f5fd5b42a227e394e673c8071118f", "shasum": "" }, "require": { @@ -3174,20 +3248,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-03-04T12:20:59+00:00" }, { "name": "symfony/stopwatch", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8" + "reference": "9e4369666d02ee9b8830da878b7f6a769eb96f4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e8bb9de52febc4ee9922b33b1f04ba5feed457b8", - "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/9e4369666d02ee9b8830da878b7f6a769eb96f4b", + "reference": "9e4369666d02ee9b8830da878b7f6a769eb96f4b", "shasum": "" }, "require": { @@ -3223,7 +3297,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-02-18T17:06:33+00:00" }, { "name": "symfony/translation", @@ -3287,20 +3361,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:22:48" + "time": "2016-07-30T07:22:48+00:00" }, { "name": "symfony/validator", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811" + "reference": "43f617ee200af4f4dedbb0782c6c689e06994286" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/3b1a3188efea75ec7c0419a2568b6e5f82031811", - "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811", + "url": "https://api.github.com/repos/symfony/validator/zipball/43f617ee200af4f4dedbb0782c6c689e06994286", + "reference": "43f617ee200af4f4dedbb0782c6c689e06994286", "shasum": "" }, "require": { @@ -3311,13 +3385,13 @@ "require-dev": { "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", - "egulias/email-validator": "~1.2,>=1.2.1", + "egulias/email-validator": "^1.2.1", "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/http-foundation": "~2.3|~3.0.0", - "symfony/intl": "~2.7.4|~2.8|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", "symfony/property-access": "~2.3|~3.0.0", - "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" + "symfony/yaml": "^2.0.5|~3.0.0" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", @@ -3360,20 +3434,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2017-01-12 19:24:25" + "time": "2017-03-23T16:08:03+00:00" }, { "name": "symfony/yaml", - "version": "v3.2.2", + "version": "v3.2.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "50eadbd7926e31842893c957eca362b21592a97d" + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/50eadbd7926e31842893c957eca362b21592a97d", - "reference": "50eadbd7926e31842893c957eca362b21592a97d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621", + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621", "shasum": "" }, "require": { @@ -3415,33 +3489,34 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-03 13:51:32" + "time": "2017-03-20T09:45:15+00:00" }, { "name": "twig/twig", - "version": "v1.31.0", + "version": "v1.33.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7" + "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddc9e3e20ee9c0b6908f401ac8353635b750eca7", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/dd6ca96227917e1e85b41c7c3cc6507b411e0927", + "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927", "shasum": "" }, "require": { "php": ">=5.2.7" }, "require-dev": { + "psr/container": "^1.0", "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.2" + "symfony/phpunit-bridge": "~3.3@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.31-dev" + "dev-master": "1.33-dev" } }, "autoload": { @@ -3476,7 +3551,7 @@ "keywords": [ "templating" ], - "time": "2017-01-11 19:36:15" + "time": "2017-04-20T17:39:48+00:00" }, { "name": "zendframework/zend-cache", @@ -3545,7 +3620,7 @@ "cache", "zf2" ], - "time": "2016-12-16 11:35:47" + "time": "2016-12-16T11:35:47+00:00" }, { "name": "zendframework/zend-config", @@ -3601,7 +3676,7 @@ "config", "zf2" ], - "time": "2016-02-04 23:01:10" + "time": "2016-02-04T23:01:10+00:00" }, { "name": "zendframework/zend-eventmanager", @@ -3655,7 +3730,7 @@ "events", "zf2" ], - "time": "2016-12-19 21:47:12" + "time": "2016-12-19T21:47:12+00:00" }, { "name": "zendframework/zend-filter", @@ -3715,7 +3790,7 @@ "filter", "zf2" ], - "time": "2016-04-18 18:32:43" + "time": "2016-04-18T18:32:43+00:00" }, { "name": "zendframework/zend-hydrator", @@ -3773,7 +3848,7 @@ "hydrator", "zf2" ], - "time": "2016-02-18 22:38:26" + "time": "2016-02-18T22:38:26+00:00" }, { "name": "zendframework/zend-i18n", @@ -3840,44 +3915,39 @@ "i18n", "zf2" ], - "time": "2016-06-07 21:08:30" + "time": "2016-06-07T21:08:30+00:00" }, { "name": "zendframework/zend-json", - "version": "2.6.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-http": "^2.5.4", - "zendframework/zend-server": "^2.6.1", - "zendframework/zend-stdlib": "^2.5 || ^3.0", - "zendframework/zendxml": "^1.0.2" + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "suggest": { - "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", - "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", - "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", - "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev", - "dev-develop": "2.7-dev" + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -3895,42 +3965,42 @@ "json", "zf2" ], - "time": "2016-02-04 21:20:26" + "time": "2016-04-01T02:34:00+00:00" }, { "name": "zendframework/zend-serializer", - "version": "2.7.2", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b" + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/95385c2342fc335d5164eb95ac3ca230aa51223b", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b", + "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/ff74ea020f5f90866eb28365327e9bc765a61a6e", + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "zendframework/zend-json": "^2.5", + "php": "^5.6 || ^7.0", + "zendframework/zend-json": "^2.5 || ^3.0", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "^4.5", + "squizlabs/php_codesniffer": "^2.3.1", "zendframework/zend-math": "^2.6", "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { - "zendframework/zend-math": "(^2.6) To support Python Pickle serialization", - "zendframework/zend-servicemanager": "To support plugin manager support" + "zendframework/zend-math": "(^2.6 || ^3.0) To support Python Pickle serialization", + "zendframework/zend-servicemanager": "(^2.7.5 || ^3.0.3) To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev", - "dev-develop": "2.8-dev" + "dev-master": "2.8-dev", + "dev-develop": "2.9-dev" }, "zf": { "component": "Zend\\Serializer", @@ -3952,7 +4022,7 @@ "serializer", "zf2" ], - "time": "2016-05-11 16:05:56" + "time": "2016-06-21T17:01:55+00:00" }, { "name": "zendframework/zend-servicemanager", @@ -4004,7 +4074,7 @@ "servicemanager", "zf2" ], - "time": "2016-12-19 19:14:29" + "time": "2016-12-19T19:14:29+00:00" }, { "name": "zendframework/zend-stdlib", @@ -4063,7 +4133,7 @@ "stdlib", "zf2" ], - "time": "2016-04-12 21:17:31" + "time": "2016-04-12T21:17:31+00:00" }, { "name": "zetacomponents/base", @@ -4126,7 +4196,7 @@ ], "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", "homepage": "https://github.com/zetacomponents", - "time": "2014-09-19 03:28:34" + "time": "2014-09-19T03:28:34+00:00" }, { "name": "zetacomponents/document", @@ -4177,7 +4247,7 @@ ], "description": "The Document components provides a general conversion framework for different semantic document markup languages like XHTML, Docbook, RST and similar.", "homepage": "https://github.com/zetacomponents", - "time": "2013-12-19 11:40:00" + "time": "2013-12-19T11:40:00+00:00" } ], "aliases": [], diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index c1cc7b419..af3e006df 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -17,14 +17,22 @@ class GuzzleFeatureRequester implements FeatureRequester private $_baseUri; /** @var array */ private $_defaults; - /** @var LoggerInterface */ + /** @var LoggerInterface */ private $_logger; + /** @var boolean */ + private $_loggedCacheNotice = FALSE; function __construct($baseUri, $sdkKey, $options) { $this->_baseUri = $baseUri; + $this->_logger = $options['logger']; $stack = HandlerStack::create(); - $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); + if (class_exists('Kevinrob\GuzzleCache\CacheMiddleware')) { + $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); + } else if (!$this->_loggedCacheNotice) { + $this->_logger->info("GuzzleFeatureRequester is not using an HTTP cache because Kevinrob\GuzzleCache\CacheMiddleware was not installed"); + $this->_loggedCacheNotice = TRUE; + } $this->_defaults = array( 'headers' => array( @@ -35,7 +43,6 @@ function __construct($baseUri, $sdkKey, $options) 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ); - $this->_logger = $options['logger']; $this->_client = new Client(['handler' => $stack, 'debug' => false]); } @@ -56,9 +63,9 @@ public function get($key) } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); if ($code == 404) { - $this->_logger->warning("GuzzleFeatureRetriever::get returned 404. Feature flag does not exist for key: " . $key); + $this->_logger->warning("GuzzleFeatureRequester::get returned 404. Feature flag does not exist for key: " . $key); } else { - $this->_logger->error("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); + $this->_logger->error("GuzzleFeatureRequester::get received an unexpected HTTP status code $code"); } return null; } @@ -77,7 +84,7 @@ public function getAll() { return array_map(FeatureFlag::getDecoder(), json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); - $this->_logger->error("GuzzleFeatureRetriever::getAll received an unexpected HTTP status code $code"); + $this->_logger->error("GuzzleFeatureRequester::getAll received an unexpected HTTP status code $code"); return null; } } From 5f2f74c0a68495b4115ce19aa6e33780e307c481 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Tue, 25 Apr 2017 17:17:17 -0700 Subject: [PATCH 106/150] Update README to use ld-relay --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06ca1c622..d01dde878 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Using Redis 2. Create the LDClient with the Redis feature requester as an option: - $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester']); + $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', 'redis_host' => 'your.redis.host', 'redis_port' => 6379]); Testing ------- From ea88b72a1da9d182a3680c7ed5178fccc1a7eed3 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 27 Apr 2017 11:29:45 -0700 Subject: [PATCH 107/150] Add dependency suggestions (#78) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t require kevinrob/guzzle-cache-middleware in GuzzleFeatureRequester --- composer.json | 8 +- composer.lock | 522 +++++++++++--------- src/LaunchDarkly/GuzzleFeatureRequester.php | 19 +- 3 files changed, 313 insertions(+), 236 deletions(-) diff --git a/composer.json b/composer.json index 9293d011e..2ed48998a 100644 --- a/composer.json +++ b/composer.json @@ -26,10 +26,10 @@ "predis/predis": "^1.0", "zendframework/zend-serializer": "^2.7" }, - "suggested": { - "guzzlehttp/guzzle": "^6.2.1", - "kevinrob/guzzle-cache-middleware": "^1.4.1", - "predis/predis": "^1.0" + "suggest": { + "guzzlehttp/guzzle": "(^6.2.1) Required when using the default FeatureRequester", + "kevinrob/guzzle-cache-middleware": "(^1.4.1) Recommended for performance when using the default FeatureRequester", + "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 6796b4600..1e40df487 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fe2ef61776962bb0e97f4889c939534d", - "content-hash": "12982c87565739e6a9c652a75ee41de6", + "content-hash": "ad2c6c29c2c748655900711de6dba807", "packages": [ { "name": "monolog/monolog", - "version": "1.22.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", "shasum": "" }, "require": { @@ -83,7 +82,7 @@ "logging", "psr-3" ], - "time": "2016-11-26 00:15:39" + "time": "2017-03-13T07:08:03+00:00" }, { "name": "psr/log", @@ -130,7 +129,7 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2016-10-10T12:19:37+00:00" } ], "packages-dev": [ @@ -191,7 +190,7 @@ "cli", "microframework" ], - "time": "2014-03-29 14:03:13" + "time": "2014-03-29T14:03:13+00:00" }, { "name": "cilex/console-service-provider", @@ -250,22 +249,25 @@ "service-provider", "silex" ], - "time": "2012-12-19 10:50:58" + "time": "2012-12-19T10:50:58+00:00" }, { "name": "container-interop/container-interop", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/container-interop/container-interop.git", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", "shasum": "" }, + "require": { + "psr/container": "^1.0" + }, "type": "library", "autoload": { "psr-4": { @@ -277,20 +279,21 @@ "MIT" ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "time": "2014-12-30 15:22:37" + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" }, { "name": "doctrine/annotations", - "version": "v1.3.1", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558" + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/bd4461328621bde0ae6b1b2675fbc6aca4ceb558", - "reference": "bd4461328621bde0ae6b1b2675fbc6aca4ceb558", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", "shasum": "" }, "require": { @@ -299,7 +302,7 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.6.1" + "phpunit/phpunit": "^5.7" }, "type": "library", "extra": { @@ -345,7 +348,7 @@ "docblock", "parser" ], - "time": "2016-12-30 15:59:45" + "time": "2017-02-24T16:22:25+00:00" }, { "name": "doctrine/instantiator", @@ -399,7 +402,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "doctrine/lexer", @@ -453,20 +456,20 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "erusev/parsedown", - "version": "1.6.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb" + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/20ff8bbb57205368b4b42d094642a3e52dac85fb", - "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01", + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01", "shasum": "" }, "require": { @@ -495,25 +498,25 @@ "markdown", "parser" ], - "time": "2016-11-02 15:56:58" + "time": "2017-03-29T16:04:15+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.2.2", + "version": "6.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", "shasum": "" }, "require": { "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.3.1", + "guzzlehttp/psr7": "^1.4", "php": ">=5.5" }, "require-dev": { @@ -557,7 +560,7 @@ "rest", "web service" ], - "time": "2016-10-08 15:01:37" + "time": "2017-02-28T22:50:30+00:00" }, { "name": "guzzlehttp/promises", @@ -608,20 +611,20 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.3.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -657,28 +660,35 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" } ], - "description": "PSR-7 message implementation", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "request", + "response", "stream", - "uri" + "uri", + "url" ], - "time": "2016-06-24 23:00:38" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "herrera-io/json", "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/php-json.git", + "url": "https://github.com/kherge-php/json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "url": "https://api.github.com/repos/kherge-php/json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, @@ -726,7 +736,8 @@ "schema", "validate" ], - "time": "2013-10-30 16:51:34" + "abandoned": "kherge/json", + "time": "2013-10-30T16:51:34+00:00" }, { "name": "herrera-io/phar-update", @@ -783,7 +794,8 @@ "phar", "update" ], - "time": "2013-10-30 17:23:01" + "abandoned": true, + "time": "2013-10-30T17:23:01+00:00" }, { "name": "jms/metadata", @@ -834,7 +846,7 @@ "xml", "yaml" ], - "time": "2016-12-05 10:18:33" + "time": "2016-12-05T10:18:33+00:00" }, { "name": "jms/parser-lib", @@ -869,20 +881,20 @@ "Apache2" ], "description": "A library for easily creating recursive-descent parsers.", - "time": "2012-11-18 18:08:43" + "time": "2012-11-18T18:08:43+00:00" }, { "name": "jms/serializer", - "version": "1.4.2", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b" + "reference": "b8683d206e7297f54034f67a877f966c14dc12ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f39d8b4660d5cef43b0c3265ce642173d9b2c58b", - "reference": "f39d8b4660d5cef43b0c3265ce642173d9b2c58b", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/b8683d206e7297f54034f67a877f966c14dc12ea", + "reference": "b8683d206e7297f54034f67a877f966c14dc12ea", "shasum": "" }, "require": { @@ -895,6 +907,7 @@ "phpoption/phpoption": "^1.1" }, "conflict": { + "jms/serializer-bundle": "<1.2.1", "twig/twig": "<1.12" }, "require-dev": { @@ -904,20 +917,23 @@ "jackalope/jackalope-doctrine-dbal": "^1.1.5", "phpunit/phpunit": "^4.8|^5.0", "propel/propel1": "~1.7", + "symfony/expression-language": "^2.6|^3.0", "symfony/filesystem": "^2.1", - "symfony/form": "~2.1", - "symfony/translation": "^2.1", - "symfony/validator": "^2.2", - "symfony/yaml": "^2.1", + "symfony/form": "~2.1|^3.0", + "symfony/translation": "^2.1|^3.0", + "symfony/validator": "^2.2|^3.0", + "symfony/yaml": "^2.1|^3.0", "twig/twig": "~1.12|~2.0" }, "suggest": { + "doctrine/cache": "Required if you like to use cache functionality.", + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", "symfony/yaml": "Required if you'd like to serialize data to YAML format." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -944,7 +960,7 @@ "serialization", "xml" ], - "time": "2016-11-13 10:20:11" + "time": "2017-04-17T15:27:46+00:00" }, { "name": "justinrainbow/json-schema", @@ -1010,7 +1026,7 @@ "json", "schema" ], - "time": "2016-01-25 15:43:01" + "time": "2016-01-25T15:43:01+00:00" }, { "name": "kevinrob/guzzle-cache-middleware", @@ -1088,7 +1104,7 @@ "rfc7234", "validation" ], - "time": "2017-01-16 07:02:13" + "time": "2017-01-16T07:02:13+00:00" }, { "name": "kherge/version", @@ -1130,20 +1146,21 @@ ], "description": "A parsing and comparison library for semantic versioning.", "homepage": "http://github.com/kherge/Version", - "time": "2012-08-16 17:13:03" + "abandoned": true, + "time": "2012-08-16T17:13:03+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", "shasum": "" }, "require": { @@ -1172,7 +1189,7 @@ "object", "object graph" ], - "time": "2017-01-26 22:05:40" + "time": "2017-04-12T18:52:22+00:00" }, { "name": "nikic/php-parser", @@ -1217,7 +1234,7 @@ "parser", "php" ], - "time": "2015-09-19 14:15:08" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "phpcollection/phpcollection", @@ -1265,7 +1282,7 @@ "sequence", "set" ], - "time": "2015-05-17 12:39:23" + "time": "2015-05-17T12:39:23+00:00" }, { "name": "phpdocumentor/fileset", @@ -1308,7 +1325,7 @@ "fileset", "phpdoc" ], - "time": "2013-08-06 21:07:42" + "time": "2013-08-06T21:07:42+00:00" }, { "name": "phpdocumentor/graphviz", @@ -1349,7 +1366,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2016-02-02 13:00:08" + "time": "2016-02-02T13:00:08+00:00" }, { "name": "phpdocumentor/phpdocumentor", @@ -1438,7 +1455,7 @@ "documentation", "phpdoc" ], - "time": "2016-05-22 09:50:56" + "time": "2016-05-22T09:50:56+00:00" }, { "name": "phpdocumentor/reflection", @@ -1492,7 +1509,7 @@ "reflection", "static analysis" ], - "time": "2016-05-21 08:42:32" + "time": "2016-05-21T08:42:32+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -1541,7 +1558,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2015-02-03T12:10:50+00:00" }, { "name": "phpoption/phpoption", @@ -1591,31 +1608,31 @@ "php", "type" ], - "time": "2015-07-25 16:39:46" + "time": "2015-07-25T16:39:46+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -1654,7 +1671,7 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1717,7 +1734,7 @@ "testing", "xunit" ], - "time": "2016-05-27 16:24:29" + "time": "2016-05-27T16:24:29+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1764,7 +1781,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -1805,29 +1822,34 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1849,20 +1871,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -1898,7 +1920,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", @@ -1973,7 +1995,7 @@ "testing", "xunit" ], - "time": "2016-06-03 09:42:56" + "time": "2016-06-03T09:42:56+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -2029,7 +2051,7 @@ "mock", "xunit" ], - "time": "2016-04-20 14:39:26" + "time": "2016-04-20T14:39:26+00:00" }, { "name": "pimple/pimple", @@ -2075,24 +2097,24 @@ "container", "dependency injection" ], - "time": "2013-11-22 08:30:29" + "time": "2013-11-22T08:30:29+00:00" }, { "name": "predis/predis", - "version": "v1.0.4", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/nrk/predis.git", - "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f" + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/9ead747663bb1b1ae017dfa0d152aca87792b42f", - "reference": "9ead747663bb1b1ae017dfa0d152aca87792b42f", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.9" }, "require-dev": { "phpunit/phpunit": "~4.8" @@ -2125,7 +2147,56 @@ "predis", "redis" ], - "time": "2016-05-30 15:25:52" + "time": "2016-06-16T16:22:20+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/http-message", @@ -2175,27 +2246,27 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -2220,7 +2291,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -2284,7 +2355,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -2336,7 +2407,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", @@ -2386,7 +2457,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -2453,7 +2524,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -2504,7 +2575,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -2550,20 +2621,20 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" + "time": "2016-01-28T13:25:10+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { @@ -2603,7 +2674,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/resource-operations", @@ -2645,7 +2716,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", @@ -2688,25 +2759,28 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "seld/jsonlint", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "19495c181d6d53a0a13414154e52817e3b504189" + "reference": "791f8c594f300d246cdf01c6b3e1e19611e301d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/19495c181d6d53a0a13414154e52817e3b504189", - "reference": "19495c181d6d53a0a13414154e52817e3b504189", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/791f8c594f300d246cdf01c6b3e1e19611e301d8", + "reference": "791f8c594f300d246cdf01c6b3e1e19611e301d8", "shasum": "" }, "require": { "php": "^5.3 || ^7.0" }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, "bin": [ "bin/jsonlint" ], @@ -2734,20 +2808,20 @@ "parser", "validator" ], - "time": "2016-11-14 17:59:58" + "time": "2017-03-06T16:42:24+00:00" }, { "name": "symfony/config", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c" + "reference": "35b7dfa089d7605eb1fdd46281b3070fb9f38750" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4537f2413348fe271c2c4b09da219ed615d79f9c", - "reference": "4537f2413348fe271c2c4b09da219ed615d79f9c", + "url": "https://api.github.com/repos/symfony/config/zipball/35b7dfa089d7605eb1fdd46281b3070fb9f38750", + "reference": "35b7dfa089d7605eb1fdd46281b3070fb9f38750", "shasum": "" }, "require": { @@ -2790,25 +2864,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-04-04T15:24:26+00:00" }, { "name": "symfony/console", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912" + "reference": "86407ff20855a5eaa2a7219bd815e9c40a88633e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2e18b8903d9c498ba02e1dfa73f64d4894bb6912", - "reference": "2e18b8903d9c498ba02e1dfa73f64d4894bb6912", + "url": "https://api.github.com/repos/symfony/console/zipball/86407ff20855a5eaa2a7219bd815e9c40a88633e", + "reference": "86407ff20855a5eaa2a7219bd815e9c40a88633e", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/debug": "~2.7,>=2.7.2|~3.0.0", + "symfony/debug": "^2.7.2|~3.0.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -2851,7 +2925,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-01-08 20:43:03" + "time": "2017-04-03T20:37:06+00:00" }, { "name": "symfony/debug", @@ -2908,20 +2982,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:22:48" + "time": "2016-07-30T07:22:48+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34" + "reference": "88b65f0ac25355090e524aba4ceb066025df8bd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74877977f90fb9c3e46378d5764217c55f32df34", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/88b65f0ac25355090e524aba4ceb066025df8bd2", + "reference": "88b65f0ac25355090e524aba4ceb066025df8bd2", "shasum": "" }, "require": { @@ -2929,7 +3003,7 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/config": "^2.0.5|~3.0.0", "symfony/dependency-injection": "~2.6|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0" @@ -2968,7 +3042,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-04-03T20:37:06+00:00" }, { "name": "symfony/filesystem", @@ -3017,20 +3091,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-07-20 05:43:46" + "time": "2016-07-20T05:43:46+00:00" }, { "name": "symfony/finder", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b" + "reference": "7131327eb95d86d72039fd1216226c28f36fd02a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/355fccac526522dc5fca8ecf0e62749a149f3b8b", - "reference": "355fccac526522dc5fca8ecf0e62749a149f3b8b", + "url": "https://api.github.com/repos/symfony/finder/zipball/7131327eb95d86d72039fd1216226c28f36fd02a", + "reference": "7131327eb95d86d72039fd1216226c28f36fd02a", "shasum": "" }, "require": { @@ -3066,7 +3140,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-03-20T08:46:40+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3125,20 +3199,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/process", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231" + "reference": "41336b20b52f5fd5b42a227e394e673c8071118f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/ebb3c2abe0940a703f08e0cbe373f62d97d40231", - "reference": "ebb3c2abe0940a703f08e0cbe373f62d97d40231", + "url": "https://api.github.com/repos/symfony/process/zipball/41336b20b52f5fd5b42a227e394e673c8071118f", + "reference": "41336b20b52f5fd5b42a227e394e673c8071118f", "shasum": "" }, "require": { @@ -3174,20 +3248,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-03-04T12:20:59+00:00" }, { "name": "symfony/stopwatch", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8" + "reference": "9e4369666d02ee9b8830da878b7f6a769eb96f4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e8bb9de52febc4ee9922b33b1f04ba5feed457b8", - "reference": "e8bb9de52febc4ee9922b33b1f04ba5feed457b8", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/9e4369666d02ee9b8830da878b7f6a769eb96f4b", + "reference": "9e4369666d02ee9b8830da878b7f6a769eb96f4b", "shasum": "" }, "require": { @@ -3223,7 +3297,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:30:24" + "time": "2017-02-18T17:06:33+00:00" }, { "name": "symfony/translation", @@ -3287,20 +3361,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:22:48" + "time": "2016-07-30T07:22:48+00:00" }, { "name": "symfony/validator", - "version": "v2.8.16", + "version": "v2.8.19", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811" + "reference": "43f617ee200af4f4dedbb0782c6c689e06994286" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/3b1a3188efea75ec7c0419a2568b6e5f82031811", - "reference": "3b1a3188efea75ec7c0419a2568b6e5f82031811", + "url": "https://api.github.com/repos/symfony/validator/zipball/43f617ee200af4f4dedbb0782c6c689e06994286", + "reference": "43f617ee200af4f4dedbb0782c6c689e06994286", "shasum": "" }, "require": { @@ -3311,13 +3385,13 @@ "require-dev": { "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", - "egulias/email-validator": "~1.2,>=1.2.1", + "egulias/email-validator": "^1.2.1", "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/http-foundation": "~2.3|~3.0.0", - "symfony/intl": "~2.7.4|~2.8|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", "symfony/property-access": "~2.3|~3.0.0", - "symfony/yaml": "~2.0,>=2.0.5|~3.0.0" + "symfony/yaml": "^2.0.5|~3.0.0" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", @@ -3360,20 +3434,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2017-01-12 19:24:25" + "time": "2017-03-23T16:08:03+00:00" }, { "name": "symfony/yaml", - "version": "v3.2.2", + "version": "v3.2.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "50eadbd7926e31842893c957eca362b21592a97d" + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/50eadbd7926e31842893c957eca362b21592a97d", - "reference": "50eadbd7926e31842893c957eca362b21592a97d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621", + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621", "shasum": "" }, "require": { @@ -3415,33 +3489,34 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-03 13:51:32" + "time": "2017-03-20T09:45:15+00:00" }, { "name": "twig/twig", - "version": "v1.31.0", + "version": "v1.33.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7" + "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddc9e3e20ee9c0b6908f401ac8353635b750eca7", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/dd6ca96227917e1e85b41c7c3cc6507b411e0927", + "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927", "shasum": "" }, "require": { "php": ">=5.2.7" }, "require-dev": { + "psr/container": "^1.0", "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.2" + "symfony/phpunit-bridge": "~3.3@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.31-dev" + "dev-master": "1.33-dev" } }, "autoload": { @@ -3476,7 +3551,7 @@ "keywords": [ "templating" ], - "time": "2017-01-11 19:36:15" + "time": "2017-04-20T17:39:48+00:00" }, { "name": "zendframework/zend-cache", @@ -3545,7 +3620,7 @@ "cache", "zf2" ], - "time": "2016-12-16 11:35:47" + "time": "2016-12-16T11:35:47+00:00" }, { "name": "zendframework/zend-config", @@ -3601,7 +3676,7 @@ "config", "zf2" ], - "time": "2016-02-04 23:01:10" + "time": "2016-02-04T23:01:10+00:00" }, { "name": "zendframework/zend-eventmanager", @@ -3655,7 +3730,7 @@ "events", "zf2" ], - "time": "2016-12-19 21:47:12" + "time": "2016-12-19T21:47:12+00:00" }, { "name": "zendframework/zend-filter", @@ -3715,7 +3790,7 @@ "filter", "zf2" ], - "time": "2016-04-18 18:32:43" + "time": "2016-04-18T18:32:43+00:00" }, { "name": "zendframework/zend-hydrator", @@ -3773,7 +3848,7 @@ "hydrator", "zf2" ], - "time": "2016-02-18 22:38:26" + "time": "2016-02-18T22:38:26+00:00" }, { "name": "zendframework/zend-i18n", @@ -3840,44 +3915,39 @@ "i18n", "zf2" ], - "time": "2016-06-07 21:08:30" + "time": "2016-06-07T21:08:30+00:00" }, { "name": "zendframework/zend-json", - "version": "2.6.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-http": "^2.5.4", - "zendframework/zend-server": "^2.6.1", - "zendframework/zend-stdlib": "^2.5 || ^3.0", - "zendframework/zendxml": "^1.0.2" + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "suggest": { - "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", - "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", - "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", - "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev", - "dev-develop": "2.7-dev" + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -3895,42 +3965,42 @@ "json", "zf2" ], - "time": "2016-02-04 21:20:26" + "time": "2016-04-01T02:34:00+00:00" }, { "name": "zendframework/zend-serializer", - "version": "2.7.2", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b" + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/95385c2342fc335d5164eb95ac3ca230aa51223b", - "reference": "95385c2342fc335d5164eb95ac3ca230aa51223b", + "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/ff74ea020f5f90866eb28365327e9bc765a61a6e", + "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "zendframework/zend-json": "^2.5", + "php": "^5.6 || ^7.0", + "zendframework/zend-json": "^2.5 || ^3.0", "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "^4.5", + "squizlabs/php_codesniffer": "^2.3.1", "zendframework/zend-math": "^2.6", "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" }, "suggest": { - "zendframework/zend-math": "(^2.6) To support Python Pickle serialization", - "zendframework/zend-servicemanager": "To support plugin manager support" + "zendframework/zend-math": "(^2.6 || ^3.0) To support Python Pickle serialization", + "zendframework/zend-servicemanager": "(^2.7.5 || ^3.0.3) To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev", - "dev-develop": "2.8-dev" + "dev-master": "2.8-dev", + "dev-develop": "2.9-dev" }, "zf": { "component": "Zend\\Serializer", @@ -3952,7 +4022,7 @@ "serializer", "zf2" ], - "time": "2016-05-11 16:05:56" + "time": "2016-06-21T17:01:55+00:00" }, { "name": "zendframework/zend-servicemanager", @@ -4004,7 +4074,7 @@ "servicemanager", "zf2" ], - "time": "2016-12-19 19:14:29" + "time": "2016-12-19T19:14:29+00:00" }, { "name": "zendframework/zend-stdlib", @@ -4063,7 +4133,7 @@ "stdlib", "zf2" ], - "time": "2016-04-12 21:17:31" + "time": "2016-04-12T21:17:31+00:00" }, { "name": "zetacomponents/base", @@ -4126,7 +4196,7 @@ ], "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", "homepage": "https://github.com/zetacomponents", - "time": "2014-09-19 03:28:34" + "time": "2014-09-19T03:28:34+00:00" }, { "name": "zetacomponents/document", @@ -4177,7 +4247,7 @@ ], "description": "The Document components provides a general conversion framework for different semantic document markup languages like XHTML, Docbook, RST and similar.", "homepage": "https://github.com/zetacomponents", - "time": "2013-12-19 11:40:00" + "time": "2013-12-19T11:40:00+00:00" } ], "aliases": [], diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index c1cc7b419..af3e006df 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -17,14 +17,22 @@ class GuzzleFeatureRequester implements FeatureRequester private $_baseUri; /** @var array */ private $_defaults; - /** @var LoggerInterface */ + /** @var LoggerInterface */ private $_logger; + /** @var boolean */ + private $_loggedCacheNotice = FALSE; function __construct($baseUri, $sdkKey, $options) { $this->_baseUri = $baseUri; + $this->_logger = $options['logger']; $stack = HandlerStack::create(); - $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); + if (class_exists('Kevinrob\GuzzleCache\CacheMiddleware')) { + $stack->push(new CacheMiddleware(new PublicCacheStrategy(isset($options['cache']) ? $options['cache'] : null), 'cache')); + } else if (!$this->_loggedCacheNotice) { + $this->_logger->info("GuzzleFeatureRequester is not using an HTTP cache because Kevinrob\GuzzleCache\CacheMiddleware was not installed"); + $this->_loggedCacheNotice = TRUE; + } $this->_defaults = array( 'headers' => array( @@ -35,7 +43,6 @@ function __construct($baseUri, $sdkKey, $options) 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ); - $this->_logger = $options['logger']; $this->_client = new Client(['handler' => $stack, 'debug' => false]); } @@ -56,9 +63,9 @@ public function get($key) } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); if ($code == 404) { - $this->_logger->warning("GuzzleFeatureRetriever::get returned 404. Feature flag does not exist for key: " . $key); + $this->_logger->warning("GuzzleFeatureRequester::get returned 404. Feature flag does not exist for key: " . $key); } else { - $this->_logger->error("GuzzleFeatureRetriever::get received an unexpected HTTP status code $code"); + $this->_logger->error("GuzzleFeatureRequester::get received an unexpected HTTP status code $code"); } return null; } @@ -77,7 +84,7 @@ public function getAll() { return array_map(FeatureFlag::getDecoder(), json_decode($body, true)); } catch (BadResponseException $e) { $code = $e->getResponse()->getStatusCode(); - $this->_logger->error("GuzzleFeatureRetriever::getAll received an unexpected HTTP status code $code"); + $this->_logger->error("GuzzleFeatureRequester::getAll received an unexpected HTTP status code $code"); return null; } } From b0b75f087624582cf0477cdc799a1c027c697b6c Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 27 Apr 2017 11:43:59 -0700 Subject: [PATCH 108/150] Release version 2.1.2 --- CHANGELOG.md | 8 ++++++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a426cd1..dd9beb412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.1.2] - 2017-04-27 +### Changed +- Relaxed the requirement on `kevinrob/guzzle-cache-middleware` for the default `GuzzleFeatureRequester`. +- Added package suggestions in `composer.json`. + +### Fixed +- Better handling of possibly null variations. Thanks @idirouhab! + ## [2.1.1] - 2017-04-11 ### Changed - Better handling of possibly null targets. Thanks @idirouhab! diff --git a/VERSION b/VERSION index 3e3c2f1e5..eca07e4c1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.1 +2.1.2 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index f85b602b9..a10031a6c 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,7 +10,7 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.1.1'; + const VERSION = '2.1.2'; /** @var string */ protected $_sdkKey; From 67fc7611f30589f9f4c9d32210f20d2b8616e065 Mon Sep 17 00:00:00 2001 From: Tim Younger Date: Fri, 12 May 2017 16:48:14 -0700 Subject: [PATCH 109/150] allow curl to be overridden. --- src/LaunchDarkly/EventProcessor.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index 4e2c2ea12..cfa74043e 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -13,6 +13,7 @@ class EventProcessor { private $_host; private $_port; private $_ssl; + private $_curl = '/usr/bin/env curl'; public function __construct($apiKey, $options = array()) { $this->_sdkKey = $apiKey; @@ -39,6 +40,10 @@ public function __construct($apiKey, $options = array()) { $this->_path = ''; } } + + if (array_key_exists('curl', $options)) { + $this->_curl = $options['curl']; + } $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; @@ -89,7 +94,7 @@ private function createArgs($payload) { } private function makeRequest($args) { - $cmd = "/usr/bin/env curl " . $args . ">> /dev/null 2>&1 &"; + $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; shell_exec($cmd); return true; } From bcfa71a167fff8f372d705c9c40318e3970253c9 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 16 May 2017 14:49:26 -0700 Subject: [PATCH 110/150] clarifying ld-relay usage --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d01dde878..0fd7d4f0d 100644 --- a/README.md +++ b/README.md @@ -41,29 +41,31 @@ Your first feature flag Fetching flags -------------- -There are two approaches to fetching the flag rules from LaunchDarkly: +There are two approaches to fetching and caching flag rules from LaunchDarkly with the PHP SDK: -* Making HTTP requests (using Guzzle) -* Setting up the [ld-relay](https://github.com/launchdarkly/ld-relay) to store the flags in Redis +* [Guzzle Cache Middleware](https://github.com/Kevinrob/guzzle-cache-middleware) to cache HTTP responses in an in-memory array (default) +* [ld-relay](https://github.com/launchdarkly/ld-relay) to retrieve and store flags in Redis Using Guzzle ============ -To use Guzzle it must be required as a dependency: +Require Guzzle as a dependency: php composer.phar require "guzzlehttp/guzzle:6.2.1" php composer.phar require "kevinrob/guzzle-cache-middleware:1.4.1" It will then be used as the default way of fetching flags. -Using Redis -=========== +Using LD-Relay +============== -1. Require Predis as a dependency: +* Setup [ld-relay](https://github.com/launchdarkly/ld-relay) in [daemon-mode](https://github.com/launchdarkly/ld-relay#redis-storage-and-daemon-mode) with Redis + +* Require Predis as a dependency: php composer.phar require "predis/predis:1.0.*" -2. Create the LDClient with the Redis feature requester as an option: +* Create the LDClient with the Redis feature requester as an option: $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', 'redis_host' => 'your.redis.host', 'redis_port' => 6379]); From aa0035ccebb9e293d1557ccc50c84696c5b27b1a Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 16 May 2017 14:52:08 -0700 Subject: [PATCH 111/150] clarify role of guzzle --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fd7d4f0d..9d3316920 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Fetching flags There are two approaches to fetching and caching flag rules from LaunchDarkly with the PHP SDK: -* [Guzzle Cache Middleware](https://github.com/Kevinrob/guzzle-cache-middleware) to cache HTTP responses in an in-memory array (default) +* [Guzzle Cache Middleware](https://github.com/Kevinrob/guzzle-cache-middleware) to request and cache HTTP responses in an in-memory array (default) * [ld-relay](https://github.com/launchdarkly/ld-relay) to retrieve and store flags in Redis Using Guzzle From c8995d0d1fba7674411447744e51268df64fa275 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 16 May 2017 15:02:19 -0700 Subject: [PATCH 112/150] recommending relay --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d3316920..2ee28e500 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,12 @@ Your first feature flag Fetching flags -------------- -There are two approaches to fetching and caching flag rules from LaunchDarkly with the PHP SDK: +There are two distinct methods of integrating LaunchDarkly in a PHP environment. * [Guzzle Cache Middleware](https://github.com/Kevinrob/guzzle-cache-middleware) to request and cache HTTP responses in an in-memory array (default) -* [ld-relay](https://github.com/launchdarkly/ld-relay) to retrieve and store flags in Redis +* [ld-relay](https://github.com/launchdarkly/ld-relay) to retrieve and store flags in Redis (recommended) + +We strongly recommend using the ld-relay. Per-flag caching (Guzzle method) is only intended for low-throughput environments. Using Guzzle ============ From 90e6bad633c7e77922fa811181766c76d3f276b3 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 16 May 2017 17:18:04 -0700 Subject: [PATCH 113/150] persistence with cache middleware --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2ee28e500..db889dd62 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,11 @@ Require Guzzle as a dependency: It will then be used as the default way of fetching flags. +With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L42). + + $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", array("cache" => $cacheStorage)); + + Using LD-Relay ============== From c1fca88fc3f5be20218d92922add07726161458b Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 25 May 2017 02:34:42 -0700 Subject: [PATCH 114/150] [CH3370] Support publishing events via ld-relay --- composer.json | 2 +- src/LaunchDarkly/CurlEventPublisher.php | 63 ++++++++++++++++++++ src/LaunchDarkly/EventProcessor.php | 76 +++++++----------------- src/LaunchDarkly/EventPublisher.php | 18 ++++++ src/LaunchDarkly/LDClient.php | 21 +++++-- src/LaunchDarkly/RelayEventPublisher.php | 52 ++++++++++++++++ 6 files changed, 173 insertions(+), 59 deletions(-) create mode 100644 src/LaunchDarkly/CurlEventPublisher.php create mode 100644 src/LaunchDarkly/EventPublisher.php create mode 100644 src/LaunchDarkly/RelayEventPublisher.php diff --git a/composer.json b/composer.json index 2ed48998a..8f18b4c7b 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "zendframework/zend-serializer": "^2.7" }, "suggest": { - "guzzlehttp/guzzle": "(^6.2.1) Required when using the default FeatureRequester", + "guzzlehttp/guzzle": "(^6.2.1) Required when using RelayEventPublisher or the default FeatureRequester", "kevinrob/guzzle-cache-middleware": "(^1.4.1) Recommended for performance when using the default FeatureRequester", "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php new file mode 100644 index 000000000..d14a6e152 --- /dev/null +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -0,0 +1,63 @@ +_sdkKey = $apiKey; + + $eventsUri = LDClient::DEFAULT_EVENTS_URI; + if (isset($options['events_uri'])) { + $eventsUri = $options['events_uri']; + } + $url = parse_url(rtrim($eventsUri,'/')); + $this->_host = $url['host']; + $this->_ssl = $url['scheme'] === 'https'; + if (isset($url['port'])) { + $this->_port = $url['port']; + } + else { + $this->_port = $this->_ssl ? 443 : 80; + } + if (isset($url['path'])) { + $this->_path = $url['path']; + } + else { + $this->_path = ''; + } + + if (array_key_exists('curl', $options)) { + $this->_curl = $options['curl']; + } + } + + public function publish($payload) { + $args = $this->createArgs($payload); + + return $this->makeRequest($args); + } + + private function createArgs($payload) { + $scheme = $this->_ssl ? "https://" : "http://"; + $args = " -X POST"; + $args.= " -H 'Content-Type: application/json'"; + $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); + $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; + $args.= " -H 'Accept: application/json'"; + $args.= " -d " . escapeshellarg($payload); + $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . $this->_path . "/bulk"); + return $args; + } + + private function makeRequest($args) { + $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; + shell_exec($cmd); + return true; + } +} \ No newline at end of file diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index cfa74043e..621789097 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -6,44 +6,13 @@ */ class EventProcessor { - private $_sdkKey; + private $_eventPublisher; private $_queue; private $_capacity; private $_timeout; - private $_host; - private $_port; - private $_ssl; - private $_curl = '/usr/bin/env curl'; public function __construct($apiKey, $options = array()) { - $this->_sdkKey = $apiKey; - if (!isset($options['events_uri'])) { - $this->_host = 'events.launchdarkly.com'; - $this->_port = 443; - $this->_ssl = true; - $this->_path = ''; - } - else { - $url = parse_url(rtrim($options['events_uri'],'/')); - $this->_host = $url['host']; - $this->_ssl = $url['scheme'] === 'https'; - if (isset($url['port'])) { - $this->_port = $url['port']; - } - else { - $this->_port = $this->_ssl ? 443 : 80; - } - if (isset($url['path'])) { - $this->_path = $url['path']; - } - else { - $this->_path = ''; - } - } - - if (array_key_exists('curl', $options)) { - $this->_curl = $options['curl']; - } + $this->_eventPublisher = $this->getEventPublisher($apiKey, $options); $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; @@ -76,28 +45,29 @@ protected function flush() { $payload = json_encode($this->_queue); - $args = $this->createArgs($payload); - - return $this->makeRequest($args); + return $this->_eventPublisher->publish($payload); } - private function createArgs($payload) { - $scheme = $this->_ssl ? "https://" : "http://"; - $args = " -X POST"; - $args.= " -H 'Content-Type: application/json'"; - $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); - $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; - $args.= " -H 'Accept: application/json'"; - $args.= " -d " . escapeshellarg($payload); - $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . $this->_path . "/bulk"); - return $args; - } - - private function makeRequest($args) { - $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; - shell_exec($cmd); - return true; - } + /** + * @param string $sdkKey + * @param mixed[] $options + * @return EventPublisher + */ + private function getEventPublisher($sdkKey, array $options) + { + if (isset($options['event_publisher']) && $options['event_publisher'] instanceof EventPublisher) { + return $options['event_publisher']; + } + if (isset($options['event_publisher_class'])) { + $eventPublisherClass = $options['event_publisher_class']; + } else { + $eventPublisherClass = CurlEventPublisher::class; + } + if (!is_a($eventPublisherClass, EventPublisher::class, true)) { + throw new \InvalidArgumentException; + } + return new $eventPublisherClass($sdkKey, $options); + } } \ No newline at end of file diff --git a/src/LaunchDarkly/EventPublisher.php b/src/LaunchDarkly/EventPublisher.php new file mode 100644 index 000000000..63b9446e8 --- /dev/null +++ b/src/LaunchDarkly/EventPublisher.php @@ -0,0 +1,18 @@ +_sdkKey = $sdkKey; @@ -51,6 +57,11 @@ public function __construct($sdkKey, $options = array()) { } else { $this->_baseUri = rtrim($options['base_uri'], '/'); } + if (!isset($options['events_uri'])) { + $this->_eventsUri = self::DEFAULT_EVENTS_URI; + } else { + $this->_eventsUri = rtrim($options['events_uri'], '/'); + } if (isset($options['send_events'])) { $this->_send_events = $options['send_events']; } @@ -82,15 +93,15 @@ public function __construct($sdkKey, $options = array()) { $this->_eventProcessor = new EventProcessor($sdkKey, $options); - $this->_featureRequester = $this->getFeatureRequester($options, $sdkKey); + $this->_featureRequester = $this->getFeatureRequester($sdkKey, $options); } /** - * @param mixed[] $options * @param string $sdkKey + * @param mixed[] $options * @return FeatureRequester */ - private function getFeatureRequester(array $options, $sdkKey) + private function getFeatureRequester($sdkKey, array $options) { if (isset($options['feature_requester']) && $options['feature_requester'] instanceof FeatureRequester) { return $options['feature_requester']; diff --git a/src/LaunchDarkly/RelayEventPublisher.php b/src/LaunchDarkly/RelayEventPublisher.php new file mode 100644 index 000000000..fcffe656e --- /dev/null +++ b/src/LaunchDarkly/RelayEventPublisher.php @@ -0,0 +1,52 @@ +_sdkKey = $apiKey; + $this->_logger = $options['logger']; + if (isset($options['events_uri'])) { + $this->_eventsUri = $options['events_uri']; + } else { + $this->_eventsUri = LDClient::DEFAULT_EVENTS_URI; + } + $this->_requestOptions = [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Authorization' => $this->_sdkKey, + 'User-Agent' => 'PHPClient/' . LDClient::VERSION, + 'Accept' => 'application/json' + ], + 'timeout' => $options['timeout'], + 'connect_timeout' => $options['connect_timeout'] + ]; + } + + public function publish($payload) { + $client = new Client(['base_uri' => $this->_eventsUri]); + + try { + $options = $this->_requestOptions; + $options['body'] = $payload; + $response = $client->request('POST', '/bulk', $options); + + return $response->getStatusCode() < 300; + } catch (\Exception $e) { + $this->_logger->warning("RelayEventPublisher::publish caught $e"); + return false; + } + } +} \ No newline at end of file From ae90fe1d9810968fa58b4f96b1f424c5a48b7286 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 25 May 2017 12:13:44 -0700 Subject: [PATCH 115/150] Rename `apiKey` to `sdkKey` --- src/LaunchDarkly/ApcLDDFeatureRequester.php | 4 ++-- src/LaunchDarkly/CurlEventPublisher.php | 4 ++-- src/LaunchDarkly/EventProcessor.php | 4 ++-- src/LaunchDarkly/LDDFeatureRequester.php | 6 +++--- src/LaunchDarkly/RelayEventPublisher.php | 4 ++-- tests/LDDFeatureRequesterTest.php | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/LaunchDarkly/ApcLDDFeatureRequester.php b/src/LaunchDarkly/ApcLDDFeatureRequester.php index ad4a36af7..d6d56e005 100644 --- a/src/LaunchDarkly/ApcLDDFeatureRequester.php +++ b/src/LaunchDarkly/ApcLDDFeatureRequester.php @@ -13,8 +13,8 @@ class ApcLDDFeatureRequester extends LDDFeatureRequester { protected $_expiration = 30; - function __construct($baseUri, $apiKey, $options) { - parent::__construct($baseUri, $apiKey, $options); + function __construct($baseUri, $sdkKey, $options) { + parent::__construct($baseUri, $sdkKey, $options); if (isset($options['apc_expiration'])) { $this->_expiration = (int)$options['apc_expiration']; diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php index d14a6e152..e898edbed 100644 --- a/src/LaunchDarkly/CurlEventPublisher.php +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -9,8 +9,8 @@ class CurlEventPublisher implements EventPublisher private $_ssl; private $_curl = '/usr/bin/env curl'; - function __construct($apiKey, array $options = array()) { - $this->_sdkKey = $apiKey; + function __construct($sdkKey, array $options = array()) { + $this->_sdkKey = $sdkKey; $eventsUri = LDClient::DEFAULT_EVENTS_URI; if (isset($options['events_uri'])) { diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index 621789097..af6ea81ab 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -11,8 +11,8 @@ class EventProcessor { private $_capacity; private $_timeout; - public function __construct($apiKey, $options = array()) { - $this->_eventPublisher = $this->getEventPublisher($apiKey, $options); + public function __construct($sdkKey, $options = array()) { + $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index 67142b538..dd5ec7262 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -7,7 +7,7 @@ class LDDFeatureRequester implements FeatureRequester { protected $_baseUri; - protected $_apiKey; + protected $_sdkKey; protected $_options; protected $_features_key; /** @var LoggerInterface */ @@ -15,9 +15,9 @@ class LDDFeatureRequester implements FeatureRequester { /** @var ClientInterface */ private $_connection; - function __construct($baseUri, $apiKey, $options) { + function __construct($baseUri, $sdkKey, $options) { $this->_baseUri = $baseUri; - $this->_apiKey = $apiKey; + $this->_sdkKey = $sdkKey; if (!isset($options['redis_host'])) { $options['redis_host'] = 'localhost'; } diff --git a/src/LaunchDarkly/RelayEventPublisher.php b/src/LaunchDarkly/RelayEventPublisher.php index fcffe656e..8b59dc992 100644 --- a/src/LaunchDarkly/RelayEventPublisher.php +++ b/src/LaunchDarkly/RelayEventPublisher.php @@ -15,8 +15,8 @@ class RelayEventPublisher implements EventPublisher /** @var mixed[] */ private $_requestOptions; - function __construct($apiKey, array $options = array()) { - $this->_sdkKey = $apiKey; + function __construct($sdkKey, array $options = array()) { + $this->_sdkKey = $sdkKey; $this->_logger = $options['logger']; if (isset($options['events_uri'])) { $this->_eventsUri = $options['events_uri']; diff --git a/tests/LDDFeatureRequesterTest.php b/tests/LDDFeatureRequesterTest.php index 97bfcc428..2fb2d7d07 100644 --- a/tests/LDDFeatureRequesterTest.php +++ b/tests/LDDFeatureRequesterTest.php @@ -29,7 +29,7 @@ protected function setUp() public function testGet() { - $sut = new LDDFeatureRequester('example.com', 'MyApiKey', [ + $sut = new LDDFeatureRequester('example.com', 'MySdkKey', [ 'logger' => $this->logger, 'predis_client' => $this->predisClient, ]); From 384a406f63bc5bc7100c3d9745d19af2203d0bf1 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 25 May 2017 15:09:27 -0700 Subject: [PATCH 116/150] Add documentation for GuzzleEventPublisher and CurlEventPublisher --- README.md | 29 +++++++++++++++---- composer.json | 2 +- src/LaunchDarkly/CurlEventPublisher.php | 10 +++++++ src/LaunchDarkly/EventPublisher.php | 3 ++ ...Publisher.php => GuzzleEventPublisher.php} | 14 +++++++-- 5 files changed, 49 insertions(+), 9 deletions(-) rename src/LaunchDarkly/{RelayEventPublisher.php => GuzzleEventPublisher.php} (69%) diff --git a/README.md b/README.md index db889dd62..368d8ed30 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Require Guzzle as a dependency: It will then be used as the default way of fetching flags. -With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L42). +With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L44). $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", array("cache" => $cacheStorage)); @@ -66,15 +66,32 @@ With Guzzle, you could persist your cache somewhere other than the default in-me Using LD-Relay ============== -* Setup [ld-relay](https://github.com/launchdarkly/ld-relay) in [daemon-mode](https://github.com/launchdarkly/ld-relay#redis-storage-and-daemon-mode) with Redis +The LaunchDarkly Relay Proxy ([ld-relay](https://github.com/launchdarkly/ld-relay)) consumes the LaunchDarkly streaming API and can update +a Redis cache operating in your production environment. The ld-relay offers many benefits such as performance and feature flag consistency. With PHP applications, we strongly recommend setting up ld-relay with a Redis store. -* Require Predis as a dependency: +1. Set up ld-relay in [daemon-mode](https://github.com/launchdarkly/ld-relay#redis-storage-and-daemon-mode) with Redis - php composer.phar require "predis/predis:1.0.*" +2. Require Predis as a dependency: -* Create the LDClient with the Redis feature requester as an option: + php composer.phar require "predis/predis:1.0.*" - $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', 'redis_host' => 'your.redis.host', 'redis_port' => 6379]); +3. Create the LDClient with the Redis feature requester as an option: + + $client = new LaunchDarkly\LDClient("your_sdk_key", [ + 'feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', + 'redis_host' => 'your.redis.host', + 'redis_port' => 6379 + ]); + +4. If ld-relay is configured for [event forwarding](https://github.com/launchdarkly/ld-relay#event-forwarding), you can configure the LDClient to publish events to ld-relay instead of directly to `events.launchdarkly.com`. Using `GuzzleEventPublisher` with ld-relay event forwarding can be an efficient alternative to the default `curl`-based event publishing. + + $client = new LaunchDarkly\LDClient("your_sdk_key", [ + 'event_publisher_class' => 'LaunchDarkly\GuzzleEventPublisher', + 'events_uri' => 'http://your-ldrelay-host:8030', + 'feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', + 'redis_host' => 'your.redis.host', + 'redis_port' => 6379 + ]); Testing ------- diff --git a/composer.json b/composer.json index 8f18b4c7b..28d09d16e 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "zendframework/zend-serializer": "^2.7" }, "suggest": { - "guzzlehttp/guzzle": "(^6.2.1) Required when using RelayEventPublisher or the default FeatureRequester", + "guzzlehttp/guzzle": "(^6.2.1) Required when using GuzzleEventPublisher or the default FeatureRequester", "kevinrob/guzzle-cache-middleware": "(^1.4.1) Recommended for performance when using the default FeatureRequester", "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php index e898edbed..96131ed55 100644 --- a/src/LaunchDarkly/CurlEventPublisher.php +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -1,6 +1,16 @@ getStatusCode() < 300; } catch (\Exception $e) { - $this->_logger->warning("RelayEventPublisher::publish caught $e"); + $this->_logger->warning("GuzzleEventPublisher::publish caught $e"); return false; } } From 630f575d789cdfbd0e58718423c82bff085efa16 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Tue, 6 Jun 2017 10:25:41 -0700 Subject: [PATCH 117/150] Release version 2.2.0 * Support publishing events via ld-relay * Add documentation for GuzzleEventPublisher and CurlEventPublisher --- CHANGELOG.md | 7 ++ README.md | 29 ++++++-- VERSION | 2 +- composer.json | 2 +- src/LaunchDarkly/ApcLDDFeatureRequester.php | 4 +- src/LaunchDarkly/CurlEventPublisher.php | 73 +++++++++++++++++++ src/LaunchDarkly/EventProcessor.php | 80 +++++++-------------- src/LaunchDarkly/EventPublisher.php | 21 ++++++ src/LaunchDarkly/GuzzleEventPublisher.php | 62 ++++++++++++++++ src/LaunchDarkly/LDClient.php | 23 ++++-- src/LaunchDarkly/LDDFeatureRequester.php | 6 +- tests/LDDFeatureRequesterTest.php | 2 +- 12 files changed, 236 insertions(+), 75 deletions(-) create mode 100644 src/LaunchDarkly/CurlEventPublisher.php create mode 100644 src/LaunchDarkly/EventPublisher.php create mode 100644 src/LaunchDarkly/GuzzleEventPublisher.php diff --git a/CHANGELOG.md b/CHANGELOG.md index dd9beb412..053377e84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.2.0] - 2017-06-06 +### Added +- Support for [publishing events via ld-relay](README.md#using-ld-relay) +- Allow `EventPublisher` to be injected into the client. +- `GuzzleEventPublisher` as a synchronous, in-process alternative to publishing events via background processes. +- Allow the `curl` path used by `CurlEventPublisher` to be customized via the `curl` option to `LDClient`. Thanks @abacaphiliac! + ## [2.1.2] - 2017-04-27 ### Changed - Relaxed the requirement on `kevinrob/guzzle-cache-middleware` for the default `GuzzleFeatureRequester`. diff --git a/README.md b/README.md index db889dd62..368d8ed30 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Require Guzzle as a dependency: It will then be used as the default way of fetching flags. -With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L42). +With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L44). $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", array("cache" => $cacheStorage)); @@ -66,15 +66,32 @@ With Guzzle, you could persist your cache somewhere other than the default in-me Using LD-Relay ============== -* Setup [ld-relay](https://github.com/launchdarkly/ld-relay) in [daemon-mode](https://github.com/launchdarkly/ld-relay#redis-storage-and-daemon-mode) with Redis +The LaunchDarkly Relay Proxy ([ld-relay](https://github.com/launchdarkly/ld-relay)) consumes the LaunchDarkly streaming API and can update +a Redis cache operating in your production environment. The ld-relay offers many benefits such as performance and feature flag consistency. With PHP applications, we strongly recommend setting up ld-relay with a Redis store. -* Require Predis as a dependency: +1. Set up ld-relay in [daemon-mode](https://github.com/launchdarkly/ld-relay#redis-storage-and-daemon-mode) with Redis - php composer.phar require "predis/predis:1.0.*" +2. Require Predis as a dependency: -* Create the LDClient with the Redis feature requester as an option: + php composer.phar require "predis/predis:1.0.*" - $client = new LaunchDarkly\LDClient("your_sdk_key", ['feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', 'redis_host' => 'your.redis.host', 'redis_port' => 6379]); +3. Create the LDClient with the Redis feature requester as an option: + + $client = new LaunchDarkly\LDClient("your_sdk_key", [ + 'feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', + 'redis_host' => 'your.redis.host', + 'redis_port' => 6379 + ]); + +4. If ld-relay is configured for [event forwarding](https://github.com/launchdarkly/ld-relay#event-forwarding), you can configure the LDClient to publish events to ld-relay instead of directly to `events.launchdarkly.com`. Using `GuzzleEventPublisher` with ld-relay event forwarding can be an efficient alternative to the default `curl`-based event publishing. + + $client = new LaunchDarkly\LDClient("your_sdk_key", [ + 'event_publisher_class' => 'LaunchDarkly\GuzzleEventPublisher', + 'events_uri' => 'http://your-ldrelay-host:8030', + 'feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester', + 'redis_host' => 'your.redis.host', + 'redis_port' => 6379 + ]); Testing ------- diff --git a/VERSION b/VERSION index eca07e4c1..ccbccc3dc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.2 +2.2.0 diff --git a/composer.json b/composer.json index 2ed48998a..28d09d16e 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "zendframework/zend-serializer": "^2.7" }, "suggest": { - "guzzlehttp/guzzle": "(^6.2.1) Required when using the default FeatureRequester", + "guzzlehttp/guzzle": "(^6.2.1) Required when using GuzzleEventPublisher or the default FeatureRequester", "kevinrob/guzzle-cache-middleware": "(^1.4.1) Recommended for performance when using the default FeatureRequester", "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, diff --git a/src/LaunchDarkly/ApcLDDFeatureRequester.php b/src/LaunchDarkly/ApcLDDFeatureRequester.php index ad4a36af7..d6d56e005 100644 --- a/src/LaunchDarkly/ApcLDDFeatureRequester.php +++ b/src/LaunchDarkly/ApcLDDFeatureRequester.php @@ -13,8 +13,8 @@ class ApcLDDFeatureRequester extends LDDFeatureRequester { protected $_expiration = 30; - function __construct($baseUri, $apiKey, $options) { - parent::__construct($baseUri, $apiKey, $options); + function __construct($baseUri, $sdkKey, $options) { + parent::__construct($baseUri, $sdkKey, $options); if (isset($options['apc_expiration'])) { $this->_expiration = (int)$options['apc_expiration']; diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php new file mode 100644 index 000000000..96131ed55 --- /dev/null +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -0,0 +1,73 @@ +_sdkKey = $sdkKey; + + $eventsUri = LDClient::DEFAULT_EVENTS_URI; + if (isset($options['events_uri'])) { + $eventsUri = $options['events_uri']; + } + $url = parse_url(rtrim($eventsUri,'/')); + $this->_host = $url['host']; + $this->_ssl = $url['scheme'] === 'https'; + if (isset($url['port'])) { + $this->_port = $url['port']; + } + else { + $this->_port = $this->_ssl ? 443 : 80; + } + if (isset($url['path'])) { + $this->_path = $url['path']; + } + else { + $this->_path = ''; + } + + if (array_key_exists('curl', $options)) { + $this->_curl = $options['curl']; + } + } + + public function publish($payload) { + $args = $this->createArgs($payload); + + return $this->makeRequest($args); + } + + private function createArgs($payload) { + $scheme = $this->_ssl ? "https://" : "http://"; + $args = " -X POST"; + $args.= " -H 'Content-Type: application/json'"; + $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); + $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; + $args.= " -H 'Accept: application/json'"; + $args.= " -d " . escapeshellarg($payload); + $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . $this->_path . "/bulk"); + return $args; + } + + private function makeRequest($args) { + $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; + shell_exec($cmd); + return true; + } +} \ No newline at end of file diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index cfa74043e..af6ea81ab 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -6,44 +6,13 @@ */ class EventProcessor { - private $_sdkKey; + private $_eventPublisher; private $_queue; private $_capacity; private $_timeout; - private $_host; - private $_port; - private $_ssl; - private $_curl = '/usr/bin/env curl'; - - public function __construct($apiKey, $options = array()) { - $this->_sdkKey = $apiKey; - if (!isset($options['events_uri'])) { - $this->_host = 'events.launchdarkly.com'; - $this->_port = 443; - $this->_ssl = true; - $this->_path = ''; - } - else { - $url = parse_url(rtrim($options['events_uri'],'/')); - $this->_host = $url['host']; - $this->_ssl = $url['scheme'] === 'https'; - if (isset($url['port'])) { - $this->_port = $url['port']; - } - else { - $this->_port = $this->_ssl ? 443 : 80; - } - if (isset($url['path'])) { - $this->_path = $url['path']; - } - else { - $this->_path = ''; - } - } - - if (array_key_exists('curl', $options)) { - $this->_curl = $options['curl']; - } + + public function __construct($sdkKey, $options = array()) { + $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; @@ -76,28 +45,29 @@ protected function flush() { $payload = json_encode($this->_queue); - $args = $this->createArgs($payload); - - return $this->makeRequest($args); - } - - private function createArgs($payload) { - $scheme = $this->_ssl ? "https://" : "http://"; - $args = " -X POST"; - $args.= " -H 'Content-Type: application/json'"; - $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); - $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; - $args.= " -H 'Accept: application/json'"; - $args.= " -d " . escapeshellarg($payload); - $args.= " " . escapeshellarg($scheme . $this->_host . ":" . $this->_port . $this->_path . "/bulk"); - return $args; + return $this->_eventPublisher->publish($payload); } - private function makeRequest($args) { - $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; - shell_exec($cmd); - return true; - } + /** + * @param string $sdkKey + * @param mixed[] $options + * @return EventPublisher + */ + private function getEventPublisher($sdkKey, array $options) + { + if (isset($options['event_publisher']) && $options['event_publisher'] instanceof EventPublisher) { + return $options['event_publisher']; + } + if (isset($options['event_publisher_class'])) { + $eventPublisherClass = $options['event_publisher_class']; + } else { + $eventPublisherClass = CurlEventPublisher::class; + } + if (!is_a($eventPublisherClass, EventPublisher::class, true)) { + throw new \InvalidArgumentException; + } + return new $eventPublisherClass($sdkKey, $options); + } } \ No newline at end of file diff --git a/src/LaunchDarkly/EventPublisher.php b/src/LaunchDarkly/EventPublisher.php new file mode 100644 index 000000000..0b21d6fb7 --- /dev/null +++ b/src/LaunchDarkly/EventPublisher.php @@ -0,0 +1,21 @@ +_sdkKey = $sdkKey; + $this->_logger = $options['logger']; + if (isset($options['events_uri'])) { + $this->_eventsUri = $options['events_uri']; + } else { + $this->_eventsUri = LDClient::DEFAULT_EVENTS_URI; + } + $this->_requestOptions = [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Authorization' => $this->_sdkKey, + 'User-Agent' => 'PHPClient/' . LDClient::VERSION, + 'Accept' => 'application/json' + ], + 'timeout' => $options['timeout'], + 'connect_timeout' => $options['connect_timeout'] + ]; + } + + public function publish($payload) { + $client = new Client(['base_uri' => $this->_eventsUri]); + + try { + $options = $this->_requestOptions; + $options['body'] = $payload; + $response = $client->request('POST', '/bulk', $options); + + return $response->getStatusCode() < 300; + } catch (\Exception $e) { + $this->_logger->warning("GuzzleEventPublisher::publish caught $e"); + return false; + } + } +} \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index a10031a6c..becd4e6a6 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -10,12 +10,15 @@ */ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; - const VERSION = '2.1.2'; + const DEFAULT_EVENTS_URI = 'https://events.launchdarkly.com'; + const VERSION = '2.2.0'; /** @var string */ protected $_sdkKey; /** @var string */ protected $_baseUri; + /** @var string */ + protected $_eventsUri; /** @var EventProcessor */ protected $_eventProcessor; /** @var bool */ @@ -26,8 +29,7 @@ class LDClient { protected $_defaults = array(); /** @var LoggerInterface */ protected $_logger; - - /** @var FeatureRequester */ + /** @var FeatureRequester */ protected $_featureRequester; /** @@ -43,6 +45,10 @@ class LDClient { * - send_events: An optional bool that can disable the sending of events to LaunchDarkly. Defaults to false. * - logger: An optional Psr\Log\LoggerInterface. Defaults to a Monolog\Logger sending all messages to the php error_log. * - offline: An optional boolean which will disable all network calls and always return the default value. Defaults to false. + * - feature_requester: An optional LaunchDarkly\FeatureRequester instance. + * - feature_requester_class: An optional class implementing LaunchDarkly\FeatureRequester, if `feature_requester` is not specified. Defaults to GuzzleFeatureRequester. + * - event_publisher: An optional LaunchDarkly\EventPublisher instance. + * - event_publisher_class: An optional class implementing LaunchDarkly\EventPublisher, if `event_publisher` is not specified. Defaults to CurlEventPublisher. */ public function __construct($sdkKey, $options = array()) { $this->_sdkKey = $sdkKey; @@ -51,6 +57,11 @@ public function __construct($sdkKey, $options = array()) { } else { $this->_baseUri = rtrim($options['base_uri'], '/'); } + if (!isset($options['events_uri'])) { + $this->_eventsUri = self::DEFAULT_EVENTS_URI; + } else { + $this->_eventsUri = rtrim($options['events_uri'], '/'); + } if (isset($options['send_events'])) { $this->_send_events = $options['send_events']; } @@ -82,15 +93,15 @@ public function __construct($sdkKey, $options = array()) { $this->_eventProcessor = new EventProcessor($sdkKey, $options); - $this->_featureRequester = $this->getFeatureRequester($options, $sdkKey); + $this->_featureRequester = $this->getFeatureRequester($sdkKey, $options); } /** - * @param mixed[] $options * @param string $sdkKey + * @param mixed[] $options * @return FeatureRequester */ - private function getFeatureRequester(array $options, $sdkKey) + private function getFeatureRequester($sdkKey, array $options) { if (isset($options['feature_requester']) && $options['feature_requester'] instanceof FeatureRequester) { return $options['feature_requester']; diff --git a/src/LaunchDarkly/LDDFeatureRequester.php b/src/LaunchDarkly/LDDFeatureRequester.php index 67142b538..dd5ec7262 100644 --- a/src/LaunchDarkly/LDDFeatureRequester.php +++ b/src/LaunchDarkly/LDDFeatureRequester.php @@ -7,7 +7,7 @@ class LDDFeatureRequester implements FeatureRequester { protected $_baseUri; - protected $_apiKey; + protected $_sdkKey; protected $_options; protected $_features_key; /** @var LoggerInterface */ @@ -15,9 +15,9 @@ class LDDFeatureRequester implements FeatureRequester { /** @var ClientInterface */ private $_connection; - function __construct($baseUri, $apiKey, $options) { + function __construct($baseUri, $sdkKey, $options) { $this->_baseUri = $baseUri; - $this->_apiKey = $apiKey; + $this->_sdkKey = $sdkKey; if (!isset($options['redis_host'])) { $options['redis_host'] = 'localhost'; } diff --git a/tests/LDDFeatureRequesterTest.php b/tests/LDDFeatureRequesterTest.php index 97bfcc428..2fb2d7d07 100644 --- a/tests/LDDFeatureRequesterTest.php +++ b/tests/LDDFeatureRequesterTest.php @@ -29,7 +29,7 @@ protected function setUp() public function testGet() { - $sut = new LDDFeatureRequester('example.com', 'MyApiKey', [ + $sut = new LDDFeatureRequester('example.com', 'MySdkKey', [ 'logger' => $this->logger, 'predis_client' => $this->predisClient, ]); From bd3a93088dd8c0982e03129eb8199b2b43cef585 Mon Sep 17 00:00:00 2001 From: Valentin Prugnaud Date: Wed, 6 Sep 2017 04:57:11 -0700 Subject: [PATCH 118/150] Public access to flush method --- src/LaunchDarkly/EventProcessor.php | 8 ++++++-- src/LaunchDarkly/LDClient.php | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index af6ea81ab..f408ac635 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -17,7 +17,7 @@ public function __construct($sdkKey, $options = array()) { $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; - $this->_queue = array(); + $this->_queue = array(); } public function __destruct() { @@ -38,7 +38,11 @@ public function enqueue($event) { return true; } - protected function flush() { + /** + * Publish events to LaunchDarkly + * @return bool Whether the events were successfully published + */ + public function flush() { if (empty($this->_queue)) { return null; } diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index becd4e6a6..0d1898745 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -95,7 +95,7 @@ public function __construct($sdkKey, $options = array()) { $this->_featureRequester = $this->getFeatureRequester($sdkKey, $options); } - + /** * @param string $sdkKey * @param mixed[] $options @@ -106,7 +106,7 @@ private function getFeatureRequester($sdkKey, array $options) if (isset($options['feature_requester']) && $options['feature_requester'] instanceof FeatureRequester) { return $options['feature_requester']; } - + if (isset($options['feature_requester_class'])) { $featureRequesterClass = $options['feature_requester_class']; } else { @@ -279,6 +279,16 @@ public function secureModeHash($user) { return hash_hmac("sha256", $user->getKey(), $this->_sdkKey, false); } + /** + * Publish events to LaunchDarkly + * @param $payload string Event payload + * @return bool Whether the events were successfully published + */ + public function flush() + { + return $this->_eventProcessor->flush(); + } + /** * @param $key string * @param $user LDUser From 1b8a81bcc689b3da0392cb3c1ee6865608e37541 Mon Sep 17 00:00:00 2001 From: Peter Meth Date: Fri, 6 Oct 2017 15:29:31 -0400 Subject: [PATCH 119/150] Fix class of LDClient::__construct cache option As per this https://github.com/Kevinrob/guzzle-cache-middleware/blob/v1.5.2/src/Strategy/PublicCacheStrategy.php#L6 the proper class is `Kevinrob\GuzzleCache\Storage\CacheStorageInterface` --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index becd4e6a6..0d960d26c 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -41,7 +41,7 @@ class LDClient { * - events_uri: Base URI for sending events to LaunchDarkly. Defaults to 'https://events.launchdarkly.com' * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 - * - cache: An optional Kevinrob\GuzzleCache\Strategy\CacheStorageInterface. Defaults to an in-memory cache. + * - cache: An optional Kevinrob\GuzzleCache\Storage\CacheStorageInterface. Defaults to an in-memory cache. * - send_events: An optional bool that can disable the sending of events to LaunchDarkly. Defaults to false. * - logger: An optional Psr\Log\LoggerInterface. Defaults to a Monolog\Logger sending all messages to the php error_log. * - offline: An optional boolean which will disable all network calls and always return the default value. Defaults to false. From 32a48b7ed8ab0578febeea97631f9c231dd41ec0 Mon Sep 17 00:00:00 2001 From: Valentin Prugnaud Date: Fri, 6 Oct 2017 14:16:08 -0700 Subject: [PATCH 120/150] Remove unused comment --- src/LaunchDarkly/LDClient.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 0d1898745..5d8820ec5 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -281,7 +281,6 @@ public function secureModeHash($user) { /** * Publish events to LaunchDarkly - * @param $payload string Event payload * @return bool Whether the events were successfully published */ public function flush() From 909ccbc6812bb61b5de0e50d2a30273a76780e25 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Fri, 6 Oct 2017 16:12:52 -0700 Subject: [PATCH 121/150] Release version 2.3.0 --- CHANGELOG.md | 7 +++++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 053377e84..899970378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.3.0] - 2017-10-06 +### Added +- New `flush` method forces events to be published to the LaunchDarkly service. This can be useful if `LDClient` is not automatically destroyed at the end of a request. Thanks @foxted! + +### Fixed +- Documentation comment references the correct namespace for `CacheStorageInterface`. Thanks @pmeth! + ## [2.2.0] - 2017-06-06 ### Added - Support for [publishing events via ld-relay](README.md#using-ld-relay) diff --git a/VERSION b/VERSION index ccbccc3dc..276cbf9e2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0 +2.3.0 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index ff0a94776..64d007b52 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -11,7 +11,7 @@ class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; const DEFAULT_EVENTS_URI = 'https://events.launchdarkly.com'; - const VERSION = '2.2.0'; + const VERSION = '2.3.0'; /** @var string */ protected $_sdkKey; From fbe5bfc6823edfa4b82f57672a32e503935180b0 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 13 Oct 2017 14:17:19 -0700 Subject: [PATCH 122/150] implement private user attributes --- src/LaunchDarkly/EventProcessor.php | 9 +- src/LaunchDarkly/EventSerializer.php | 87 +++++++++++++ src/LaunchDarkly/LDClient.php | 4 +- src/LaunchDarkly/LDUser.php | 45 ++----- src/LaunchDarkly/LDUserBuilder.php | 10 +- src/LaunchDarkly/Util.php | 2 +- tests/EventSerializerTest.php | 187 +++++++++++++++++++++++++++ tests/LDUserTest.php | 26 ---- 8 files changed, 300 insertions(+), 70 deletions(-) create mode 100644 src/LaunchDarkly/EventSerializer.php create mode 100644 tests/EventSerializerTest.php diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index f408ac635..a199a43a8 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -7,13 +7,15 @@ class EventProcessor { private $_eventPublisher; + private $_eventSerializer; private $_queue; private $_capacity; private $_timeout; public function __construct($sdkKey, $options = array()) { $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); - + $this->_eventSerializer = new EventSerializer($options); + $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; @@ -47,7 +49,10 @@ public function flush() { return null; } - $payload = json_encode($this->_queue); + $payload = $this->_eventSerializer->serializeEvents($this->_queue); + + // We don't expect flush to be called more than once per request cycle, but let's empty the queue just in case + $this->_queue = array(); return $this->_eventPublisher->publish($payload); } diff --git a/src/LaunchDarkly/EventSerializer.php b/src/LaunchDarkly/EventSerializer.php new file mode 100644 index 000000000..d980417d1 --- /dev/null +++ b/src/LaunchDarkly/EventSerializer.php @@ -0,0 +1,87 @@ +_allAttrsPrivate = isset($options['allAttrsPrivate']) && $options['allAttrsPrivate']; + $this->_privateAttrNames = isset($options['privateAttrNames']) ? $options['privateAttrNames'] : array(); + } + + public function serializeEvents($events) { + $filtered = array(); + foreach ($events as $e) { + array_push($filtered, $this->filterEvent($e)); + } + return json_encode($filtered); + } + + private function filterEvent($e) { + $ret = array(); + foreach ($e as $key => $value) { + if ($key == 'user') { + $ret[$key] = $this->serializeUser($value); + } + else { + $ret[$key] = $value; + } + } + return $ret; + } + + private function isPrivateAttr($name, $userPrivateAttrs, &$allPrivateAttrs) { + if ($this->_allAttrsPrivate || + array_search($name, $userPrivateAttrs) !== FALSE || + array_search($name, $this->_privateAttrNames) !== FALSE) { + $allPrivateAttrs[$name] = $name; + return true; + } + else { + return false; + } + } + + private function serializeUser($user) { + $json = array("key" => $user->getKey()); + $userPrivateAttrs = $user->getPrivateAttrs(); + $allPrivateAttrs = array(); + + $attrs = array( + 'secondary' => $user->getSecondary(), + 'ip' => $user->getIP(), + 'country' => $user->getCountry(), + 'email' => $user->getEmail(), + 'name' => $user->getName(), + 'avatar' => $user->getAvatar(), + 'firstName' => $user->getFirstName(), + 'lastName' => $user->getLastName(), + 'anonymous' => $user->getAnonymous() + ); + foreach ($attrs as $key => $value) { + if ($value != null && !$this->isPrivateAttr($key, $userPrivateAttrs, $allPrivateAttrs)) { + $json[$key] = $value; + } + } + if (!empty($user->getCustom())) { + $customs = array(); + foreach ($user->getCustom() as $key => $value) { + if ($value != null && !$this->isPrivateAttr($key, $userPrivateAttrs, $allPrivateAttrs)) { + $customs[$key] = $value; + } + } + $json['custom'] = $customs; + } + if (count($allPrivateAttrs)) { + $pa = array_keys($allPrivateAttrs); + sort($pa); + $json['privateAttrs'] = $pa; + } + return $json; + } +} diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 64d007b52..1dc276398 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -207,7 +207,7 @@ public function track($eventName, $user, $data) { } $event = array(); - $event['user'] = $user->toJSON(); + $event['user'] = $user; $event['kind'] = "custom"; $event['creationDate'] = Util::currentTimeUnixMillis(); $event['key'] = $eventName; @@ -229,7 +229,7 @@ public function identify($user) { } $event = array(); - $event['user'] = $user->toJSON(); + $event['user'] = $user; $event['kind'] = "identify"; $event['creationDate'] = Util::currentTimeUnixMillis(); $event['key'] = $user->getKey(); diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index 76aaac5fe..b309c6d3c 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -18,6 +18,7 @@ class LDUser { protected $_lastName = null; protected $_anonyomus = false; protected $_custom = array(); + protected $_privateAttrs = array(); /** * @param string $key Unique key for the user. For authenticated users, this may be a username or e-mail address. For anonymous users, this could be an IP address or session ID. @@ -32,7 +33,8 @@ class LDUser { * @param boolean|null $anonymous Whether this is an anonymous user * @param array|null $custom Other custom attributes that can be used to create custom rules */ - public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array()) { + public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array(), + $privateAttrs = array()) { if ($key !== null) { $this->_key = strval($key); } @@ -46,6 +48,7 @@ public function __construct($key, $secondary = null, $ip = null, $country = null $this->_lastName = $lastName; $this->_anonymous = $anonymous; $this->_custom = $custom; + $this->_privateAttrs = $privateAttrs; } public function getValueForEvaluation($attr) { @@ -129,43 +132,11 @@ public function getAnonymous() { return $this->_anonymous; } + public function getPrivateAttrs() { + return $this->_privateAttrs; + } + public function isKeyBlank() { return isset($this->_key) && empty($this->_key); } - - public function toJSON() { - $json = array("key" => $this->_key); - - if (isset($this->_secondary)) { - $json['secondary'] = $this->_secondary; - } - if (isset($this->_ip)) { - $json['ip'] = $this->_ip; - } - if (isset($this->_country)) { - $json['country'] = $this->_country; - } - if (isset($this->_email)) { - $json['email'] = $this->_email; - } - if (isset($this->_name)) { - $json['name'] = $this->_name; - } - if (isset($this->_avatar)) { - $json['avatar'] = $this->_avatar; - } - if (isset($this->_firstName)) { - $json['firstName'] = $this->_firstName; - } - if (isset($this->_lastName)) { - $json['lastName'] = $this->_lastName; - } - if (isset($this->_custom) && !empty($this->_custom)) { - $json['custom'] = $this->_custom; - } - if (isset($this->_anonymous)) { - $json['anonymous'] = $this->_anonymous; - } - return $json; - } } diff --git a/src/LaunchDarkly/LDUserBuilder.php b/src/LaunchDarkly/LDUserBuilder.php index e0a4484d7..9065432e7 100644 --- a/src/LaunchDarkly/LDUserBuilder.php +++ b/src/LaunchDarkly/LDUserBuilder.php @@ -13,7 +13,8 @@ class LDUserBuilder { protected $_lastName = null; protected $_anonymous = null; protected $_custom = array(); - + protected $_privateAttrs = array(); + public function __construct($key) { $this->_key = $key; } @@ -68,8 +69,13 @@ public function custom($custom) { return $this; } + public function privateAttrs($privateAttrs) { + $this->_privateAttrs = $privateAttrs; + return $this; + } + public function build() { - return new LDUser($this->_key, $this->_secondary, $this->_ip, $this->_country, $this->_email, $this->_name, $this->_avatar, $this->_firstName, $this->_lastName, $this->_anonymous, $this->_custom); + return new LDUser($this->_key, $this->_secondary, $this->_ip, $this->_country, $this->_email, $this->_name, $this->_avatar, $this->_firstName, $this->_lastName, $this->_anonymous, $this->_custom, $this->_privateAttrs); } } \ No newline at end of file diff --git a/src/LaunchDarkly/Util.php b/src/LaunchDarkly/Util.php index e1d84897a..b2eb3b246 100644 --- a/src/LaunchDarkly/Util.php +++ b/src/LaunchDarkly/Util.php @@ -36,7 +36,7 @@ public static function currentTimeUnixMillis() { */ public static function newFeatureRequestEvent($key, $user, $value, $default, $version = null, $prereqOf = null) { $event = array(); - $event['user'] = $user->toJSON(); + $event['user'] = $user; $event['value'] = $value; $event['kind'] = "feature"; $event['creationDate'] = Util::currentTimeUnixMillis(); diff --git a/tests/EventSerializerTest.php b/tests/EventSerializerTest.php new file mode 100644 index 000000000..70662922f --- /dev/null +++ b/tests/EventSerializerTest.php @@ -0,0 +1,187 @@ +firstName('Sue') + ->custom(array('bizzle' => 'def', 'dizzle' => 'ghi')) + ->build(); + } + + private function getUserSpecifyingOwnPrivateAttr() { + return (new LDUserBuilder('abc'))->firstName('Sue') + ->custom(array('bizzle' => 'def', 'dizzle' => 'ghi')) + ->privateAttrs(array('dizzle', 'unused')) + ->build(); + } + + private function getFullUserResult() { + return array( + 'key' => 'abc', + 'firstName' => 'Sue', + 'custom' => array('bizzle' => 'def', 'dizzle' => 'ghi') + ); + } + + private function getUserResultWithAllAttrsHidden() { + return array( + 'key' => 'abc', + 'custom' => array(), + 'privateAttrs' => array('bizzle', 'dizzle', 'firstName') + ); + } + + private function getUserResultWithSomeAttrsHidden() { + return array( + 'key' => 'abc', + 'custom' => array('dizzle' => 'ghi'), + 'privateAttrs' => array('bizzle', 'firstName') + ); + } + + private function getUserResultWithOwnSpecifiedAttrHidden() { + return array( + 'key' => 'abc', + 'firstName' => 'Sue', + 'custom' => array('bizzle' => 'def'), + 'privateAttrs' => array('dizzle') + ); + } + + private function makeEvent($user) { + return array( + 'creationDate' => 1000000, + 'key' => 'abc', + 'kind' => 'thing', + 'user' => $user + ); + } + + private function getJsonForUserBySerializingEvent($user) { + $es = new EventSerializer(array()); + $event = $this->makeEvent($user); + return json_decode($es->serializeEvents(array($event)), true)[0]['user']; + } + + public function testAllUserAttrsSerialized() { + $es = new EventSerializer(array()); + $event = $this->makeEvent($this->getUser()); + $json = $es->serializeEvents(array($event)); + $expected = $this->makeEvent($this->getFullUserResult()); + $this->assertEquals(array($expected), json_decode($json, true)); + } + + public function testAllUserAttrsPrivate() { + $es = new EventSerializer(array('allAttrsPrivate' => true)); + $event = $this->makeEvent($this->getUser()); + $json = $es->serializeEvents(array($event)); + $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); + $this->assertEquals(array($expected), json_decode($json, true)); + } + + public function testSomeUserAttrsPrivate() { + $es = new EventSerializer(array('privateAttrNames' => array('firstName', 'bizzle'))); + $event = $this->makeEvent($this->getUser()); + $json = $es->serializeEvents(array($event)); + $expected = $this->makeEvent($this->getUserResultWithSomeAttrsHidden()); + $this->assertEquals(array($expected), json_decode($json, true)); + } + + public function testPerUserPrivateAttr() { + $es = new EventSerializer(array()); + $event = $this->makeEvent($this->getUserSpecifyingOwnPrivateAttr()); + $json = $es->serializeEvents(array($event)); + $expected = $this->makeEvent($this->getUserResultWithOwnSpecifiedAttrHidden()); + $this->assertEquals(array($expected), json_decode($json, true)); + } + + public function testPerUserPrivateAttrPlusGlobalPrivateAttrs() { + $es = new EventSerializer(array('privateAttrNames' => array('firstName', 'bizzle'))); + $event = $this->makeEvent($this->getUserSpecifyingOwnPrivateAttr()); + $json = $es->serializeEvents(array($event)); + $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); + $this->assertEquals(array($expected), json_decode($json, true)); + } + + public function testUserKey() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("foo@bar.com", $json['key']); + } + + public function testEmptyCustom() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertFalse(isset($json['custom'])); + } + + public function testUserSecondary() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->secondary("secondary")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("secondary", $json['secondary']); + } + + public function testLDUserIP() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->ip("127.0.0.1")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("127.0.0.1", $json['ip']); + } + + public function testLDUserCountry() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->country("US")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("US", $json['country']); + } + + public function testLDUserEmail() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->email("foo+test@bar.com")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("foo+test@bar.com", $json['email']); + } + + public function testLDUserName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->name("Foo Bar")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("Foo Bar", $json['name']); + } + + public function testLDUserAvatar() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->avatar("http://www.gravatar.com/avatar/1")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("http://www.gravatar.com/avatar/1", $json['avatar']); + } + + public function testLDUserFirstName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->firstName("Foo")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("Foo", $json['firstName']); + } + + public function testLDUserLastName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->lastName("Bar")->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals("Bar", $json['lastName']); + } + + public function testLDUserAnonymous() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->anonymous(true)->build(); + $json = $this->getJsonForUserBySerializingEvent($user); + $this->assertEquals(true, $json['anonymous']); + } +} + diff --git a/tests/LDUserTest.php b/tests/LDUserTest.php index 0dfbb0d01..9253ad415 100644 --- a/tests/LDUserTest.php +++ b/tests/LDUserTest.php @@ -9,96 +9,71 @@ public function testLDUserKey() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->build(); $this->assertEquals("foo@bar.com", $user->getKey()); - $json = $user->toJSON(); - $this->assertEquals("foo@bar.com", $json['key']); } public function testCoerceLDUserKey() { $builder = new LDUserBuilder(3); $user = $builder->build(); $this->assertEquals("string", gettype($user->getKey())); - $json = $user->toJSON(); - $this->assertEquals("string", gettype($json['key'])); } public function testEmptyCustom() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->build(); - $json = $user->toJSON(); - $this->assertTrue(!isset($json['custom'])); } public function testLDUserSecondary() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->secondary("secondary")->build(); $this->assertEquals("secondary", $user->getSecondary()); - $json = $user->toJSON(); - $this->assertEquals("secondary", $json['secondary']); } public function testLDUserIP() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->ip("127.0.0.1")->build(); $this->assertEquals("127.0.0.1", $user->getIP()); - $json = $user->toJSON(); - $this->assertEquals("127.0.0.1", $json['ip']); } public function testLDUserCountry() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->country("US")->build(); $this->assertEquals("US", $user->getCountry()); - $json = $user->toJSON(); - $this->assertEquals("US", $json['country']); } public function testLDUserEmail() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->email("foo+test@bar.com")->build(); $this->assertEquals("foo+test@bar.com", $user->getEmail()); - $json = $user->toJSON(); - $this->assertEquals("foo+test@bar.com", $json['email']); } public function testLDUserName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->name("Foo Bar")->build(); $this->assertEquals("Foo Bar", $user->getName()); - $json = $user->toJSON(); - $this->assertEquals("Foo Bar", $json['name']); } public function testLDUserAvatar() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->avatar("http://www.gravatar.com/avatar/1")->build(); $this->assertEquals("http://www.gravatar.com/avatar/1", $user->getAvatar()); - $json = $user->toJSON(); - $this->assertEquals("http://www.gravatar.com/avatar/1", $json['avatar']); } public function testLDUserFirstName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->firstName("Foo")->build(); $this->assertEquals("Foo", $user->getFirstName()); - $json = $user->toJSON(); - $this->assertEquals("Foo", $json['firstName']); } public function testLDUserLastName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->lastName("Bar")->build(); $this->assertEquals("Bar", $user->getLastName()); - $json = $user->toJSON(); - $this->assertEquals("Bar", $json['lastName']); } public function testLDUserAnonymous() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->anonymous(true)->build(); $this->assertEquals(true, $user->getAnonymous()); - $json = $user->toJSON(); - $this->assertEquals(true, $json['anonymous']); - } public function testLDUserBlankKey() { @@ -116,4 +91,3 @@ public function testLDUserBlankKey() { $this->assertFalse($user->isKeyBlank()); } } - From 7e954063c6d1d552d404f8b1cb7e81d3595487ae Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 13 Oct 2017 14:25:53 -0700 Subject: [PATCH 123/150] oh what the heck, let's write pure functions even in PHP --- src/LaunchDarkly/EventSerializer.php | 30 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/LaunchDarkly/EventSerializer.php b/src/LaunchDarkly/EventSerializer.php index d980417d1..d32d8ebb5 100644 --- a/src/LaunchDarkly/EventSerializer.php +++ b/src/LaunchDarkly/EventSerializer.php @@ -35,16 +35,10 @@ private function filterEvent($e) { return $ret; } - private function isPrivateAttr($name, $userPrivateAttrs, &$allPrivateAttrs) { - if ($this->_allAttrsPrivate || + private function isPrivateAttr($name, $userPrivateAttrs) { + return ($this->_allAttrsPrivate || array_search($name, $userPrivateAttrs) !== FALSE || - array_search($name, $this->_privateAttrNames) !== FALSE) { - $allPrivateAttrs[$name] = $name; - return true; - } - else { - return false; - } + array_search($name, $this->_privateAttrNames) !== FALSE); } private function serializeUser($user) { @@ -64,15 +58,25 @@ private function serializeUser($user) { 'anonymous' => $user->getAnonymous() ); foreach ($attrs as $key => $value) { - if ($value != null && !$this->isPrivateAttr($key, $userPrivateAttrs, $allPrivateAttrs)) { - $json[$key] = $value; + if ($value != null) { + if ($this->isPrivateAttr($key, $userPrivateAttrs)) { + $allPrivateAttrs[$key] = $key; + } + else { + $json[$key] = $value; + } } } if (!empty($user->getCustom())) { $customs = array(); foreach ($user->getCustom() as $key => $value) { - if ($value != null && !$this->isPrivateAttr($key, $userPrivateAttrs, $allPrivateAttrs)) { - $customs[$key] = $value; + if ($value != null) { + if ($this->isPrivateAttr($key, $userPrivateAttrs)) { + $allPrivateAttrs[$key] = $key; + } + else { + $customs[$key] = $value; + } } } $json['custom'] = $customs; From 99261222c64d57bb1e52d42ce4a69c2df7054bbe Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 13 Oct 2017 14:30:01 -0700 Subject: [PATCH 124/150] consistent test names --- tests/EventSerializerTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/EventSerializerTest.php b/tests/EventSerializerTest.php index 70662922f..b7f7436e1 100644 --- a/tests/EventSerializerTest.php +++ b/tests/EventSerializerTest.php @@ -128,56 +128,56 @@ public function testUserSecondary() { $this->assertEquals("secondary", $json['secondary']); } - public function testLDUserIP() { + public function testUserIP() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->ip("127.0.0.1")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("127.0.0.1", $json['ip']); } - public function testLDUserCountry() { + public function testUserCountry() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->country("US")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("US", $json['country']); } - public function testLDUserEmail() { + public function testUserEmail() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->email("foo+test@bar.com")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("foo+test@bar.com", $json['email']); } - public function testLDUserName() { + public function testUserName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->name("Foo Bar")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("Foo Bar", $json['name']); } - public function testLDUserAvatar() { + public function testUserAvatar() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->avatar("http://www.gravatar.com/avatar/1")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("http://www.gravatar.com/avatar/1", $json['avatar']); } - public function testLDUserFirstName() { + public function testUserFirstName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->firstName("Foo")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("Foo", $json['firstName']); } - public function testLDUserLastName() { + public function testUserLastName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->lastName("Bar")->build(); $json = $this->getJsonForUserBySerializingEvent($user); $this->assertEquals("Bar", $json['lastName']); } - public function testLDUserAnonymous() { + public function testUserAnonymous() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->anonymous(true)->build(); $json = $this->getJsonForUserBySerializingEvent($user); From 51a6af1d51595a1e9b03127bc38b4ad956ed6b5b Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 18 Oct 2017 14:39:30 -0700 Subject: [PATCH 125/150] revise private user info naming conventions & methods to match Java SDK --- src/LaunchDarkly/EventSerializer.php | 6 +-- src/LaunchDarkly/LDUser.php | 10 ++--- src/LaunchDarkly/LDUserBuilder.php | 55 +++++++++++++++++++++++++--- tests/EventSerializerTest.php | 16 ++++---- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/LaunchDarkly/EventSerializer.php b/src/LaunchDarkly/EventSerializer.php index d32d8ebb5..add0d1bb8 100644 --- a/src/LaunchDarkly/EventSerializer.php +++ b/src/LaunchDarkly/EventSerializer.php @@ -10,8 +10,8 @@ class EventSerializer { private $_privateAttrNames; public function __construct($options) { - $this->_allAttrsPrivate = isset($options['allAttrsPrivate']) && $options['allAttrsPrivate']; - $this->_privateAttrNames = isset($options['privateAttrNames']) ? $options['privateAttrNames'] : array(); + $this->_allAttrsPrivate = isset($options['allAttributesPrivate']) && $options['allAttributesPrivate']; + $this->_privateAttrNames = isset($options['privateAttributeNames']) ? $options['privateAttributeNames'] : array(); } public function serializeEvents($events) { @@ -43,7 +43,7 @@ private function isPrivateAttr($name, $userPrivateAttrs) { private function serializeUser($user) { $json = array("key" => $user->getKey()); - $userPrivateAttrs = $user->getPrivateAttrs(); + $userPrivateAttrs = $user->getPrivateAttributeNames(); $allPrivateAttrs = array(); $attrs = array( diff --git a/src/LaunchDarkly/LDUser.php b/src/LaunchDarkly/LDUser.php index b309c6d3c..fdd4d110e 100644 --- a/src/LaunchDarkly/LDUser.php +++ b/src/LaunchDarkly/LDUser.php @@ -18,7 +18,7 @@ class LDUser { protected $_lastName = null; protected $_anonyomus = false; protected $_custom = array(); - protected $_privateAttrs = array(); + protected $_privateAttributeNames = array(); /** * @param string $key Unique key for the user. For authenticated users, this may be a username or e-mail address. For anonymous users, this could be an IP address or session ID. @@ -34,7 +34,7 @@ class LDUser { * @param array|null $custom Other custom attributes that can be used to create custom rules */ public function __construct($key, $secondary = null, $ip = null, $country = null, $email = null, $name = null, $avatar = null, $firstName = null, $lastName = null, $anonymous = null, $custom = array(), - $privateAttrs = array()) { + $privateAttributeNames = array()) { if ($key !== null) { $this->_key = strval($key); } @@ -48,7 +48,7 @@ public function __construct($key, $secondary = null, $ip = null, $country = null $this->_lastName = $lastName; $this->_anonymous = $anonymous; $this->_custom = $custom; - $this->_privateAttrs = $privateAttrs; + $this->_privateAttributeNames = $privateAttributeNames; } public function getValueForEvaluation($attr) { @@ -132,8 +132,8 @@ public function getAnonymous() { return $this->_anonymous; } - public function getPrivateAttrs() { - return $this->_privateAttrs; + public function getPrivateAttributeNames() { + return $this->_privateAttributeNames; } public function isKeyBlank() { diff --git a/src/LaunchDarkly/LDUserBuilder.php b/src/LaunchDarkly/LDUserBuilder.php index 9065432e7..58843aefe 100644 --- a/src/LaunchDarkly/LDUserBuilder.php +++ b/src/LaunchDarkly/LDUserBuilder.php @@ -13,7 +13,7 @@ class LDUserBuilder { protected $_lastName = null; protected $_anonymous = null; protected $_custom = array(); - protected $_privateAttrs = array(); + protected $_privateAttributeNames = array(); public function __construct($key) { $this->_key = $key; @@ -24,41 +24,81 @@ public function secondary($secondary) { return $this; } + public function privateSecondary($seondary) { + array_push($this->_privateAttributeNames, 'secondary'); + return $this->secondary($secondary); + } + public function ip($ip) { $this->_ip = $ip; return $this; } + public function privateIp($ip) { + array_push($this->_privateAttributeNames, 'ip'); + return $this->ip($ip); + } + public function country($country) { $this->_country = $country; return $this; } + public function privateCountry($country) { + array_push($this->_privateAttributeNames, 'country'); + return $this->country($country); + } + public function email($email) { $this->_email = $email; return $this; } + public function privateEmail($email) { + array_push($this->_privateAttributeNames, 'email'); + return $this->email($email); + } + public function name($name) { $this->_name = $name; return $this; } + public function privateName($name) { + array_push($this->_privateAttributeNames, 'name'); + return $this->name($name); + } + public function avatar($avatar) { $this->_avatar = $avatar; return $this; } + public function privateAvatar($avatar) { + array_push($this->_privateAttributeNames, 'avatar'); + return $this->avatar($avatar); + } + public function firstName($firstName) { $this->_firstName = $firstName; return $this; } + public function privateFirstName($firstName) { + array_push($this->_privateAttributeNames, 'firstName'); + return $this->firstName($firstName); + } + public function lastName($lastName) { $this->_lastName = $lastName; return $this; } + public function privateLastName($lastName) { + array_push($this->_privateAttributeNames, 'lastName'); + return $this->lastName($lastName); + } + public function anonymous($anonymous) { $this->_anonymous = $anonymous; return $this; @@ -69,13 +109,18 @@ public function custom($custom) { return $this; } - public function privateAttrs($privateAttrs) { - $this->_privateAttrs = $privateAttrs; + public function customAttribute($customKey, $customValue) { + $this->_custom[$customKey] = $customValue; return $this; } - + + public function privateCustomAttribute($customKey, $customValue) { + array_push($this->_privateAttributeNames, $customKey); + return $this->customAttribute($customKey, $customValue); + } + public function build() { - return new LDUser($this->_key, $this->_secondary, $this->_ip, $this->_country, $this->_email, $this->_name, $this->_avatar, $this->_firstName, $this->_lastName, $this->_anonymous, $this->_custom, $this->_privateAttrs); + return new LDUser($this->_key, $this->_secondary, $this->_ip, $this->_country, $this->_email, $this->_name, $this->_avatar, $this->_firstName, $this->_lastName, $this->_anonymous, $this->_custom, $this->_privateAttributeNames); } } \ No newline at end of file diff --git a/tests/EventSerializerTest.php b/tests/EventSerializerTest.php index b7f7436e1..59b4d93c2 100644 --- a/tests/EventSerializerTest.php +++ b/tests/EventSerializerTest.php @@ -7,15 +7,17 @@ class EventSerializerTest extends \PHPUnit_Framework_TestCase { private function getUser() { - return (new LDUserBuilder('abc'))->firstName('Sue') + return (new LDUserBuilder('abc')) + ->firstName('Sue') ->custom(array('bizzle' => 'def', 'dizzle' => 'ghi')) ->build(); } private function getUserSpecifyingOwnPrivateAttr() { - return (new LDUserBuilder('abc'))->firstName('Sue') - ->custom(array('bizzle' => 'def', 'dizzle' => 'ghi')) - ->privateAttrs(array('dizzle', 'unused')) + return (new LDUserBuilder('abc')) + ->firstName('Sue') + ->customAttribute('bizzle', 'def') + ->privateCustomAttribute('dizzle', 'ghi') ->build(); } @@ -76,7 +78,7 @@ public function testAllUserAttrsSerialized() { } public function testAllUserAttrsPrivate() { - $es = new EventSerializer(array('allAttrsPrivate' => true)); + $es = new EventSerializer(array('allAttributesPrivate' => true)); $event = $this->makeEvent($this->getUser()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); @@ -84,7 +86,7 @@ public function testAllUserAttrsPrivate() { } public function testSomeUserAttrsPrivate() { - $es = new EventSerializer(array('privateAttrNames' => array('firstName', 'bizzle'))); + $es = new EventSerializer(array('privateAttributeNames' => array('firstName', 'bizzle'))); $event = $this->makeEvent($this->getUser()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithSomeAttrsHidden()); @@ -100,7 +102,7 @@ public function testPerUserPrivateAttr() { } public function testPerUserPrivateAttrPlusGlobalPrivateAttrs() { - $es = new EventSerializer(array('privateAttrNames' => array('firstName', 'bizzle'))); + $es = new EventSerializer(array('privateAttributeNames' => array('firstName', 'bizzle'))); $event = $this->makeEvent($this->getUserSpecifyingOwnPrivateAttr()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); From 0bac87ff1cb2d94b1202b5e1696185684d9ae4b9 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 18 Oct 2017 16:13:44 -0700 Subject: [PATCH 126/150] typo --- src/LaunchDarkly/LDUserBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDUserBuilder.php b/src/LaunchDarkly/LDUserBuilder.php index 58843aefe..ad91ec7d0 100644 --- a/src/LaunchDarkly/LDUserBuilder.php +++ b/src/LaunchDarkly/LDUserBuilder.php @@ -24,7 +24,7 @@ public function secondary($secondary) { return $this; } - public function privateSecondary($seondary) { + public function privateSecondary($secondary) { array_push($this->_privateAttributeNames, 'secondary'); return $this->secondary($secondary); } From 7475d87995b785416617f8266eb11087b34a6f2c Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 18 Oct 2017 16:13:50 -0700 Subject: [PATCH 127/150] unit tests for user builder --- tests/LDUserTest.php | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/LDUserTest.php b/tests/LDUserTest.php index 9253ad415..fd8a635dc 100644 --- a/tests/LDUserTest.php +++ b/tests/LDUserTest.php @@ -28,48 +28,117 @@ public function testLDUserSecondary() { $this->assertEquals("secondary", $user->getSecondary()); } + public function testLDUserPrivateSecondary() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateSecondary("secondary")->build(); + $this->assertEquals("secondary", $user->getSecondary()); + $this->assertEquals(array("secondary"), $user->getPrivateAttributeNames()); + } + public function testLDUserIP() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->ip("127.0.0.1")->build(); $this->assertEquals("127.0.0.1", $user->getIP()); } + public function testLDUserPrivateIP() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateIp("127.0.0.1")->build(); + $this->assertEquals("127.0.0.1", $user->getIP()); + $this->assertEquals(array("ip"), $user->getPrivateAttributeNames()); + } + public function testLDUserCountry() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->country("US")->build(); $this->assertEquals("US", $user->getCountry()); } + public function testLDUserPrivateCountry() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateCountry("US")->build(); + $this->assertEquals("US", $user->getCountry()); + $this->assertEquals(array("country"), $user->getPrivateAttributeNames()); + } + public function testLDUserEmail() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->email("foo+test@bar.com")->build(); $this->assertEquals("foo+test@bar.com", $user->getEmail()); } + public function testLDUserPrivateEmail() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateEmail("foo+test@bar.com")->build(); + $this->assertEquals("foo+test@bar.com", $user->getEmail()); + $this->assertEquals(array("email"), $user->getPrivateAttributeNames()); + } + public function testLDUserName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->name("Foo Bar")->build(); $this->assertEquals("Foo Bar", $user->getName()); } + public function testLDUserPrivateName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateName("Foo Bar")->build(); + $this->assertEquals("Foo Bar", $user->getName()); + $this->assertEquals(array("name"), $user->getPrivateAttributeNames()); + } + public function testLDUserAvatar() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->avatar("http://www.gravatar.com/avatar/1")->build(); $this->assertEquals("http://www.gravatar.com/avatar/1", $user->getAvatar()); } + public function testLDUserPrivateAvatar() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateAvatar("http://www.gravatar.com/avatar/1")->build(); + $this->assertEquals("http://www.gravatar.com/avatar/1", $user->getAvatar()); + $this->assertEquals(array("avatar"), $user->getPrivateAttributeNames()); + } + public function testLDUserFirstName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->firstName("Foo")->build(); $this->assertEquals("Foo", $user->getFirstName()); } + public function testLDUserPrivateFirstName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateFirstName("Foo")->build(); + $this->assertEquals("Foo", $user->getFirstName()); + $this->assertEquals(array("firstName"), $user->getPrivateAttributeNames()); + } + public function testLDUserLastName() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->lastName("Bar")->build(); $this->assertEquals("Bar", $user->getLastName()); } + public function testLDUserPrivateLastName() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateLastName("Bar")->build(); + $this->assertEquals("Bar", $user->getLastName()); + $this->assertEquals(array("lastName"), $user->getPrivateAttributeNames()); + } + + public function testLDUserCustom() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->customAttribute("foo", "bar")->customAttribute("baz", "boo")->build(); + $this->assertEquals(array("foo" => "bar", "baz" => "boo"), $user->getCustom()); + } + + public function testLDUserPrivateCustom() { + $builder = new LDUserBuilder("foo@bar.com"); + $user = $builder->privateCustomAttribute("foo", "bar")->privateCustomAttribute("baz", "boo")->build(); + $this->assertEquals(array("foo" => "bar", "baz" => "boo"), $user->getCustom()); + $this->assertEquals(array("foo", "baz"), $user->getPrivateAttributeNames()); + } + public function testLDUserAnonymous() { $builder = new LDUserBuilder("foo@bar.com"); $user = $builder->anonymous(true)->build(); From 913146e7bfa626879cfb52c31221a0ca8ac9de94 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 18 Oct 2017 16:19:15 -0700 Subject: [PATCH 128/150] factor out common logic --- src/LaunchDarkly/EventSerializer.php | 39 +++++++++++----------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/LaunchDarkly/EventSerializer.php b/src/LaunchDarkly/EventSerializer.php index add0d1bb8..5b7d40e6e 100644 --- a/src/LaunchDarkly/EventSerializer.php +++ b/src/LaunchDarkly/EventSerializer.php @@ -35,10 +35,19 @@ private function filterEvent($e) { return $ret; } - private function isPrivateAttr($name, $userPrivateAttrs) { - return ($this->_allAttrsPrivate || - array_search($name, $userPrivateAttrs) !== FALSE || - array_search($name, $this->_privateAttrNames) !== FALSE); + private function filterAttrs($attrs, &$json, $userPrivateAttrs, &$allPrivateAttrs) { + foreach ($attrs as $key => $value) { + if ($value != null) { + if ($this->_allAttrsPrivate || + array_search($key, $userPrivateAttrs) !== FALSE || + array_search($key, $this->_privateAttrNames) !== FALSE) { + $allPrivateAttrs[$key] = true; + } + else { + $json[$key] = $value; + } + } + } } private function serializeUser($user) { @@ -57,28 +66,10 @@ private function serializeUser($user) { 'lastName' => $user->getLastName(), 'anonymous' => $user->getAnonymous() ); - foreach ($attrs as $key => $value) { - if ($value != null) { - if ($this->isPrivateAttr($key, $userPrivateAttrs)) { - $allPrivateAttrs[$key] = $key; - } - else { - $json[$key] = $value; - } - } - } + $this->filterAttrs($attrs, $json, $userPrivateAttrs, $allPrivateAttrs); if (!empty($user->getCustom())) { $customs = array(); - foreach ($user->getCustom() as $key => $value) { - if ($value != null) { - if ($this->isPrivateAttr($key, $userPrivateAttrs)) { - $allPrivateAttrs[$key] = $key; - } - else { - $customs[$key] = $value; - } - } - } + $this->filterAttrs($user->getCustom(), $customs, $userPrivateAttrs, $allPrivateAttrs); $json['custom'] = $customs; } if (count($allPrivateAttrs)) { From 2cfebd25f80bf467c7a4073053d1aa7c886e993c Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 20 Oct 2017 13:38:29 -0700 Subject: [PATCH 129/150] stop trying to do HTTP after we get a 401 --- src/LaunchDarkly/EventProcessor.php | 14 ++++++++++++-- src/LaunchDarkly/EventPublisher.php | 6 +++++- src/LaunchDarkly/GuzzleEventPublisher.php | 7 +++++-- src/LaunchDarkly/GuzzleFeatureRequester.php | 21 ++++++++++++++++++--- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index f408ac635..726ccac5d 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -10,12 +10,15 @@ class EventProcessor { private $_queue; private $_capacity; private $_timeout; + private $_logger; + private $_stopped = FALSE; public function __construct($sdkKey, $options = array()) { $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; + $this->_logger = $options['logger']; $this->_queue = array(); } @@ -43,13 +46,20 @@ public function enqueue($event) { * @return bool Whether the events were successfully published */ public function flush() { - if (empty($this->_queue)) { + if ($this->_stopped || empty($this->_queue)) { return null; } $payload = json_encode($this->_queue); - return $this->_eventPublisher->publish($payload); + $this->queue = array(); + + try { + $this->_eventPublisher->publish($payload); + } catch (InvalidSDKException $e) { + $this->_logger->error("Received 401 error, no further events will be posted during lifetime of LD client since SDK key is invalid"); + $this->_stopped = TRUE; + } } /** diff --git a/src/LaunchDarkly/EventPublisher.php b/src/LaunchDarkly/EventPublisher.php index 0b21d6fb7..da3980b7c 100644 --- a/src/LaunchDarkly/EventPublisher.php +++ b/src/LaunchDarkly/EventPublisher.php @@ -18,4 +18,8 @@ public function __construct($sdkKey, array $options); * @return bool Whether the events were successfully published */ public function publish($payload); -} \ No newline at end of file +} + +class InvalidSDKKeyException extends \Exception +{ +} diff --git a/src/LaunchDarkly/GuzzleEventPublisher.php b/src/LaunchDarkly/GuzzleEventPublisher.php index 27c728110..12b1431d8 100644 --- a/src/LaunchDarkly/GuzzleEventPublisher.php +++ b/src/LaunchDarkly/GuzzleEventPublisher.php @@ -47,16 +47,19 @@ function __construct($sdkKey, array $options = array()) { public function publish($payload) { $client = new Client(['base_uri' => $this->_eventsUri]); + $response = null; try { $options = $this->_requestOptions; $options['body'] = $payload; $response = $client->request('POST', '/bulk', $options); - - return $response->getStatusCode() < 300; } catch (\Exception $e) { $this->_logger->warning("GuzzleEventPublisher::publish caught $e"); return false; } + if ($response && ($response->getStatusCode() == 401)) { + throw new InvalidSDKKeyException(); + } + return $response && ($response->getStatusCode() < 300); } } \ No newline at end of file diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index af3e006df..fb301c9c1 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -21,6 +21,8 @@ class GuzzleFeatureRequester implements FeatureRequester private $_logger; /** @var boolean */ private $_loggedCacheNotice = FALSE; + /** @var boolean */ + private $_stopped = FALSE; function __construct($baseUri, $sdkKey, $options) { @@ -55,6 +57,9 @@ function __construct($baseUri, $sdkKey, $options) */ public function get($key) { + if ($this->_stopped) { + return null; + } try { $uri = $this->_baseUri . self::SDK_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); @@ -65,7 +70,7 @@ public function get($key) if ($code == 404) { $this->_logger->warning("GuzzleFeatureRequester::get returned 404. Feature flag does not exist for key: " . $key); } else { - $this->_logger->error("GuzzleFeatureRequester::get received an unexpected HTTP status code $code"); + $this->handleUnexpectedStatus($code, "GuzzleFeatureRequester::get"); } return null; } @@ -77,15 +82,25 @@ public function get($key) * @return array()|null The decoded FeatureFlags, or null if missing */ public function getAll() { + if ($this->_stopped) { + return null; + } try { $uri = $this->_baseUri . self::SDK_FLAGS; $response = $this->_client->get($uri, $this->_defaults); $body = $response->getBody(); return array_map(FeatureFlag::getDecoder(), json_decode($body, true)); } catch (BadResponseException $e) { - $code = $e->getResponse()->getStatusCode(); - $this->_logger->error("GuzzleFeatureRequester::getAll received an unexpected HTTP status code $code"); + $this->handleUnexpectedStatus($e->getResponse()->getStatusCode(), "GuzzleFeatureRequester::getAll"); return null; } } + + private function handleUnexpectedStatus($code, $method) { + $this->_logger->error("$method received an unexpected HTTP status code $code"); + if ($code == 401) { + $this->_logger->error("Received 401 error, no further feature requests will be made during lifetime of LD client since SDK key is invalid"); + $this->stopped = TRUE; + } + } } \ No newline at end of file From 29ad4618c96576c8baaafe6cb934b03af7e967f7 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 20 Oct 2017 14:47:16 -0700 Subject: [PATCH 130/150] better implementation - put entire client offline the first time we see a 401 --- src/LaunchDarkly/CurlEventPublisher.php | 13 +++++--- src/LaunchDarkly/EventProcessor.php | 10 ++---- src/LaunchDarkly/EventPublisher.php | 4 --- src/LaunchDarkly/GuzzleFeatureRequester.php | 11 +------ src/LaunchDarkly/LDClient.php | 35 +++++++++++++++++++-- 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php index 96131ed55..b19e91e93 100644 --- a/src/LaunchDarkly/CurlEventPublisher.php +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -55,7 +55,7 @@ public function publish($payload) { private function createArgs($payload) { $scheme = $this->_ssl ? "https://" : "http://"; - $args = " -X POST"; + $args = " -s -i -X POST"; $args.= " -H 'Content-Type: application/json'"; $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; @@ -66,8 +66,13 @@ private function createArgs($payload) { } private function makeRequest($args) { - $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; - shell_exec($cmd); - return true; + $cmd = $this->_curl . " " . $args . " 2>&1"; + $output = shell_exec($cmd); + preg_match('#^HTTP/[^ ]* *([0-9]*)#', $output, $matches); + $status = intval($matches[1]); + if ($status == 401) { + throw new InvalidSDKKeyException(); + } + return ($status < 300); } } \ No newline at end of file diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index 726ccac5d..b144fa805 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -11,7 +11,6 @@ class EventProcessor { private $_capacity; private $_timeout; private $_logger; - private $_stopped = FALSE; public function __construct($sdkKey, $options = array()) { $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); @@ -46,7 +45,7 @@ public function enqueue($event) { * @return bool Whether the events were successfully published */ public function flush() { - if ($this->_stopped || empty($this->_queue)) { + if (empty($this->_queue)) { return null; } @@ -54,12 +53,7 @@ public function flush() { $this->queue = array(); - try { - $this->_eventPublisher->publish($payload); - } catch (InvalidSDKException $e) { - $this->_logger->error("Received 401 error, no further events will be posted during lifetime of LD client since SDK key is invalid"); - $this->_stopped = TRUE; - } + $this->_eventPublisher->publish($payload); } /** diff --git a/src/LaunchDarkly/EventPublisher.php b/src/LaunchDarkly/EventPublisher.php index da3980b7c..bfcc27764 100644 --- a/src/LaunchDarkly/EventPublisher.php +++ b/src/LaunchDarkly/EventPublisher.php @@ -19,7 +19,3 @@ public function __construct($sdkKey, array $options); */ public function publish($payload); } - -class InvalidSDKKeyException extends \Exception -{ -} diff --git a/src/LaunchDarkly/GuzzleFeatureRequester.php b/src/LaunchDarkly/GuzzleFeatureRequester.php index fb301c9c1..0c913fff0 100644 --- a/src/LaunchDarkly/GuzzleFeatureRequester.php +++ b/src/LaunchDarkly/GuzzleFeatureRequester.php @@ -21,8 +21,6 @@ class GuzzleFeatureRequester implements FeatureRequester private $_logger; /** @var boolean */ private $_loggedCacheNotice = FALSE; - /** @var boolean */ - private $_stopped = FALSE; function __construct($baseUri, $sdkKey, $options) { @@ -57,9 +55,6 @@ function __construct($baseUri, $sdkKey, $options) */ public function get($key) { - if ($this->_stopped) { - return null; - } try { $uri = $this->_baseUri . self::SDK_FLAGS . "/" . $key; $response = $this->_client->get($uri, $this->_defaults); @@ -82,9 +77,6 @@ public function get($key) * @return array()|null The decoded FeatureFlags, or null if missing */ public function getAll() { - if ($this->_stopped) { - return null; - } try { $uri = $this->_baseUri . self::SDK_FLAGS; $response = $this->_client->get($uri, $this->_defaults); @@ -99,8 +91,7 @@ public function getAll() { private function handleUnexpectedStatus($code, $method) { $this->_logger->error("$method received an unexpected HTTP status code $code"); if ($code == 401) { - $this->_logger->error("Received 401 error, no further feature requests will be made during lifetime of LD client since SDK key is invalid"); - $this->stopped = TRUE; + throw new InvalidSDKKeyException(); } } } \ No newline at end of file diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 64d007b52..53b0323ec 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -5,6 +5,13 @@ use Monolog\Logger; use Psr\Log\LoggerInterface; +/** + * Used internally. + */ +class InvalidSDKKeyException extends \Exception +{ +} + /** * A client for the LaunchDarkly API. */ @@ -144,7 +151,12 @@ public function variation($key, $user, $default = false) { if ($user->isKeyBlank()) { $this->_logger->warning("User key is blank. Flag evaluation will proceed, but the user will not be stored in LaunchDarkly."); } - $flag = $this->_featureRequester->get($key); + try { + $flag = $this->_featureRequester->get($key); + } catch (InvalidSDKKeyException $e) { + $this->handleInvalidSDKKey(); + return $default; + } if (is_null($flag)) { $this->_sendFlagRequestEvent($key, $user, $default, $default); @@ -252,7 +264,15 @@ public function allFlags($user) { $this->_logger->warn("allFlags called with null user or null/empty user key! Returning null"); return null; } - $flags = $this->_featureRequester->getAll(); + if ($this->isOffline()) { + return null; + } + try { + $flags = $this->_featureRequester->getAll(); + } catch (InvalidSDKKeyException $e) { + $this->handleInvalidSDKKey(); + return null; + } if ($flags === null) { return null; } @@ -285,7 +305,11 @@ public function secureModeHash($user) { */ public function flush() { - return $this->_eventProcessor->flush(); + try { + return $this->_eventProcessor->flush(); + } catch (InvalidSDKKeyException $e) { + $this->handleInvalidSDKKey()); + } } /** @@ -310,4 +334,9 @@ protected function _get_default($key, $default) { return $default; } } + + protected function handleInvalidSDKKey() { + $this->_logger->error("Received 401 error, no further HTTP requests will be made during lifetime of LDClient since SDK key is invalid"); + $this->_offline = true; + } } From 86b452414e2830ad4609217bec436b0b63a24f1c Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 20 Oct 2017 14:54:52 -0700 Subject: [PATCH 131/150] revert unneeded changes --- src/LaunchDarkly/EventProcessor.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index b144fa805..f408ac635 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -10,14 +10,12 @@ class EventProcessor { private $_queue; private $_capacity; private $_timeout; - private $_logger; public function __construct($sdkKey, $options = array()) { $this->_eventPublisher = $this->getEventPublisher($sdkKey, $options); $this->_capacity = $options['capacity']; $this->_timeout = $options['timeout']; - $this->_logger = $options['logger']; $this->_queue = array(); } @@ -51,9 +49,7 @@ public function flush() { $payload = json_encode($this->_queue); - $this->queue = array(); - - $this->_eventPublisher->publish($payload); + return $this->_eventPublisher->publish($payload); } /** From 02f4cefef32566e0928ed8c8a072cc313980b5c0 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 20 Oct 2017 14:57:10 -0700 Subject: [PATCH 132/150] revert CurlEventPublisher changes - see PR comments --- src/LaunchDarkly/CurlEventPublisher.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/LaunchDarkly/CurlEventPublisher.php b/src/LaunchDarkly/CurlEventPublisher.php index b19e91e93..96131ed55 100644 --- a/src/LaunchDarkly/CurlEventPublisher.php +++ b/src/LaunchDarkly/CurlEventPublisher.php @@ -55,7 +55,7 @@ public function publish($payload) { private function createArgs($payload) { $scheme = $this->_ssl ? "https://" : "http://"; - $args = " -s -i -X POST"; + $args = " -X POST"; $args.= " -H 'Content-Type: application/json'"; $args.= " -H " . escapeshellarg("Authorization: " . $this->_sdkKey); $args.= " -H 'User-Agent: PHPClient/" . LDClient::VERSION . "'"; @@ -66,13 +66,8 @@ private function createArgs($payload) { } private function makeRequest($args) { - $cmd = $this->_curl . " " . $args . " 2>&1"; - $output = shell_exec($cmd); - preg_match('#^HTTP/[^ ]* *([0-9]*)#', $output, $matches); - $status = intval($matches[1]); - if ($status == 401) { - throw new InvalidSDKKeyException(); - } - return ($status < 300); + $cmd = $this->_curl . " " . $args . ">> /dev/null 2>&1 &"; + shell_exec($cmd); + return true; } } \ No newline at end of file From 15fd0efe552f399839380855cfbd6c4ae7923356 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 20 Oct 2017 17:42:33 -0700 Subject: [PATCH 133/150] typo --- src/LaunchDarkly/LDClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 53b0323ec..464bed943 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -308,7 +308,7 @@ public function flush() try { return $this->_eventProcessor->flush(); } catch (InvalidSDKKeyException $e) { - $this->handleInvalidSDKKey()); + $this->handleInvalidSDKKey(); } } From 05b5594f4f64c1bcd4dd40f7f822a72c292a1dc8 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Dec 2017 20:17:37 -0800 Subject: [PATCH 134/150] closure fix for PHP 5.3 --- src/LaunchDarkly/LDClient.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 964a8990b..5ede18d93 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -261,8 +261,9 @@ public function allFlags($user) { * @param $flag FeatureFlag * @return mixed|null */ - $eval = function($flag) use($user) { - return $flag->evaluate($user, $this->_featureRequester)->getValue(); + $fr = $this->_featureRequester; + $eval = function($flag) use($user, $fr) { + return $flag->evaluate($user, $fr)->getValue(); }; return array_map($eval, $flags); From bf219598c5b038d3cc6e44e4f0632ee2be9a7394 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Dec 2017 20:22:05 -0800 Subject: [PATCH 135/150] backporting to PHP 5.3 --- src/LaunchDarkly/GuzzleEventPublisher.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/LaunchDarkly/GuzzleEventPublisher.php b/src/LaunchDarkly/GuzzleEventPublisher.php index 27c728110..89bbf9655 100644 --- a/src/LaunchDarkly/GuzzleEventPublisher.php +++ b/src/LaunchDarkly/GuzzleEventPublisher.php @@ -1,7 +1,7 @@ _eventsUri = LDClient::DEFAULT_EVENTS_URI; } - $this->_requestOptions = [ - 'headers' => [ + $this->_requestOptions = array( + 'headers' => array( 'Content-Type' => 'application/json', 'Authorization' => $this->_sdkKey, 'User-Agent' => 'PHPClient/' . LDClient::VERSION, 'Accept' => 'application/json' - ], + ), 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ]; } public function publish($payload) { - $client = new Client(['base_uri' => $this->_eventsUri]); + $client = new Client($this->_eventsUri); try { $options = $this->_requestOptions; From afc6d7179bea6999c4a170180cb80e743b69e600 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Dec 2017 20:25:10 -0800 Subject: [PATCH 136/150] use latest available php in build image --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index fc2e68831..a6dfd4abd 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: php: - version: 5.3.29 + version: 5.3.25 services: - redis - docker From 8d6355a28fe8ff4b5b057e69562a5d07fa16400b Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Dec 2017 20:29:59 -0800 Subject: [PATCH 137/150] partially revert merge of build file from master --- circle.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/circle.yml b/circle.yml index a6dfd4abd..a81ace970 100644 --- a/circle.yml +++ b/circle.yml @@ -5,14 +5,6 @@ machine: - redis - docker -dependencies: - pre: - - yes '' | pecl install -f apcu-4.0.10 - - echo "extension=apcu.so" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini - - echo "apc.enable_cli = 1" | sudo tee -a /opt/circleci/php/$(phpenv global)/etc/php.ini - - docker pull php - - docker pull nyanpass/php5.5 - test: override: # syntax check php files @@ -21,15 +13,3 @@ test: - vendor/bin/phpunit tests --coverage-text - vendor/bin/phpunit integration-tests/LDDFeatureRequesterTest.php - - - composer update && vendor/bin/phpunit tests - - composer update --prefer-lowest && vendor/bin/phpunit tests - - - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client php:7.0-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" - - - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" - - - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" From c518b74f9bd58d4407a0312c270275186086d63b Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 09:11:39 -0800 Subject: [PATCH 138/150] typo --- src/LaunchDarkly/GuzzleEventPublisher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/GuzzleEventPublisher.php b/src/LaunchDarkly/GuzzleEventPublisher.php index 89bbf9655..ee393161d 100644 --- a/src/LaunchDarkly/GuzzleEventPublisher.php +++ b/src/LaunchDarkly/GuzzleEventPublisher.php @@ -42,7 +42,7 @@ function __construct($sdkKey, array $options = array()) { ), 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] - ]; + ); } public function publish($payload) { From cf7b3bba861e9168a7f3505b6f2b07c71005c865 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 13:50:06 -0800 Subject: [PATCH 139/150] rm reference to cache package --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6ad778a08..6c8d4a348 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ Quick setup php composer.phar require launchdarkly/launchdarkly-php php composer.phar require "guzzlehttp/guzzle:6.2.1" - php composer.phar require "kevinrob/guzzle-cache-middleware": "1.4.1" 1. After installing, require Composer's autoloader: From 805b5c8ee716ca203c3c472297a1fa59cdbb90e2 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 14:00:28 -0800 Subject: [PATCH 140/150] backport to PHP 5.3 --- integration-tests/LDDFeatureRequesterTest.php | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 6d41355ed..7974066b4 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -17,7 +17,7 @@ public function testGet() { "scheme" => "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient(static::API_KEY, array('feature_requester_class' => LDDFeatureRequester::class)); + $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester')); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -35,7 +35,7 @@ public function testGetApc() { "scheme" => "tcp", "host" => 'localhost', "port" => 6379)); - $client = new LDClient(static::API_KEY, array('feature_requester_class' => ApcLDDFeatureRequester::class, + $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\ApcLDDFeatureRequester', 'apc_expiration' => 1)); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -65,7 +65,7 @@ public function testGetApcu() { ]); $client = new LDClient(static::API_KEY, [ - 'feature_requester_class' => ApcuLDDFeatureRequester::class, + 'feature_requester_class' => 'LaunchDarkly\ApcuLDDFeatureRequester', 'apc_expiration' => 1 ]); @@ -94,7 +94,7 @@ public function testGetAllWithoutFeatures() ]); $redis->flushall(); - $client = new LDClient(static::API_KEY, ['feature_requester_class' => LDDFeatureRequester::class]); + $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester')); $user = new LDUser(static::API_KEY); $allFlags = $client->allFlags($user); @@ -111,7 +111,7 @@ public function testGetAll() 'host' => 'localhost', 'port' => 6379, ]); - $client = new LDClient(static::API_KEY, ['feature_requester_class' => LDDFeatureRequester::class]); + $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester')); $redis->hset('launchdarkly:features', $featureKey, $this->gen_feature($featureKey, $featureValue)); $user = new LDUser(static::API_KEY); $allFlags = $client->allFlags($user); @@ -122,52 +122,52 @@ public function testGetAll() } private function gen_feature($key, $val) { - $data = [ + $data = array( 'name' => 'Feature ' . $key, 'key' => $key, 'kind' => 'flag', 'salt' => 'Zm9v', 'on' => true, - 'variations' => [ + 'variations' => array( $val, false, - ], + ), 'commitDate' => '2015-09-08T21:24:16.712Z', 'creationDate' => '2015-09-08T21:06:16.527Z', 'version' => 4, - 'prerequisites' => [], - 'targets' => [ - [ - 'values' => [ + 'prerequisites' => array(), + 'targets' => array( + array( + 'values' => array( $val, - ], + ), 'variation' => 0, - ], - [ - 'values' => [ + ), + array( + 'values' => array( false, - ], + ), 'variation' => 1, - ], - ], - 'rules' => [], - 'fallthrough' => [ - 'rollout' => [ - 'variations' => [ - [ + ), + ), + 'rules' => array(), + 'fallthrough' => array( + 'rollout' => array( + 'variations' => array( + array( 'variation' => 0, 'weight' => 95000, - ], - [ + ), + array( 'variation' => 1, 'weight' => 5000, - ], - ], - ], - ], + ), + ), + ), + ), 'offVariation' => null, 'deleted' => false, - ]; + ); return \json_encode($data); } From a115976c4ee35242f3393f9519926f6c28d461be Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 14:05:30 -0800 Subject: [PATCH 141/150] backport to PHP 5.3 --- integration-tests/LDDFeatureRequesterTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/integration-tests/LDDFeatureRequesterTest.php b/integration-tests/LDDFeatureRequesterTest.php index 7974066b4..b4d82780d 100644 --- a/integration-tests/LDDFeatureRequesterTest.php +++ b/integration-tests/LDDFeatureRequesterTest.php @@ -58,16 +58,16 @@ public function testGetApcu() { self::markTestSkipped('Install `apcu` extension to run this test.'); } - $redis = new Client([ + $redis = new Client(array( 'scheme' => 'tcp', 'host' => 'localhost', 'port' => 6379 - ]); + )); - $client = new LDClient(static::API_KEY, [ + $client = new LDClient(static::API_KEY, array( 'feature_requester_class' => 'LaunchDarkly\ApcuLDDFeatureRequester', 'apc_expiration' => 1 - ]); + )); $builder = new LDUserBuilder(3); $user = $builder->build(); @@ -87,11 +87,11 @@ public function testGetApcu() { public function testGetAllWithoutFeatures() { - $redis = new \Predis\Client([ + $redis = new \Predis\Client(array( 'scheme' => 'tcp', 'host' => 'localhost', 'port' => 6379, - ]); + )); $redis->flushall(); $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester')); @@ -106,11 +106,11 @@ public function testGetAll() $featureKey = 'foo'; $featureValue = 'bar'; - $redis = new \Predis\Client([ + $redis = new \Predis\Client(array( 'scheme' => 'tcp', 'host' => 'localhost', 'port' => 6379, - ]); + )); $client = new LDClient(static::API_KEY, array('feature_requester_class' => 'LaunchDarkly\LDDFeatureRequester')); $redis->hset('launchdarkly:features', $featureKey, $this->gen_feature($featureKey, $featureValue)); $user = new LDUser(static::API_KEY); From 625c65f5c9b46fb6d1a761246c4c2fd653e60d07 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 14:21:00 -0800 Subject: [PATCH 142/150] documentation fixes for PHP 5.3 --- README.md | 10 ++++------ composer.json | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6c8d4a348..8df0f1fa0 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Quick setup 1. Install the PHP SDK and monolog for logging with [Composer](https://getcomposer.org/) php composer.phar require launchdarkly/launchdarkly-php - php composer.phar require "guzzlehttp/guzzle:6.2.1" + php composer.phar require "guzzle/guzzle:dev-master#ecb935d2d0ecd8cddae4dcfb90515cac5e2cb023" 1. After installing, require Composer's autoloader: @@ -44,7 +44,7 @@ Fetching flags There are two distinct methods of integrating LaunchDarkly in a PHP environment. -* [Guzzle Cache Middleware](https://github.com/Kevinrob/guzzle-cache-middleware) to request and cache HTTP responses in an in-memory array (default) +* [Guzzle](https://github.com/launchdarkly/guzzle3) with its [cache plugin](https://github.com/launchdarkly/guzzle3/blob/master/docs/plugins/cache-plugin.rst) to request and cache HTTP responses in an in-memory array (default) -- note, this is a forked older version of Guzzle for PHP 5.3 compatibility * [ld-relay](https://github.com/launchdarkly/ld-relay) to retrieve and store flags in Redis (recommended) We strongly recommend using the ld-relay. Per-flag caching (Guzzle method) is only intended for low-throughput environments. @@ -54,15 +54,13 @@ Using Guzzle Require Guzzle as a dependency: - php composer.phar require "guzzlehttp/guzzle:6.2.1" - php composer.phar require "kevinrob/guzzle-cache-middleware:1.4.1" + php composer.phar require "guzzle/guzzle:dev-master#ecb935d2d0ecd8cddae4dcfb90515cac5e2cb023" It will then be used as the default way of fetching flags. With Guzzle, you could persist your cache somewhere other than the default in-memory store, like Memcached or Redis. You could then specify your cache when initializing the client with the [cache option](https://github.com/launchdarkly/php-client/blob/master/src/LaunchDarkly/LDClient.php#L44). - $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", array("cache" => $cacheStorage)); - + $client = new LaunchDarkly\LDClient("YOUR_SDK_KEY", array("cache_storage" => $cacheStorage)); Using LD-Relay ============== diff --git a/composer.json b/composer.json index 1ef7802ee..8e56a5722 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "predis/predis": "^1.0" }, "suggested": { - "guzzle/guzzle": "(^6.2.1) Required when using GuzzleEventPublisher or the default FeatureRequester", + "guzzle/guzzle": "(^dev-master#ecb935d2d0ecd8cddae4dcfb90515cac5e2cb023) Required when using GuzzleEventPublisher or the default FeatureRequester", "predis/predis": "(^1.0) Required when using LDDFeatureRequester" }, "autoload": { From 2f99fefd3b7dd87e05d8def46f2e90cb587afd46 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 14:24:13 -0800 Subject: [PATCH 143/150] documentation fixes for PHP 5.3 --- CHANGELOG.md | 4 ---- src/LaunchDarkly/LDClient.php | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 899970378..5f54e53d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,6 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. ### Added - New `flush` method forces events to be published to the LaunchDarkly service. This can be useful if `LDClient` is not automatically destroyed at the end of a request. Thanks @foxted! -### Fixed -- Documentation comment references the correct namespace for `CacheStorageInterface`. Thanks @pmeth! - ## [2.2.0] - 2017-06-06 ### Added - Support for [publishing events via ld-relay](README.md#using-ld-relay) @@ -18,7 +15,6 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. ## [2.1.2] - 2017-04-27 ### Changed -- Relaxed the requirement on `kevinrob/guzzle-cache-middleware` for the default `GuzzleFeatureRequester`. - Added package suggestions in `composer.json`. ### Fixed diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 5ede18d93..d03faaa0d 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -41,7 +41,7 @@ class LDClient { * - events_uri: Base URI for sending events to LaunchDarkly. Defaults to 'https://events.launchdarkly.com' * - timeout: Float describing the maximum length of a request in seconds. Defaults to 3 * - connect_timeout: Float describing the number of seconds to wait while trying to connect to a server. Defaults to 3 - * - cache: An optional Kevinrob\GuzzleCache\Storage\CacheStorageInterface. Defaults to an in-memory cache. + * - cache_storage: An optional Guzzle\Plugin\Cache\DefaultCacheStorage. Defaults to an in-memory cache. * - send_events: An optional bool that can disable the sending of events to LaunchDarkly. Defaults to false. * - logger: An optional Psr\Log\LoggerInterface. Defaults to a Monolog\Logger sending all messages to the php error_log. * - offline: An optional boolean which will disable all network calls and always return the default value. Defaults to false. From b7a007d05d53725863bb2cb1ff265dbe3fceeeee Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 15:05:48 -0800 Subject: [PATCH 144/150] backport to Guzzle 3 --- src/LaunchDarkly/GuzzleEventPublisher.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/LaunchDarkly/GuzzleEventPublisher.php b/src/LaunchDarkly/GuzzleEventPublisher.php index ee393161d..6b280c75e 100644 --- a/src/LaunchDarkly/GuzzleEventPublisher.php +++ b/src/LaunchDarkly/GuzzleEventPublisher.php @@ -23,6 +23,8 @@ class GuzzleEventPublisher implements EventPublisher /** @var LoggerInterface */ private $_logger; /** @var mixed[] */ + private $_requestHeaders; + /** @var mixed[] */ private $_requestOptions; function __construct($sdkKey, array $options = array()) { @@ -33,13 +35,13 @@ function __construct($sdkKey, array $options = array()) { } else { $this->_eventsUri = LDClient::DEFAULT_EVENTS_URI; } + $this->_requestHeaders = array( + 'Content-Type' => 'application/json', + 'Authorization' => $this->_sdkKey, + 'User-Agent' => 'PHPClient/' . LDClient::VERSION, + 'Accept' => 'application/json' + ); $this->_requestOptions = array( - 'headers' => array( - 'Content-Type' => 'application/json', - 'Authorization' => $this->_sdkKey, - 'User-Agent' => 'PHPClient/' . LDClient::VERSION, - 'Accept' => 'application/json' - ), 'timeout' => $options['timeout'], 'connect_timeout' => $options['connect_timeout'] ); @@ -49,9 +51,8 @@ public function publish($payload) { $client = new Client($this->_eventsUri); try { - $options = $this->_requestOptions; - $options['body'] = $payload; - $response = $client->request('POST', '/bulk', $options); + $req = $client->post('/bulk', $this->_requestHeaders, $payload, $this->_requestOptions); + $response = $req->send(); return $response->getStatusCode() < 300; } catch (\Exception $e) { From 970e2ce370dd5bd6d98c39b259261e392abf131e Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 15:22:23 -0800 Subject: [PATCH 145/150] make sure flushing the queue actually flushes it --- src/LaunchDarkly/EventProcessor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LaunchDarkly/EventProcessor.php b/src/LaunchDarkly/EventProcessor.php index d803f1966..70181100e 100644 --- a/src/LaunchDarkly/EventProcessor.php +++ b/src/LaunchDarkly/EventProcessor.php @@ -49,6 +49,8 @@ public function flush() { $payload = json_encode($this->_queue); + $this->_queue = array(); + return $this->_eventPublisher->publish($payload); } From 82f97b7c91148d59064d6ca186c045000a870ce2 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Dec 2017 15:23:10 -0800 Subject: [PATCH 146/150] backporting to PHP 5.3 --- src/LaunchDarkly/FeatureFlag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LaunchDarkly/FeatureFlag.php b/src/LaunchDarkly/FeatureFlag.php index 611910546..7b2be6d61 100644 --- a/src/LaunchDarkly/FeatureFlag.php +++ b/src/LaunchDarkly/FeatureFlag.php @@ -306,7 +306,7 @@ class Prerequisite { /** @var int */ private $_variation = null; - protected function __construct($key, $variation) { + public function __construct($key, $variation) { $this->_key = $key; $this->_variation = $variation; } From a3b86caf0e92c2a47ad90f862c05ece8e2494e61 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Mon, 1 Jan 2018 12:36:33 -0800 Subject: [PATCH 147/150] use underscore naming convention for config options --- src/LaunchDarkly/EventSerializer.php | 4 ++-- tests/EventSerializerTest.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/LaunchDarkly/EventSerializer.php b/src/LaunchDarkly/EventSerializer.php index 5b7d40e6e..5dc083163 100644 --- a/src/LaunchDarkly/EventSerializer.php +++ b/src/LaunchDarkly/EventSerializer.php @@ -10,8 +10,8 @@ class EventSerializer { private $_privateAttrNames; public function __construct($options) { - $this->_allAttrsPrivate = isset($options['allAttributesPrivate']) && $options['allAttributesPrivate']; - $this->_privateAttrNames = isset($options['privateAttributeNames']) ? $options['privateAttributeNames'] : array(); + $this->_allAttrsPrivate = isset($options['all_attributes_private']) && $options['all_attributes_private']; + $this->_privateAttrNames = isset($options['private_attribute_names']) ? $options['private_attribute_names'] : array(); } public function serializeEvents($events) { diff --git a/tests/EventSerializerTest.php b/tests/EventSerializerTest.php index 59b4d93c2..432273bc0 100644 --- a/tests/EventSerializerTest.php +++ b/tests/EventSerializerTest.php @@ -78,7 +78,7 @@ public function testAllUserAttrsSerialized() { } public function testAllUserAttrsPrivate() { - $es = new EventSerializer(array('allAttributesPrivate' => true)); + $es = new EventSerializer(array('all_attributes_private' => true)); $event = $this->makeEvent($this->getUser()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); @@ -86,7 +86,7 @@ public function testAllUserAttrsPrivate() { } public function testSomeUserAttrsPrivate() { - $es = new EventSerializer(array('privateAttributeNames' => array('firstName', 'bizzle'))); + $es = new EventSerializer(array('private_attribute_names' => array('firstName', 'bizzle'))); $event = $this->makeEvent($this->getUser()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithSomeAttrsHidden()); @@ -102,7 +102,7 @@ public function testPerUserPrivateAttr() { } public function testPerUserPrivateAttrPlusGlobalPrivateAttrs() { - $es = new EventSerializer(array('privateAttributeNames' => array('firstName', 'bizzle'))); + $es = new EventSerializer(array('private_attribute_names' => array('firstName', 'bizzle'))); $event = $this->makeEvent($this->getUserSpecifyingOwnPrivateAttr()); $json = $es->serializeEvents(array($event)); $expected = $this->makeEvent($this->getUserResultWithAllAttrsHidden()); From 90dfe937b810907b933b0a336a33389278c35e79 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Mon, 1 Jan 2018 12:50:24 -0800 Subject: [PATCH 148/150] document private attribute options (and all user builder setters) --- src/LaunchDarkly/LDClient.php | 2 + src/LaunchDarkly/LDUserBuilder.php | 71 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 1dc276398..cb45560e1 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -49,6 +49,8 @@ class LDClient { * - feature_requester_class: An optional class implementing LaunchDarkly\FeatureRequester, if `feature_requester` is not specified. Defaults to GuzzleFeatureRequester. * - event_publisher: An optional LaunchDarkly\EventPublisher instance. * - event_publisher_class: An optional class implementing LaunchDarkly\EventPublisher, if `event_publisher` is not specified. Defaults to CurlEventPublisher. + * - all_attributes_private: True if no user attributes (other than the key) should be sent back to LaunchDarkly. By default, this is false. + * - private_attribute_names: An optional array of user attribute names to be marked private. Any users sent to LaunchDarkly with this configuration active will have attributes with these names removed. You can also set private attributes on a per-user basis in LDUserBuilder. */ public function __construct($sdkKey, $options = array()) { $this->_sdkKey = $sdkKey; diff --git a/src/LaunchDarkly/LDUserBuilder.php b/src/LaunchDarkly/LDUserBuilder.php index ad91ec7d0..f08b523cb 100644 --- a/src/LaunchDarkly/LDUserBuilder.php +++ b/src/LaunchDarkly/LDUserBuilder.php @@ -1,6 +1,14 @@ builder that helps construct LDUser objects. + * + * Note that all user attributes, except for key and anonymous, can be designated as + * private so that they will not be sent back to LaunchDarkly. You can do this either on a per-user basis in + * LDUserBuilder, or globally via the private_attribute_names and all_attributes_private + * options in the client configuration. + */ class LDUserBuilder { protected $_key = null; protected $_secondary = null; @@ -15,6 +23,9 @@ class LDUserBuilder { protected $_custom = array(); protected $_privateAttributeNames = array(); + /** + * Creates a builder with the specified key. + */ public function __construct($key) { $this->_key = $key; } @@ -29,91 +40,151 @@ public function privateSecondary($secondary) { return $this->secondary($secondary); } + /** + * Sets the IP for a user. + */ public function ip($ip) { $this->_ip = $ip; return $this; } + /** + * Sets the IP for a user, and ensures that the IP attribute will not be sent back to LaunchDarkly. + */ public function privateIp($ip) { array_push($this->_privateAttributeNames, 'ip'); return $this->ip($ip); } + /** + * Sets the country for a user. The country should be a valid ISO 3166-1 + * alpha-2 or alpha-3 code. If it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its name. + * If that fails, a warning will be logged, and the country will not be set. + */ public function country($country) { $this->_country = $country; return $this; } + /** + * Sets the country for a user, and ensures that the country attribute will not be sent back to LaunchDarkly. + * The country should be a valid ISO 3166-1 + * alpha-2 or alpha-3 code. If it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its name. + * If that fails, a warning will be logged, and the country will not be set. + */ public function privateCountry($country) { array_push($this->_privateAttributeNames, 'country'); return $this->country($country); } + /** + * Sets the user's email address. + */ public function email($email) { $this->_email = $email; return $this; } + /** + * Sets the user's email address, and ensures that the email attribute will not be sent back to LaunchDarkly. + */ public function privateEmail($email) { array_push($this->_privateAttributeNames, 'email'); return $this->email($email); } + /** + * Sets the user's full name. + */ public function name($name) { $this->_name = $name; return $this; } + /** + * Sets the user's full name, and ensures that the name attribute will not be sent back to LaunchDarkly. + */ public function privateName($name) { array_push($this->_privateAttributeNames, 'name'); return $this->name($name); } + /** + * Sets the user's avatar. + */ public function avatar($avatar) { $this->_avatar = $avatar; return $this; } + /** + * Sets the user's avatar, and ensures that the avatar attribute will not be sent back to LaunchDarkly. + */ public function privateAvatar($avatar) { array_push($this->_privateAttributeNames, 'avatar'); return $this->avatar($avatar); } + /** + * Sets the user's first name. + */ public function firstName($firstName) { $this->_firstName = $firstName; return $this; } + /** + * Sets the user's first name, and ensures that the first name attribute will not be sent back to LaunchDarkly. + */ public function privateFirstName($firstName) { array_push($this->_privateAttributeNames, 'firstName'); return $this->firstName($firstName); } + /** + * Sets the user's last name. + */ public function lastName($lastName) { $this->_lastName = $lastName; return $this; } + /** + * Sets the user's last name, and ensures that the last name attribute will not be sent back to LaunchDarkly. + */ public function privateLastName($lastName) { array_push($this->_privateAttributeNames, 'lastName'); return $this->lastName($lastName); } + /** + * Sets whether this user is anonymous. The default is false. + */ public function anonymous($anonymous) { $this->_anonymous = $anonymous; return $this; } + /** + * Sets any number of custom attributes for the user. + * @param array $custom An associative array of custom attribute names and values. + */ public function custom($custom) { $this->_custom = $custom; return $this; } + /** + * Sets a single custom attribute for the user. + */ public function customAttribute($customKey, $customValue) { $this->_custom[$customKey] = $customValue; return $this; } + /** + * Sets a single custom attribute for the user, and ensures that the attribute will not be sent back to LaunchDarkly. + */ public function privateCustomAttribute($customKey, $customValue) { array_push($this->_privateAttributeNames, $customKey); return $this->customAttribute($customKey, $customValue); From 5dd9a15cc63ffb9e8cc4bfcaedaba4b4d3cfdf7e Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Wed, 3 Jan 2018 14:15:36 -0800 Subject: [PATCH 149/150] Update PHP version for Circle's Ubuntu 12.04 machine --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 73fa1cac4..8dee97a50 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: php: - version: 5.6.17 + version: 5.6.14 services: - redis - docker @@ -27,4 +27,4 @@ test: - docker run -it -v `pwd`:/php-client php:7.1-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update && vendor/bin/phpunit" - - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" \ No newline at end of file + - docker run -it -v `pwd`:/php-client nyanpass/php5.5:5.5-alpine sh -c "curl -s https://getcomposer.org/installer | php && cd /php-client && /composer.phar update --prefer-lowest && vendor/bin/phpunit" From 2d65ada12618cb58b4395900a7f3109f99af7ef3 Mon Sep 17 00:00:00 2001 From: Arun Bhalla Date: Thu, 4 Jan 2018 16:55:53 -0800 Subject: [PATCH 150/150] Update branch to release 2.4.0 --- CHANGELOG.md | 9 +++++++++ VERSION | 2 +- src/LaunchDarkly/LDClient.php | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f54e53d3..bb727de79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.4.0] - 2018-01-04 +### Added +- Support for [private user attributes](https://docs.launchdarkly.com/docs/private-user-attributes). + +### Changed +- Stop retrying HTTP requests if the API key has been invalidated. +- User bucketing supports integer attributes. Thanks @mlund01! +- Source code complies with the PSR-2 standard. Thanks @valerianpereira! + ## [2.3.0] - 2017-10-06 ### Added - New `flush` method forces events to be published to the LaunchDarkly service. This can be useful if `LDClient` is not automatically destroyed at the end of a request. Thanks @foxted! diff --git a/VERSION b/VERSION index 276cbf9e2..197c4d5c2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.0 +2.4.0 diff --git a/src/LaunchDarkly/LDClient.php b/src/LaunchDarkly/LDClient.php index 934f13e34..4152fb782 100644 --- a/src/LaunchDarkly/LDClient.php +++ b/src/LaunchDarkly/LDClient.php @@ -18,7 +18,7 @@ class InvalidSDKKeyException extends \Exception class LDClient { const DEFAULT_BASE_URI = 'https://app.launchdarkly.com'; const DEFAULT_EVENTS_URI = 'https://events.launchdarkly.com'; - const VERSION = '2.3.0'; + const VERSION = '2.4.0'; /** @var string */ protected $_sdkKey;