From 89a0424438cb9cb24d2fd330f5a25793c27c0ded Mon Sep 17 00:00:00 2001 From: Robert Churchill Date: Tue, 1 Mar 2016 15:35:23 +0000 Subject: [PATCH 1/3] Fix problem using IteratorAggregates with skip and take --- src/Fusonic/Linq/Linq.php | 28 ++++++++++--------- tests/Fusonic/Linq/Test/SkipTakeTest.php | 19 +++++++++++++ .../Linq/Test/TestIteratorAggregate.php | 17 +++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 tests/Fusonic/Linq/Test/TestIteratorAggregate.php diff --git a/src/Fusonic/Linq/Linq.php b/src/Fusonic/Linq/Linq.php index 68f9db2..39a8de2 100644 --- a/src/Fusonic/Linq/Linq.php +++ b/src/Fusonic/Linq/Linq.php @@ -91,17 +91,17 @@ public function where(callable $func) return new Linq(new WhereIterator($this->iterator, $func)); } - /** - * Filters the Linq object according to type. - * - * @param string $type - * - * @return Linq Filtered results according to $func - */ - public function ofType($type) - { - return new Linq(new OfTypeIterator($this->iterator, $type)); - } + /** + * Filters the Linq object according to type. + * + * @param string $type + * + * @return Linq Filtered results according to $func + */ + public function ofType($type) + { + return new Linq(new OfTypeIterator($this->iterator, $type)); + } /** * Bypasses a specified number of elements and then returns the remaining elements. @@ -120,7 +120,8 @@ public function skip($count) } } - return new Linq(new \LimitIterator($innerIterator, $count, -1)); + // IteratorIterator wraps $innerIterator because it might be Traversable but not an Iterator. + return new Linq(new \LimitIterator(new \IteratorIterator($innerIterator), $count, -1)); } /** @@ -135,7 +136,8 @@ public function take($count) return new Linq([]); } - return new Linq(new \LimitIterator($this->iterator, 0, $count)); + // IteratorIterator wraps $this->iterator because it might be Traversable but not an Iterator. + return new Linq(new \LimitIterator(new \IteratorIterator($this->iterator), 0, $count)); } /** diff --git a/tests/Fusonic/Linq/Test/SkipTakeTest.php b/tests/Fusonic/Linq/Test/SkipTakeTest.php index 30d1f39..e755c48 100644 --- a/tests/Fusonic/Linq/Test/SkipTakeTest.php +++ b/tests/Fusonic/Linq/Test/SkipTakeTest.php @@ -1,6 +1,7 @@ take(0); $this->assertEquals(0, $matching->count()); } + + public function testTake_WithIteratorAggregate() + { + $items = new TestIteratorAggregate(["a", "b", "c", "d", "e", "f"]); + $matching = Linq::from($items)->take(4); + + $this->assertTrue($matching instanceof Linq); + $this->assertEquals(4, $matching->count()); + } + + public function testSkip_WithIteratorAggregate() + { + $items = new TestIteratorAggregate(["a", "b", "c", "d", "e", "f"]); + $matching = Linq::from($items)->skip(2); + + $this->assertTrue($matching instanceof Linq); + $this->assertEquals(4, $matching->count()); + } } \ No newline at end of file diff --git a/tests/Fusonic/Linq/Test/TestIteratorAggregate.php b/tests/Fusonic/Linq/Test/TestIteratorAggregate.php new file mode 100644 index 0000000..c2f24e5 --- /dev/null +++ b/tests/Fusonic/Linq/Test/TestIteratorAggregate.php @@ -0,0 +1,17 @@ +x = $x; + } + + public function getIterator() + { + return new \ArrayIterator($this->x); + } +} From 9003bde6f39f5388fc8b29088ff8601791497c20 Mon Sep 17 00:00:00 2001 From: Robert Churchill Date: Tue, 1 Mar 2016 16:11:52 +0000 Subject: [PATCH 2/3] Make traversable wrapping only apply when necessary --- src/Fusonic/Linq/Linq.php | 17 +++++++++++++---- tests/Fusonic/Linq/Test/SkipTakeTest.php | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Fusonic/Linq/Linq.php b/src/Fusonic/Linq/Linq.php index 39a8de2..7c1a4ce 100644 --- a/src/Fusonic/Linq/Linq.php +++ b/src/Fusonic/Linq/Linq.php @@ -119,9 +119,13 @@ public function skip($count) return new Linq([]); } } + if ($innerIterator instanceof \Iterator === false) { + // IteratorIterator wraps $innerIterator because it is Traversable but not an Iterator. + // (see https://bugs.php.net/bug.php?id=52280) + $innerIterator = new \IteratorIterator($innerIterator); + } - // IteratorIterator wraps $innerIterator because it might be Traversable but not an Iterator. - return new Linq(new \LimitIterator(new \IteratorIterator($innerIterator), $count, -1)); + return new Linq(new \LimitIterator($innerIterator, $count, -1)); } /** @@ -135,9 +139,14 @@ public function take($count) if ($count == 0) { return new Linq([]); } + $innerIterator = $this->iterator; + if ($innerIterator instanceof \Iterator === false) { + // IteratorIterator wraps $this->iterator because it is Traversable but not an Iterator. + // (see https://bugs.php.net/bug.php?id=52280) + $innerIterator = new \IteratorIterator($innerIterator); + } - // IteratorIterator wraps $this->iterator because it might be Traversable but not an Iterator. - return new Linq(new \LimitIterator(new \IteratorIterator($this->iterator), 0, $count)); + return new Linq(new \LimitIterator($innerIterator, 0, $count)); } /** diff --git a/tests/Fusonic/Linq/Test/SkipTakeTest.php b/tests/Fusonic/Linq/Test/SkipTakeTest.php index e755c48..8b147f9 100644 --- a/tests/Fusonic/Linq/Test/SkipTakeTest.php +++ b/tests/Fusonic/Linq/Test/SkipTakeTest.php @@ -1,7 +1,7 @@ Date: Tue, 1 Mar 2016 16:33:35 +0000 Subject: [PATCH 3/3] Fix coding style for negation --- src/Fusonic/Linq/Linq.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Fusonic/Linq/Linq.php b/src/Fusonic/Linq/Linq.php index 7c1a4ce..9c0e359 100644 --- a/src/Fusonic/Linq/Linq.php +++ b/src/Fusonic/Linq/Linq.php @@ -119,7 +119,7 @@ public function skip($count) return new Linq([]); } } - if ($innerIterator instanceof \Iterator === false) { + if (!($innerIterator instanceof \Iterator)) { // IteratorIterator wraps $innerIterator because it is Traversable but not an Iterator. // (see https://bugs.php.net/bug.php?id=52280) $innerIterator = new \IteratorIterator($innerIterator); @@ -140,7 +140,7 @@ public function take($count) return new Linq([]); } $innerIterator = $this->iterator; - if ($innerIterator instanceof \Iterator === false) { + if (!($innerIterator instanceof \Iterator)) { // IteratorIterator wraps $this->iterator because it is Traversable but not an Iterator. // (see https://bugs.php.net/bug.php?id=52280) $innerIterator = new \IteratorIterator($innerIterator);