Merge pull request #233 from domnikl/iterator-bug

#232 removed Iterator classes
This commit is contained in:
Dominik Liebler
2016-09-22 18:01:14 +02:00
committed by GitHub
14 changed files with 575 additions and 389 deletions

View File

@@ -4,27 +4,33 @@ namespace DesignPatterns\Behavioral\Iterator;
class Book
{
/**
* @var string
*/
private $author;
/**
* @var string
*/
private $title;
public function __construct($title, $author)
public function __construct(string $title, string $author)
{
$this->author = $author;
$this->title = $title;
}
public function getAuthor()
public function getAuthor(): string
{
return $this->author;
}
public function getTitle()
public function getTitle(): string
{
return $this->title;
}
public function getAuthorAndTitle()
public function getAuthorAndTitle(): string
{
return $this->getTitle().' by '.$this->getAuthor();
}

View File

@@ -2,16 +2,17 @@
namespace DesignPatterns\Behavioral\Iterator;
class BookList implements \Countable
class BookList implements \Countable, \Iterator
{
private $books;
/**
* @var Book[]
*/
private $books = [];
public function getBook($bookNumberToGet)
{
if (isset($this->books[$bookNumberToGet])) {
return $this->books[$bookNumberToGet];
}
}
/**
* @var int
*/
private $currentIndex = 0;
public function addBook(Book $book)
{
@@ -21,15 +22,41 @@ class BookList implements \Countable
public function removeBook(Book $bookToRemove)
{
foreach ($this->books as $key => $book) {
/** @var Book $book */
if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {
unset($this->books[$key]);
}
}
$this->books = array_values($this->books);
}
public function count()
public function count(): int
{
return count($this->books);
}
public function current(): Book
{
return $this->books[$this->currentIndex];
}
public function key(): int
{
return $this->currentIndex;
}
public function next()
{
$this->currentIndex++;
}
public function rewind()
{
$this->currentIndex = 0;
}
public function valid(): bool
{
return isset($this->books[$this->currentIndex]);
}
}

View File

@@ -1,86 +0,0 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class BookListIterator implements \Iterator
{
/**
* @var BookList
*/
private $bookList;
/**
* @var int
*/
protected $currentBook = 0;
public function __construct(BookList $bookList)
{
$this->bookList = $bookList;
}
/**
* Return the current book.
*
* @link http://php.net/manual/en/iterator.current.php
*
* @return Book Can return any type.
*/
public function current()
{
return $this->bookList->getBook($this->currentBook);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element.
*
* @link http://php.net/manual/en/iterator.next.php
*
* @return void Any returned value is ignored.
*/
public function next()
{
$this->currentBook++;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element.
*
* @link http://php.net/manual/en/iterator.key.php
*
* @return mixed scalar on success, or null on failure.
*/
public function key()
{
return $this->currentBook;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid.
*
* @link http://php.net/manual/en/iterator.valid.php
*
* @return bool The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
return null !== $this->bookList->getBook($this->currentBook);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element.
*
* @link http://php.net/manual/en/iterator.rewind.php
*
* @return void Any returned value is ignored.
*/
public function rewind()
{
$this->currentBook = 0;
}
}

View File

@@ -1,87 +0,0 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class BookListReverseIterator implements \Iterator
{
/**
* @var BookList
*/
private $bookList;
/**
* @var int
*/
protected $currentBook = 0;
public function __construct(BookList $bookList)
{
$this->bookList = $bookList;
$this->currentBook = $this->bookList->count() - 1;
}
/**
* Return the current book.
*
* @link http://php.net/manual/en/iterator.current.php
*
* @return Book Can return any type.
*/
public function current()
{
return $this->bookList->getBook($this->currentBook);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element.
*
* @link http://php.net/manual/en/iterator.next.php
*
* @return void Any returned value is ignored.
*/
public function next()
{
$this->currentBook--;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element.
*
* @link http://php.net/manual/en/iterator.key.php
*
* @return mixed scalar on success, or null on failure.
*/
public function key()
{
return $this->currentBook;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid.
*
* @link http://php.net/manual/en/iterator.valid.php
*
* @return bool The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
return null !== $this->bookList->getBook($this->currentBook);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element.
*
* @link http://php.net/manual/en/iterator.rewind.php
*
* @return void Any returned value is ignored.
*/
public function rewind()
{
$this->currentBook = $this->bookList->count() - 1;
}
}

View File

@@ -4,8 +4,7 @@
Purpose
-------
To make an object iterable and to make it appear like a collection of
objects.
To make an object iterable and to make it appear like a collection of objects.
Examples
--------
@@ -45,18 +44,6 @@ BookList.php
:language: php
:linenos:
BookListIterator.php
.. literalinclude:: BookListIterator.php
:language: php
:linenos:
BookListReverseIterator.php
.. literalinclude:: BookListReverseIterator.php
:language: php
:linenos:
Test
----
@@ -67,4 +54,4 @@ Tests/IteratorTest.php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Behavioral/Iterator
.. __: http://en.wikipedia.org/wiki/Iterator_pattern
.. __: http://en.wikipedia.org/wiki/Iterator_pattern

View File

@@ -9,66 +9,68 @@ use DesignPatterns\Behavioral\Iterator\BookListReverseIterator;
class IteratorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var BookList
*/
protected $bookList;
protected function setUp()
public function testCanIterateOverBookList()
{
$this->bookList = new BookList();
$this->bookList->addBook(new Book('Learning PHP Design Patterns', 'William Sanders'));
$this->bookList->addBook(new Book('Professional Php Design Patterns', 'Aaron Saray'));
$this->bookList->addBook(new Book('Clean Code', 'Robert C. Martin'));
}
$bookList = new BookList();
$bookList->addBook(new Book('Learning PHP Design Patterns', 'William Sanders'));
$bookList->addBook(new Book('Professional Php Design Patterns', 'Aaron Saray'));
$bookList->addBook(new Book('Clean Code', 'Robert C. Martin'));
public function expectedAuthors()
{
return array(
array(
array(
'Learning PHP Design Patterns by William Sanders',
'Professional Php Design Patterns by Aaron Saray',
'Clean Code by Robert C. Martin',
),
),
$books = [];
foreach ($bookList as $book) {
$books[] = $book->getAuthorAndTitle();
}
$this->assertEquals(
[
'Learning PHP Design Patterns by William Sanders',
'Professional Php Design Patterns by Aaron Saray',
'Clean Code by Robert C. Martin',
],
$books
);
}
/**
* @dataProvider expectedAuthors
*/
public function testUseAIteratorAndValidateAuthors($expected)
public function testCanIterateOverBookListAfterRemovingBook()
{
$iterator = new BookListIterator($this->bookList);
$book = new Book('Clean Code', 'Robert C. Martin');
$book2 = new Book('Professional Php Design Patterns', 'Aaron Saray');
while ($iterator->valid()) {
$expectedBook = array_shift($expected);
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
$iterator->next();
$bookList = new BookList();
$bookList->addBook($book);
$bookList->addBook($book2);
$bookList->removeBook($book);
$books = [];
foreach ($bookList as $book) {
$books[] = $book->getAuthorAndTitle();
}
$this->assertEquals(
['Professional Php Design Patterns by Aaron Saray'],
$books
);
}
/**
* @dataProvider expectedAuthors
*/
public function testUseAReverseIteratorAndValidateAuthors($expected)
public function testCanAddBookToList()
{
$iterator = new BookListReverseIterator($this->bookList);
$book = new Book('Clean Code', 'Robert C. Martin');
while ($iterator->valid()) {
$expectedBook = array_pop($expected);
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
$iterator->next();
}
$bookList = new BookList();
$bookList->addBook($book);
$this->assertCount(1, $bookList);
}
/**
* Test BookList Remove.
*/
public function testBookRemove()
public function testCanRemoveBookFromList()
{
$this->bookList->removeBook($this->bookList->getBook(0));
$this->assertEquals($this->bookList->count(), 2);
$book = new Book('Clean Code', 'Robert C. Martin');
$bookList = new BookList();
$bookList->addBook($book);
$bookList->removeBook($book);
$this->assertCount(0, $bookList);
}
}