mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-08-02 21:17:29 +02:00
Merge commit 'refs/pull/origin/86'
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler is a generic handler in the chain of responsibilities
|
* Handler is a generic handler in the chain of responsibilities
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request is a request which goes through the chain of responsibilities.
|
* Request is a request which goes through the chain of responsibilities.
|
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
||||||
|
|
||||||
use DesignPatterns\ChainOfResponsibilities\Handler;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
||||||
use DesignPatterns\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class FastStorage
|
* Class FastStorage
|
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\ChainOfResponsibilities\Responsible;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
||||||
|
|
||||||
use DesignPatterns\ChainOfResponsibilities\Handler;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
||||||
use DesignPatterns\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is mostly the same code as FastStorage but in fact, it may greatly differs
|
* This is mostly the same code as FastStorage but in fact, it may greatly differs
|
@@ -1,9 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\ChainOfResponsibilities;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
|
||||||
|
|
||||||
use DesignPatterns\ChainOfResponsibilities\Request;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Request;
|
||||||
use DesignPatterns\ChainOfResponsibilities\Responsible;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage;
|
||||||
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage;
|
||||||
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ChainTest tests the CoR
|
* ChainTest tests the CoR
|
||||||
@@ -11,12 +13,15 @@ use DesignPatterns\ChainOfResponsibilities\Responsible;
|
|||||||
class ChainTest extends \PHPUnit_Framework_TestCase
|
class ChainTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FastStorage
|
||||||
|
*/
|
||||||
protected $chain;
|
protected $chain;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
$this->chain = new Responsible\FastStorage(array('bar' => 'baz'));
|
$this->chain = new FastStorage(array('bar' => 'baz'));
|
||||||
$this->chain->append(new Responsible\SlowStorage(array('bar' => 'baz', 'foo' => 'bar')));
|
$this->chain->append(new SlowStorage(array('bar' => 'baz', 'foo' => 'bar')));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeRequest()
|
public function makeRequest()
|
||||||
@@ -40,7 +45,8 @@ class ChainTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertObjectHasAttribute('response', $request);
|
$this->assertObjectHasAttribute('response', $request);
|
||||||
$this->assertEquals('baz', $request->response);
|
$this->assertEquals('baz', $request->response);
|
||||||
// despite both handle owns the 'bar' key, the FastStorage is responding first
|
// despite both handle owns the 'bar' key, the FastStorage is responding first
|
||||||
$this->assertEquals('DesignPatterns\ChainOfResponsibilities\Responsible\FastStorage', $request->forDebugOnly);
|
$className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage';
|
||||||
|
$this->assertEquals($className, $request->forDebugOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +61,8 @@ class ChainTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertObjectHasAttribute('response', $request);
|
$this->assertObjectHasAttribute('response', $request);
|
||||||
$this->assertEquals('bar', $request->response);
|
$this->assertEquals('bar', $request->response);
|
||||||
// FastStorage has no 'foo' key, the SlowStorage is responding
|
// FastStorage has no 'foo' key, the SlowStorage is responding
|
||||||
$this->assertEquals('DesignPatterns\ChainOfResponsibilities\Responsible\SlowStorage', $request->forDebugOnly);
|
$className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage';
|
||||||
|
$this->assertEquals($className, $request->forDebugOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,6 +75,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertFalse($ret);
|
$this->assertFalse($ret);
|
||||||
// the last responsible :
|
// the last responsible :
|
||||||
$this->assertEquals('DesignPatterns\ChainOfResponsibilities\Responsible\SlowStorage', $request->forDebugOnly);
|
$className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage';
|
||||||
|
$this->assertEquals($className, $request->forDebugOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class CommandInterface
|
* class CommandInterface
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This concrete command calls "print" on the Receiver, but an external
|
* This concrete command calls "print" on the Receiver, but an external
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoker is using the command given to it.
|
* Invoker is using the command given to it.
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receiver is specific service with its own contract and can be only concrete
|
* Receiver is specific service with its own contract and can be only concrete
|
@@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Command;
|
namespace DesignPatterns\Behavioral\Command\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Command\Invoker;
|
use DesignPatterns\Behavioral\Command\Invoker;
|
||||||
use DesignPatterns\Command\Receiver;
|
use DesignPatterns\Behavioral\Command\Receiver;
|
||||||
use DesignPatterns\Command\HelloCommand;
|
use DesignPatterns\Behavioral\Command\HelloCommand;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CommandTest has the role of the Client in the Command Pattern
|
* CommandTest has the role of the Client in the Command Pattern
|
||||||
@@ -12,12 +12,18 @@ use DesignPatterns\Command\HelloCommand;
|
|||||||
class CommandTest extends \PHPUnit_Framework_TestCase
|
class CommandTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Invoker
|
||||||
|
*/
|
||||||
protected $invoker;
|
protected $invoker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Receiver
|
||||||
|
*/
|
||||||
protected $receiver;
|
protected $receiver;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
// this is the context of the application
|
|
||||||
$this->invoker = new Invoker();
|
$this->invoker = new Invoker();
|
||||||
$this->receiver = new Receiver();
|
$this->receiver = new Receiver();
|
||||||
}
|
}
|
32
Behavioral/Iterator/Book.php
Normal file
32
Behavioral/Iterator/Book.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
|
||||||
|
private $author;
|
||||||
|
|
||||||
|
private $title;
|
||||||
|
|
||||||
|
public function __construct($title, $author)
|
||||||
|
{
|
||||||
|
$this->author = $author;
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthor()
|
||||||
|
{
|
||||||
|
return $this->author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthorAndTitle()
|
||||||
|
{
|
||||||
|
return $this->getTitle() . ' by ' . $this->getAuthor();
|
||||||
|
}
|
||||||
|
}
|
42
Behavioral/Iterator/BookList.php
Normal file
42
Behavioral/Iterator/BookList.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
|
class BookList implements \Countable
|
||||||
|
{
|
||||||
|
|
||||||
|
private $books;
|
||||||
|
|
||||||
|
public function getBook($bookNumberToGet)
|
||||||
|
{
|
||||||
|
if ((int)$bookNumberToGet <= $this->count()) {
|
||||||
|
return $this->books[$bookNumberToGet];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addBook(Book $book)
|
||||||
|
{
|
||||||
|
$this->books[] = $book;
|
||||||
|
|
||||||
|
return $this->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeBook(Book $bookToRemove)
|
||||||
|
{
|
||||||
|
foreach ($this as $key => $book) {
|
||||||
|
/** @var Book $book */
|
||||||
|
if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {
|
||||||
|
unset($this->books[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->books);
|
||||||
|
}
|
||||||
|
}
|
77
Behavioral/Iterator/BookListIterator.php
Normal file
77
Behavioral/Iterator/BookListIterator.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
|
class BookListIterator implements \Iterator
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var BookList
|
||||||
|
*/
|
||||||
|
protected $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 >= 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 >= 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 >= 5.0.0)<br/>
|
||||||
|
* Checks if current position is valid
|
||||||
|
* @link http://php.net/manual/en/iterator.valid.php
|
||||||
|
* @return boolean The return value will be casted to boolean and then evaluated.
|
||||||
|
* Returns true on success or false on failure.
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return $this->currentBook < $this->bookList->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (PHP 5 >= 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;
|
||||||
|
}
|
||||||
|
}
|
23
Behavioral/Iterator/BookListReverseIterator.php
Normal file
23
Behavioral/Iterator/BookListReverseIterator.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
|
class BookListReverseIterator extends BookListIterator
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(BookList $bookList)
|
||||||
|
{
|
||||||
|
$this->bookList = $bookList;
|
||||||
|
$this->currentBook = $this->bookList->count() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
$this->currentBook--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return 0 <= $this->currentBook;
|
||||||
|
}
|
||||||
|
}
|
66
Behavioral/Iterator/Tests/IteratorTest.php
Normal file
66
Behavioral/Iterator/Tests/IteratorTest.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Iterator\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Iterator\Book;
|
||||||
|
use DesignPatterns\Behavioral\Iterator\BookList;
|
||||||
|
use DesignPatterns\Behavioral\Iterator\BookListIterator;
|
||||||
|
use DesignPatterns\Behavioral\Iterator\BookListReverseIterator;
|
||||||
|
|
||||||
|
class IteratorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var BookList
|
||||||
|
*/
|
||||||
|
protected $bookList;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$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'));
|
||||||
|
}
|
||||||
|
|
||||||
|
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'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider expectedAuthors
|
||||||
|
*/
|
||||||
|
public function testUseAIteratorAndValidateAuthors($expected)
|
||||||
|
{
|
||||||
|
$iterator = new BookListIterator($this->bookList);
|
||||||
|
|
||||||
|
while ($iterator->valid()) {
|
||||||
|
$expectedBook = array_shift($expected);
|
||||||
|
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
|
||||||
|
$iterator->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider expectedAuthors
|
||||||
|
*/
|
||||||
|
public function testUseAReverseIteratorAndValidateAuthors($expected)
|
||||||
|
{
|
||||||
|
$iterator = new BookListReverseIterator($this->bookList);
|
||||||
|
|
||||||
|
while ($iterator->valid()) {
|
||||||
|
$expectedBook = array_pop($expected);
|
||||||
|
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
|
||||||
|
$iterator->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Behavioral\Mediator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Colleague is an abstract colleague who works together but he only knows
|
* Colleague is an abstract colleague who works together but he only knows
|
@@ -1,20 +1,29 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Behavioral\Mediator;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Subsystem;
|
use DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mediator is the concrete Mediator for this design pattern.
|
* Mediator is the concrete Mediator for this design pattern.
|
||||||
*
|
|
||||||
* In this example, I have made a "Hello World" with the Mediator Pattern.
|
* In this example, I have made a "Hello World" with the Mediator Pattern.
|
||||||
*/
|
*/
|
||||||
class Mediator implements MediatorInterface
|
class Mediator implements MediatorInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
// you could have an array
|
/**
|
||||||
|
* @var Subsystem\Server
|
||||||
|
*/
|
||||||
protected $server;
|
protected $server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Subsystem\Database
|
||||||
|
*/
|
||||||
protected $database;
|
protected $database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Subsystem\Client
|
||||||
|
*/
|
||||||
protected $client;
|
protected $client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +48,6 @@ class Mediator implements MediatorInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* query db
|
* query db
|
||||||
*
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function queryDb()
|
public function queryDb()
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator;
|
namespace DesignPatterns\Behavioral\Mediator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediatorInterface is a contract for the Mediator
|
* MediatorInterface is a contract for the Mediator
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client is a client that make request et get response
|
* Client is a client that make request et get response
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database is a database service
|
* Database is a database service
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Mediator\Subsystem;
|
namespace DesignPatterns\Behavioral\Mediator\Subsystem;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Colleague;
|
use DesignPatterns\Behavioral\Mediator\Colleague;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server serves responses
|
* Server serves responses
|
@@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Mediator;
|
namespace DesignPatterns\Tests\Mediator\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Mediator\Mediator;
|
use DesignPatterns\Behavioral\Mediator\Mediator;
|
||||||
use DesignPatterns\Mediator\Subsystem\Database;
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Database;
|
||||||
use DesignPatterns\Mediator\Subsystem\Client;
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Client;
|
||||||
use DesignPatterns\Mediator\Subsystem\Server;
|
use DesignPatterns\Behavioral\Mediator\Subsystem\Server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediatorTest tests hello world
|
* MediatorTest tests hello world
|
33
Behavioral/Memento/Caretaker.php
Normal file
33
Behavioral/Memento/Caretaker.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Memento;
|
||||||
|
|
||||||
|
class Caretaker
|
||||||
|
{
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
/* @var $savedStates Memento[] */
|
||||||
|
|
||||||
|
$savedStates = array();
|
||||||
|
|
||||||
|
$originator = new Originator();
|
||||||
|
|
||||||
|
//Setting state to State1
|
||||||
|
$originator->setState("State1");
|
||||||
|
//Setting state to State2
|
||||||
|
$originator->setState("State2");
|
||||||
|
//Saving State2 to Memento
|
||||||
|
$savedStates[] = $originator->saveToMemento();
|
||||||
|
//Setting state to State3
|
||||||
|
$originator->setState("State3");
|
||||||
|
|
||||||
|
// We can request multiple mementos, and choose which one to roll back to.
|
||||||
|
// Saving State3 to Memento
|
||||||
|
$savedStates[] = $originator->saveToMemento();
|
||||||
|
//Setting state to State4
|
||||||
|
$originator->setState("State4");
|
||||||
|
|
||||||
|
$originator->restoreFromMemento($savedStates[1]);
|
||||||
|
//State after restoring from Memento: State3
|
||||||
|
}
|
||||||
|
}
|
25
Behavioral/Memento/Memento.php
Normal file
25
Behavioral/Memento/Memento.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Memento;
|
||||||
|
|
||||||
|
class Memento
|
||||||
|
{
|
||||||
|
/* @var mixed */
|
||||||
|
private $state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $stateToSave
|
||||||
|
*/
|
||||||
|
public function __construct($stateToSave)
|
||||||
|
{
|
||||||
|
$this->state = $stateToSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getState()
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
}
|
35
Behavioral/Memento/Originator.php
Normal file
35
Behavioral/Memento/Originator.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Memento;
|
||||||
|
|
||||||
|
class Originator
|
||||||
|
{
|
||||||
|
/* @var mixed */
|
||||||
|
private $state;
|
||||||
|
|
||||||
|
// The class could also contain additional data that is not part of the
|
||||||
|
// state saved in the memento..
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $state
|
||||||
|
*/
|
||||||
|
public function setState($state)
|
||||||
|
{
|
||||||
|
$this->state = $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Memento
|
||||||
|
*/
|
||||||
|
public function saveToMemento()
|
||||||
|
{
|
||||||
|
$state = is_object($this->state) ? clone $this->state : $this->state;
|
||||||
|
|
||||||
|
return new Memento($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restoreFromMemento(Memento $memento)
|
||||||
|
{
|
||||||
|
$this->state = $memento->getState();
|
||||||
|
}
|
||||||
|
}
|
18
Behavioral/Memento/README.md
Normal file
18
Behavioral/Memento/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Memento
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Provide the ability to restore an object to its previous state (undo via rollback).
|
||||||
|
|
||||||
|
The memento pattern is implemented with three objects: the originator, a caretaker and a memento.
|
||||||
|
The originator is some object that has an internal state.
|
||||||
|
The caretaker is going to do something to the originator, but wants to be able to undo the change.
|
||||||
|
The caretaker first asks the originator for a memento object. Then it does whatever operation (or sequence of operations) it was going to do.
|
||||||
|
To roll back to the state before the operations, it returns the memento object to the originator.
|
||||||
|
The memento object itself is an opaque object (one which the caretaker cannot, or should not, change).
|
||||||
|
When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
* The seed of a pseudorandom number generator
|
||||||
|
* The state in a finite state machine
|
69
Behavioral/Memento/Tests/MementoTest.php
Normal file
69
Behavioral/Memento/Tests/MementoTest.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Behavioral\Memento\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Memento\Originator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MementoTest tests the memento pattern
|
||||||
|
*/
|
||||||
|
class MementoTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testStringState()
|
||||||
|
{
|
||||||
|
$originator = new Originator();
|
||||||
|
$originator->setState("State1");
|
||||||
|
|
||||||
|
$this->assertAttributeEquals("State1", "state", $originator);
|
||||||
|
|
||||||
|
$originator->setState("State2");
|
||||||
|
|
||||||
|
$this->assertAttributeEquals("State2", "state", $originator);
|
||||||
|
|
||||||
|
$savedState = $originator->saveToMemento();
|
||||||
|
|
||||||
|
$this->assertAttributeEquals("State2", "state", $savedState);
|
||||||
|
|
||||||
|
$originator->setState("State3");
|
||||||
|
|
||||||
|
$this->assertAttributeEquals("State3", "state", $originator);
|
||||||
|
|
||||||
|
$originator->restoreFromMemento($savedState);
|
||||||
|
|
||||||
|
$this->assertAttributeEquals("State2", "state", $originator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testObjectState()
|
||||||
|
{
|
||||||
|
$originator = new Originator();
|
||||||
|
|
||||||
|
$foo = new \stdClass();
|
||||||
|
$foo->data = "foo";
|
||||||
|
|
||||||
|
$originator->setState($foo);
|
||||||
|
|
||||||
|
$this->assertAttributeEquals($foo, "state", $originator);
|
||||||
|
|
||||||
|
$savedState = $originator->saveToMemento();
|
||||||
|
|
||||||
|
$this->assertAttributeEquals($foo, "state", $savedState);
|
||||||
|
|
||||||
|
$bar = new \stdClass();
|
||||||
|
$bar->data = "bar";
|
||||||
|
|
||||||
|
$originator->setState($bar);
|
||||||
|
|
||||||
|
$this->assertAttributeEquals($bar, "state", $originator);
|
||||||
|
|
||||||
|
$originator->restoreFromMemento($savedState);
|
||||||
|
|
||||||
|
$this->assertAttributeEquals($foo, "state", $originator);
|
||||||
|
|
||||||
|
$foo->data = null;
|
||||||
|
|
||||||
|
$this->assertAttributeNotEquals($foo, "state", $savedState);
|
||||||
|
|
||||||
|
$this->assertAttributeNotEquals($foo, "state", $originator);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggerInterface is a contract for logging something
|
* LoggerInterface is a contract for logging something
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performance concerns : ok there is a call for nothing but we spare an "if is_null"
|
* Performance concerns : ok there is a call for nothing but we spare an "if is_null"
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PrintLogger is a logger that prints the log entry to standard output
|
* PrintLogger is a logger that prints the log entry to standard output
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service is dummy service that uses a logger
|
* Service is dummy service that uses a logger
|
@@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\NullObject;
|
namespace DesignPatterns\Behavioral\NullObject\Tests;
|
||||||
|
|
||||||
use DesignPatterns\NullObject\NullLogger;
|
use DesignPatterns\Behavioral\NullObject\NullLogger;
|
||||||
use DesignPatterns\NullObject\Service;
|
use DesignPatterns\Behavioral\NullObject\Service;
|
||||||
use DesignPatterns\NullObject\PrintLogger;
|
use DesignPatterns\Behavioral\NullObject\PrintLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LoggerTest tests for different loggers
|
* LoggerTest tests for different loggers
|
||||||
@@ -24,7 +24,7 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testStandardLogger()
|
public function testStandardLogger()
|
||||||
{
|
{
|
||||||
$service = new Service(new PrintLogger());
|
$service = new Service(new PrintLogger());
|
||||||
$this->expectOutputString('We are in DesignPatterns\NullObject\Service::doSomething');
|
$this->expectOutputString('We are in DesignPatterns\Behavioral\NullObject\Service::doSomething');
|
||||||
$service->doSomething();
|
$service->doSomething();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Observer;
|
namespace DesignPatterns\Behavioral\Observer\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Observer\UserObserver;
|
use DesignPatterns\Behavioral\Observer\UserObserver;
|
||||||
use DesignPatterns\Observer\User;
|
use DesignPatterns\Behavioral\Observer\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ObserverTest tests the Observer pattern
|
* ObserverTest tests the Observer pattern
|
||||||
@@ -23,7 +23,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testNotify()
|
public function testNotify()
|
||||||
{
|
{
|
||||||
$this->expectOutputString('DesignPatterns\Observer\User has been updated');
|
$this->expectOutputString('DesignPatterns\Behavioral\Observer\User has been updated');
|
||||||
$subject = new User();
|
$subject = new User();
|
||||||
|
|
||||||
$subject->attach($this->observer);
|
$subject->attach($this->observer);
|
||||||
@@ -53,10 +53,9 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
|
|||||||
$subject->attach($observer);
|
$subject->attach($observer);
|
||||||
|
|
||||||
$observer->expects($this->once())
|
$observer->expects($this->once())
|
||||||
->method('update')
|
->method('update')
|
||||||
->with($subject);
|
->with($subject);
|
||||||
|
|
||||||
$subject->notify();
|
$subject->notify();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observer pattern : The observed object (the subject)
|
* Observer pattern : The observed object (the subject)
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class UserObserver
|
* class UserObserver
|
18
Behavioral/README.md
Normal file
18
Behavioral/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Behavioral
|
||||||
|
|
||||||
|
In software engineering, behavioral design patterns are design patterns that
|
||||||
|
identify common communication patterns between objects and realize these
|
||||||
|
patterns. By doing so, these patterns increase flexibility in carrying out this
|
||||||
|
communication.
|
||||||
|
|
||||||
|
* [ChainOfResponsibilities](ChainOfResponsibilities) [:notebook:](http://en.wikipedia.org/wiki/Chain_of_responsibility_pattern)
|
||||||
|
* [Command](Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern)
|
||||||
|
* [Iterator](Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_pattern)
|
||||||
|
* [Mediator](Mediator) [:notebook:](http://en.wikipedia.org/wiki/Mediator_pattern)
|
||||||
|
* [NullObject](NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern)
|
||||||
|
* [Observer](Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern)
|
||||||
|
* [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern)
|
||||||
|
* [State](State) [:notebook:](http://en.wikipedia.org/wiki/State_pattern)
|
||||||
|
* [Strategy](Strategy) [:notebook:](http://en.wikipedia.org/wiki/Strategy_pattern)
|
||||||
|
* [TemplateMethod](TemplateMethod) [:notebook:](http://en.wikipedia.org/wiki/Template_method_pattern)
|
||||||
|
* [Visitor](Visitor) [:notebook:](http://en.wikipedia.org/wiki/Visitor_pattern)
|
18
Specification/AbstractSpecification.php → Behavioral/Specification/AbstractSpecification.php
Executable file → Normal file
18
Specification/AbstractSpecification.php → Behavioral/Specification/AbstractSpecification.php
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract specification allows the creation of wrapped specifications
|
* An abstract specification allows the creation of wrapped specifications
|
||||||
@@ -8,18 +8,18 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Checks if given item meets all criteria
|
* Checks if given item meets all criteria
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
abstract public function isSatisfiedBy(Item $item);
|
abstract public function isSatisfiedBy(Item $item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical AND specification
|
* Creates a new logical AND specification
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*
|
*
|
||||||
* @return SpecificationInterface
|
* @return SpecificationInterface
|
||||||
*/
|
*/
|
||||||
public function plus(SpecificationInterface $spec)
|
public function plus(SpecificationInterface $spec)
|
||||||
@@ -29,9 +29,9 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical OR composite specification
|
* Creates a new logical OR composite specification
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
*
|
*
|
||||||
* @return SpecificationInterface
|
* @return SpecificationInterface
|
||||||
*/
|
*/
|
||||||
public function either(SpecificationInterface $spec)
|
public function either(SpecificationInterface $spec)
|
||||||
@@ -41,11 +41,11 @@ abstract class AbstractSpecification implements SpecificationInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new logical NOT specification
|
* Creates a new logical NOT specification
|
||||||
*
|
*
|
||||||
* @return SpecificationInterface
|
* @return SpecificationInterface
|
||||||
*/
|
*/
|
||||||
public function not()
|
public function not()
|
||||||
{
|
{
|
||||||
return new Not($this);
|
return new Not($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
2
Specification/Either.php → Behavioral/Specification/Either.php
Executable file → Normal file
2
Specification/Either.php → Behavioral/Specification/Either.php
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical OR specification
|
* A logical OR specification
|
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An trivial item
|
* An trivial item
|
4
Specification/Not.php → Behavioral/Specification/Not.php
Executable file → Normal file
4
Specification/Not.php → Behavioral/Specification/Not.php
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical Not specification
|
* A logical Not specification
|
||||||
@@ -31,4 +31,4 @@ class Not extends AbstractSpecification
|
|||||||
{
|
{
|
||||||
return !$this->spec->isSatisfiedBy($item);
|
return !$this->spec->isSatisfiedBy($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
11
Specification/Plus.php → Behavioral/Specification/Plus.php
Executable file → Normal file
11
Specification/Plus.php → Behavioral/Specification/Plus.php
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical AND specification
|
* A logical AND specification
|
||||||
@@ -12,10 +12,9 @@ class Plus extends AbstractSpecification
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creation of a locical AND of two specifications
|
* Creation of a locical AND of two specifications
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $left
|
* @param SpecificationInterface $left
|
||||||
* @param SpecificationInterface $right
|
* @param SpecificationInterface $right
|
||||||
|
|
||||||
*/
|
*/
|
||||||
public function __construct(SpecificationInterface $left, SpecificationInterface $right)
|
public function __construct(SpecificationInterface $left, SpecificationInterface $right)
|
||||||
{
|
{
|
||||||
@@ -25,13 +24,13 @@ class Plus extends AbstractSpecification
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the composite AND of specifications passes
|
* Checks if the composite AND of specifications passes
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isSatisfiedBy(Item $item)
|
public function isSatisfiedBy(Item $item)
|
||||||
{
|
{
|
||||||
return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item);
|
return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specification to check an Item is priced between min and max
|
* A specification to check an Item is priced between min and max
|
||||||
@@ -31,17 +31,17 @@ class PriceSpecification extends AbstractSpecification
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if Item price falls between bounds
|
* Checks if Item price falls between bounds
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isSatisfiedBy(Item $item)
|
public function isSatisfiedBy(Item $item)
|
||||||
{
|
{
|
||||||
if ( !empty($this->maxPrice) && $item->getPrice() > $this->maxPrice) {
|
if (!empty($this->maxPrice) && $item->getPrice() > $this->maxPrice) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( !empty($this->minPrice) && $item->getPrice() < $this->minPrice) {
|
if (!empty($this->minPrice) && $item->getPrice() < $this->minPrice) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
14
Specification/SpecificationInterface.php → Behavioral/Specification/SpecificationInterface.php
Executable file → Normal file
14
Specification/SpecificationInterface.php → Behavioral/Specification/SpecificationInterface.php
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace DesignPatterns\Specification;
|
namespace DesignPatterns\Behavioral\Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for a specification
|
* An interface for a specification
|
||||||
@@ -8,26 +8,24 @@ interface SpecificationInterface
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A boolean evaluation indicating if the object meets the specification
|
* A boolean evaluation indicating if the object meets the specification
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isSatisfiedBy(Item $item);
|
public function isSatisfiedBy(Item $item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a logical AND specification
|
* Creates a logical AND specification
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
|
|
||||||
*/
|
*/
|
||||||
public function plus(SpecificationInterface $spec);
|
public function plus(SpecificationInterface $spec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a logical OR specification
|
* Creates a logical OR specification
|
||||||
*
|
*
|
||||||
* @param SpecificationInterface $spec
|
* @param SpecificationInterface $spec
|
||||||
|
|
||||||
*/
|
*/
|
||||||
public function either(SpecificationInterface $spec);
|
public function either(SpecificationInterface $spec);
|
||||||
|
|
||||||
@@ -35,4 +33,4 @@ interface SpecificationInterface
|
|||||||
* Creates a logical not specification
|
* Creates a logical not specification
|
||||||
*/
|
*/
|
||||||
public function not();
|
public function not();
|
||||||
}
|
}
|
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Specification;
|
namespace DesignPatterns\Behavioral\Specification\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Specification\PriceSpecification;
|
use DesignPatterns\Behavioral\Specification\PriceSpecification;
|
||||||
use DesignPatterns\Specification\Item;
|
use DesignPatterns\Behavioral\Specification\Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpecificationTest tests the specification pattern
|
* SpecificationTest tests the specification pattern
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Status;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateOrder
|
* Class CreateOrder
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Status;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderController
|
* Class OrderController
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Status;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderFactory
|
* Class OrderFactory
|
||||||
@@ -9,7 +9,7 @@ class OrderFactory
|
|||||||
{
|
{
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
throw Exception('Can not instance the OrderFactory class!');
|
throw new \Exception('Can not instance the OrderFactory class!');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Status;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderInterface
|
* Class OrderInterface
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Status;
|
namespace DesignPatterns\Behavioral\State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ShippingOrder
|
* Class ShippingOrder
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ComparatorInterface
|
* Class ComparatorInterface
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DateComparator
|
* Class DateComparator
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class IdComparator
|
* Class IdComparator
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ObjectCollection
|
* Class ObjectCollection
|
||||||
@@ -30,10 +30,10 @@ class ObjectCollection
|
|||||||
*/
|
*/
|
||||||
public function sort()
|
public function sort()
|
||||||
{
|
{
|
||||||
if (!$this->comparator){
|
if (!$this->comparator) {
|
||||||
throw new \LogicException("Comparator is not set");
|
throw new \LogicException("Comparator is not set");
|
||||||
}
|
}
|
||||||
|
|
||||||
$callback = array($this->comparator, 'compare');
|
$callback = array($this->comparator, 'compare');
|
||||||
uasort($this->elements, $callback);
|
uasort($this->elements, $callback);
|
||||||
|
|
@@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Strategy\DateComparator;
|
use DesignPatterns\Behavioral\Strategy\DateComparator;
|
||||||
use DesignPatterns\Strategy\IdComparator;
|
use DesignPatterns\Behavioral\Strategy\IdComparator;
|
||||||
use DesignPatterns\Strategy\ObjectCollection;
|
use DesignPatterns\Behavioral\Strategy\ObjectCollection;
|
||||||
use DesignPatterns\Strategy\Strategy;
|
use DesignPatterns\Behavioral\Strategy\Strategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for Static Factory pattern
|
* Tests for Static Factory pattern
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BeachJourney is vacation at the beach
|
* BeachJourney is vacation at the beach
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CityJourney is a journey in a city
|
* CityJourney is a journey in a city
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\TemplateMethod;
|
namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
|
||||||
|
|
||||||
use DesignPatterns\TemplateMethod;
|
use DesignPatterns\Behavioral\TemplateMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JourneyTest tests all journeys
|
* JourneyTest tests all journeys
|
||||||
@@ -29,10 +29,10 @@ class JourneyTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testLasVegas()
|
public function testLasVegas()
|
||||||
{
|
{
|
||||||
$journey = $this->getMockForAbstractClass('DesignPatterns\TemplateMethod\Journey');
|
$journey = $this->getMockForAbstractClass('DesignPatterns\Behavioral\TemplateMethod\Journey');
|
||||||
$journey->expects($this->once())
|
$journey->expects($this->once())
|
||||||
->method('enjoyVacation')
|
->method('enjoyVacation')
|
||||||
->will($this->returnCallback(array($this, 'mockUpVacation')));
|
->will($this->returnCallback(array($this, 'mockUpVacation')));
|
||||||
$this->expectOutputRegex('#Las Vegas#');
|
$this->expectOutputRegex('#Las Vegas#');
|
||||||
$journey->takeATrip();
|
$journey->takeATrip();
|
||||||
}
|
}
|
||||||
@@ -41,5 +41,4 @@ class JourneyTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
echo "Fear and loathing in Las Vegas\n";
|
echo "Fear and loathing in Las Vegas\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example of a Visitor: Group
|
* An example of a Visitor: Group
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class Role
|
* class Role
|
||||||
@@ -12,7 +12,7 @@ abstract class Role
|
|||||||
*
|
*
|
||||||
* Feel free to override it if your object must call another visiting behavior
|
* Feel free to override it if your object must call another visiting behavior
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Visitor\RoleVisitorInterface $visitor
|
* @param \DesignPatterns\Behavioral\Visitor\RoleVisitorInterface $visitor
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern
|
||||||
@@ -18,14 +18,14 @@ interface RoleVisitorInterface
|
|||||||
/**
|
/**
|
||||||
* Visit a User object
|
* Visit a User object
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Visitor\User $role
|
* @param \DesignPatterns\Behavioral\Visitor\User $role
|
||||||
*/
|
*/
|
||||||
public function visitUser(User $role);
|
public function visitUser(User $role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a Group object
|
* Visit a Group object
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Visitor\Group $role
|
* @param \DesignPatterns\Behavioral\Visitor\Group $role
|
||||||
*/
|
*/
|
||||||
public function visitGroup(Group $role);
|
public function visitGroup(Group $role);
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\Visitor;
|
namespace DesignPatterns\Tests\Visitor\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Visitor;
|
use DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VisitorTest tests the visitor pattern
|
* VisitorTest tests the visitor pattern
|
||||||
@@ -40,8 +40,7 @@ class VisitorTest extends \PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testUnknownObject()
|
public function testUnknownObject()
|
||||||
{
|
{
|
||||||
$mock = $this->getMockForAbstractClass('DesignPatterns\Visitor\Role');
|
$mock = $this->getMockForAbstractClass('DesignPatterns\Behavioral\Visitor\Role');
|
||||||
$mock->accept($this->visitor);
|
$mock->accept($this->visitor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Behavioral\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor Pattern
|
* Visitor Pattern
|
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Door
|
|
||||||
*/
|
|
||||||
class Door
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Engine
|
|
||||||
*/
|
|
||||||
class Engine
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Wheel
|
|
||||||
*/
|
|
||||||
class Wheel
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class AbstractFactory
|
* class AbstractFactory
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory\Html;
|
namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||||
|
|
||||||
use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory\Html;
|
namespace DesignPatterns\Creational\AbstractFactory\Html;
|
||||||
|
|
||||||
use DesignPatterns\AbstractFactory\Text as BaseText;
|
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class HtmlFactory
|
* Class HtmlFactory
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory\Json;
|
namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||||
|
|
||||||
use DesignPatterns\AbstractFactory\Picture as BasePicture;
|
use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory\Json;
|
namespace DesignPatterns\Creational\AbstractFactory\Json;
|
||||||
|
|
||||||
use DesignPatterns\AbstractFactory\Text as BaseText;
|
use DesignPatterns\Creational\AbstractFactory\Text as BaseText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JsonFactory
|
* Class JsonFactory
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface MediaInterface
|
* Interface MediaInterface
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Picture
|
* Class Picture
|
@@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Tests\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory\Tests;
|
||||||
|
|
||||||
use DesignPatterns\AbstractFactory\AbstractFactory;
|
use DesignPatterns\Creational\AbstractFactory\AbstractFactory;
|
||||||
use DesignPatterns\AbstractFactory\HtmlFactory;
|
use DesignPatterns\Creational\AbstractFactory\HtmlFactory;
|
||||||
use DesignPatterns\AbstractFactory\JsonFactory;
|
use DesignPatterns\Creational\AbstractFactory\JsonFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractFactoryTest tests concrete factories
|
* AbstractFactoryTest tests concrete factories
|
||||||
@@ -34,7 +34,7 @@ class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$factory->createText('footnotes')
|
$factory->createText('footnotes')
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContainsOnly('DesignPatterns\AbstractFactory\MediaInterface', $article);
|
$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);
|
||||||
|
|
||||||
/* this is the time to look at the Builder pattern. This pattern
|
/* this is the time to look at the Builder pattern. This pattern
|
||||||
* helps you to create complex object like that article above with
|
* helps you to create complex object like that article above with
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\AbstractFactory;
|
namespace DesignPatterns\Creational\AbstractFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Text
|
* Class Text
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BikeBuilder builds bike
|
* BikeBuilder builds bike
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CarBuilder builds car
|
* CarBuilder builds car
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Director is part of the builder pattern. It knows the interface of the builder
|
* Director is part of the builder pattern. It knows the interface of the builder
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bike is a bike
|
* Bike is a bike
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Car is a car
|
* Car is a car
|
11
Creational/Builder/Parts/Door.php
Normal file
11
Creational/Builder/Parts/Door.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Door
|
||||||
|
*/
|
||||||
|
class Door
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
11
Creational/Builder/Parts/Engine.php
Normal file
11
Creational/Builder/Parts/Engine.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Engine
|
||||||
|
*/
|
||||||
|
class Engine
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace DesignPatterns\Builder\Parts;
|
namespace DesignPatterns\Creational\Builder\Parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VehicleInterface is a contract for a vehicle
|
* VehicleInterface is a contract for a vehicle
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user