From ddd3b3456d9e6e98629b8e9b5df1dc03cffed9f5 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 23 Nov 2016 23:13:01 +0100 Subject: [PATCH 1/4] Updated deps --- composer.lock | 70 ++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/composer.lock b/composer.lock index 022e813..f7bb71f 100644 --- a/composer.lock +++ b/composer.lock @@ -2337,16 +2337,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -2382,20 +2382,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", - "version": "5.6.2", + "version": "5.6.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01" + "reference": "4ddb822f1de421b4cadb47570a525fd7d9359493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cd13b23ac5a519a4708e00736c26ee0bb28b2e01", - "reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4ddb822f1de421b4cadb47570a525fd7d9359493", + "reference": "4ddb822f1de421b4cadb47570a525fd7d9359493", "shasum": "" }, "require": { @@ -2423,7 +2423,9 @@ "symfony/yaml": "~2.1|~3.0" }, "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "phpdocumentor/reflection-docblock": "3.0.2", + "sebastian/object-enumerator": "1.0.1", + "sebastian/recursion-context": "1.0.3 || 1.0.4" }, "require-dev": { "ext-pdo": "*" @@ -2464,27 +2466,27 @@ "testing", "xunit" ], - "time": "2016-10-25 07:40:25" + "time": "2016-11-18 09:50:51" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.0", + "version": "3.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" + "reference": "45026c8383187ad1dcb14fbfec77dced265b9cfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/45026c8383187ad1dcb14fbfec77dced265b9cfc", + "reference": "45026c8383187ad1dcb14fbfec77dced265b9cfc", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.6 || ^7.0", "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" + "sebastian/exporter": "^1.2 || ^2.0" }, "conflict": { "phpunit/phpunit": "<5.4.0" @@ -2523,7 +2525,7 @@ "mock", "xunit" ], - "time": "2016-10-09 07:01:45" + "time": "2016-11-19 09:07:46" }, { "name": "psr/log", @@ -2669,22 +2671,22 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -2729,7 +2731,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -3137,16 +3139,16 @@ }, { "name": "seld/jsonlint", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70" + "reference": "19495c181d6d53a0a13414154e52817e3b504189" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/e827b5254d3e58c736ea2c5616710983d80b0b70", - "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/19495c181d6d53a0a13414154e52817e3b504189", + "reference": "19495c181d6d53a0a13414154e52817e3b504189", "shasum": "" }, "require": { @@ -3179,7 +3181,7 @@ "parser", "validator" ], - "time": "2016-09-14 15:17:56" + "time": "2016-11-14 17:59:58" }, { "name": "squizlabs/php_codesniffer", @@ -3537,16 +3539,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "dff51f72b0706335131b00a7f49606168c582594" + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", - "reference": "dff51f72b0706335131b00a7f49606168c582594", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", "shasum": "" }, "require": { @@ -3558,7 +3560,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -3592,7 +3594,7 @@ "portable", "shim" ], - "time": "2016-05-18 14:26:46" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/process", From 491bfe2c9879e04d4327b0c623d0b2f1cce44587 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 24 Nov 2016 08:03:51 +0100 Subject: [PATCH 2/4] Require handlers to return promises --- src/HandlerInterface.php | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/HandlerInterface.php b/src/HandlerInterface.php index 8a6e13e..ec4635f 100644 --- a/src/HandlerInterface.php +++ b/src/HandlerInterface.php @@ -3,10 +3,37 @@ namespace ApiClients\Foundation\Hydrator; use ApiClients\Foundation\Resource\ResourceInterface; +use React\Promise\CancellablePromiseInterface; interface HandlerInterface { + /** + * HandlerInterface constructor. + * @param Hydrator $hydrator + */ public function __construct(Hydrator $hydrator); - public function hydrate(AnnotationInterface $annotation, array $json, ResourceInterface $object): array; - public function extract(AnnotationInterface $annotation, ResourceInterface $object, array $json): array; + + /** + * @param AnnotationInterface $annotation + * @param array $json + * @param ResourceInterface $object + * @return CancellablePromiseInterface + */ + public function hydrate( + AnnotationInterface $annotation, + array $json, + ResourceInterface $object + ): CancellablePromiseInterface; + + /** + * @param AnnotationInterface $annotation + * @param ResourceInterface $object + * @param array $json + * @return CancellablePromiseInterface + */ + public function extract( + AnnotationInterface $annotation, + ResourceInterface $object, + array $json + ): CancellablePromiseInterface; } From ebe4eee2265cf7a0a73e59b9a4364c3eb2d4387a Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 24 Nov 2016 08:05:10 +0100 Subject: [PATCH 3/4] Turn hydrator into using promises --- src/Hydrator.php | 80 ++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/src/Hydrator.php b/src/Hydrator.php index 23bff4d..99871cd 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -11,11 +11,13 @@ use Doctrine\Common\Cache\Cache; use GeneratedHydrator\Configuration; use Interop\Container\ContainerInterface; +use React\Promise\CancellablePromiseInterface; use ReflectionClass; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use ApiClients\Foundation\Resource\ResourceInterface; use Zend\Hydrator\HydratorInterface; +use function React\Promise\resolve; class Hydrator { @@ -115,9 +117,9 @@ public function preheat(string $scanTarget, string $namespace) /** * @param string $class * @param array $json - * @return ResourceInterface + * @return CancellablePromiseInterface */ - public function hydrate(string $class, array $json): ResourceInterface + public function hydrate(string $class, array $json): CancellablePromiseInterface { $fullClassName = implode( '\\', @@ -133,35 +135,44 @@ public function hydrate(string $class, array $json): ResourceInterface /** * @param string $class * @param array $json - * @return ResourceInterface + * @return CancellablePromiseInterface */ - public function hydrateFQCN(string $class, array $json): ResourceInterface + public function hydrateFQCN(string $class, array $json): CancellablePromiseInterface { $class = $this->getEmptyOrResource($class, $json); $hydrator = $this->getHydrator($class); $object = new $class($this->container->get(CommandBus::class)); - $json = $this->hydrateApplyAnnotations($json, $object); - $resource = $hydrator->hydrate($json, $object); - return $resource; + return $this->hydrateApplyAnnotations($json, $object)->then(function ($json) use ($hydrator, $object) { + return $hydrator->hydrate($json, $object); + }); } /** * @param array $json * @param ResourceInterface $object - * @return array + * @return CancellablePromiseInterface */ - protected function hydrateApplyAnnotations(array $json, ResourceInterface $object): array + protected function hydrateApplyAnnotations(array $json, ResourceInterface $object): CancellablePromiseInterface { + $promiseChain = resolve($json); foreach ($this->annotationHandlers as $annotationClass => $handler) { $annotation = $this->getAnnotation($object, $annotationClass); if ($annotation === null) { continue; } - $json = $handler->hydrate($annotation, $json, $object); + $req = [ + 'handler' => $handler, + 'annotation' => $annotation, + 'object' => $object, + ]; + + $promiseChain = $promiseChain->then(function (array $json) use ($req) { + return $req['handler']->hydrate($req['annotation'], $json, $req['object']); + }); } - return $json; + return $promiseChain; } protected function getEmptyOrResource(string $class, array $json): string @@ -192,9 +203,9 @@ protected function getEmptyOrResource(string $class, array $json): string /** * @param string $class * @param ResourceInterface $object - * @return array + * @return CancellablePromiseInterface */ - public function extract(string $class, ResourceInterface $object): array + public function extract(string $class, ResourceInterface $object): CancellablePromiseInterface { $fullClassName = implode( '\\', @@ -211,36 +222,45 @@ public function extract(string $class, ResourceInterface $object): array * Takes a fully qualified class name and extracts the data for that class from the given $object * @param string $class * @param ResourceInterface $object - * @return array + * @return CancellablePromiseInterface */ - public function extractFQCN(string $class, ResourceInterface $object): array + public function extractFQCN(string $class, ResourceInterface $object): CancellablePromiseInterface { if ($object instanceof EmptyResourceInterface) { return []; } - $json = $this->getHydrator($class)->extract($object); - $json = $this->extractApplyAnnotations($object, $json); - return $json; + return $this->getHydrator($class)->extract($object)->then(function (array $json) use ($object) { + return $this->extractApplyAnnotations($object, $json); + }); } /** * @param array $json * @param ResourceInterface $object - * @return array + * @return CancellablePromiseInterface */ - protected function extractApplyAnnotations(ResourceInterface $object, array $json): array + protected function extractApplyAnnotations(ResourceInterface $object, array $json): CancellablePromiseInterface { + $promiseChain = resolve($json); foreach ($this->annotationHandlers as $annotationClass => $handler) { $annotation = $this->getAnnotation($object, $annotationClass); if ($annotation === null) { continue; } - $json = $handler->extract($annotation, $object, $json); + $req = [ + 'handler' => $handler, + 'annotation' => $annotation, + 'object' => $object, + ]; + + $promiseChain = $promiseChain->then(function (array $json) use ($req) { + return $req['handler']->extract($req['annotation'], $req['object'], $json); + }); } - return $json; + return $promiseChain; } /** @@ -303,13 +323,15 @@ protected function recursivelyGetAnnotation(string $class, string $annotationCla */ public function buildAsyncFromSync(string $resource, ResourceInterface $object): ResourceInterface { - return $this->hydrateFQCN( - $this->options[Options::NAMESPACE] . '\\Async\\' . $resource, - $this->extractFQCN( - $this->options[Options::NAMESPACE] . '\\Sync\\' . $resource, - $object - ) - ); + return $this->extractFQCN( + $this->options[Options::NAMESPACE] . '\\Sync\\' . $resource, + $object + )->then(function ($json) use ($resource) { + return $this->hydrateFQCN( + $this->options[Options::NAMESPACE] . '\\Async\\' . $resource, + $json + ); + }); } /** From 9dd2596ca0ff71de4560a6c705a4a1b42ca53596 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Thu, 24 Nov 2016 23:07:46 +0100 Subject: [PATCH 4/4] WIP async API --- src/Hydrator.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Hydrator.php b/src/Hydrator.php index 99871cd..ac386d0 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -11,6 +11,7 @@ use Doctrine\Common\Cache\Cache; use GeneratedHydrator\Configuration; use Interop\Container\ContainerInterface; +use React\EventLoop\LoopInterface; use React\Promise\CancellablePromiseInterface; use ReflectionClass; use RecursiveDirectoryIterator; @@ -18,6 +19,7 @@ use ApiClients\Foundation\Resource\ResourceInterface; use Zend\Hydrator\HydratorInterface; use function React\Promise\resolve; +use function WyriHaximus\React\futurePromise; class Hydrator { @@ -26,6 +28,11 @@ class Hydrator */ protected $container; + /** + * @var LoopInterface + */ + protected $loop; + /** * @var array */ @@ -58,6 +65,7 @@ class Hydrator public function __construct(ContainerInterface $container, array $options) { $this->container = $container; + $this->loop = $this->container->get(LoopInterface::class); $this->options = $options; $reader = new AnnotationReader(); @@ -142,7 +150,9 @@ public function hydrateFQCN(string $class, array $json): CancellablePromiseInter $class = $this->getEmptyOrResource($class, $json); $hydrator = $this->getHydrator($class); $object = new $class($this->container->get(CommandBus::class)); - return $this->hydrateApplyAnnotations($json, $object)->then(function ($json) use ($hydrator, $object) { + return $this->hydrateApplyAnnotations($json, $object)->then(function ($json) { + return futurePromise($this->loop, $json); + })->then(function (array $json) use ($hydrator, $object) { return $hydrator->hydrate($json, $object); }); } @@ -230,7 +240,9 @@ public function extractFQCN(string $class, ResourceInterface $object): Cancellab return []; } - return $this->getHydrator($class)->extract($object)->then(function (array $json) use ($object) { + return futurePromise($this->loop)->then(function () use ($class, $object) { + return $this->getHydrator($class)->extract($object); + })->then(function (array $json) use ($object) { return $this->extractApplyAnnotations($object, $json); }); }