diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..521f92d --- /dev/null +++ b/.php_cs @@ -0,0 +1,21 @@ +setFinder( + PhpCsFixer\Finder::create() + ->in($paths) + ->append($paths) + ) + ->setUsingCache(false) + ; +})(); diff --git a/.travis.yml b/.travis.yml index 3d24f7e..81ea2fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,37 +5,51 @@ cache: directories: - $HOME/.composer/cache/files -## PHP versions we test against -php: - - 7.0 - - 7.1 - - nightly - ## Build matrix for lowest and highest possible targets matrix: include: - php: 7.0 - env: dependencies=lowest + env: + - qaExtended=true + - php: 7.1 + - php: nightly + env: + - dropPlatform=false + - php: 7.0 + env: + - dependencies=lowest - php: 7.1 - env: dependencies=lowest + env: + - dependencies=lowest - php: nightly - env: dependencies=lowest + env: + - dependencies=lowest + - dropPlatform=false - php: 7.0 - env: dependencies=highest + env: + - dependencies=highest - php: 7.1 - env: dependencies=highest + env: + - dependencies=highest - php: nightly - env: dependencies=highest + env: + - dependencies=highest + - dropPlatform=false ## Install or update dependencies install: + - composer validate + - if [ -z "$dropPlatform" ]; then composer config --unset platform.php; fi; + - if [ -z "$qaExtended" ]; then phpenv config-rm xdebug.ini || :; fi; - if [ -z "$dependencies" ]; then composer install --prefer-dist; fi; - if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest --prefer-dist -n; fi; - if [ "$dependencies" = "highest" ]; then composer update --prefer-dist -n; fi; - composer show ## Run the actual test -script: make travis +script: + - if [ -z "$qaExtended" ]; then make ci; fi; + - if [ "$qaExtended" = "true" ]; then make ci-extended; fi; ## Gather coverage and set it to coverage servers -after_script: make travis-coverage +after_script: if [ "$qaExtended" = "true" ]; then make ci-coverage; fi; diff --git a/LICENSE b/LICENSE index cd2d429..b7fcfc6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Cees-Jan Kiewiet +Copyright (c) 2017 Cees-Jan Kiewiet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 17f6380..f0f1bca 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,32 @@ -all: cs unit -travis: cs travis-unit -contrib: cs unit +all: + composer run-script qa-all --timeout=0 + +all-coverage: + composer run-script qa-all-coverage --timeout=0 + +ci: + composer run-script qa-ci --timeout=0 + +ci-extended: + composer run-script qa-ci-extended --timeout=0 + +contrib: + composer run-script qa-contrib --timeout=0 init: - if [ ! -d vendor ]; then composer install; fi; + composer ensure-installed + +cs: + composer cs -cs: init - ./vendor/bin/phpcs --standard=PSR2 src/ +cs-fix: + composer cs-fix -unit: init - ./vendor/bin/phpunit --coverage-text --coverage-html covHtml +unit: + composer run-script unit --timeout=0 -travis-unit: init - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml +unit-coverage: + composer run-script unit-coverage --timeout=0 -travis-coverage: init - if [ -f ./build/logs/clover.xml ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover ./build/logs/clover.xml; fi +ci-coverage: init + composer ci-coverage diff --git a/README.md b/README.md index d6fe5af..aa91f91 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The MIT License (MIT) -Copyright (c) 2016 Cees-Jan Kiewiet +Copyright (c) 2017 Cees-Jan Kiewiet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/appveyor.yml b/appveyor.yml index d51dda0..40bc389 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - dependencies: highest php_ver_target: 7.1 -## Cache composer bits +## Cache composer, chocolatey and php bits cache: - '%LOCALAPPDATA%\Composer\files -> composer.lock' @@ -33,7 +33,7 @@ init: ## Install PHP and composer, and run the appropriate composer command install: - IF EXIST c:\tools\php (SET PHP=0) - - ps: appveyor-retry cinst -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $Env:php_ver_target | Select-Object -first 1) -replace '[php|]','') + - ps: appveyor-retry cinst --params '""/InstallDir:C:\tools\php""' --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $env:php_ver_target | sort { [version]($_ -split '\|' | select -last 1) } -Descending | Select-Object -first 1) -replace '[php|]','') - cd c:\tools\php - IF %PHP%==1 copy php.ini-production php.ini /Y - IF %PHP%==1 echo date.timezone="UTC" >> php.ini @@ -44,6 +44,7 @@ install: - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat - appveyor-retry appveyor DownloadFile https://getcomposer.org/composer.phar - cd c:\projects\php-project-workspace + - composer config --unset platform.php - IF %dependencies%==lowest appveyor-retry composer update --prefer-lowest --no-progress --profile -n - IF %dependencies%==current appveyor-retry composer install --no-progress --profile - IF %dependencies%==highest appveyor-retry composer update --no-progress --profile -n diff --git a/composer.json b/composer.json index 5e74f0a..1d77caf 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,8 @@ { "name": "api-clients/pusher", + "description": "Async first Pusher client", "homepage": "https://php-api-clients.org/clients/pusher", "license": "MIT", - "minimum-stability": "dev", - "prefer-stable": true, "authors": [ { "name": "Cees-Jan Kiewiet", @@ -13,15 +12,17 @@ "require": { "php": "^7.0", "api-clients/command-bus": "^2.0", - "api-clients/rx-operators": "dev-master", - "api-clients/service": "dev-master", + "api-clients/rx-operators": "^2.0", "clue/block-react": "^1.1", "ocramius/package-versions": "^1.1", - "reactivex/rxphp": "^1.5.2", - "rx/websocket": "^0.9.2" + "react/dns": "^0.4.9", + "react/http-client": "^0.4.17", + "reactivex/rxphp": "^2.0", + "rx/websocket": "^1.0", + "voryx/event-loop": "^2.0.2" }, "require-dev": { - "api-clients/test-utilities": "^2.0" + "api-clients/test-utilities": "^4.1" }, "autoload": { "psr-4": { @@ -34,7 +35,10 @@ } }, "config": { - "sort-packages": true + "sort-packages": true, + "platform": { + "php": "7.0" + } }, "extra": { "api-clients": { @@ -43,5 +47,58 @@ "namespace": "ApiClients\\Client\\Pusher\\CommandBus" } } + }, + "scripts": { + "ensure-installed": "composer install --ansi -n -q", + "cs": [ + "@ensure-installed", + "php-cs-fixer fix --config=.php_cs --ansi --dry-run --diff --verbose --allow-risky=yes --show-progress=estimating" + ], + "cs-fix": [ + "@ensure-installed", + "php-cs-fixer fix --config=.php_cs --ansi --verbose --allow-risky=yes --show-progress=estimating" + ], + "unit": [ + "@ensure-installed", + "phpunit --colors=always -c phpunit.xml.dist" + ], + "unit-coverage": [ + "@ensure-installed", + "phpunit --colors=always -c phpunit.xml.dist --coverage-text --coverage-html covHtml --coverage-clover ./build/logs/clover.xml" + ], + "lint-php": [ + "@ensure-installed", + "parallel-lint --exclude vendor ." + ], + "qa-all": [ + "@lint-php", + "@cs", + "@unit" + ], + "qa-all-coverage": [ + "@lint-php", + "@cs", + "@unit-coverage" + ], + "qa-windows": [ + "@lint-php", + "@cs", + "@unit" + ], + "qa-ci": [ + "@unit" + ], + "qa-ci-extended": [ + "@qa-all-coverage" + ], + "qa-ci-windows": [ + "@qa-windows" + ], + "qa-contrib": [ + "@qa-all" + ], + "ci-coverage": [ + "if [ -f ./build/logs/clover.xml ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover ./build/logs/clover.xml; fi" + ] } } diff --git a/composer.lock b/composer.lock index 70a1a12..87f6042 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "846cdf28cea0ffeca189211094247dd8", + "content-hash": "de8feac65999ba4543a43797634ec7e5", "packages": [ { "name": "api-clients/command-bus", @@ -56,25 +56,25 @@ }, { "name": "api-clients/rx", - "version": "dev-master", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/php-api-clients/rx.git", - "reference": "a1d797606e1367a51055634eb73cba20112a99ed" + "reference": "e5fc4181a1050e0a6ff14ba0875647ac88e71d33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/rx/zipball/a1d797606e1367a51055634eb73cba20112a99ed", - "reference": "a1d797606e1367a51055634eb73cba20112a99ed", + "url": "https://api.github.com/repos/php-api-clients/rx/zipball/e5fc4181a1050e0a6ff14ba0875647ac88e71d33", + "reference": "e5fc4181a1050e0a6ff14ba0875647ac88e71d33", "shasum": "" }, "require": { "php": "^7.0", "react/promise": "^2.4", - "reactivex/rxphp": "^1.5" + "reactivex/rxphp": "^2.0" }, "require-dev": { - "api-clients/test-utilities": "^2.0" + "api-clients/test-utilities": "^3.0.1" }, "type": "library", "autoload": { @@ -82,7 +82,8 @@ "ApiClients\\Tools\\Rx\\": "src/" }, "files": [ - "src/functions_include.php" + "src/functions_include.php", + "src/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -95,29 +96,29 @@ "email": "ceesjank@gmail.com" } ], - "time": "2017-01-09 14:39:21" + "time": "2017-05-07T16:23:52+00:00" }, { "name": "api-clients/rx-operators", - "version": "dev-master", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-api-clients/rx-operators.git", - "reference": "d58e1744c5a4540a1d2ec69f08d4ea5627eb1cf6" + "reference": "974e38c8ce2457567d9a36f3430c524b594417e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/rx-operators/zipball/d58e1744c5a4540a1d2ec69f08d4ea5627eb1cf6", - "reference": "d58e1744c5a4540a1d2ec69f08d4ea5627eb1cf6", + "url": "https://api.github.com/repos/php-api-clients/rx-operators/zipball/974e38c8ce2457567d9a36f3430c524b594417e7", + "reference": "974e38c8ce2457567d9a36f3430c524b594417e7", "shasum": "" }, "require": { - "api-clients/rx": "dev-master", + "api-clients/rx": "^2.0", "php": "^7.0", - "rx/operator-extras": "^0.3.0" + "rx/operator-extras": "^2.0" }, "require-dev": { - "api-clients/test-utilities": "dev-master" + "api-clients/test-utilities": "^3.0.1" }, "type": "library", "autoload": { @@ -135,46 +136,7 @@ "email": "ceesjank@gmail.com" } ], - "time": "2017-01-06 06:48:42" - }, - { - "name": "api-clients/service", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-api-clients/service.git", - "reference": "535eb87807fd23996153a84cf864dd1c461de6bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/service/zipball/535eb87807fd23996153a84cf864dd1c461de6bd", - "reference": "535eb87807fd23996153a84cf864dd1c461de6bd", - "shasum": "" - }, - "require": { - "php": "^7.0", - "react/promise": "^2.4" - }, - "require-dev": { - "api-clients/test-utilities": "dev-master" - }, - "type": "library", - "autoload": { - "psr-4": { - "ApiClients\\Foundation\\Service\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Cees-Jan Kiewiet", - "email": "ceesjank@gmail.com" - } - ], - "time": "2016-12-16 22:34:48" + "time": "2017-03-23T07:06:10+00:00" }, { "name": "clue/block-react", @@ -226,18 +188,21 @@ }, { "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": { @@ -249,20 +214,21 @@ "MIT" ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "time": "2014-12-30T15:22:37+00:00" + "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": { @@ -271,7 +237,7 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.6.1" + "phpunit/phpunit": "^5.7" }, "type": "library", "extra": { @@ -317,7 +283,7 @@ "docblock", "parser" ], - "time": "2016-12-30T15:59:45+00:00" + "time": "2017-02-24T16:22:25+00:00" }, { "name": "doctrine/lexer", @@ -421,16 +387,16 @@ }, { "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": { @@ -466,16 +432,23 @@ "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-24T23:00:38+00:00" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "igorw/get-in", @@ -721,6 +694,55 @@ "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", "time": "2016-12-30T09:49:15+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", "version": "1.0.1", @@ -771,6 +793,54 @@ ], "time": "2016-08-06T14:39:51+00:00" }, + { + "name": "ratchet/rfc6455", + "version": "v0.2.2", + "source": { + "type": "git", + "url": "https://github.com/ratchetphp/RFC6455.git", + "reference": "56aecde679d72d7b1087bbe1d6f7d96e123d396a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/56aecde679d72d7b1087bbe1d6f7d96e123d396a", + "reference": "56aecde679d72d7b1087bbe1d6f7d96e123d396a", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^1.0", + "php": ">=5.4.2" + }, + "require-dev": { + "react/http": "^0.4.1", + "react/socket-client": "^0.4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ratchet\\RFC6455\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "role": "Developer" + } + ], + "description": "RFC6455 WebSocket protocol handler", + "homepage": "http://socketo.me", + "keywords": [ + "WebSockets", + "rfc6455", + "websocket" + ], + "time": "2017-01-01T15:41:18+00:00" + }, { "name": "react/cache", "version": "v0.4.1", @@ -807,23 +877,28 @@ }, { "name": "react/dns", - "version": "v0.4.3", + "version": "v0.4.9", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "751b3129556e04944f164e3556a20ca6e201e459" + "reference": "288b4f36972cdc2f81dae1d1a58a0467e3f625cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/751b3129556e04944f164e3556a20ca6e201e459", - "reference": "751b3129556e04944f164e3556a20ca6e201e459", + "url": "https://api.github.com/repos/reactphp/dns/zipball/288b4f36972cdc2f81dae1d1a58a0467e3f625cb", + "reference": "288b4f36972cdc2f81dae1d1a58a0467e3f625cb", "shasum": "" }, "require": { "php": ">=5.3.0", "react/cache": "~0.4.0|~0.3.0", "react/promise": "~2.1|~1.2", - "react/socket": "~0.4.0|~0.3.0" + "react/promise-timer": "~1.1", + "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5 || ^0.4.4", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.5" + }, + "require-dev": { + "phpunit/phpunit": "^5.0 || ^4.8.10" }, "type": "library", "autoload": { @@ -835,41 +910,39 @@ "license": [ "MIT" ], - "description": "Async DNS resolver.", + "description": "Async DNS resolver for ReactPHP", "keywords": [ "dns", "dns-resolver" ], - "time": "2016-08-01T10:09:07+00:00" + "time": "2017-05-01T17:21:03+00:00" }, { "name": "react/event-loop", - "version": "v0.4.2", + "version": "v0.4.3", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "164799f73175e1c80bba92a220ea35df6ca371dd" + "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/164799f73175e1c80bba92a220ea35df6ca371dd", - "reference": "164799f73175e1c80bba92a220ea35df6ca371dd", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/8bde03488ee897dc6bb3d91e4e17c353f9c5252f", + "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f", "shasum": "" }, "require": { "php": ">=5.4.0" }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, "suggest": { "ext-event": "~1.0", "ext-libev": "*", "ext-libevent": ">=0.1.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.5-dev" - } - }, "autoload": { "psr-4": { "React\\EventLoop\\": "src" @@ -884,28 +957,31 @@ "asynchronous", "event-loop" ], - "time": "2016-03-08T02:09:32+00:00" + "time": "2017-04-27T10:56:23+00:00" }, { "name": "react/http", - "version": "v0.4.2", + "version": "v0.4.4", "source": { "type": "git", "url": "https://github.com/reactphp/http.git", - "reference": "abedac54967d7ea237ad104cff8274e2c4077cf4" + "reference": "aac319bd789cbc7b478d42cde2d03596e97e3222" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http/zipball/abedac54967d7ea237ad104cff8274e2c4077cf4", - "reference": "abedac54967d7ea237ad104cff8274e2c4077cf4", + "url": "https://api.github.com/repos/reactphp/http/zipball/aac319bd789cbc7b478d42cde2d03596e97e3222", + "reference": "aac319bd789cbc7b478d42cde2d03596e97e3222", "shasum": "" }, "require": { - "evenement/evenement": "^2.0", - "guzzlehttp/psr7": "^1.0", - "php": ">=5.4.0", + "evenement/evenement": "^2.0 || ^1.0", + "php": ">=5.3.0", "react/socket": "^0.4", - "react/stream": "^0.4" + "react/stream": "^0.4.4", + "ringcentral/psr7": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.10||^5.0" }, "type": "library", "autoload": { @@ -921,20 +997,20 @@ "keywords": [ "http" ], - "time": "2016-11-09T15:20:39+00:00" + "time": "2017-02-13T14:12:50+00:00" }, { "name": "react/http-client", - "version": "v0.4.15", + "version": "v0.4.17", "source": { "type": "git", "url": "https://github.com/reactphp/http-client.git", - "reference": "01e919008363622334f91419a9908b3a51754ccd" + "reference": "75ee8a113f156834aaabfe0055e8db531cb4892c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http-client/zipball/01e919008363622334f91419a9908b3a51754ccd", - "reference": "01e919008363622334f91419a9908b3a51754ccd", + "url": "https://api.github.com/repos/reactphp/http-client/zipball/75ee8a113f156834aaabfe0055e8db531cb4892c", + "reference": "75ee8a113f156834aaabfe0055e8db531cb4892c", "shasum": "" }, "require": { @@ -947,6 +1023,9 @@ "react/socket-client": "^0.5 || ^0.4 || ^0.3", "react/stream": "0.4.*" }, + "require-dev": { + "phpunit/phpunit": "^5.0 || ^4.8.10" + }, "type": "library", "autoload": { "psr-4": { @@ -961,25 +1040,28 @@ "keywords": [ "http" ], - "time": "2016-12-02T10:17:42+00:00" + "time": "2017-03-20T09:55:48+00:00" }, { "name": "react/promise", - "version": "v2.5.0", + "version": "v2.5.1", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "2760f3898b7e931aa71153852dcd48a75c9b95db" + "reference": "62785ae604c8d69725d693eb370e1d67e94c4053" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/2760f3898b7e931aa71153852dcd48a75c9b95db", - "reference": "2760f3898b7e931aa71153852dcd48a75c9b95db", + "url": "https://api.github.com/repos/reactphp/promise/zipball/62785ae604c8d69725d693eb370e1d67e94c4053", + "reference": "62785ae604c8d69725d693eb370e1d67e94c4053", "shasum": "" }, "require": { "php": ">=5.4.0" }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, "type": "library", "autoload": { "psr-4": { @@ -1004,7 +1086,7 @@ "promise", "promises" ], - "time": "2016-12-22T14:09:01+00:00" + "time": "2017-03-25T12:08:31+00:00" }, { "name": "react/promise-timer", @@ -1185,41 +1267,40 @@ }, { "name": "reactivex/rxphp", - "version": "1.5.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/ReactiveX/RxPHP.git", - "reference": "84bfbd05e79d924b3d2597eaeef6156475e2a514" + "reference": "7f5f669850cc035d78f7dafb45fd797fe0ba9e7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ReactiveX/RxPHP/zipball/84bfbd05e79d924b3d2597eaeef6156475e2a514", - "reference": "84bfbd05e79d924b3d2597eaeef6156475e2a514", + "url": "https://api.github.com/repos/ReactiveX/RxPHP/zipball/7f5f669850cc035d78f7dafb45fd797fe0ba9e7d", + "reference": "7f5f669850cc035d78f7dafb45fd797fe0ba9e7d", "shasum": "" }, "require": { - "php": "~5.5|~7.0" + "php": "~7.0", + "react/promise": "~2.2" }, "require-dev": { "phpunit/phpcov": "^3.1", "phpunit/phpunit": "^5.5", - "react/event-loop": "~0.4.1", - "react/promise": "~2.2", + "react/event-loop": "^0.4.2", "satooshi/php-coveralls": "~1.0" }, "suggest": { - "react/event-loop": "For using event-loop based scheduling.", - "react/promise": "For converting promises to and from observables." + "react/event-loop": "Used for scheduling async operations" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { "psr-4": { - "Rx\\": "lib/Rx" + "Rx\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1247,29 +1328,88 @@ "reactive", "rx" ], - "time": "2017-02-07T19:28:24+00:00" + "time": "2017-05-21T01:48:34+00:00" + }, + { + "name": "ringcentral/psr7", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/ringcentral/psr7.git", + "reference": "2594fb47cdc659f3fcf0aa1559b7355460555303" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ringcentral/psr7/zipball/2594fb47cdc659f3fcf0aa1559b7355460555303", + "reference": "2594fb47cdc659f3fcf0aa1559b7355460555303", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "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.0-dev" + } + }, + "autoload": { + "psr-4": { + "RingCentral\\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-03-25T17:36:49+00:00" }, { "name": "rx/operator-extras", - "version": "0.3.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/RxPHP/RxOperatorExtras.git", - "reference": "851febebd3558350c55dcfecb8fd7df05b6dd88d" + "reference": "3ccbd8dfb414ffe2c86199a98361903d383b9072" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RxPHP/RxOperatorExtras/zipball/851febebd3558350c55dcfecb8fd7df05b6dd88d", - "reference": "851febebd3558350c55dcfecb8fd7df05b6dd88d", + "url": "https://api.github.com/repos/RxPHP/RxOperatorExtras/zipball/3ccbd8dfb414ffe2c86199a98361903d383b9072", + "reference": "3ccbd8dfb414ffe2c86199a98361903d383b9072", "shasum": "" }, "require": { - "reactivex/rxphp": "^1.0.0" + "php": "^7.0", + "reactivex/rxphp": "^2.0" }, "type": "library", "autoload": { "psr-4": { - "Rx\\Extra\\": "src/" + "Rx\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1294,33 +1434,36 @@ "rx.php", "rxphp" ], - "time": "2016-05-21T02:51:35+00:00" + "time": "2017-03-21T17:25:58+00:00" }, { "name": "rx/websocket", - "version": "0.9.2", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/RxPHP/RxWebsocket.git", - "reference": "b93125668a0f89b3ade8100f50318e12ac4bbd41" + "reference": "fc60831de1863ed0469f97a1735f6ba07e3b572e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RxPHP/RxWebsocket/zipball/b93125668a0f89b3ade8100f50318e12ac4bbd41", - "reference": "b93125668a0f89b3ade8100f50318e12ac4bbd41", + "url": "https://api.github.com/repos/RxPHP/RxWebsocket/zipball/fc60831de1863ed0469f97a1735f6ba07e3b572e", + "reference": "fc60831de1863ed0469f97a1735f6ba07e3b572e", "shasum": "" }, "require": { - "guzzlehttp/psr7": "^1.2", + "ratchet/rfc6455": "^0.2.2", "react/http": "^0.4.1", - "react/http-client": "^0.4.8", - "reactivex/rxphp": "^1.0", - "voryx/event-loop": "^0.2.0" + "react/http-client": "^0.4.10", + "reactivex/rxphp": "^2.0", + "voryx/event-loop": "^2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5.7.0" }, "type": "library", "autoload": { "psr-4": { - "Rx\\Websocket\\": "src/Websocket/" + "Rx\\Websocket\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1339,7 +1482,7 @@ "role": "Developer" } ], - "description": "Async Websockets for PHP using Rx", + "description": "Websockets for PHP using Rx", "keywords": [ "WebSockets", "react", @@ -1350,24 +1493,24 @@ "rxphp", "websocket" ], - "time": "2016-02-09T03:27:41+00:00" + "time": "2017-03-28T16:51:17+00:00" }, { "name": "voryx/event-loop", - "version": "0.2.0", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/voryx/event-loop.git", - "reference": "8ef08db3d7646fe60d1791ba9625ce65adf935cd" + "reference": "4cd6bc28465303bf6da63202201463e420d4ec79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voryx/event-loop/zipball/8ef08db3d7646fe60d1791ba9625ce65adf935cd", - "reference": "8ef08db3d7646fe60d1791ba9625ce65adf935cd", + "url": "https://api.github.com/repos/voryx/event-loop/zipball/4cd6bc28465303bf6da63202201463e420d4ec79", + "reference": "4cd6bc28465303bf6da63202201463e420d4ec79", "shasum": "" }, "require": { - "react/event-loop": "~0.4.1" + "react/event-loop": "^0.4.2" }, "type": "library", "autoload": { @@ -1375,7 +1518,8 @@ "EventLoop\\": "src" }, "files": [ - "src/functions.php" + "src/functions.php", + "src/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1402,7 +1546,7 @@ "static", "timer" ], - "time": "2015-11-23T22:10:36+00:00" + "time": "2017-03-14T01:10:32+00:00" }, { "name": "wyrihaximus/tactician-command-handler-mapper", @@ -1499,27 +1643,26 @@ "packages-dev": [ { "name": "api-clients/test-utilities", - "version": "2.1.0", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/php-api-clients/test-utilities.git", - "reference": "427429883c6d811c4c76d97f065a7db4b384cbad" + "reference": "bdf066b2396d60f5d575fd7a5caf51de634e8ca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/test-utilities/zipball/427429883c6d811c4c76d97f065a7db4b384cbad", - "reference": "427429883c6d811c4c76d97f065a7db4b384cbad", + "url": "https://api.github.com/repos/php-api-clients/test-utilities/zipball/bdf066b2396d60f5d575fd7a5caf51de634e8ca9", + "reference": "bdf066b2396d60f5d575fd7a5caf51de634e8ca9", "shasum": "" }, "require": { "clue/block-react": "^1.1", + "friendsofphp/php-cs-fixer": "^2.3", "jakub-onderka/php-console-highlighter": "^0.3.2", "jakub-onderka/php-parallel-lint": "^0.9.2", "phake/phake": "^2.3", "php": "^7.0", - "phpspec/prophecy": "^1.6", - "phpunit/phpunit": "^6.0 || ^5.6", - "squizlabs/php_codesniffer": "^2.6" + "phpunit/phpunit": "^6.0" }, "type": "library", "autoload": { @@ -1537,7 +1680,8 @@ "email": "ceesjank@gmail.com" } ], - "time": "2017-02-03T20:53:52+00:00" + "description": "Test utilities for api-clients packages", + "time": "2017-05-14T15:00:49+00:00" }, { "name": "doctrine/instantiator", @@ -1594,78 +1738,197 @@ "time": "2015-06-14T21:17:01+00:00" }, { - "name": "jakub-onderka/php-console-color", - "version": "0.1", + "name": "friendsofphp/php-cs-fixer", + "version": "v2.3.1", "source": { "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "d5257f7433bb490299c4f300d95598fd911a8ab0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/d5257f7433bb490299c4f300d95598fd911a8ab0", + "reference": "d5257f7433bb490299c4f300d95598fd911a8ab0", "shasum": "" }, "require": { - "php": ">=5.3.2" + "doctrine/annotations": "^1.2", + "ext-tokenizer": "*", + "php": "^5.6 || >=7.0 <7.2", + "sebastian/diff": "^1.4", + "symfony/console": "^3.0", + "symfony/event-dispatcher": "^3.0", + "symfony/filesystem": "^3.0", + "symfony/finder": "^3.0", + "symfony/options-resolver": "^3.0", + "symfony/polyfill-php54": "^1.0", + "symfony/polyfill-php55": "^1.3", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-xml": "^1.3", + "symfony/process": "^3.0", + "symfony/stopwatch": "^3.0" + }, + "conflict": { + "hhvm": "<3.18" }, "require-dev": { - "jakub-onderka/php-code-style": "1.0", - "jakub-onderka/php-parallel-lint": "0.*", - "jakub-onderka/php-var-dump-check": "0.*", - "phpunit/phpunit": "3.7.*", - "squizlabs/php_codesniffer": "1.*" + "gecko-packages/gecko-php-unit": "^2.0", + "justinrainbow/json-schema": "^5.0", + "phpunit/phpunit": "^4.5 || ^5.0", + "satooshi/php-coveralls": "^1.0", + "symfony/phpunit-bridge": "^3.2.2" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "ext-xml": "For better performance.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } }, - "type": "library", "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleColor": "src/" + "psr-4": { + "PhpCsFixer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-2-Clause" + "MIT" ], "authors": [ { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com", - "homepage": "http://www.acci.cz" + "name": "Dariusz RumiƄski", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "time": "2014-04-08T15:00:19+00:00" + "description": "A tool to automatically fix PHP code style", + "time": "2017-04-25T20:50:30+00:00" }, { - "name": "jakub-onderka/php-console-highlighter", - "version": "v0.3.2", + "name": "ircmaxell/password-compat", + "version": "v1.0.4", "source": { "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", "shasum": "" }, - "require": { - "jakub-onderka/php-console-color": "~0.1", - "php": ">=5.3.0" - }, "require-dev": { - "jakub-onderka/php-code-style": "~1.0", - "jakub-onderka/php-parallel-lint": "~0.5", - "jakub-onderka/php-var-dump-check": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" + "phpunit/phpunit": "4.*" }, "type": "library", "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleHighlighter": "src/" - } + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, + { + "name": "jakub-onderka/php-console-color", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ], + "time": "2014-04-08T15:00:19+00:00" + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1729,16 +1992,16 @@ }, { "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": { @@ -1767,20 +2030,68 @@ "object", "object graph" ], - "time": "2017-01-26T22:05:40+00:00" + "time": "2017-04-12T18:52:22+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.10", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2017-03-13T16:27:32+00:00" }, { "name": "phake/phake", - "version": "v2.3.0", + "version": "v2.3.2", "source": { "type": "git", "url": "https://github.com/mlively/Phake.git", - "reference": "2202d361d34f2712dcc257afdedc6c30060dc9bd" + "reference": "d5832f1a0dd2370e14d38bcbaeb6770e8546cff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mlively/Phake/zipball/2202d361d34f2712dcc257afdedc6c30060dc9bd", - "reference": "2202d361d34f2712dcc257afdedc6c30060dc9bd", + "url": "https://api.github.com/repos/mlively/Phake/zipball/d5832f1a0dd2370e14d38bcbaeb6770e8546cff2", + "reference": "d5832f1a0dd2370e14d38bcbaeb6770e8546cff2", "shasum": "" }, "require": { @@ -1825,7 +2136,7 @@ "mock", "testing" ], - "time": "2016-03-04T18:49:33+00:00" + "time": "2017-03-20T05:16:34+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1975,27 +2286,27 @@ }, { "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", @@ -2034,43 +2345,45 @@ "spy", "stub" ], - "time": "2016-11-21T14:58:47+00:00" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.0.0", + "version": "5.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e7d7a4acca58e45bdfd00221563d131cfb04ba96" + "reference": "e648abfd8ffb1d54ad549b027b75e376e9055d02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e7d7a4acca58e45bdfd00221563d131cfb04ba96", - "reference": "e7d7a4acca58e45bdfd00221563d131cfb04ba96", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e648abfd8ffb1d54ad549b027b75e376e9055d02", + "reference": "e648abfd8ffb1d54ad549b027b75e376e9055d02", "shasum": "" }, "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", "php": "^7.0", "phpunit/php-file-iterator": "^1.3", "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2", + "phpunit/php-token-stream": "^1.4.11 || ^2.0", "sebastian/code-unit-reverse-lookup": "^1.0", "sebastian/environment": "^2.0", - "sebastian/version": "^2.0" + "sebastian/version": "^2.0", + "theseer/tokenizer": "^1.1" }, "require-dev": { "ext-xdebug": "^2.5", "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-dom": "*", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-master": "5.2.x-dev" } }, "autoload": { @@ -2096,7 +2409,7 @@ "testing", "xunit" ], - "time": "2017-02-02T10:35:41+00:00" + "time": "2017-04-20T10:00:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2188,25 +2501,30 @@ }, { "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/" @@ -2228,20 +2546,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12T18:03:57+00:00" + "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": { @@ -2277,20 +2595,20 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15T14:06:22+00:00" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", - "version": "6.0.5", + "version": "6.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1fb01cbd5aa7fa2457cc10170070676a9ad315d2" + "reference": "47ee3fa1bca5c50f1d25105201eb20df777bd7b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1fb01cbd5aa7fa2457cc10170070676a9ad315d2", - "reference": "1fb01cbd5aa7fa2457cc10170070676a9ad315d2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/47ee3fa1bca5c50f1d25105201eb20df777bd7b6", + "reference": "47ee3fa1bca5c50f1d25105201eb20df777bd7b6", "shasum": "" }, "require": { @@ -2307,12 +2625,12 @@ "phpunit/php-text-template": "^1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^4.0", - "sebastian/comparator": "^1.2.4", + "sebastian/comparator": "^1.2.4 || ^2.0", "sebastian/diff": "^1.2", "sebastian/environment": "^2.0", - "sebastian/exporter": "^2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "^2.0", + "sebastian/exporter": "^2.0 || ^3.0", + "sebastian/global-state": "^1.1 || ^2.0", + "sebastian/object-enumerator": "^2.0 || ^3.0", "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0" }, @@ -2359,7 +2677,7 @@ "testing", "xunit" ], - "time": "2017-02-05T15:33:43+00:00" + "time": "2017-03-02T15:24:03+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -2420,25 +2738,72 @@ ], "time": "2017-02-02T10:36:38+00:00" }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "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-4": { + "Psr\\Log\\": "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", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+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": { @@ -2463,7 +2828,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-13T06:45:14+00:00" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -2531,23 +2896,23 @@ }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { @@ -2579,7 +2944,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08T07:14:41+00:00" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -2700,23 +3065,23 @@ }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -2724,7 +3089,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2747,20 +3112,20 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { @@ -2793,7 +3158,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-11-19T07:35:10+00:00" + "time": "2017-02-18T15:18:39+00:00" }, { "name": "sebastian/recursion-context", @@ -2934,114 +3299,106 @@ "time": "2016-10-03T07:35:21+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "2.8.0", + "name": "symfony/console", + "version": "v3.2.8", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "86dd55a522238211f9f3631e3361703578941d9a" + "url": "https://github.com/symfony/console.git", + "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/86dd55a522238211f9f3631e3361703578941d9a", - "reference": "86dd55a522238211f9f3631e3361703578941d9a", + "url": "https://api.github.com/repos/symfony/console/zipball/a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", + "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/filesystem": "", + "symfony/process": "" }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2017-02-02T03:30:00+00:00" + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2017-04-26T01:39:17+00:00" }, { - "name": "webmozart/assert", - "version": "1.2.0", + "name": "symfony/debug", + "version": "v3.2.8", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "url": "https://github.com/symfony/debug.git", + "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/symfony/debug/zipball/fd6eeee656a5a7b384d56f1072243fe1c0e81686", + "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "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": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "3.2-dev" } }, "autoload": { "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3049,29 +3406,719 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2017-04-19T20:17:50+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "b8a401f733b43251e1d088c589368b2a94155e40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b8a401f733b43251e1d088c589368b2a94155e40", + "reference": "b8a401f733b43251e1d088c589368b2a94155e40", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" ], - "time": "2016-11-23T20:04:58+00:00" - } - ], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "api-clients/rx-operators": 20, - "api-clients/service": 20 - }, - "prefer-stable": true, + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2017-05-01T14:58:48+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "040651db13cf061827a460cc10f6e36a445c45b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/040651db13cf061827a460cc10f6e36a445c45b4", + "reference": "040651db13cf061827a460cc10f6e36a445c45b4", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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 Filesystem Component", + "homepage": "https://symfony.com", + "time": "2017-04-12T14:13:17+00:00" + }, + { + "name": "symfony/finder", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/9cf076f8f492f4b1ffac40aae9c2d287b4ca6930", + "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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 Finder Component", + "homepage": "https://symfony.com", + "time": "2017-04-12T14:13:17+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "8cbb4f23414e2a5e92690cf67680a979a461113c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/8cbb4f23414e2a5e92690cf67680a979a461113c", + "reference": "8cbb4f23414e2a5e92690cf67680a979a461113c", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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 OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2017-04-12T14:13:17+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-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-11-14T01:06:16+00:00" + }, + { + "name": "symfony/polyfill-php54", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/90e085822963fdcc9d1c5b73deb3d2e5783b16a0", + "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php54\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 5.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14T01:06:16+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "03e3f0350bca2220e3623a0e340eef194405fc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/03e3f0350bca2220e3623a0e340eef194405fc67", + "reference": "03e3f0350bca2220e3623a0e340eef194405fc67", + "shasum": "" + }, + "require": { + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + }, + "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 backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14T01:06:16+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "13ce343935f0f91ca89605a2f6ca6f5c2f3faac2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/13ce343935f0f91ca89605a2f6ca6f5c2f3faac2", + "reference": "13ce343935f0f91ca89605a2f6ca6f5c2f3faac2", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14T01:06:16+00:00" + }, + { + "name": "symfony/polyfill-xml", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-xml.git", + "reference": "64b6a864f18ab4fddad49f5025f805f6781dfabd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-xml/zipball/64b6a864f18ab4fddad49f5025f805f6781dfabd", + "reference": "64b6a864f18ab4fddad49f5025f805f6781dfabd", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-xml": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Xml\\": "" + }, + "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 xml's utf8_encode and utf8_decode functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14T01:06:16+00:00" + }, + { + "name": "symfony/process", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", + "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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 Process Component", + "homepage": "https://symfony.com", + "time": "2017-04-12T14:13:17+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a0105afb670dbd38f521105c444de1b8e10cfe3", + "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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 Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2017-04-12T14:13:17+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-11-23T20:04:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^7.0" }, - "platform-dev": [] + "platform-dev": [], + "platform-overrides": { + "php": "7.0" + } } diff --git a/examples/bitstamp-async.php b/examples/bitstamp-async.php index b7d29d0..cb0a1e5 100644 --- a/examples/bitstamp-async.php +++ b/examples/bitstamp-async.php @@ -13,15 +13,15 @@ * The App ID isn't a secret and comes from the bitstamp docs: * @link https://www.bitstamp.net/websocket/ */ -$client = new AsyncClient($loop, 'de504dc5763aeef9ff52'); +$client = AsyncClient::create($loop, 'de504dc5763aeef9ff52'); $channelitems = array('live_trades','live_trades_xrpusd'); foreach ($channelitems as $channelitem) { - $client->channel($channelitem)->subscribe(new CallbackObserver(function (Event $event) { + $client->channel($channelitem)->subscribe(function (Event $event) { echo 'Channel: '. $event->getChannel(). PHP_EOL; echo 'Event: '. $event->getEvent(). PHP_EOL; echo 'Data: '. print_r($event->getData(),1). PHP_EOL; - })); + }); } $loop->run(); diff --git a/examples/reddit-async.php b/examples/reddit-async.php index b858387..b02a300 100644 --- a/examples/reddit-async.php +++ b/examples/reddit-async.php @@ -1,9 +1,8 @@ channel($subReddit)->subscribe(new CallbackObserver(function (Event $event) { - echo 'Channel: ', $event->getChannel(), PHP_EOL; - echo 'Event: ', $event->getEvent(), PHP_EOL; - echo 'Data: ', json_encode($event->getData()), PHP_EOL; - })); + $client->channel($subReddit)->subscribe( + function (Event $event) { + echo 'Channel: ', $event->getChannel(), PHP_EOL; + echo 'Event: ', $event->getEvent(), PHP_EOL; + echo 'Data: ', json_encode($event->getData()), PHP_EOL; + }, + function ($e) { + echo (string)$e; + }, + function () { + echo 'Done!', PHP_EOL; + } + ); } $loop->run(); diff --git a/examples/reddit-single.php b/examples/reddit-single.php index 9a9cd57..b970833 100644 --- a/examples/reddit-single.php +++ b/examples/reddit-single.php @@ -9,7 +9,7 @@ * The App ID isn't a secret and comes from a Pusher blog post: * @link https://blog.pusher.com/pusher-realtime-reddit-api/ */ -$client = new Client(require 'reddit.key.php'); +$client = Client::create(require 'reddit.key.php'); $client->channel((string) $argv[1], function (Event $event) { echo 'Channel: ', $event->getChannel(), PHP_EOL; diff --git a/examples/reddit.php b/examples/reddit.php index 36d0ac0..6b94516 100644 --- a/examples/reddit.php +++ b/examples/reddit.php @@ -9,7 +9,7 @@ * The App ID isn't a secret and comes from a Pusher blog post: * @link https://blog.pusher.com/pusher-realtime-reddit-api/ */ -$client = new Client(require 'reddit.key.php'); +$client = Client::create(require 'reddit.key.php'); $subReddits = $argv; array_shift($subReddits); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 428c916..d9b3788 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,5 @@ - + tests/ diff --git a/src/ApiSettings.php b/src/ApiSettings.php index e702cd6..e1eea20 100644 --- a/src/ApiSettings.php +++ b/src/ApiSettings.php @@ -7,9 +7,9 @@ final class ApiSettings { /** - * Create Pusher compatible version + * Create Pusher compatible version. * - * @param string $version + * @param string $version * @return string */ public static function getVersion(string $version = ''): string @@ -28,9 +28,9 @@ public static function getVersion(string $version = ''): string } /** - * Create WebSocket URL for given App ID + * Create WebSocket URL for given App ID. * - * @param string $appId + * @param string $appId * @return string */ public static function createUrl(string $appId): string diff --git a/src/AsyncClient.php b/src/AsyncClient.php index 9155b0c..01d6b61 100644 --- a/src/AsyncClient.php +++ b/src/AsyncClient.php @@ -2,20 +2,28 @@ namespace ApiClients\Client\Pusher; +use React\Dns\Resolver\Resolver; use React\EventLoop\LoopInterface; +use RuntimeException; use Rx\Disposable\CallbackDisposable; use Rx\Observable; -use Rx\ObservableInterface; use Rx\ObserverInterface; -use Rx\SchedulerInterface; +use Rx\Scheduler; use Rx\Websocket\Client as WebsocketClient; use Rx\Websocket\MessageSubject; +use Rx\Websocket\WebsocketErrorException; +use Throwable; +use function React\Promise\reject; use function React\Promise\resolve; -use function EventLoop\getLoop; -use function EventLoop\setLoop; final class AsyncClient { + const DEFAULT_DELAY = 200; + const NO_ACTIVITY_TIMEOUT = 120; + const NO_PING_RESPONSE_TIMEOUT = 30; + + protected $noActivityTimeout = self::NO_ACTIVITY_TIMEOUT; + /** * @var Observable\RefCountObservable */ @@ -26,36 +34,127 @@ final class AsyncClient */ protected $messages; + /** + * @var MessageSubject + */ + protected $sendSubject; + /** * @var array */ protected $channels = []; /** - * @param LoopInterface $loop - * @param string $app Application ID + * @var int */ - public function __construct(LoopInterface $loop, string $app) + protected $delay = self::DEFAULT_DELAY; + + /** + * @internal + */ + public function __construct(Observable $client) { - // Set loop into global look accessor - setLoop($loop); + $this->messages = $client + // Save this subject for sending stuff + ->do(function (MessageSubject $ms) { + $this->sendSubject = $ms; + + // Resubscribe to an channels we where subscribed to when disconnected + foreach ($this->channels as $channel => $_) { + $this->subscribeOnChannel($channel); + } + }) + + // Make sure if there is a disconnect or something + // that we unset the sendSubject + ->finally(function () { + $this->sendSubject = null; + }) - //Only create one connection and share the most recent among all subscriber - $this->client = (new WebsocketClient(ApiSettings::createUrl($app)))->shareReplay(1); - $this->messages = $this->client ->flatMap(function (MessageSubject $ms) { return $ms; }) + + // This is the ping/timeout functionality + ->flatMapLatest(function ($x) { + // this Observable emits the current value immediately + // if another value comes along, this all gets disposed (because we are using flatMapLatest) + // before the timeouts start get triggered + return Observable::never() + ->timeout($this->noActivityTimeout * 1000) + ->catch(function () use ($x) { + // ping (do something that causes incoming stream to get a message) + $this->send(['event' => 'pusher:ping']); + // this timeout will actually timeout with a TimeoutException - causing + // everything above this to dispose + return Observable::never()->timeout(self::NO_PING_RESPONSE_TIMEOUT * 1000); + }) + ->startWith($x); + }) + + // Decode JSON ->_ApiClients_jsonDecode() - ->map(function (array $message) { - return Event::createFromMessage($message); + + // Deal with connection established messages + ->flatMap(function (array $message) { + $this->delay = self::DEFAULT_DELAY; + + $event = Event::createFromMessage($message); + + if ($event->getEvent() === 'pusher:error') { + return Observable::fromPromise(reject( + new PusherErrorException($event->getData()['message'], $event->getData()['code']) + )); + } + + if ($event->getEvent() === 'pusher:connection_established') { + $this->setActivityTimeout($event); + } + + return Observable::fromPromise(resolve($event)); + }) + + // Handle connection level and Pusher procotol errors + ->retryWhen(function (Observable $errors) { + return $errors->flatMap(function (Throwable $throwable) { + return $this->handleLowLevelError($throwable); + }); + }) + + // Share client + ->share(); + } + + /** + * @param LoopInterface $loop + * @param string $app Application ID + * @param Resolver $resolver Optional DNS resolver + * @return AsyncClient + */ + public static function create(LoopInterface $loop, string $app, Resolver $resolver = null): AsyncClient + { + try { + Scheduler::setAsyncFactory(function () use ($loop) { + return new Scheduler\EventLoopScheduler($loop); }); + } catch (Throwable $t) { + } + + return new self( + new WebsocketClient( + ApiSettings::createUrl($app), + false, + [], + $loop, + $resolver + ) + ); } /** - * Listen on a channel + * Listen on a channel. * - * @param string $channel Channel to listen on + * @param string $channel Channel to listen on * @return Observable */ public function channel(string $channel): Observable @@ -64,13 +163,13 @@ public function channel(string $channel): Observable return $this->channels[$channel]; } + // Ensure we only get messages for the given channel $channelMessages = $this->messages->filter(function (Event $event) use ($channel) { return $event->getChannel() !== '' && $event->getChannel() === $channel; }); $events = Observable::create(function ( - ObserverInterface $observer, - SchedulerInterface $scheduler + ObserverInterface $observer ) use ( $channel, $channelMessages @@ -79,31 +178,108 @@ public function channel(string $channel): Observable ->filter(function (Event $event) { return $event->getEvent() !== 'pusher_internal:subscription_succeeded'; }) - ->subscribe($observer, $scheduler); + ->subscribe($observer); - $this->send(['event' => 'pusher:subscribe', 'data' => ['channel' => $channel]]); + $this->subscribeOnChannel($channel); return new CallbackDisposable(function () use ($channel, $subscription) { + // Send unsubscribe event $this->send(['event' => 'pusher:unsubscribe', 'data' => ['channel' => $channel]]); + // Dispose our own subscription to messages $subscription->dispose(); + // Remove our channel from the channel list so we don't resubscribe in case we reconnect + unset($this->channels[$channel]); }); }); + // Share stream amount subscribers to this channel $this->channels[$channel] = $events->share(); + return $this->channels[$channel]; } /** - * Send a message through the client + * Send a message through the client. * * @param array $message Message to send, will be json encoded + * + * @return A bool indicating whether or not the connection was active + * and the given message has been pass onto the connection. */ - public function send(array $message) + public function send(array $message): bool { - $this->client - ->take(1) - ->subscribeCallback(function (MessageSubject $ms) use ($message) { - $ms->send(json_encode($message)); - }); + // Don't send messages when we aren't connected + if ($this->sendSubject === null) { + return false; + } + + $this->sendSubject->onNext(json_encode($message)); + + return true; + } + + /** + * Handle errors as described at https://pusher.com/docs/pusher_protocol#error-codes. + */ + private function handleLowLevelError(Throwable $throwable) + { + if (!($throwable instanceof WebsocketErrorException) && + !($throwable instanceof RuntimeException) && + !($throwable instanceof PusherErrorException) + ) { + return Observable::fromPromise(reject($throwable)); + } + + $code = $throwable->getCode(); + $pusherError = ($throwable instanceof WebsocketErrorException || $throwable instanceof PusherErrorException); + + // Errors 4000-4099, don't retry connecting + if ($pusherError && $code >= 4000 && $code <= 4099) { + return Observable::fromPromise(reject($throwable)); + } + + // Errors 4100-4199 reconnect after 1 or more seconds, we do it after 1.001 second + if ($pusherError && $code >= 4100 && $code <= 4199) { + return Observable::timer(1001); + } + + // Errors 4200-4299 connection closed by Pusher, reconnect immediately, we wait 0.001 second + if ($pusherError && $code >= 4200 && $code <= 4299) { + return Observable::timer(1); + } + + $this->delay *= 2; + + return Observable::timer($this->delay); + } + + /** + * @param string $channel + */ + private function subscribeOnChannel(string $channel) + { + $this->send(['event' => 'pusher:subscribe', 'data' => ['channel' => $channel]]); + } + + /** + * Get connection activity timeout from connection established event. + * + * @param Event $event + */ + private function setActivityTimeout(Event $event) + { + $data = $event->getData(); + + // No activity_timeout found on event + if (!isset($data['activity_timeout'])) { + return; + } + + // activity_timeout holds zero or invalid value (we don't want to hammer Pusher) + if ((int)$data['activity_timeout'] <= 0) { + return; + } + + $this->noActivityTimeout = (int)$data['activity_timeout']; } } diff --git a/src/Client.php b/src/Client.php index c4b9936..092f900 100644 --- a/src/Client.php +++ b/src/Client.php @@ -5,7 +5,7 @@ use React\EventLoop\Factory; use React\EventLoop\LoopInterface; use React\Promise\Deferred; -use Rx\Observer\CallbackObserver; +use Throwable; use function Clue\React\Block\await; use function React\Promise\all; @@ -27,11 +27,11 @@ final class Client public function __construct(string $app) { $this->loop = Factory::create(); - $this->client = new AsyncClient($this->loop, $app); + $this->client = AsyncClient::create($this->loop, $app); } /** - * @param string $channel Channel to listen on + * @param string $channel Channel to listen on * @param callable $listener Listener to call on new messages */ public function channel(string $channel, callable $listener) @@ -54,13 +54,13 @@ public function channels(array $channels, callable $listener) foreach ($channels as $channel) { $deferred = new Deferred(); $this->client->channel($channel)->subscribe( - new CallbackObserver( - $listener, - null, - function () use ($deferred) { - $deferred->resolve(); - } - ) + $listener, + function (Throwable $throwable) { + throw $throwable; + }, + function () use ($deferred) { + $deferred->resolve(); + } ); $promises[] = $deferred->promise(); } diff --git a/src/CommandBus/Handler/SharedAppClientHandler.php b/src/CommandBus/Handler/SharedAppClientHandler.php index 7cfb481..b20f61c 100644 --- a/src/CommandBus/Handler/SharedAppClientHandler.php +++ b/src/CommandBus/Handler/SharedAppClientHandler.php @@ -6,7 +6,6 @@ use ApiClients\Client\Pusher\Service\SharedAppClientService; use React\Promise\PromiseInterface; use function React\Promise\resolve; -use function WyriHaximus\React\futureFunctionPromise; final class SharedAppClientHandler { @@ -25,11 +24,11 @@ public function __construct(SharedAppClientService $service) } /** - * @param SharedAppClientCommand $command + * @param SharedAppClientCommand $command * @return PromiseInterface */ public function handle(SharedAppClientCommand $command): PromiseInterface { - return resolve($this->service->handle($command->getAppId())); + return resolve($this->service->share($command->getAppId())); } } diff --git a/src/Event.php b/src/Event.php index 4bad7e8..68f9b3f 100644 --- a/src/Event.php +++ b/src/Event.php @@ -19,18 +19,9 @@ final class Event */ private $data; - public static function createFromMessage(array $message): self - { - return new self( - $message['event'], - json_decode($message['data'], true), - isset($message['channel']) ? $message['channel'] : '' - ); - } - /** * @param string $event - * @param array $data + * @param array $data * @param string $channel */ public function __construct(string $event, array $data, string $channel = '') @@ -40,6 +31,15 @@ public function __construct(string $event, array $data, string $channel = '') $this->channel = $channel; } + public static function createFromMessage(array $message): self + { + return new self( + $message['event'], + is_array($message['data']) ? $message['data'] : json_decode($message['data'], true), + isset($message['channel']) ? $message['channel'] : '' + ); + } + /** * @return string */ diff --git a/src/PusherErrorException.php b/src/PusherErrorException.php new file mode 100644 index 0000000..20781d0 --- /dev/null +++ b/src/PusherErrorException.php @@ -0,0 +1,9 @@ +apps[$appId])) { return resolve($this->apps[$appId]); } - $this->apps[$appId] = new AsyncClient($this->loop, $appId); + $this->apps[$appId] = AsyncClient::create($this->loop, $appId); + return resolve($this->apps[$appId]); } } diff --git a/tests/AsyncClientTest.php b/tests/AsyncClientTest.php index ece1949..9c3144e 100644 --- a/tests/AsyncClientTest.php +++ b/tests/AsyncClientTest.php @@ -1,14 +1,51 @@ -channel('test')->subscribe( + function () { + }, + function ($e) use (&$capturedException) { + $capturedException = $e; + } + ); + self::assertNull($capturedException); + } + + public function testConnectionRetry() + { + $loop = Factory::create(); + $error = new RuntimeException('', 4199); + $resolver = $this->prophesize(Resolver::class); + $resolver->resolve('ws.pusherapp.com')->shouldBeCalled()->willReturn(reject($error)); + $client = AsyncClient::create($loop, 'abc', $resolver->reveal()); + $client->channel('test')->subscribe(); + $loop->addTimer(1, function () { + }); + $loop->run(); } } diff --git a/tests/CommandBus/Handler/SharedAppClientHandlerTest.php b/tests/CommandBus/Handler/SharedAppClientHandlerTest.php index d337212..634cb38 100644 --- a/tests/CommandBus/Handler/SharedAppClientHandlerTest.php +++ b/tests/CommandBus/Handler/SharedAppClientHandlerTest.php @@ -7,8 +7,8 @@ use ApiClients\Client\Pusher\CommandBus\Handler\SharedAppClientHandler; use ApiClients\Client\Pusher\Service\SharedAppClientService; use ApiClients\Tools\TestUtilities\TestCase; -use function EventLoop\getLoop; use function Clue\React\Block\await; +use function EventLoop\getLoop; final class SharedAppClientHandlerTest extends TestCase { @@ -19,7 +19,7 @@ public function testHandle() $handler = new SharedAppClientHandler(new SharedAppClientService($loop)); $app = await($handler->handle(new SharedAppClientCommand($appId)), $loop); - self::assertInstanceOf(AsyncClient::class, await($handler->handle(new SharedAppClientCommand($appId)), $loop)); + self::assertInstanceOf(AsyncClient::class, $app); self::assertSame($app, await($handler->handle(new SharedAppClientCommand($appId)), $loop)); self::assertNotSame($app, await($handler->handle(new SharedAppClientCommand(md5($appId))), $loop)); } diff --git a/tests/EventTest.php b/tests/EventTest.php index ab04510..204068f 100644 --- a/tests/EventTest.php +++ b/tests/EventTest.php @@ -45,13 +45,27 @@ public function eventsProvider() $data, ]; + $data = [ + 'time' => time(), + 'pid' => getmypid(), + ]; + yield [ + [ + 'event' => 'event:name', + 'channel' => 'foo-bar', + 'data' => $data, + ], + 'event:name', + 'foo-bar', + $data, + ]; } /** - * @param array $input + * @param array $input * @param string $event * @param string $channel - * @param array $data + * @param array $data * * @dataProvider eventsProvider */ diff --git a/tests/Service/SharedAppClientServiceTest.php b/tests/Service/SharedAppClientServiceTest.php index 4b46480..4ecd04a 100644 --- a/tests/Service/SharedAppClientServiceTest.php +++ b/tests/Service/SharedAppClientServiceTest.php @@ -5,8 +5,8 @@ use ApiClients\Client\Pusher\AsyncClient; use ApiClients\Client\Pusher\Service\SharedAppClientService; use ApiClients\Tools\TestUtilities\TestCase; -use function EventLoop\getLoop; use function Clue\React\Block\await; +use function EventLoop\getLoop; final class SharedAppClientServiceTest extends TestCase { @@ -16,9 +16,9 @@ public function testHandle() $appId = uniqid('app-id-', true); $handler = new SharedAppClientService($loop); - $app = await($handler->handle($appId), $loop); - self::assertInstanceOf(AsyncClient::class, await($handler->handle($appId), $loop)); - self::assertSame($app, await($handler->handle($appId), $loop)); - self::assertNotSame($app, await($handler->handle(md5($appId)), $loop)); + $app = await($handler->share($appId), $loop); + self::assertInstanceOf(AsyncClient::class, $app); + self::assertSame($app, await($handler->share($appId), $loop)); + self::assertNotSame($app, await($handler->share(md5($appId)), $loop)); } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 6de025e..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,8 +0,0 @@ -