Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongo-php-library
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sinan
mongo-php-library
Commits
ca4cc976
Commit
ca4cc976
authored
Oct 27, 2017
by
Jeremy Mikola
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #424
parents
85f772c2
5ea6f35d
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
306 additions
and
10 deletions
+306
-10
composer.json
composer.json
+1
-1
CachingIterator.php
src/Model/CachingIterator.php
+166
-0
ListCollections.php
src/Operation/ListCollections.php
+3
-2
ListIndexes.php
src/Operation/ListIndexes.php
+3
-2
CachingIteratorTest.php
tests/Model/CachingIteratorTest.php
+130
-0
ListCollectionsFunctionalTest.php
tests/Operation/ListCollectionsFunctionalTest.php
+3
-2
ListIndexesFunctionalTest.php
tests/Operation/ListIndexesFunctionalTest.php
+0
-3
No files found.
composer.json
View file @
ca4cc976
...
...
@@ -10,7 +10,7 @@
{
"name"
:
"Derick Rethans"
,
"email"
:
"github@derickrethans.nl"
}
],
"require"
:
{
"php"
:
">=5.
4
"
,
"php"
:
">=5.
5
"
,
"ext-hash"
:
"*"
,
"ext-json"
:
"*"
,
"ext-mongodb"
:
"^1.3.0"
...
...
src/Model/CachingIterator.php
0 → 100644
View file @
ca4cc976
<?php
/*
* Copyright 2017 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace
MongoDB\Model
;
use
Countable
;
use
Generator
;
use
Iterator
;
use
Traversable
;
/**
* Iterator for wrapping a Traversable and caching its results.
*
* By caching results, this iterators allows a Traversable to be counted and
* rewound multiple times, even if the wrapped object does not natively support
* those operations (e.g. MongoDB\Driver\Cursor).
*
* @internal
*/
class
CachingIterator
implements
Countable
,
Iterator
{
private
$items
=
[];
private
$iterator
;
private
$iteratorAdvanced
=
false
;
private
$iteratorExhausted
=
false
;
/**
* Constructor.
*
* Initialize the iterator and stores the first item in the cache. This
* effectively rewinds the Traversable and the wrapping Generator, which
* will execute up to its first yield statement. Additionally, this mimics
* behavior of the SPL iterators and allows users to omit an explicit call
* to rewind() before using the other methods.
*
* @param Traversable $traversable
*/
public
function
__construct
(
Traversable
$traversable
)
{
$this
->
iterator
=
$this
->
wrapTraversable
(
$traversable
);
$this
->
storeCurrentItem
();
}
/**
* @see http://php.net/countable.count
* @return integer
*/
public
function
count
()
{
$this
->
exhaustIterator
();
return
count
(
$this
->
items
);
}
/**
* @see http://php.net/iterator.current
* @return mixed
*/
public
function
current
()
{
return
current
(
$this
->
items
);
}
/**
* @see http://php.net/iterator.mixed
* @return mixed
*/
public
function
key
()
{
return
key
(
$this
->
items
);
}
/**
* @see http://php.net/iterator.next
* @return void
*/
public
function
next
()
{
if
(
!
$this
->
iteratorExhausted
)
{
$this
->
iterator
->
next
();
$this
->
storeCurrentItem
();
}
next
(
$this
->
items
);
}
/**
* @see http://php.net/iterator.rewind
* @return void
*/
public
function
rewind
()
{
/* If the iterator has advanced, exhaust it now so that future iteration
* can rely on the cache.
*/
if
(
$this
->
iteratorAdvanced
)
{
$this
->
exhaustIterator
();
}
reset
(
$this
->
items
);
}
/**
*
* @see http://php.net/iterator.valid
* @return boolean
*/
public
function
valid
()
{
return
$this
->
key
()
!==
null
;
}
/**
* Ensures that the inner iterator is fully consumed and cached.
*/
private
function
exhaustIterator
()
{
while
(
!
$this
->
iteratorExhausted
)
{
$this
->
next
();
}
}
/**
* Stores the current item in the cache.
*/
private
function
storeCurrentItem
()
{
$key
=
$this
->
iterator
->
key
();
if
(
$key
===
null
)
{
return
;
}
$this
->
items
[
$key
]
=
$this
->
iterator
->
current
();
}
/**
* Wraps the Traversable with a Generator.
*
* @param Traversable $traversable
* @return Generator
*/
private
function
wrapTraversable
(
Traversable
$traversable
)
{
foreach
(
$traversable
as
$key
=>
$value
)
{
yield
$key
=>
$value
;
$this
->
iteratorAdvanced
=
true
;
}
$this
->
iteratorExhausted
=
true
;
}
}
src/Operation/ListCollections.php
View file @
ca4cc976
...
...
@@ -22,6 +22,7 @@ use MongoDB\Driver\Query;
use
MongoDB\Driver\Server
;
use
MongoDB\Driver\Exception\RuntimeException
as
DriverRuntimeException
;
use
MongoDB\Exception\InvalidArgumentException
;
use
MongoDB\Model\CachingIterator
;
use
MongoDB\Model\CollectionInfoCommandIterator
;
use
MongoDB\Model\CollectionInfoIterator
;
use
MongoDB\Model\CollectionInfoLegacyIterator
;
...
...
@@ -107,7 +108,7 @@ class ListCollections implements Executable
$cursor
=
$server
->
executeCommand
(
$this
->
databaseName
,
new
Command
(
$cmd
));
$cursor
->
setTypeMap
([
'root'
=>
'array'
,
'document'
=>
'array'
]);
return
new
CollectionInfoCommandIterator
(
$cursor
);
return
new
CollectionInfoCommandIterator
(
new
CachingIterator
(
$cursor
)
);
}
/**
...
...
@@ -138,6 +139,6 @@ class ListCollections implements Executable
$cursor
=
$server
->
executeQuery
(
$this
->
databaseName
.
'.system.namespaces'
,
new
Query
(
$filter
,
$options
));
$cursor
->
setTypeMap
([
'root'
=>
'array'
,
'document'
=>
'array'
]);
return
new
CollectionInfoLegacyIterator
(
$cursor
);
return
new
CollectionInfoLegacyIterator
(
new
CachingIterator
(
$cursor
)
);
}
}
src/Operation/ListIndexes.php
View file @
ca4cc976
...
...
@@ -22,6 +22,7 @@ use MongoDB\Driver\Query;
use
MongoDB\Driver\Server
;
use
MongoDB\Driver\Exception\RuntimeException
as
DriverRuntimeException
;
use
MongoDB\Exception\InvalidArgumentException
;
use
MongoDB\Model\CachingIterator
;
use
MongoDB\Model\IndexInfoIterator
;
use
MongoDB\Model\IndexInfoIteratorIterator
;
use
EmptyIterator
;
...
...
@@ -114,7 +115,7 @@ class ListIndexes implements Executable
$cursor
->
setTypeMap
([
'root'
=>
'array'
,
'document'
=>
'array'
]);
return
new
IndexInfoIteratorIterator
(
$cursor
);
return
new
IndexInfoIteratorIterator
(
new
CachingIterator
(
$cursor
)
);
}
/**
...
...
@@ -136,6 +137,6 @@ class ListIndexes implements Executable
$cursor
=
$server
->
executeQuery
(
$this
->
databaseName
.
'.system.indexes'
,
new
Query
(
$filter
,
$options
));
$cursor
->
setTypeMap
([
'root'
=>
'array'
,
'document'
=>
'array'
]);
return
new
IndexInfoIteratorIterator
(
$cursor
);
return
new
IndexInfoIteratorIterator
(
new
CachingIterator
(
$cursor
)
);
}
}
tests/Model/CachingIteratorTest.php
0 → 100644
View file @
ca4cc976
<?php
namespace
MongoDB\Tests\Model
;
use
MongoDB\Model\CachingIterator
;
use
Exception
;
class
CachingIteratorTest
extends
\PHPUnit_Framework_TestCase
{
/**
* Sanity check for all following tests.
*
* @expectedException \Exception
* @expectedExceptionMessage Cannot traverse an already closed generator
*/
public
function
testTraversingGeneratorConsumesIt
()
{
$iterator
=
$this
->
getTraversable
([
1
,
2
,
3
]);
$this
->
assertSame
([
1
,
2
,
3
],
iterator_to_array
(
$iterator
));
$this
->
assertSame
([
1
,
2
,
3
],
iterator_to_array
(
$iterator
));
}
public
function
testConstructorRewinds
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([
1
,
2
,
3
]));
$this
->
assertTrue
(
$iterator
->
valid
());
$this
->
assertSame
(
0
,
$iterator
->
key
());
$this
->
assertSame
(
1
,
$iterator
->
current
());
}
public
function
testIteration
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([
1
,
2
,
3
]));
$expectedKey
=
0
;
$expectedItem
=
1
;
foreach
(
$iterator
as
$key
=>
$item
)
{
$this
->
assertSame
(
$expectedKey
++
,
$key
);
$this
->
assertSame
(
$expectedItem
++
,
$item
);
}
$this
->
assertFalse
(
$iterator
->
valid
());
}
public
function
testIterationWithEmptySet
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([]));
$iterator
->
rewind
();
$this
->
assertFalse
(
$iterator
->
valid
());
}
public
function
testPartialIterationDoesNotExhaust
()
{
$traversable
=
$this
->
getTraversableThatThrows
([
1
,
2
,
new
Exception
]);
$iterator
=
new
CachingIterator
(
$traversable
);
$expectedKey
=
0
;
$expectedItem
=
1
;
foreach
(
$iterator
as
$key
=>
$item
)
{
$this
->
assertSame
(
$expectedKey
++
,
$key
);
$this
->
assertSame
(
$expectedItem
++
,
$item
);
if
(
$key
===
1
)
{
break
;
}
}
$this
->
assertTrue
(
$iterator
->
valid
());
}
public
function
testRewindAfterPartialIteration
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([
1
,
2
,
3
]));
$iterator
->
rewind
();
$this
->
assertTrue
(
$iterator
->
valid
());
$this
->
assertSame
(
0
,
$iterator
->
key
());
$this
->
assertSame
(
1
,
$iterator
->
current
());
$iterator
->
next
();
$this
->
assertSame
([
1
,
2
,
3
],
iterator_to_array
(
$iterator
));
}
public
function
testCount
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([
1
,
2
,
3
]));
$this
->
assertCount
(
3
,
$iterator
);
}
public
function
testCountAfterPartialIteration
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([
1
,
2
,
3
]));
$iterator
->
rewind
();
$this
->
assertTrue
(
$iterator
->
valid
());
$this
->
assertSame
(
0
,
$iterator
->
key
());
$this
->
assertSame
(
1
,
$iterator
->
current
());
$iterator
->
next
();
$this
->
assertCount
(
3
,
$iterator
);
}
public
function
testCountWithEmptySet
()
{
$iterator
=
new
CachingIterator
(
$this
->
getTraversable
([]));
$this
->
assertCount
(
0
,
$iterator
);
}
private
function
getTraversable
(
$items
)
{
foreach
(
$items
as
$item
)
{
yield
$item
;
}
}
private
function
getTraversableThatThrows
(
$items
)
{
foreach
(
$items
as
$item
)
{
if
(
$item
instanceof
Exception
)
{
throw
$item
;
}
else
{
yield
$item
;
}
}
}
}
tests/Operation/ListCollectionsFunctionalTest.php
View file @
ca4cc976
...
...
@@ -20,8 +20,9 @@ class ListCollectionsFunctionalTest extends FunctionalTestCase
$this
->
assertEquals
(
1
,
$writeResult
->
getInsertedCount
());
$operation
=
new
ListCollections
(
$this
->
getDatabaseName
(),
[
'filter'
=>
[
'name'
=>
$this
->
getCollectionName
()]]);
// Convert the CollectionInfoIterator to an array since we cannot rewind its cursor
$collections
=
iterator_to_array
(
$operation
->
execute
(
$server
));
$collections
=
$operation
->
execute
(
$server
);
$this
->
assertInstanceOf
(
'MongoDB\Model\CollectionInfoIterator'
,
$collections
);
$this
->
assertCount
(
1
,
$collections
);
...
...
tests/Operation/ListIndexesFunctionalTest.php
View file @
ca4cc976
...
...
@@ -22,9 +22,6 @@ class ListIndexesFunctionalTest extends FunctionalTestCase
$this
->
assertInstanceOf
(
'MongoDB\Model\IndexInfoIterator'
,
$indexes
);
// Convert the CursorInfoIterator to an array since we cannot rewind its cursor
$indexes
=
iterator_to_array
(
$indexes
);
$this
->
assertCount
(
1
,
$indexes
);
foreach
(
$indexes
as
$index
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment