From 20c24a097535f1f54eccdb210396979535fcd3d3 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 20 Mar 2017 22:07:04 +0100 Subject: [PATCH 1/3] Transformed IteratePagesService from a promised based service to a observer based service --- src/Service/IteratePagesService.php | 93 ++++++++---------- tests/Service/IteratePagesServiceTest.php | 111 +++++++++++++++++++--- 2 files changed, 139 insertions(+), 65 deletions(-) diff --git a/src/Service/IteratePagesService.php b/src/Service/IteratePagesService.php index 5d4380e8c6..6d9128c26d 100644 --- a/src/Service/IteratePagesService.php +++ b/src/Service/IteratePagesService.php @@ -6,12 +6,12 @@ use ApiClients\Foundation\Transport\Service\RequestService; use Psr\Http\Message\ResponseInterface; use React\Promise\CancellablePromiseInterface; -use React\Promise\FulfilledPromise; use RingCentral\Psr7\Request; use Rx\Disposable\CallbackDisposable; use Rx\Observable; use Rx\ObserverInterface; use Rx\SchedulerInterface; +use Rx\Subject\Subject; use function React\Promise\all; use function React\Promise\resolve; @@ -36,30 +36,52 @@ public function handle(string $path = null): CancellablePromiseInterface ObserverInterface $observer, SchedulerInterface $scheduler ) use ($path) { - $promise = $this->requestService-> - handle(new Request('GET', $path))-> - then( - function ($response) use ($observer) { - return $this->handleResponse($response, $observer); - }, - function ($error) use ($observer) { - $observer->onError($error); - } - ) - ; - return new CallbackDisposable(function () use ($promise) { - //$promise->cancel(); + $subject = new Subject(); + $subject->asObservable()->subscribeCallback( + [$observer, 'onNext'], + [$observer, 'onError'], + [$observer, 'onCompleted'], + $scheduler + ); + + $this->sendRequest($path, $subject); + + return new CallbackDisposable(function () use ($subject) { + $subject->dispose(); }); })); } + private function sendRequest(string $path, Subject $subject) + { + $this->requestService-> + handle(new Request('GET', $path))-> + then( + function ($response) use ($subject) { + $this->handleResponse($response, $subject); + }, + function ($error) use ($subject) { + $subject->onError($error); + } + ) + ; + } + private function handleResponse( ResponseInterface $response, - ObserverInterface $observer - ): CancellablePromiseInterface { + Subject $subject + ) { + $subject->onNext($response->getBody()->getJson()); + + if ($subject->isDisposed() || !$subject->hasObservers()) { + $subject->onCompleted(); + return; + } + if (!$response->hasHeader('link')) { - return $this->handleResponseContentsComplete($response, $observer); + $subject->onCompleted(); + return; } $links = [ @@ -74,41 +96,10 @@ private function handleResponse( } if ($links['next'] === false || $links['last'] === false) { - return $this->handleResponseContentsComplete($response, $observer); + $subject->onCompleted(); + return; } - $promises = []; - - $promises[] = $this->requestService-> - handle(new Request('GET', $links['next']))-> - then(function (ResponseInterface $response) use ($observer) { - return $this->handleResponse($response, $observer); - }) - ; - - $promises[] = $this->handleResponseContents($response, $observer); - - return all($promises); - } - - private function handleResponseContentsComplete( - ResponseInterface $response, - ObserverInterface $observer - ): CancellablePromiseInterface { - return $this->handleResponseContents($response, $observer)->then(function () use ($observer) { - $observer->onCompleted(); - return new FulfilledPromise(); - }, function ($error) use ($observer) { - $observer->onError($error); - return new FulfilledPromise(); - }); - } - - private function handleResponseContents( - ResponseInterface $response, - ObserverInterface $observer - ): CancellablePromiseInterface { - $observer->onNext($response->getBody()->getJson()); - return new FulfilledPromise(); + $this->sendRequest($links['next'], $subject); } } diff --git a/tests/Service/IteratePagesServiceTest.php b/tests/Service/IteratePagesServiceTest.php index 3f7f9e8b7a..ef2acc489e 100644 --- a/tests/Service/IteratePagesServiceTest.php +++ b/tests/Service/IteratePagesServiceTest.php @@ -3,13 +3,14 @@ namespace ApiClients\Client\Github\Service; use ApiClients\Foundation\Transport\ClientInterface; +use ApiClients\Foundation\Transport\JsonStream; use ApiClients\Foundation\Transport\Service\RequestService; use ApiClients\Tools\TestUtilities\TestCase; use Prophecy\Argument; -use RingCentral\Psr7\BufferStream; use RingCentral\Psr7\Request; use RingCentral\Psr7\Response; use Rx\Observable; +use Rx\Scheduler\ImmediateScheduler; use function ApiClients\Tools\Rx\unwrapObservableFromPromise; use function React\Promise\all; use function React\Promise\resolve; @@ -26,47 +27,129 @@ public function testHandle() * First request */ $firstRequest = new Request('GET', '/foo.bar'); - $firstBody = 'a'; - $firstStream = new BufferStream(strlen($firstBody)); - $firstStream->write($firstBody); + $firstBody = ['a']; + $firstStream = new JsonStream($firstBody); $firstHeaders = [ 'Link' => [ '; rel="next", ; rel="last"', ], ]; - $firstResponse = new Response(200, $firstHeaders, $firstBody); + $firstResponse = new Response(200, $firstHeaders, $firstStream); $client->request($firstRequest, Argument::type('array'))->shouldBeCalled()->willReturn(resolve($firstResponse)); /** * Second request */ $secondRequest = new Request('GET', 'https://api.example.com/1'); - $secondBody = 'a'; - $secondStream = new BufferStream(strlen($secondBody)); - $secondStream->write($secondBody); + $secondBody = ['b']; + $secondStream = new JsonStream($secondBody); $secondHeaders = [ 'Link' => [ - '; rel="last"', + '; rel="next", ; rel="last"', ], ]; - $secondResponse = new Response(200, $secondHeaders, $secondBody); + $secondResponse = new Response(200, $secondHeaders, $secondStream); $client->request($secondRequest, Argument::type('array'))->shouldBeCalled()->willReturn(resolve($secondResponse)); + /** + * Third request + */ + $thirdRequest = new Request('GET', 'https://api.example.com/2'); + $client->request($thirdRequest, Argument::type('array'))->shouldNotBeCalled(); + $requestService = new RequestService($client->reveal()); $iteratePagesService = new IteratePagesService($requestService); $items = []; $completed = false; - unwrapObservableFromPromise($iteratePagesService->handle($path))->subscribeCallback( - function ($item) use (&$items) { + $stream = unwrapObservableFromPromise($iteratePagesService->handle($path))->subscribeCallback( + function ($item) use (&$items, &$stream) { $items[] = $item; + + if (count($items) == 2) { + $stream->dispose(); + } + }, + function ($t) { + throw $t; }, - null, function () use (&$completed) { $completed = true; - } + }, + new ImmediateScheduler() + ); + + self::assertFalse($completed); + self::assertSame([$firstBody, $secondBody], $items); + } + + public function testHandleContinueEvenThoughNoOneIsListeningDontDoThisHopingRxPHPChangesSomeThingsAfterIveOpenedAnIssueButOnlyIfItIsValid() + { + $path = '/foo.bar'; + + $client = $this->prophesize(ClientInterface::class); + + /** + * First request + */ + $firstRequest = new Request('GET', '/foo.bar'); + $firstBody = ['a']; + $firstStream = new JsonStream($firstBody); + $firstHeaders = [ + 'Link' => [ + '; rel="next", ; rel="last"', + ], + ]; + $firstResponse = new Response(200, $firstHeaders, $firstStream); + $client->request($firstRequest, Argument::type('array'))->shouldBeCalled()->willReturn(resolve($firstResponse)); + + /** + * Second request + */ + $secondRequest = new Request('GET', 'https://api.example.com/1'); + $secondBody = ['b']; + $secondStream = new JsonStream($secondBody); + $secondHeaders = [ + 'Link' => [ + '; rel="next", ; rel="last"', + ], + ]; + $secondResponse = new Response(200, $secondHeaders, $secondStream); + $client->request($secondRequest, Argument::type('array'))->shouldBeCalled()->willReturn(resolve($secondResponse)); + + /** + * Third request + */ + $thirdRequest = new Request('GET', 'https://api.example.com/2'); + $thirdBody = ['b']; + $thirdStream = new JsonStream($thirdBody); + $thirdHeaders = [ + 'Link' => [ + '; rel="last"', + ], + ]; + $thirdResponse = new Response(200, $thirdHeaders, $thirdStream); + $client->request($thirdRequest, Argument::type('array'))->shouldBeCalled()->willReturn(resolve($thirdResponse)); + + $requestService = new RequestService($client->reveal()); + $iteratePagesService = new IteratePagesService($requestService); + + $items = []; + $completed = false; + unwrapObservableFromPromise($iteratePagesService->handle($path))->take(2)->subscribeCallback( + function ($item) use (&$items, &$stream) { + $items[] = $item; + }, + function ($t) { + throw $t; + }, + function () use (&$completed) { + $completed = true; + }, + new ImmediateScheduler() ); self::assertTrue($completed); + self::assertSame([$firstBody, $secondBody], $items); } } From 98206e12114f7ff2f642b4ca485a92256e71e1f0 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Tue, 21 Mar 2017 19:54:38 +0100 Subject: [PATCH 2/3] Updated test method name, no need to create issue --- tests/Service/IteratePagesServiceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Service/IteratePagesServiceTest.php b/tests/Service/IteratePagesServiceTest.php index ef2acc489e..ebf3321883 100644 --- a/tests/Service/IteratePagesServiceTest.php +++ b/tests/Service/IteratePagesServiceTest.php @@ -83,7 +83,7 @@ function () use (&$completed) { self::assertSame([$firstBody, $secondBody], $items); } - public function testHandleContinueEvenThoughNoOneIsListeningDontDoThisHopingRxPHPChangesSomeThingsAfterIveOpenedAnIssueButOnlyIfItIsValid() + public function testHandleTakingTwoWillStillMakeThirdRequest() { $path = '/foo.bar'; From e03fde72a8332dc3f765a592fc8b752f41da3915 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Fri, 24 Mar 2017 08:01:51 +0100 Subject: [PATCH 3/3] Upgraded to RxPHP 20 --- composer.json | 3 +- composer.lock | 202 +++++++++++++----- .../Handler/IteratePagesHandler.php | 2 +- .../Handler/MyOrganizationsHandler.php | 6 +- src/CommandBus/Handler/RefreshHandler.php | 2 +- .../Handler/Repository/BranchesHandler.php | 15 +- .../Repository/Commit/StatusesHandler.php | 15 +- .../Handler/Repository/CommitsHandler.php | 15 +- .../Handler/Repository/LabelsHandler.php | 15 +- .../Handler/User/OrganizationsHandler.php | 6 +- .../Handler/User/RepositoriesHandler.php | 6 +- src/Service/IteratePagesService.php | 18 +- .../CommandBus/Handler/RefreshHandlerTest.php | 2 +- .../Repository/BranchesHandlerTest.php | 2 +- .../Repository/Commit/StatusesHandlerTest.php | 2 +- .../Handler/Repository/CommitsHandlerTest.php | 2 +- .../Handler/Repository/LabelsHandlerTest.php | 2 +- tests/Service/IteratePagesServiceTest.php | 4 +- 18 files changed, 205 insertions(+), 114 deletions(-) diff --git a/composer.json b/composer.json index ca25212e5b..2b30240ab9 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "api-clients/middleware-http-exceptions": "^1.0", "api-clients/middleware-token-authorization": "^2.0", "api-clients/middleware-user-agent": "^1.0", - "api-clients/service": "dev-master", + "api-clients/rx": "^2.0", + "api-clients/rx-operators": "^2.0", "api-clients/transport": "dev-master" }, "require-dev": { diff --git a/composer.lock b/composer.lock index d2995c7b54..6695b666d9 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": "dc77dd7e01b6c020997c1df8a9d91813", + "content-hash": "30ac447c9df31f1dcc32e5cd03d6c526", "packages": [ { "name": "api-clients/client-services", @@ -12,24 +12,23 @@ "source": { "type": "git", "url": "https://github.com/php-api-clients/client-services.git", - "reference": "d15175524cb218e4a4f4b68e1c2aa6639d037feb" + "reference": "3a509eb987b8920c2e5a13aa297dabd0abf05d5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/client-services/zipball/d15175524cb218e4a4f4b68e1c2aa6639d037feb", - "reference": "d15175524cb218e4a4f4b68e1c2aa6639d037feb", + "url": "https://api.github.com/repos/php-api-clients/client-services/zipball/3a509eb987b8920c2e5a13aa297dabd0abf05d5b", + "reference": "3a509eb987b8920c2e5a13aa297dabd0abf05d5b", "shasum": "" }, "require": { "api-clients/hydrator": "dev-master", - "api-clients/rx": "dev-master", - "api-clients/service": "dev-master", + "api-clients/rx": "^2.0||^1.0", "api-clients/transport": "dev-master", "igorw/get-in": "^1.0", "php": "^7.0" }, "require-dev": { - "api-clients/test-utilities": "^2.0" + "api-clients/test-utilities": "^3.0.1" }, "type": "library", "autoload": { @@ -48,7 +47,7 @@ } ], "description": "Generic client services", - "time": "2016-12-25 18:20:13" + "time": "2017-03-23 18:03:29" }, { "name": "api-clients/command-bus", @@ -481,25 +480,25 @@ }, { "name": "api-clients/rx", - "version": "dev-master", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-api-clients/rx.git", - "reference": "a1d797606e1367a51055634eb73cba20112a99ed" + "reference": "baadcfcc2f088423bce8ee66f1d46cdeac1192b6" }, "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/baadcfcc2f088423bce8ee66f1d46cdeac1192b6", + "reference": "baadcfcc2f088423bce8ee66f1d46cdeac1192b6", "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": { @@ -507,7 +506,8 @@ "ApiClients\\Tools\\Rx\\": "src/" }, "files": [ - "src/functions_include.php" + "src/functions_include.php", + "src/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -520,7 +520,47 @@ "email": "ceesjank@gmail.com" } ], - "time": "2017-01-09 14:39:21" + "time": "2017-03-22T20:37:41+00:00" + }, + { + "name": "api-clients/rx-operators", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-api-clients/rx-operators.git", + "reference": "974e38c8ce2457567d9a36f3430c524b594417e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-api-clients/rx-operators/zipball/974e38c8ce2457567d9a36f3430c524b594417e7", + "reference": "974e38c8ce2457567d9a36f3430c524b594417e7", + "shasum": "" + }, + "require": { + "api-clients/rx": "^2.0", + "php": "^7.0", + "rx/operator-extras": "^2.0" + }, + "require-dev": { + "api-clients/test-utilities": "^3.0.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "ApiClients\\Rx\\Operator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + } + ], + "time": "2017-03-23T07:06:10+00:00" }, { "name": "api-clients/service", @@ -567,18 +607,18 @@ "source": { "type": "git", "url": "https://github.com/php-api-clients/transport.git", - "reference": "8cad202e27aaff6ba777938d11bc8f778716b34e" + "reference": "3437675937df0110d515be6c8099e6b7ca281964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/transport/zipball/8cad202e27aaff6ba777938d11bc8f778716b34e", - "reference": "8cad202e27aaff6ba777938d11bc8f778716b34e", + "url": "https://api.github.com/repos/php-api-clients/transport/zipball/3437675937df0110d515be6c8099e6b7ca281964", + "reference": "3437675937df0110d515be6c8099e6b7ca281964", "shasum": "" }, "require": { "api-clients/middleware": "^2.0", "api-clients/resource": "^3.0", - "api-clients/rx": "dev-master", + "api-clients/rx": "^2.0", "api-clients/service": "dev-master", "clue/block-react": "^1.1", "clue/buzz-react": "^1.1", @@ -623,7 +663,7 @@ "email": "ceesjank@gmail.com" } ], - "time": "2017-03-11 00:03:30" + "time": "2017-03-23 16:48:30" }, { "name": "clue/block-react", @@ -1034,16 +1074,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/0d6c7ca039329247e4f0f8f8f6506810e8248855", - "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -1095,7 +1135,7 @@ "uri", "url" ], - "time": "2017-02-27T10:51:17+00:00" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "igorw/get-in", @@ -1600,23 +1640,24 @@ }, { "name": "php-di/php-di", - "version": "5.4.0", + "version": "5.4.1", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "e348393488fa909e4bc0707ba5c9c44cd602a1cb" + "reference": "4ec345f6e7f5e18e955d0973f8611dcc0ab348be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/e348393488fa909e4bc0707ba5c9c44cd602a1cb", - "reference": "e348393488fa909e4bc0707ba5c9c44cd602a1cb", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/4ec345f6e7f5e18e955d0973f8611dcc0ab348be", + "reference": "4ec345f6e7f5e18e955d0973f8611dcc0ab348be", "shasum": "" }, "require": { - "container-interop/container-interop": "~1.0", + "container-interop/container-interop": "~1.2", "php": ">=5.5.0", "php-di/invoker": "^1.3.2", - "php-di/phpdoc-reader": "^2.0.1" + "php-di/phpdoc-reader": "^2.0.1", + "psr/container": "~1.0" }, "provide": { "container-interop/container-interop-implementation": "^1.0" @@ -1656,7 +1697,7 @@ "dependency injection", "di" ], - "time": "2016-08-23T20:18:00+00:00" + "time": "2017-03-22T21:09:54+00:00" }, { "name": "php-di/phpdoc-reader", @@ -1916,16 +1957,16 @@ }, { "name": "react/http-client", - "version": "v0.4.16", + "version": "v0.4.17", "source": { "type": "git", "url": "https://github.com/reactphp/http-client.git", - "reference": "307d8f9c9062c9f2fb21cde6ad13afee040cce15" + "reference": "75ee8a113f156834aaabfe0055e8db531cb4892c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http-client/zipball/307d8f9c9062c9f2fb21cde6ad13afee040cce15", - "reference": "307d8f9c9062c9f2fb21cde6ad13afee040cce15", + "url": "https://api.github.com/repos/reactphp/http-client/zipball/75ee8a113f156834aaabfe0055e8db531cb4892c", + "reference": "75ee8a113f156834aaabfe0055e8db531cb4892c", "shasum": "" }, "require": { @@ -1938,6 +1979,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": { @@ -1952,7 +1996,7 @@ "keywords": [ "http" ], - "time": "2017-03-01T11:07:56+00:00" + "time": "2017-03-20T09:55:48+00:00" }, { "name": "react/promise", @@ -2176,41 +2220,40 @@ }, { "name": "reactivex/rxphp", - "version": "1.5.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/ReactiveX/RxPHP.git", - "reference": "84bfbd05e79d924b3d2597eaeef6156475e2a514" + "reference": "4ad811032428074485d7ca99b779aec54b242982" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ReactiveX/RxPHP/zipball/84bfbd05e79d924b3d2597eaeef6156475e2a514", - "reference": "84bfbd05e79d924b3d2597eaeef6156475e2a514", + "url": "https://api.github.com/repos/ReactiveX/RxPHP/zipball/4ad811032428074485d7ca99b779aec54b242982", + "reference": "4ad811032428074485d7ca99b779aec54b242982", "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/", @@ -2238,7 +2281,7 @@ "reactive", "rx" ], - "time": "2017-02-07T19:28:24+00:00" + "time": "2017-03-21T13:29:22+00:00" }, { "name": "ringcentral/psr7", @@ -2298,6 +2341,54 @@ ], "time": "2016-03-25T17:36:49+00:00" }, + { + "name": "rx/operator-extras", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/RxPHP/RxOperatorExtras.git", + "reference": "3ccbd8dfb414ffe2c86199a98361903d383b9072" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/RxPHP/RxOperatorExtras/zipball/3ccbd8dfb414ffe2c86199a98361903d383b9072", + "reference": "3ccbd8dfb414ffe2c86199a98361903d383b9072", + "shasum": "" + }, + "require": { + "php": "^7.0", + "reactivex/rxphp": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Rx\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Bonneau", + "email": "matt@bonneau.net", + "role": "Developer" + }, + { + "name": "David Dan", + "email": "davidwdan@gmail.com", + "role": "Developer" + } + ], + "description": "Extra Operators and Observables for RxPHP", + "keywords": [ + "reactivex", + "rx.php", + "rxphp" + ], + "time": "2017-03-21T17:25:58+00:00" + }, { "name": "wyrihaximus/tactician-command-handler-mapper", "version": "1.0.0", @@ -3039,16 +3130,16 @@ }, { "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": { @@ -3093,7 +3184,7 @@ "mock", "testing" ], - "time": "2016-03-04T18:49:33+00:00" + "time": "2017-03-20T05:16:34+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -4878,7 +4969,6 @@ "stability-flags": { "api-clients/client-services": 20, "api-clients/foundation": 20, - "api-clients/service": 20, "api-clients/transport": 20, "api-clients/appveyor": 20, "api-clients/resource-generator": 20, diff --git a/src/CommandBus/Handler/IteratePagesHandler.php b/src/CommandBus/Handler/IteratePagesHandler.php index fbfcb4f8a0..5f76cb8076 100644 --- a/src/CommandBus/Handler/IteratePagesHandler.php +++ b/src/CommandBus/Handler/IteratePagesHandler.php @@ -26,6 +26,6 @@ public function __construct(IteratePagesService $service) public function handle(IteratePagesCommand $command): CancellablePromiseInterface { - return $this->service->handle($command->getPath()); + return resolve($this->service->iterate($command->getPath())); } } diff --git a/src/CommandBus/Handler/MyOrganizationsHandler.php b/src/CommandBus/Handler/MyOrganizationsHandler.php index d4dc05e365..730e6212a5 100644 --- a/src/CommandBus/Handler/MyOrganizationsHandler.php +++ b/src/CommandBus/Handler/MyOrganizationsHandler.php @@ -40,12 +40,12 @@ public function __construct(IteratePagesService $service, Hydrator $hydrator) */ public function handle(MyOrganizationsCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->service->handle('user/orgs') + return resolve( + $this->service->iterate('user/orgs') )->flatMap(function ($organizations) { return Observable::fromArray($organizations); })->map(function ($organization) { return $this->hydrator->hydrate(OrganizationInterface::HYDRATE_CLASS, $organization); - })); + }); } } diff --git a/src/CommandBus/Handler/RefreshHandler.php b/src/CommandBus/Handler/RefreshHandler.php index 46aa766dc8..e6e1e1a40d 100644 --- a/src/CommandBus/Handler/RefreshHandler.php +++ b/src/CommandBus/Handler/RefreshHandler.php @@ -31,6 +31,6 @@ public function handle(RefreshCommand $command): PromiseInterface { $resource = $command->getResource(); - return $this->service->handle($resource->url(), '', $resource::HYDRATE_CLASS); + return $this->service->fetch($resource->url(), '', $resource::HYDRATE_CLASS); } } diff --git a/src/CommandBus/Handler/Repository/BranchesHandler.php b/src/CommandBus/Handler/Repository/BranchesHandler.php index 9cefa53232..4941e7e19c 100644 --- a/src/CommandBus/Handler/Repository/BranchesHandler.php +++ b/src/CommandBus/Handler/Repository/BranchesHandler.php @@ -40,12 +40,13 @@ public function __construct(IteratePagesService $iteratePagesService, Hydrator $ */ public function handle(BranchesCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->iteratePagesService->handle('repos/' . $command->getFullName() . '/branches') - )->flatMap(function ($labels) { - return Observable::fromArray($labels); - })->map(function ($label) { - return $this->hydrator->hydrate(BranchInterface::HYDRATE_CLASS, $label); - })); + return resolve( + $this->iteratePagesService->iterate('repos/' . $command->getFullName() . '/branches') + ->flatMap(function ($labels) { + return Observable::fromArray($labels); + })->map(function ($label) { + return $this->hydrator->hydrate(BranchInterface::HYDRATE_CLASS, $label); + }) + ); } } diff --git a/src/CommandBus/Handler/Repository/Commit/StatusesHandler.php b/src/CommandBus/Handler/Repository/Commit/StatusesHandler.php index 823e3e3a49..5e74f610a1 100644 --- a/src/CommandBus/Handler/Repository/Commit/StatusesHandler.php +++ b/src/CommandBus/Handler/Repository/Commit/StatusesHandler.php @@ -40,12 +40,13 @@ public function __construct(IteratePagesService $iteratePagesService, Hydrator $ */ public function handle(StatusesCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->iteratePagesService->handle($command->getCommit()->url() . '/statuses') - )->flatMap(function ($statuses) { - return Observable::fromArray($statuses); - })->map(function ($status) { - return $this->hydrator->hydrate(StatusInterface::HYDRATE_CLASS, $status); - })); + return resolve( + $this->iteratePagesService->iterate($command->getCommit()->url() . '/statuses') + ->flatMap(function ($statuses) { + return Observable::fromArray($statuses); + })->map(function ($status) { + return $this->hydrator->hydrate(StatusInterface::HYDRATE_CLASS, $status); + }) + ); } } diff --git a/src/CommandBus/Handler/Repository/CommitsHandler.php b/src/CommandBus/Handler/Repository/CommitsHandler.php index f7bb850ea0..a7aaeb792b 100644 --- a/src/CommandBus/Handler/Repository/CommitsHandler.php +++ b/src/CommandBus/Handler/Repository/CommitsHandler.php @@ -40,12 +40,13 @@ public function __construct(IteratePagesService $iteratePagesService, Hydrator $ */ public function handle(CommitsCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->iteratePagesService->handle('repos/' . $command->getFullName() . '/commits') - )->flatMap(function ($commits) { - return Observable::fromArray($commits); - })->map(function ($commit) { - return $this->hydrator->hydrate(CommitInterface::HYDRATE_CLASS, $commit); - })); + return resolve( + $this->iteratePagesService->iterate('repos/' . $command->getFullName() . '/commits') + ->flatMap(function ($commits) { + return Observable::fromArray($commits); + })->map(function ($commit) { + return $this->hydrator->hydrate(CommitInterface::HYDRATE_CLASS, $commit); + }) + ); } } diff --git a/src/CommandBus/Handler/Repository/LabelsHandler.php b/src/CommandBus/Handler/Repository/LabelsHandler.php index 0b1a9fe5e2..f31ed47279 100644 --- a/src/CommandBus/Handler/Repository/LabelsHandler.php +++ b/src/CommandBus/Handler/Repository/LabelsHandler.php @@ -40,12 +40,13 @@ public function __construct(IteratePagesService $iteratePagesService, Hydrator $ */ public function handle(LabelsCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->iteratePagesService->handle('repos/' . $command->getFullName() . '/labels') - )->flatMap(function ($labels) { - return Observable::fromArray($labels); - })->map(function ($label) { - return $this->hydrator->hydrate(LabelInterface::HYDRATE_CLASS, $label); - })); + return resolve( + $this->iteratePagesService->iterate('repos/' . $command->getFullName() . '/labels') + ->flatMap(function ($labels) { + return Observable::fromArray($labels); + })->map(function ($label) { + return $this->hydrator->hydrate(LabelInterface::HYDRATE_CLASS, $label); + }) + ); } } diff --git a/src/CommandBus/Handler/User/OrganizationsHandler.php b/src/CommandBus/Handler/User/OrganizationsHandler.php index 1bef367e98..7c7a506d38 100644 --- a/src/CommandBus/Handler/User/OrganizationsHandler.php +++ b/src/CommandBus/Handler/User/OrganizationsHandler.php @@ -40,12 +40,12 @@ public function __construct(IteratePagesService $service, Hydrator $hydrator) */ public function handle(OrganizationsCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->service->handle('users/' . $command->getLogin() . '/orgs') + return resolve( + $this->service->iterate('users/' . $command->getLogin() . '/orgs') )->flatMap(function ($organizations) { return Observable::fromArray($organizations); })->map(function ($organization) { return $this->hydrator->hydrate(OrganizationInterface::HYDRATE_CLASS, $organization); - })); + }); } } diff --git a/src/CommandBus/Handler/User/RepositoriesHandler.php b/src/CommandBus/Handler/User/RepositoriesHandler.php index ccdf4d3d8a..d4c13a0c37 100644 --- a/src/CommandBus/Handler/User/RepositoriesHandler.php +++ b/src/CommandBus/Handler/User/RepositoriesHandler.php @@ -42,12 +42,12 @@ public function __construct(IteratePagesService $iteratePagesService, Hydrator $ */ public function handle(RepositoriesCommand $command): PromiseInterface { - return resolve(unwrapObservableFromPromise( - $this->iteratePagesService->handle('users/' . $command->getLogin() . '/repos') + return resolve( + $this->iteratePagesService->iterate('users/' . $command->getLogin() . '/repos') )->flatMap(function ($repositories) { return Observable::fromArray($repositories); })->map(function ($repository) { return $this->hydrator->hydrate(RepositoryInterface::HYDRATE_CLASS, $repository); - })); + }); } } diff --git a/src/Service/IteratePagesService.php b/src/Service/IteratePagesService.php index 6d9128c26d..98f9797503 100644 --- a/src/Service/IteratePagesService.php +++ b/src/Service/IteratePagesService.php @@ -2,7 +2,6 @@ namespace ApiClients\Client\Github\Service; -use ApiClients\Foundation\Service\ServiceInterface; use ApiClients\Foundation\Transport\Service\RequestService; use Psr\Http\Message\ResponseInterface; use React\Promise\CancellablePromiseInterface; @@ -15,7 +14,7 @@ use function React\Promise\all; use function React\Promise\resolve; -class IteratePagesService implements ServiceInterface +class IteratePagesService { /** * @var RequestService @@ -30,19 +29,16 @@ public function __construct(RequestService $requestService) $this->requestService = $requestService; } - public function handle(string $path = null): CancellablePromiseInterface + public function iterate(string $path): Observable { - return resolve(Observable::create(function ( - ObserverInterface $observer, - SchedulerInterface $scheduler + return Observable::create(function ( + ObserverInterface $observer ) use ($path) { - $subject = new Subject(); - $subject->asObservable()->subscribeCallback( + $subject->asObservable()->subscribe( [$observer, 'onNext'], [$observer, 'onError'], - [$observer, 'onCompleted'], - $scheduler + [$observer, 'onCompleted'] ); $this->sendRequest($path, $subject); @@ -50,7 +46,7 @@ public function handle(string $path = null): CancellablePromiseInterface return new CallbackDisposable(function () use ($subject) { $subject->dispose(); }); - })); + }); } private function sendRequest(string $path, Subject $subject) diff --git a/tests/CommandBus/Handler/RefreshHandlerTest.php b/tests/CommandBus/Handler/RefreshHandlerTest.php index e032f484c8..9dbbee44f1 100644 --- a/tests/CommandBus/Handler/RefreshHandlerTest.php +++ b/tests/CommandBus/Handler/RefreshHandlerTest.php @@ -24,7 +24,7 @@ public function url(): string $command = new RefreshCommand($resource); $service = $this->prophesize(FetchAndHydrateService::class); - $service->handle('https://example.com/', '', 'foo.bar')->shouldBeCalled()->willReturn(resolve(true)); + $service->fetch('https://example.com/', '', 'foo.bar')->shouldBeCalled()->willReturn(resolve(true)); $handler = new RefreshHandler($service->reveal()); diff --git a/tests/CommandBus/Handler/Repository/BranchesHandlerTest.php b/tests/CommandBus/Handler/Repository/BranchesHandlerTest.php index 521d173980..b0ff3ac0ec 100644 --- a/tests/CommandBus/Handler/Repository/BranchesHandlerTest.php +++ b/tests/CommandBus/Handler/Repository/BranchesHandlerTest.php @@ -25,7 +25,7 @@ public function testCommand() $command = new BranchesCommand('api-clients/github'); $iteratePagesService = $this->prophesize(IteratePagesService::class); - $iteratePagesService->handle('repos/api-clients/github/branches')->shouldBeCalled()->willReturn(resolve(Observable::fromArray([[$branchArray]]))); + $iteratePagesService->iterate('repos/api-clients/github/branches')->shouldBeCalled()->willReturn(Observable::fromArray([[$branchArray]])); $hydrator = $this->prophesize(Hydrator::class); $hydrator->hydrate(BranchInterface::HYDRATE_CLASS, $branchArray)->shouldBeCalled()->wilLReturn($branch); diff --git a/tests/CommandBus/Handler/Repository/Commit/StatusesHandlerTest.php b/tests/CommandBus/Handler/Repository/Commit/StatusesHandlerTest.php index 55f4114a87..bcd3af1dda 100644 --- a/tests/CommandBus/Handler/Repository/Commit/StatusesHandlerTest.php +++ b/tests/CommandBus/Handler/Repository/Commit/StatusesHandlerTest.php @@ -29,7 +29,7 @@ public function testCommand() $command = new StatusesCommand($commit->reveal()); $iteratePagesService = $this->prophesize(IteratePagesService::class); - $iteratePagesService->handle('repos/api-clients/github/commits/123/statuses')->shouldBeCalled()->willReturn(resolve(Observable::fromArray([[$branchArray]]))); + $iteratePagesService->iterate('repos/api-clients/github/commits/123/statuses')->shouldBeCalled()->willReturn(Observable::fromArray([[$branchArray]])); $hydrator = $this->prophesize(Hydrator::class); $hydrator->hydrate(StatusInterface::HYDRATE_CLASS, $branchArray)->shouldBeCalled()->wilLReturn($branch); diff --git a/tests/CommandBus/Handler/Repository/CommitsHandlerTest.php b/tests/CommandBus/Handler/Repository/CommitsHandlerTest.php index c514a0c4b9..b9182e42fc 100644 --- a/tests/CommandBus/Handler/Repository/CommitsHandlerTest.php +++ b/tests/CommandBus/Handler/Repository/CommitsHandlerTest.php @@ -25,7 +25,7 @@ public function testCommand() $command = new CommitsCommand('api-clients/github'); $iteratePagesService = $this->prophesize(IteratePagesService::class); - $iteratePagesService->handle('repos/api-clients/github/commits')->shouldBeCalled()->willReturn(resolve(Observable::fromArray([[$branchArray]]))); + $iteratePagesService->iterate('repos/api-clients/github/commits')->shouldBeCalled()->willReturn(Observable::fromArray([[$branchArray]])); $hydrator = $this->prophesize(Hydrator::class); $hydrator->hydrate(CommitInterface::HYDRATE_CLASS, $branchArray)->shouldBeCalled()->wilLReturn($branch); diff --git a/tests/CommandBus/Handler/Repository/LabelsHandlerTest.php b/tests/CommandBus/Handler/Repository/LabelsHandlerTest.php index e64b91cb6e..5fa028063b 100644 --- a/tests/CommandBus/Handler/Repository/LabelsHandlerTest.php +++ b/tests/CommandBus/Handler/Repository/LabelsHandlerTest.php @@ -24,7 +24,7 @@ public function testCommand() $command = new LabelsCommand('api-clients/github'); $iteratePagesService = $this->prophesize(IteratePagesService::class); - $iteratePagesService->handle('repos/api-clients/github/labels')->shouldBeCalled()->willReturn(resolve(Observable::fromArray([[$labelArray]]))); + $iteratePagesService->iterate('repos/api-clients/github/labels')->shouldBeCalled()->willReturn(Observable::fromArray([[$labelArray]])); $hydrator = $this->prophesize(Hydrator::class); $hydrator->hydrate(LabelInterface::HYDRATE_CLASS, $labelArray)->shouldBeCalled()->wilLReturn($label); diff --git a/tests/Service/IteratePagesServiceTest.php b/tests/Service/IteratePagesServiceTest.php index ef2acc489e..ffcf848fea 100644 --- a/tests/Service/IteratePagesServiceTest.php +++ b/tests/Service/IteratePagesServiceTest.php @@ -62,7 +62,7 @@ public function testHandle() $items = []; $completed = false; - $stream = unwrapObservableFromPromise($iteratePagesService->handle($path))->subscribeCallback( + $stream = $iteratePagesService->iterate($path)->subscribe( function ($item) use (&$items, &$stream) { $items[] = $item; @@ -136,7 +136,7 @@ public function testHandleContinueEvenThoughNoOneIsListeningDontDoThisHopingRxPH $items = []; $completed = false; - unwrapObservableFromPromise($iteratePagesService->handle($path))->take(2)->subscribeCallback( + $iteratePagesService->iterate($path)->take(2)->subscribe( function ($item) use (&$items, &$stream) { $items[] = $item; },