diff --git a/.travis.yml b/.travis.yml index d405d18..9a086e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ cache: before_install: - if [[ "$TRAVIS_PHP_VERSION" != "5.6" && "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini || true; fi - composer selfupdate + - composer require "guzzlehttp/promises" install: composer update --prefer-dist --no-interaction diff --git a/README.md b/README.md index 63343e0..92cb6d9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ data sources such as databases or web services via batching and caching. ## Requirements -This library require [React/Promise](https://github.com/reactphp/promise) and PHP >= 5.5 to works. +This library require PHP >= 5.5 to works. ## Getting Started @@ -31,8 +31,9 @@ Create loaders by providing a batch loading instance. use Overblog\DataLoader\DataLoader; $myBatchGetUsers = function ($keys) { /* ... */ }; +$promiseFactory = new MyPromiseFactory(); -$userLoader = new DataLoader($myBatchGetUsers); +$userLoader = new DataLoader($myBatchGetUsers, $promiseFactory); ``` A batch loading callable / callback accepts an Array of keys, and returns a Promise which @@ -122,11 +123,12 @@ Each `DataLoaderPHP` instance contains a unique memoized cache. Use caution when used in long-lived applications or those which serve many users with different access permissions and consider creating a new instance per web request. -##### `new DataLoader(callable $batchLoadFn [, Option $options])` +##### `new DataLoader(callable $batchLoadFn, PromiseFactoryInterface $promiseFactory [, Option $options])` Create a new `DataLoaderPHP` given a batch loading instance and options. - *$batchLoadFn*: A callable / callback which accepts an Array of keys, and returns a Promise which resolves to an Array of values. +- *$promiseFactory*: Any object that implements `McGWeb\PromiseFactory\PromiseFactoryInterface`. (see [McGWeb/Promise-Factory](https://github.com/mcg-web/promise-factory)) - *$options*: An optional object of options: - *batch*: Default `true`. Set to `false` to disable batching, instead diff --git a/composer.json b/composer.json index a361c1b..b4f2f1a 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,8 @@ "name": "overblog/dataloader-php", "type": "library", "license": "MIT", + "description": "DataLoaderPhp is a generic utility to be used as part of your application's data fetching layer to provide a simplified and consistent API over various remote data sources such as databases or web services via batching and caching.", + "keywords": ["dataLoader", "caching", "batching"], "autoload": { "psr-4": { "Overblog\\DataLoader\\": "src/" @@ -14,7 +16,7 @@ }, "require": { "php": "^5.5|^7.0", - "react/promise": "^2.4" + "mcg-web/promise-factory": "^0.2" }, "require-dev": { "phpunit/phpunit": "^4.1|^5.1" diff --git a/src/DataLoader.php b/src/DataLoader.php index e8980d2..0ba3283 100644 --- a/src/DataLoader.php +++ b/src/DataLoader.php @@ -11,7 +11,7 @@ namespace Overblog\DataLoader; -use React\Promise\Promise; +use McGWeb\PromiseFactory\PromiseFactoryInterface; class DataLoader { @@ -31,7 +31,7 @@ class DataLoader private $promiseCache; /** - * @var Promise[] + * @var array */ private $queue = []; @@ -40,9 +40,15 @@ class DataLoader */ private static $instances = []; - public function __construct(callable $batchLoadFn, Option $options = null) + /** + * @var PromiseFactoryInterface + */ + private $promiseFactory; + + public function __construct(callable $batchLoadFn, PromiseFactoryInterface $promiseFactory, Option $options = null) { $this->batchLoadFn = $batchLoadFn; + $this->promiseFactory = $promiseFactory; $this->options = $options ?: new Option(); $this->promiseCache = $this->options->getCacheMap(); self::$instances[] = $this; @@ -53,7 +59,7 @@ public function __construct(callable $batchLoadFn, Option $options = null) * * @param string $key * - * @return Promise + * @return mixed return a Promise */ public function load($key) { @@ -70,33 +76,34 @@ public function load($key) return $cachedPromise; } } - $promise = null; // Otherwise, produce a new Promise for this value. - $promise = new Promise( - function ($resolve, $reject) use (&$promise, $key, $shouldBatch) { - $this->queue[] = [ - 'key' => $key, - 'resolve' => $resolve, - 'reject' => $reject, - 'promise' => &$promise, - ]; - - // Determine if a dispatch of this queue should be scheduled. - // A single dispatch should be scheduled per queue at the time when the - // queue changes from "empty" to "full". - if (count($this->queue) === 1) { - if (!$shouldBatch) { - // Otherwise dispatch the (queue of one) immediately. - $this->dispatchQueue(); - } - } - }, - function (callable $resolve, callable $reject) { + $promise = $this->getPromiseFactory()->create( + $resolve, + $reject, + function () { // Cancel/abort any running operations like network connections, streams etc. - $reject(new \RuntimeException('DataLoader destroyed before promise complete.')); - }); + throw new \RuntimeException('DataLoader destroyed before promise complete.'); + } + ); + + $this->queue[] = [ + 'key' => $key, + 'resolve' => $resolve, + 'reject' => $reject, + 'promise' => $promise, + ]; + + // Determine if a dispatch of this queue should be scheduled. + // A single dispatch should be scheduled per queue at the time when the + // queue changes from "empty" to "full". + if (count($this->queue) === 1) { + if (!$shouldBatch) { + // Otherwise dispatch the (queue of one) immediately. + $this->dispatchQueue(); + } + } // If caching, cache this promise. if ($shouldCache) { $this->promiseCache->set($cacheKey, $promise); @@ -118,14 +125,14 @@ function (callable $resolve, callable $reject) { * ]); * @param array $keys * - * @return Promise + * @return mixed return a Promise */ public function loadMany($keys) { if (!is_array($keys) && !$keys instanceof \Traversable) { throw new \InvalidArgumentException(sprintf('The "%s" method must be called with Array but got: %s.', __METHOD__, gettype($keys))); } - return \React\Promise\all(array_map( + return $this->getPromiseFactory()->createAll(array_map( function ($key) { return $this->load($key); }, @@ -178,7 +185,7 @@ public function prime($key, $value) if (!$this->promiseCache->has($cacheKey)) { // Cache a rejected promise if the value is an Error, in order to match // the behavior of load(key). - $promise = $value instanceof \Exception ? \React\Promise\reject($value) : \React\Promise\resolve($value); + $promise = $value instanceof \Exception ? $this->getPromiseFactory()->createReject($value) : $this->getPromiseFactory()->createResolve($value); $this->promiseCache->set($cacheKey, $promise); } @@ -191,13 +198,12 @@ public function __destruct() if ($this->needProcess()) { foreach ($this->queue as $data) { try { - /** @var Promise $promise */ - $promise = $data['promise']; - $promise->cancel(); + $this->getPromiseFactory()->cancel($data['promise']); } catch (\Exception $e) { // no need to do nothing if cancel failed } } + $this->await(); } foreach (self::$instances as $i => $instance) { if ($this !== $instance) { @@ -215,10 +221,16 @@ protected function needProcess() protected function process() { if ($this->needProcess()) { + $this->getPromiseFactory()->await(); $this->dispatchQueue(); } } + protected function getPromiseFactory() + { + return $this->promiseFactory; + } + /** * @param $promise * @param bool $unwrap controls whether or not the value of the promise is returned for a fulfilled promise or if an exception is thrown if the promise is rejected @@ -227,48 +239,28 @@ protected function process() */ public static function await($promise = null, $unwrap = true) { - self::awaitInstances(); - - if (null === $promise) { - return null; - } - $resolvedValue = null; - $exception = null; - - if (!is_callable([$promise, 'then'])) { - throw new \InvalidArgumentException(sprintf('The "%s" method must be called with a Promise ("then" method).', __METHOD__)); - } - - $promise->then(function ($values) use (&$resolvedValue) { - $resolvedValue = $values; - }, function ($reason) use (&$exception) { - $exception = $reason; - }); - if ($exception instanceof \Exception) { - if (!$unwrap) { - return $exception; - } - throw $exception; + if (empty(self::$instances)) { + throw new \RuntimeException('Found no active DataLoader instance.'); } + self::awaitInstances(); - return $resolvedValue; + return self::$instances[0]->getPromiseFactory()->await($promise, $unwrap); } private static function awaitInstances() { $dataLoaders = self::$instances; - if (!empty($dataLoaders)) { - $wait = true; - - while ($wait) { - foreach ($dataLoaders as $dataLoader) { - if (!$dataLoader || !$dataLoader->needProcess()) { - $wait = false; - continue; - } - $wait = true; - $dataLoader->process(); + + $wait = true; + + while ($wait) { + foreach ($dataLoaders as $dataLoader) { + if (!$dataLoader || !$dataLoader->needProcess()) { + $wait = false; + continue; } + $wait = true; + $dataLoader->process(); } } } @@ -322,7 +314,6 @@ private function dispatchQueueBatch(array $queue) // Call the provided batchLoadFn for this loader with the loader queue's keys. $batchLoadFn = $this->batchLoadFn; - /** @var Promise $batchPromise */ $batchPromise = $batchLoadFn($keys); // Assert the expected response from batchLoadFn @@ -374,7 +365,7 @@ function ($values) use ($keys, $queue) { /** * Do not cache individual loads if the entire batch dispatch fails, * but still reject each request so they do not hang. - * @param Promise[] $queue + * @param array $queue * @param \Exception $error */ private function failedDispatch($queue, \Exception $error) diff --git a/tests/AbuseTest.php b/tests/AbuseTest.php index 8c9928f..41580f9 100644 --- a/tests/AbuseTest.php +++ b/tests/AbuseTest.php @@ -13,7 +13,7 @@ use Overblog\DataLoader\DataLoader; -class AbuseTest extends \PHPUnit_Framework_TestCase +class AbuseTest extends TestCase { /** * @group provides-descriptive-error-messages-for-api-abuse @@ -75,7 +75,7 @@ public function testBatchFunctionMustReturnAPromiseNotAValue() public function testBatchFunctionMustReturnAPromiseOfAnArrayNotNull() { DataLoader::await(self::idLoader(function () { - return \React\Promise\resolve(); + return self::$promiseFactory->createResolve(null); })->load(1)); } @@ -87,20 +87,33 @@ public function testBatchFunctionMustReturnAPromiseOfAnArrayNotNull() public function testBatchFunctionMustPromiseAnArrayOfCorrectLength() { DataLoader::await(self::idLoader(function () { - return \React\Promise\resolve([]); + return self::$promiseFactory->createResolve([]); })->load(1)); } /** * @group provides-descriptive-error-messages-for-api-abuse * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "Overblog\DataLoader\DataLoader::await" method must be called with a Promise ("then" method). + * @expectedExceptionMessage ::await" method must be called with a Promise ("then" method). + * @runInSeparateProcess */ public function testAwaitPromiseMustHaveAThenMethod() { + self::idLoader(); DataLoader::await([]); } + /** + * @group provides-descriptive-error-messages-for-api-abuse + * @expectedException \RuntimeException + * @expectedExceptionMessage Found no active DataLoader instance. + * @runInSeparateProcess + */ + public function testAwaitWithoutNoInstance() + { + DataLoader::await(); + } + /** * @param callable $batchLoadFn * @return DataLoader @@ -109,10 +122,10 @@ private static function idLoader(callable $batchLoadFn = null) { if (null === $batchLoadFn) { $batchLoadFn = function ($keys) { - return \React\Promise\all($keys); + return self::$promiseFactory->createAll($keys); }; } - return new DataLoader($batchLoadFn); + return new DataLoader($batchLoadFn, self::$promiseFactory); } } diff --git a/tests/DataLoadTest.php b/tests/DataLoadTest.php index bfc16f8..589e530 100644 --- a/tests/DataLoadTest.php +++ b/tests/DataLoadTest.php @@ -13,9 +13,8 @@ use Overblog\DataLoader\DataLoader; use Overblog\DataLoader\Option; -use React\Promise\Promise; -class DataLoadTest extends \PHPUnit_Framework_TestCase +class DataLoadTest extends TestCase { /** * @group primary-api @@ -65,7 +64,7 @@ public function testBatchesMultipleRequests() $promise1 = $identityLoader->load(1); $promise2 = $identityLoader->load(2); - list($value1, $value2) = DataLoader::await(\React\Promise\all([$promise1, $promise2])); + list($value1, $value2) = DataLoader::await(self::$promiseFactory->createAll([$promise1, $promise2])); $this->assertEquals(1, $value1); $this->assertEquals(2, $value2); @@ -87,7 +86,7 @@ public function testBatchesMultipleRequestsWithMaxBatchSizes() $promise2 = $identityLoader->load(2); $promise3 = $identityLoader->load(3); - list($value1, $value2, $value3) = DataLoader::await(\React\Promise\all([$promise1, $promise2, $promise3])); + list($value1, $value2, $value3) = DataLoader::await(self::$promiseFactory->createAll([$promise1, $promise2, $promise3])); $this->assertEquals(1, $value1); $this->assertEquals(2, $value2); $this->assertEquals(3, $value3); @@ -111,7 +110,7 @@ public function testCoalescesIdenticalRequests() $this->assertTrue($promise1a === $promise1b); - list($value1a, $value1b) = DataLoader::await(\React\Promise\all([$promise1a, $promise1b])); + list($value1a, $value1b) = DataLoader::await(self::$promiseFactory->createAll([$promise1a, $promise1b])); $this->assertEquals(1, $value1a); $this->assertEquals(1, $value1b); @@ -129,17 +128,17 @@ public function testCachesRepeatedRequests() */ list($identityLoader, $loadCalls) = self::idLoader(); - list($a, $b) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a, $b) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a); $this->assertEquals('B', $b); $this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy()); - list($a2, $c) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('C')])); + list($a2, $c) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('C')])); $this->assertEquals('A', $a2); $this->assertEquals('C', $c); $this->assertEquals([['A', 'B'], ['C']], $loadCalls->getArrayCopy()); - list($a3, $b2, $c2) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')])); + list($a3, $b2, $c2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')])); $this->assertEquals('A', $a3); $this->assertEquals('B', $b2); $this->assertEquals('C', $c2); @@ -157,13 +156,13 @@ public function testClearsSingleValueInLoader() */ list($identityLoader, $loadCalls) = self::idLoader(); - list($a, $b) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a, $b) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a); $this->assertEquals('B', $b); $this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy()); $identityLoader->clear('A'); - list($a2, $b2) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a2, $b2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a2); $this->assertEquals('B', $b2); $this->assertEquals([['A', 'B'], ['A']], $loadCalls->getArrayCopy()); @@ -180,13 +179,13 @@ public function testClearsAllValuesInLoader() */ list($identityLoader, $loadCalls) = self::idLoader(); - list($a, $b) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a, $b) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a); $this->assertEquals('B', $b); $this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy()); $identityLoader->clearAll(); - list($a2, $b2) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a2, $b2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a2); $this->assertEquals('B', $b2); $this->assertEquals([['A', 'B'], ['A', 'B']], $loadCalls->getArrayCopy()); @@ -204,7 +203,7 @@ public function testAllowsPrimingTheCache() list($identityLoader, $loadCalls) = self::idLoader(); $identityLoader->prime('A', 'A'); - list($a, $b) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a, $b) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a); $this->assertEquals('B', $b); $this->assertEquals([['B']], $loadCalls->getArrayCopy()); @@ -424,7 +423,7 @@ public function testPropagatesErrorToAllLoads() * @var \ArrayObject $loadCalls */ list($failLoader, $loadCalls) = self::idLoader(null, function () { - return \React\Promise\reject(new \Exception('I am a terrible loader')); + return self::$promiseFactory->createReject(new \Exception('I am a terrible loader')); }); $promise1 = $failLoader->load(1); @@ -464,7 +463,7 @@ public function testAcceptsObjectsAsKeys() $keyA = new \stdClass(); $keyB = new \stdClass(); - list($valueA, $valueB) = DataLoader::await(\React\Promise\all([$identityLoader->load($keyA), $identityLoader->load($keyB)])); + list($valueA, $valueB) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load($keyA), $identityLoader->load($keyB)])); $this->assertEquals($keyA, $valueA); $this->assertEquals($keyB, $valueB); @@ -477,7 +476,7 @@ public function testAcceptsObjectsAsKeys() // Caching $identityLoader->clear($keyA); - list($valueA2, $valueB2) = DataLoader::await(\React\Promise\all([$identityLoader->load($keyA), $identityLoader->load($keyB)])); + list($valueA2, $valueB2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load($keyA), $identityLoader->load($keyB)])); $this->assertEquals($keyA, $valueA2); $this->assertEquals($keyB, $valueB2); @@ -503,7 +502,7 @@ public function testMayDisableBatching() $promise1 = $identityLoader->load(1); $promise2 = $identityLoader->load(2); - list($value1, $value2) = DataLoader::await(\React\Promise\all([$promise1, $promise2])); + list($value1, $value2) = DataLoader::await(self::$promiseFactory->createAll([$promise1, $promise2])); $this->assertEquals(1, $value1); $this->assertEquals(2, $value2); @@ -523,17 +522,17 @@ public function testMayDisableCaching() */ list($identityLoader, $loadCalls) = self::idLoader(new Option(['cache' => false])); - list($a, $b) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B')])); + list($a, $b) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B')])); $this->assertEquals('A', $a); $this->assertEquals('B', $b); $this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy()); - list($a2, $c) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('C')])); + list($a2, $c) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('C')])); $this->assertEquals('A', $a2); $this->assertEquals('C', $c); $this->assertEquals([['A', 'B'], ['A', 'C']], $loadCalls->getArrayCopy()); - list($a3, $b2, $c2) = DataLoader::await(\React\Promise\all([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')])); + list($a3, $b2, $c2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')])); $this->assertEquals('A', $a3); $this->assertEquals('B', $b2); $this->assertEquals('C', $c2); @@ -651,13 +650,13 @@ public function testAcceptsACustomCacheMapImplementation() */ list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheMap' => $aCustomMap])); - list($valueA, $valueB1) = DataLoader::await(\React\Promise\all([$identityLoader->load('a'), $identityLoader->load('b')])); + list($valueA, $valueB1) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('a'), $identityLoader->load('b')])); $this->assertEquals('a', $valueA); $this->assertEquals('b', $valueB1); $this->assertEquals([['a', 'b']], $loadCalls->getArrayCopy()); $this->assertEquals(['a', 'b'], array_keys($aCustomMap->stash->getArrayCopy())); - list($valueC, $valueB2) = DataLoader::await(\React\Promise\all([$identityLoader->load('c'), $identityLoader->load('b')])); + list($valueC, $valueB2) = DataLoader::await(self::$promiseFactory->createAll([$identityLoader->load('c'), $identityLoader->load('b')])); $this->assertEquals('c', $valueC); $this->assertEquals('b', $valueB2); $this->assertEquals([['a', 'b'], ['c']], $loadCalls->getArrayCopy()); @@ -689,29 +688,29 @@ public function testBatchesLoadsOccurringWithinPromises() list($identityLoader, $loadCalls) = self::idLoader(); DataLoader::await( - \React\Promise\all([ + self::$promiseFactory->createAll([ $identityLoader->load('A'), - \React\Promise\resolve()->then( - function () use ($identityLoader) { - \React\Promise\resolve()->then(function () use ($identityLoader) { - $identityLoader->load('B'); - \React\Promise\resolve()->then( - function () use ($identityLoader) { - \React\Promise\resolve()->then(function () use ($identityLoader) { - $identityLoader->load('C'); - \React\Promise\resolve()->then( - function () use ($identityLoader) { - \React\Promise\resolve()->then(function () use ($identityLoader) { - $identityLoader->load('D'); - }); - } - ); + self::$promiseFactory->createResolve() + ->then(function () { + return self::$promiseFactory->createResolve(); + }) + ->then(function () use ($identityLoader) { + $identityLoader->load('B'); + self::$promiseFactory->createResolve() + ->then(function () use ($identityLoader) { + return self::$promiseFactory->createResolve(); + }) + ->then(function () use ($identityLoader) { + $identityLoader->load('C'); + self::$promiseFactory->createResolve() + ->then(function () { + return self::$promiseFactory->createResolve(); + }) + ->then(function () use ($identityLoader) { + $identityLoader->load('D'); }); - } - ); - }); - } - ) + }); + }) ]) ); @@ -747,7 +746,7 @@ public function testCanCallALoaderFromALoader() return $deepLoader->load($keys); }); - list($a1, $b1, $a2, $b2) = DataLoader::await(\React\Promise\all([ + list($a1, $b1, $a2, $b2) = DataLoader::await(self::$promiseFactory->createAll([ $aLoader->load('A1'), $bLoader->load('B1'), $aLoader->load('A2'), @@ -802,7 +801,7 @@ public function cacheKey($key) private static function errorLoader() { return self::idLoader(null, function ($keys) { - return \React\Promise\resolve( + return self::$promiseFactory->createResolve( array_map(function ($key) { return new \Exception("Error: $key"); }, $keys) @@ -814,7 +813,7 @@ private static function eventLoader() { return self::idLoader(null, function ($keys) { $loadCalls[] = $keys; - return \React\Promise\resolve( + return self::$promiseFactory->createResolve( array_map(function ($key) { return $key % 2 === 0 ? $key : new \Exception("Odd: $key"); }, $keys) @@ -827,7 +826,7 @@ private static function idLoader(Option $options = null, callable $batchLoadFnCa $loadCalls = new \ArrayObject(); if (null === $batchLoadFnCallBack) { $batchLoadFnCallBack = function ($keys) { - return \React\Promise\resolve($keys); + return self::$promiseFactory->createResolve($keys); }; } @@ -835,13 +834,13 @@ private static function idLoader(Option $options = null, callable $batchLoadFnCa $loadCalls[] = $keys; return $batchLoadFnCallBack($keys); - }, $options); + }, self::$promiseFactory, $options); return [$identityLoader, $loadCalls]; } private function assertInstanceOfPromise($object) { - $this->assertInstanceOf(Promise::class, $object); + $this->assertTrue(self::$promiseFactory->isPromise($object, true)); } } diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..ca4c69d --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Overblog\DataLoader\Tests; + +use McGWeb\PromiseFactory\Factory\GuzzleHttpPromiseFactory; +use McGWeb\PromiseFactory\PromiseFactoryInterface; + +class TestCase extends \PHPUnit_Framework_TestCase +{ + /** + * @var PromiseFactoryInterface + */ + protected static $promiseFactory; + + public function setUp() + { + self::$promiseFactory = new GuzzleHttpPromiseFactory(); + } + +}