update deps & install rector

This commit is contained in:
Dominik Liebler
2019-12-14 12:50:05 +01:00
parent 04acce6759
commit 579a5ac946
87 changed files with 2432 additions and 786 deletions

View File

@@ -3,9 +3,7 @@ language: php
sudo: false sudo: false
php: php:
- 7.2 - 7.4
- 7.3
- 7.4snapshot
matrix: matrix:
fast_finish: true fast_finish: true

View File

@@ -3,14 +3,10 @@
namespace DesignPatterns\Behavioral\ChainOfResponsibilities; namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
abstract class Handler abstract class Handler
{ {
/** private ?Handler $successor = null;
* @var Handler|null
*/
private $successor = null;
public function __construct(Handler $handler = null) public function __construct(Handler $handler = null)
{ {
@@ -20,12 +16,8 @@ abstract class Handler
/** /**
* This approach by using a template method pattern ensures you that * This approach by using a template method pattern ensures you that
* each subclass will not forget to call the successor * each subclass will not forget to call the successor
*
* @param RequestInterface $request
*
* @return string|null
*/ */
final public function handle(RequestInterface $request) final public function handle(RequestInterface $request): ?string
{ {
$processed = $this->processing($request); $processed = $this->processing($request);
@@ -37,5 +29,5 @@ abstract class Handler
return $processed; return $processed;
} }
abstract protected function processing(RequestInterface $request); abstract protected function processing(RequestInterface $request): ?string;
} }

View File

@@ -7,28 +7,16 @@ use Psr\Http\Message\RequestInterface;
class HttpInMemoryCacheHandler extends Handler class HttpInMemoryCacheHandler extends Handler
{ {
/** private array $data;
* @var array
*/
private $data;
/** public function __construct(array $data, ?Handler $successor = null)
* @param array $data
* @param Handler|null $successor
*/
public function __construct(array $data, Handler $successor = null)
{ {
parent::__construct($successor); parent::__construct($successor);
$this->data = $data; $this->data = $data;
} }
/** protected function processing(RequestInterface $request): ?string
* @param RequestInterface $request
*
* @return string|null
*/
protected function processing(RequestInterface $request)
{ {
$key = sprintf( $key = sprintf(
'%s?%s', '%s?%s',

View File

@@ -7,12 +7,7 @@ use Psr\Http\Message\RequestInterface;
class SlowDatabaseHandler extends Handler class SlowDatabaseHandler extends Handler
{ {
/** protected function processing(RequestInterface $request): ?string
* @param RequestInterface $request
*
* @return string|null
*/
protected function processing(RequestInterface $request)
{ {
// this is a mockup, in production code you would ask a slow (compared to in-memory) DB for the results // this is a mockup, in production code you would ask a slow (compared to in-memory) DB for the results

View File

@@ -5,17 +5,13 @@ namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler; use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\HttpInMemoryCacheHandler; use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\HttpInMemoryCacheHandler;
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowDatabaseHandler; use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowDatabaseHandler;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
class ChainTest extends TestCase class ChainTest extends TestCase
{ {
/** private Handler $chain;
* @var Handler
*/
private $chain;
protected function setUp(): void protected function setUp(): void
{ {

View File

@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
*/ */
class AddMessageDateCommand implements UndoableCommand class AddMessageDateCommand implements UndoableCommand
{ {
/** private Receiver $output;
* @var Receiver
*/
private $output;
/** /**
* Each concrete command is built with different receivers. * Each concrete command is built with different receivers.
* There can be one, many or completely no receivers, but there can be other commands in the parameters. * There can be one, many or completely no receivers, but there can be other commands in the parameters.
*
* @param Receiver $console
*/ */
public function __construct(Receiver $console) public function __construct(Receiver $console)
{ {

View File

@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
*/ */
class HelloCommand implements Command class HelloCommand implements Command
{ {
/** private Receiver $output;
* @var Receiver
*/
private $output;
/** /**
* Each concrete command is built with different receivers. * Each concrete command is built with different receivers.
* There can be one, many or completely no receivers, but there can be other commands in the parameters * There can be one, many or completely no receivers, but there can be other commands in the parameters
*
* @param Receiver $console
*/ */
public function __construct(Receiver $console) public function __construct(Receiver $console)
{ {

View File

@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
*/ */
class Invoker class Invoker
{ {
/** private Command $command;
* @var Command
*/
private $command;
/** /**
* in the invoker we find this kind of method for subscribing the command * in the invoker we find this kind of method for subscribing the command
* There can be also a stack, a list, a fixed set ... * There can be also a stack, a list, a fixed set ...
*
* @param Command $cmd
*/ */
public function setCommand(Command $cmd) public function setCommand(Command $cmd)
{ {

View File

@@ -3,23 +3,17 @@
namespace DesignPatterns\Behavioral\Command; namespace DesignPatterns\Behavioral\Command;
/** /**
* Receiver is specific service with its own contract and can be only concrete. * Receiver is a specific service with its own contract and can be only concrete.
*/ */
class Receiver class Receiver
{ {
/** private bool $enableDate = false;
* @var bool
*/
private $enableDate = false;
/** /**
* @var string[] * @var string[]
*/ */
private $output = []; private array $output = [];
/**
* @param string $str
*/
public function write(string $str) public function write(string $str)
{ {
if ($this->enableDate) { if ($this->enableDate) {

View File

@@ -4,15 +4,8 @@ namespace DesignPatterns\Behavioral\Iterator;
class Book class Book
{ {
/** private string $author;
* @var string private string $title;
*/
private $author;
/**
* @var string
*/
private $title;
public function __construct(string $title, string $author) public function __construct(string $title, string $author)
{ {

View File

@@ -2,17 +2,16 @@
namespace DesignPatterns\Behavioral\Iterator; namespace DesignPatterns\Behavioral\Iterator;
class BookList implements \Countable, \Iterator use Countable;
use Iterator;
class BookList implements Countable, Iterator
{ {
/** /**
* @var Book[] * @var Book[]
*/ */
private $books = []; private array $books = [];
private int $currentIndex = 0;
/**
* @var int
*/
private $currentIndex = 0;
public function addBook(Book $book) public function addBook(Book $book)
{ {

View File

@@ -4,14 +4,8 @@ namespace DesignPatterns\Behavioral\Mediator;
abstract class Colleague abstract class Colleague
{ {
/** protected Mediator $mediator;
* @var Mediator
*/
protected $mediator;
/**
* @param Mediator $mediator
*/
public function setMediator(Mediator $mediator) public function setMediator(Mediator $mediator)
{ {
$this->mediator = $mediator; $this->mediator = $mediator;

View File

@@ -11,7 +11,7 @@ class MediatorTest extends TestCase
{ {
public function testOutputHelloWorld() public function testOutputHelloWorld()
{ {
$mediator = new UserRepositoryUiMediator(new UserRepository(), new UI()); $mediator = new UserRepositoryUiMediator(new UserRepository(), new Ui());
$this->expectOutputString('User: Dominik'); $this->expectOutputString('User: Dominik');
$mediator->printInfoAbout('Dominik'); $mediator->printInfoAbout('Dominik');

View File

@@ -4,15 +4,8 @@ namespace DesignPatterns\Behavioral\Mediator;
class UserRepositoryUiMediator implements Mediator class UserRepositoryUiMediator implements Mediator
{ {
/** private UserRepository $userRepository;
* @var UserRepository private Ui $ui;
*/
private $userRepository;
/**
* @var Ui
*/
private $ui;
public function __construct(UserRepository $userRepository, Ui $ui) public function __construct(UserRepository $userRepository, Ui $ui)
{ {

View File

@@ -4,23 +4,14 @@ namespace DesignPatterns\Behavioral\Memento;
class Memento class Memento
{ {
/** private State $state;
* @var State
*/
private $state;
/**
* @param State $stateToSave
*/
public function __construct(State $stateToSave) public function __construct(State $stateToSave)
{ {
$this->state = $stateToSave; $this->state = $stateToSave;
} }
/** public function getState(): State
* @return State
*/
public function getState()
{ {
return $this->state; return $this->state;
} }

View File

@@ -2,6 +2,8 @@
namespace DesignPatterns\Behavioral\Memento; namespace DesignPatterns\Behavioral\Memento;
use InvalidArgumentException;
class State class State
{ {
const STATE_CREATED = 'created'; const STATE_CREATED = 'created';
@@ -9,24 +11,18 @@ class State
const STATE_ASSIGNED = 'assigned'; const STATE_ASSIGNED = 'assigned';
const STATE_CLOSED = 'closed'; const STATE_CLOSED = 'closed';
/** private string $state;
* @var string
*/
private $state;
/** /**
* @var string[] * @var string[]
*/ */
private static $validStates = [ private static array $validStates = [
self::STATE_CREATED, self::STATE_CREATED,
self::STATE_OPENED, self::STATE_OPENED,
self::STATE_ASSIGNED, self::STATE_ASSIGNED,
self::STATE_CLOSED, self::STATE_CLOSED,
]; ];
/**
* @param string $state
*/
public function __construct(string $state) public function __construct(string $state)
{ {
self::ensureIsValidState($state); self::ensureIsValidState($state);
@@ -37,7 +33,7 @@ class State
private static function ensureIsValidState(string $state) private static function ensureIsValidState(string $state)
{ {
if (!in_array($state, self::$validStates)) { if (!in_array($state, self::$validStates)) {
throw new \InvalidArgumentException('Invalid state given'); throw new InvalidArgumentException('Invalid state given');
} }
} }

View File

@@ -7,10 +7,7 @@ namespace DesignPatterns\Behavioral\Memento;
*/ */
class Ticket class Ticket
{ {
/** private State $currentState;
* @var State
*/
private $currentState;
public function __construct() public function __construct()
{ {

View File

@@ -4,14 +4,8 @@ namespace DesignPatterns\Behavioral\NullObject;
class Service class Service
{ {
/** private Logger $logger;
* @var Logger
*/
private $logger;
/**
* @param Logger $logger
*/
public function __construct(Logger $logger) public function __construct(Logger $logger)
{ {
$this->logger = $logger; $this->logger = $logger;

View File

@@ -2,33 +2,30 @@
namespace DesignPatterns\Behavioral\Observer; namespace DesignPatterns\Behavioral\Observer;
use SplSubject;
use SplObjectStorage;
use SplObserver;
/** /**
* User implements the observed object (called Subject), it maintains a list of observers and sends notifications to * User implements the observed object (called Subject), it maintains a list of observers and sends notifications to
* them in case changes are made on the User object * them in case changes are made on the User object
*/ */
class User implements \SplSubject class User implements SplSubject
{ {
/** private string $email;
* @var string private SplObjectStorage $observers;
*/
private $email;
/**
* @var \SplObjectStorage
*/
private $observers;
public function __construct() public function __construct()
{ {
$this->observers = new \SplObjectStorage(); $this->observers = new SplObjectStorage();
} }
public function attach(\SplObserver $observer) public function attach(SplObserver $observer)
{ {
$this->observers->attach($observer); $this->observers->attach($observer);
} }
public function detach(\SplObserver $observer) public function detach(SplObserver $observer)
{ {
$this->observers->detach($observer); $this->observers->detach($observer);
} }
@@ -41,7 +38,7 @@ class User implements \SplSubject
public function notify() public function notify()
{ {
/** @var \SplObserver $observer */ /** @var SplObserver $observer */
foreach ($this->observers as $observer) { foreach ($this->observers as $observer) {
$observer->update($this); $observer->update($this);
} }

View File

@@ -2,19 +2,18 @@
namespace DesignPatterns\Behavioral\Observer; namespace DesignPatterns\Behavioral\Observer;
use SplObserver;
use SplSubject; use SplSubject;
class UserObserver implements \SplObserver class UserObserver implements SplObserver
{ {
/** /**
* @var SplSubject[] * @var SplSubject[]
*/ */
private $changedUsers = []; private array $changedUsers = [];
/** /**
* It is called by the Subject, usually by SplSubject::notify() * It is called by the Subject, usually by SplSubject::notify()
*
* @param SplSubject $subject
*/ */
public function update(SplSubject $subject) public function update(SplSubject $subject)
{ {

View File

@@ -7,7 +7,7 @@ class AndSpecification implements Specification
/** /**
* @var Specification[] * @var Specification[]
*/ */
private $specifications; private array $specifications;
/** /**
* @param Specification[] $specifications * @param Specification[] $specifications

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Specification;
class Item class Item
{ {
/** private float $price;
* @var float
*/
private $price;
public function __construct(float $price) public function __construct(float $price)
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Specification;
class NotSpecification implements Specification class NotSpecification implements Specification
{ {
/** private Specification $specification;
* @var Specification
*/
private $specification;
public function __construct(Specification $specification) public function __construct(Specification $specification)
{ {

View File

@@ -7,7 +7,7 @@ class OrSpecification implements Specification
/** /**
* @var Specification[] * @var Specification[]
*/ */
private $specifications; private array $specifications;
/** /**
* @param Specification[] $specifications * @param Specification[] $specifications
@@ -27,6 +27,7 @@ class OrSpecification implements Specification
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -4,21 +4,10 @@ namespace DesignPatterns\Behavioral\Specification;
class PriceSpecification implements Specification class PriceSpecification implements Specification
{ {
/** private ?float $maxPrice;
* @var float|null private ?float $minPrice;
*/
private $maxPrice;
/** public function __construct(?float $minPrice, ?float $maxPrice)
* @var float|null
*/
private $minPrice;
/**
* @param float $minPrice
* @param float $maxPrice
*/
public function __construct($minPrice, $maxPrice)
{ {
$this->minPrice = $minPrice; $this->minPrice = $minPrice;
$this->maxPrice = $maxPrice; $this->maxPrice = $maxPrice;

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\State;
class OrderContext class OrderContext
{ {
/** private State $state;
* @var State
*/
private $state;
public static function create(): OrderContext public static function create(): OrderContext
{ {

View File

@@ -4,17 +4,14 @@ namespace DesignPatterns\Behavioral\Strategy;
class Context class Context
{ {
/** private Comparator $comparator;
* @var Comparator
*/
private $comparator;
public function __construct(Comparator $comparator) public function __construct(Comparator $comparator)
{ {
$this->comparator = $comparator; $this->comparator = $comparator;
} }
public function executeStrategy(array $elements) : array public function executeStrategy(array $elements): array
{ {
uasort($elements, [$this->comparator, 'compare']); uasort($elements, [$this->comparator, 'compare']);

View File

@@ -2,18 +2,14 @@
namespace DesignPatterns\Behavioral\Strategy; namespace DesignPatterns\Behavioral\Strategy;
use DateTime;
class DateComparator implements Comparator class DateComparator implements Comparator
{ {
/**
* @param mixed $a
* @param mixed $b
*
* @return int
*/
public function compare($a, $b): int public function compare($a, $b): int
{ {
$aDate = new \DateTime($a['date']); $aDate = new DateTime($a['date']);
$bDate = new \DateTime($b['date']); $bDate = new DateTime($b['date']);
return $aDate <=> $bDate; return $aDate <=> $bDate;
} }

View File

@@ -4,12 +4,6 @@ namespace DesignPatterns\Behavioral\Strategy;
class IdComparator implements Comparator class IdComparator implements Comparator
{ {
/**
* @param mixed $a
* @param mixed $b
*
* @return int
*/
public function compare($a, $b): int public function compare($a, $b): int
{ {
return $a['id'] <=> $b['id']; return $a['id'] <=> $b['id'];

View File

@@ -9,7 +9,7 @@ class CityJourney extends Journey
return "Eat, drink, take photos and sleep"; return "Eat, drink, take photos and sleep";
} }
protected function buyGift(): string protected function buyGift(): ?string
{ {
return "Buy a gift"; return "Buy a gift";
} }

View File

@@ -7,7 +7,7 @@ abstract class Journey
/** /**
* @var string[] * @var string[]
*/ */
private $thingsToDo = []; private array $thingsToDo = [];
/** /**
* This is the public service provided by this class and its subclasses. * This is the public service provided by this class and its subclasses.
@@ -37,10 +37,8 @@ abstract class Journey
/** /**
* This method is also part of the algorithm but it is optional. * This method is also part of the algorithm but it is optional.
* You can override it only if you need to * You can override it only if you need to
*
* @return null|string
*/ */
protected function buyGift() protected function buyGift(): ?string
{ {
return null; return null;
} }

View File

@@ -2,14 +2,15 @@
namespace DesignPatterns\Behavioral\TemplateMethod\Tests; namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
use DesignPatterns\Behavioral\TemplateMethod; use DesignPatterns\Behavioral\TemplateMethod\BeachJourney;
use DesignPatterns\Behavioral\TemplateMethod\CityJourney;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class JourneyTest extends TestCase class JourneyTest extends TestCase
{ {
public function testCanGetOnVacationOnTheBeach() public function testCanGetOnVacationOnTheBeach()
{ {
$beachJourney = new TemplateMethod\BeachJourney(); $beachJourney = new BeachJourney();
$beachJourney->takeATrip(); $beachJourney->takeATrip();
$this->assertSame( $this->assertSame(
@@ -20,7 +21,7 @@ class JourneyTest extends TestCase
public function testCanGetOnAJourneyToACity() public function testCanGetOnAJourneyToACity()
{ {
$cityJourney = new TemplateMethod\CityJourney(); $cityJourney = new CityJourney();
$cityJourney->takeATrip(); $cityJourney->takeATrip();
$this->assertSame( $this->assertSame(

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Visitor;
class Group implements Role class Group implements Role
{ {
/** private string $name;
* @var string
*/
private $name;
public function __construct(string $name) public function __construct(string $name)
{ {

View File

@@ -7,7 +7,7 @@ class RecordingVisitor implements RoleVisitor
/** /**
* @var Role[] * @var Role[]
*/ */
private $visited = []; private array $visited = [];
public function visitGroup(Group $role) public function visitGroup(Group $role)
{ {

View File

@@ -2,35 +2,34 @@
namespace DesignPatterns\Tests\Visitor\Tests; namespace DesignPatterns\Tests\Visitor\Tests;
use DesignPatterns\Behavioral\Visitor\RecordingVisitor;
use DesignPatterns\Behavioral\Visitor\User;
use DesignPatterns\Behavioral\Visitor\Group;
use DesignPatterns\Behavioral\Visitor\Role;
use DesignPatterns\Behavioral\Visitor; use DesignPatterns\Behavioral\Visitor;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class VisitorTest extends TestCase class VisitorTest extends TestCase
{ {
/** private RecordingVisitor $visitor;
* @var Visitor\RecordingVisitor
*/
private $visitor;
protected function setUp(): void protected function setUp(): void
{ {
$this->visitor = new Visitor\RecordingVisitor(); $this->visitor = new RecordingVisitor();
} }
public function provideRoles() public function provideRoles()
{ {
return [ return [
[new Visitor\User('Dominik')], [new User('Dominik')],
[new Visitor\Group('Administrators')], [new Group('Administrators')],
]; ];
} }
/** /**
* @dataProvider provideRoles * @dataProvider provideRoles
*
* @param Visitor\Role $role
*/ */
public function testVisitSomeRole(Visitor\Role $role) public function testVisitSomeRole(Role $role)
{ {
$role->accept($this->visitor); $role->accept($this->visitor);
$this->assertSame($role, $this->visitor->getVisited()[0]); $this->assertSame($role, $this->visitor->getVisited()[0]);

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Visitor;
class User implements Role class User implements Role
{ {
/** private string $name;
* @var string
*/
private $name;
public function __construct(string $name) public function __construct(string $name)
{ {

View File

@@ -2,38 +2,39 @@
namespace DesignPatterns\Creational\Builder; namespace DesignPatterns\Creational\Builder;
use DesignPatterns\Creational\Builder\Parts\Door;
use DesignPatterns\Creational\Builder\Parts\Engine;
use DesignPatterns\Creational\Builder\Parts\Wheel;
use DesignPatterns\Creational\Builder\Parts\Car;
use DesignPatterns\Creational\Builder\Parts\Vehicle; use DesignPatterns\Creational\Builder\Parts\Vehicle;
class CarBuilder implements Builder class CarBuilder implements Builder
{ {
/** private Car $car;
* @var Parts\Car
*/
private $car;
public function addDoors() public function addDoors()
{ {
$this->car->setPart('rightDoor', new Parts\Door()); $this->car->setPart('rightDoor', new Door());
$this->car->setPart('leftDoor', new Parts\Door()); $this->car->setPart('leftDoor', new Door());
$this->car->setPart('trunkLid', new Parts\Door()); $this->car->setPart('trunkLid', new Door());
} }
public function addEngine() public function addEngine()
{ {
$this->car->setPart('engine', new Parts\Engine()); $this->car->setPart('engine', new Engine());
} }
public function addWheel() public function addWheel()
{ {
$this->car->setPart('wheelLF', new Parts\Wheel()); $this->car->setPart('wheelLF', new Wheel());
$this->car->setPart('wheelRF', new Parts\Wheel()); $this->car->setPart('wheelRF', new Wheel());
$this->car->setPart('wheelLR', new Parts\Wheel()); $this->car->setPart('wheelLR', new Wheel());
$this->car->setPart('wheelRR', new Parts\Wheel()); $this->car->setPart('wheelRR', new Wheel());
} }
public function createVehicle() public function createVehicle()
{ {
$this->car = new Parts\Car(); $this->car = new Car();
} }
public function getVehicle(): Vehicle public function getVehicle(): Vehicle

View File

@@ -7,13 +7,9 @@ abstract class Vehicle
/** /**
* @var object[] * @var object[]
*/ */
private $data = []; private array $data = [];
/** public function setPart(string $key, object $value)
* @param string $key
* @param object $value
*/
public function setPart($key, $value)
{ {
$this->data[$key] = $value; $this->data[$key] = $value;
} }

View File

@@ -2,39 +2,40 @@
namespace DesignPatterns\Creational\Builder; namespace DesignPatterns\Creational\Builder;
use DesignPatterns\Creational\Builder\Parts\Door;
use DesignPatterns\Creational\Builder\Parts\Engine;
use DesignPatterns\Creational\Builder\Parts\Wheel;
use DesignPatterns\Creational\Builder\Parts\Truck;
use DesignPatterns\Creational\Builder\Parts\Vehicle; use DesignPatterns\Creational\Builder\Parts\Vehicle;
class TruckBuilder implements Builder class TruckBuilder implements Builder
{ {
/** private Truck $truck;
* @var Parts\Truck
*/
private $truck;
public function addDoors() public function addDoors()
{ {
$this->truck->setPart('rightDoor', new Parts\Door()); $this->truck->setPart('rightDoor', new Door());
$this->truck->setPart('leftDoor', new Parts\Door()); $this->truck->setPart('leftDoor', new Door());
} }
public function addEngine() public function addEngine()
{ {
$this->truck->setPart('truckEngine', new Parts\Engine()); $this->truck->setPart('truckEngine', new Engine());
} }
public function addWheel() public function addWheel()
{ {
$this->truck->setPart('wheel1', new Parts\Wheel()); $this->truck->setPart('wheel1', new Wheel());
$this->truck->setPart('wheel2', new Parts\Wheel()); $this->truck->setPart('wheel2', new Wheel());
$this->truck->setPart('wheel3', new Parts\Wheel()); $this->truck->setPart('wheel3', new Wheel());
$this->truck->setPart('wheel4', new Parts\Wheel()); $this->truck->setPart('wheel4', new Wheel());
$this->truck->setPart('wheel5', new Parts\Wheel()); $this->truck->setPart('wheel5', new Wheel());
$this->truck->setPart('wheel6', new Parts\Wheel()); $this->truck->setPart('wheel6', new Wheel());
} }
public function createVehicle() public function createVehicle()
{ {
$this->truck = new Parts\Truck(); $this->truck = new Truck();
} }
public function getVehicle(): Vehicle public function getVehicle(): Vehicle

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\FactoryMethod;
class FileLogger implements Logger class FileLogger implements Logger
{ {
/** private string $filePath;
* @var string
*/
private $filePath;
public function __construct(string $filePath) public function __construct(string $filePath)
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\FactoryMethod;
class FileLoggerFactory implements LoggerFactory class FileLoggerFactory implements LoggerFactory
{ {
/** private string $filePath;
* @var string
*/
private $filePath;
public function __construct(string $filePath) public function __construct(string $filePath)
{ {

View File

@@ -10,7 +10,7 @@ final class Multiton
/** /**
* @var Multiton[] * @var Multiton[]
*/ */
private static $instances = []; private static array $instances = [];
/** /**
* this is private to prevent from creating arbitrary instances * this is private to prevent from creating arbitrary instances

View File

@@ -2,16 +2,15 @@
namespace DesignPatterns\Creational\Pool; namespace DesignPatterns\Creational\Pool;
use DateTime;
class StringReverseWorker class StringReverseWorker
{ {
/** private DateTime $createdAt;
* @var \DateTime
*/
private $createdAt;
public function __construct() public function __construct()
{ {
$this->createdAt = new \DateTime(); $this->createdAt = new DateTime();
} }
public function run(string $text) public function run(string $text)

View File

@@ -2,17 +2,19 @@
namespace DesignPatterns\Creational\Pool; namespace DesignPatterns\Creational\Pool;
class WorkerPool implements \Countable use Countable;
class WorkerPool implements Countable
{ {
/** /**
* @var StringReverseWorker[] * @var StringReverseWorker[]
*/ */
private $occupiedWorkers = []; private array $occupiedWorkers = [];
/** /**
* @var StringReverseWorker[] * @var StringReverseWorker[]
*/ */
private $freeWorkers = []; private array $freeWorkers = [];
public function get(): StringReverseWorker public function get(): StringReverseWorker
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Prototype;
class BarBookPrototype extends BookPrototype class BarBookPrototype extends BookPrototype
{ {
/** protected string $category = 'Bar';
* @var string
*/
protected $category = 'Bar';
public function __clone() public function __clone()
{ {

View File

@@ -4,15 +4,8 @@ namespace DesignPatterns\Creational\Prototype;
abstract class BookPrototype abstract class BookPrototype
{ {
/** protected string $title;
* @var string protected string $category;
*/
protected $title;
/**
* @var string
*/
protected $category;
abstract public function __clone(); abstract public function __clone();
@@ -21,7 +14,7 @@ abstract class BookPrototype
return $this->title; return $this->title;
} }
public function setTitle($title) public function setTitle(string $title)
{ {
$this->title = $title; $this->title = $title;
} }

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Prototype;
class FooBookPrototype extends BookPrototype class FooBookPrototype extends BookPrototype
{ {
/** protected string $category = 'Foo';
* @var string
*/
protected $category = 'Foo';
public function __clone() public function __clone()
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Singleton;
final class Singleton final class Singleton
{ {
/** private static ?Singleton $instance = null;
* @var Singleton
*/
private static $instance;
/** /**
* gets the instance via lazy initialization (created on first usage) * gets the instance via lazy initialization (created on first usage)

View File

@@ -2,17 +2,14 @@
namespace DesignPatterns\Creational\StaticFactory; namespace DesignPatterns\Creational\StaticFactory;
use InvalidArgumentException;
/** /**
* Note1: Remember, static means global state which is evil because it can't be mocked for tests * Note1: Remember, static means global state which is evil because it can't be mocked for tests
* Note2: Cannot be subclassed or mock-upped or have multiple different instances. * Note2: Cannot be subclassed or mock-upped or have multiple different instances.
*/ */
final class StaticFactory final class StaticFactory
{ {
/**
* @param string $type
*
* @return Formatter
*/
public static function factory(string $type): Formatter public static function factory(string $type): Formatter
{ {
if ($type == 'number') { if ($type == 'number') {
@@ -21,6 +18,6 @@ final class StaticFactory
return new FormatString(); return new FormatString();
} }
throw new \InvalidArgumentException('Unknown format given'); throw new InvalidArgumentException('Unknown format given');
} }
} }

View File

@@ -2,6 +2,7 @@
namespace DesignPatterns\Creational\StaticFactory\Tests; namespace DesignPatterns\Creational\StaticFactory\Tests;
use InvalidArgumentException;
use DesignPatterns\Creational\StaticFactory\FormatNumber; use DesignPatterns\Creational\StaticFactory\FormatNumber;
use DesignPatterns\Creational\StaticFactory\FormatString; use DesignPatterns\Creational\StaticFactory\FormatString;
use DesignPatterns\Creational\StaticFactory\StaticFactory; use DesignPatterns\Creational\StaticFactory\StaticFactory;
@@ -21,7 +22,7 @@ class StaticFactoryTest extends TestCase
public function testException() public function testException()
{ {
$this->expectException(\InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
StaticFactory::factory('object'); StaticFactory::factory('object');
} }

View File

@@ -2,21 +2,16 @@
namespace DesignPatterns\More\EAV; namespace DesignPatterns\More\EAV;
use SplObjectStorage;
class Attribute class Attribute
{ {
/** private SplObjectStorage $values;
* @var \SplObjectStorage private string $name;
*/
private $values;
/**
* @var string
*/
private $name;
public function __construct(string $name) public function __construct(string $name)
{ {
$this->values = new \SplObjectStorage(); $this->values = new SplObjectStorage();
$this->name = $name; $this->name = $name;
} }
@@ -25,10 +20,7 @@ class Attribute
$this->values->attach($value); $this->values->attach($value);
} }
/** public function getValues(): SplObjectStorage
* @return \SplObjectStorage
*/
public function getValues(): \SplObjectStorage
{ {
return $this->values; return $this->values;
} }

View File

@@ -14,7 +14,7 @@ class Entity
/** /**
* @var string * @var string
*/ */
private $name; private string $name;
/** /**
* @param string $name * @param string $name
@@ -22,6 +22,7 @@ class Entity
*/ */
public function __construct(string $name, $values) public function __construct(string $name, $values)
{ {
/** @var SplObjectStorage<Value,Value> values */
$this->values = new SplObjectStorage(); $this->values = new SplObjectStorage();
$this->name = $name; $this->name = $name;

View File

@@ -4,15 +4,8 @@ namespace DesignPatterns\More\EAV;
class Value class Value
{ {
/** private Attribute $attribute;
* @var Attribute private string $name;
*/
private $attribute;
/**
* @var string
*/
private $name;
public function __construct(Attribute $attribute, string $name) public function __construct(Attribute $attribute, string $name)
{ {

View File

@@ -4,25 +4,10 @@ namespace DesignPatterns\More\Repository\Domain;
class Post class Post
{ {
/** private PostId $id;
* @var PostId private PostStatus $status;
*/ private string $title;
private $id; private string $text;
/**
* @var PostStatus
*/
private $status;
/**
* @var string
*/
private $title;
/**
* @var string
*/
private $text;
public static function draft(PostId $id, string $title, string $text): Post public static function draft(PostId $id, string $title, string $text): Post
{ {
@@ -44,12 +29,6 @@ class Post
); );
} }
/**
* @param PostId $id
* @param PostStatus $status
* @param string $title
* @param string $text
*/
private function __construct(PostId $id, PostStatus $status, string $title, string $text) private function __construct(PostId $id, PostStatus $status, string $title, string $text)
{ {
$this->id = $id; $this->id = $id;

View File

@@ -2,6 +2,8 @@
namespace DesignPatterns\More\Repository\Domain; namespace DesignPatterns\More\Repository\Domain;
use InvalidArgumentException;
/** /**
* This is a perfect example of a value object that is identifiable by it's value alone and * This is a perfect example of a value object that is identifiable by it's value alone and
* is guaranteed to be valid each time an instance is created. Another important property of value objects * is guaranteed to be valid each time an instance is created. Another important property of value objects
@@ -11,12 +13,9 @@ namespace DesignPatterns\More\Repository\Domain;
*/ */
class PostId class PostId
{ {
/** private int $id;
* @var int
*/
private $id;
public static function fromInt(int $id) public static function fromInt(int $id): PostId
{ {
self::ensureIsValid($id); self::ensureIsValid($id);
@@ -36,7 +35,7 @@ class PostId
private static function ensureIsValid(int $id) private static function ensureIsValid(int $id)
{ {
if ($id <= 0) { if ($id <= 0) {
throw new \InvalidArgumentException('Invalid PostId given'); throw new InvalidArgumentException('Invalid PostId given');
} }
} }
} }

View File

@@ -2,6 +2,8 @@
namespace DesignPatterns\More\Repository\Domain; namespace DesignPatterns\More\Repository\Domain;
use InvalidArgumentException;
/** /**
* Like PostId, this is a value object which holds the value of the current status of a Post. It can be constructed * Like PostId, this is a value object which holds the value of the current status of a Post. It can be constructed
* either from a string or int and is able to validate itself. An instance can then be converted back to int or string. * either from a string or int and is able to validate itself. An instance can then be converted back to int or string.
@@ -14,20 +16,13 @@ class PostStatus
const STATE_DRAFT = 'draft'; const STATE_DRAFT = 'draft';
const STATE_PUBLISHED = 'published'; const STATE_PUBLISHED = 'published';
private static $validStates = [ private static array $validStates = [
self::STATE_DRAFT_ID => self::STATE_DRAFT, self::STATE_DRAFT_ID => self::STATE_DRAFT,
self::STATE_PUBLISHED_ID => self::STATE_PUBLISHED, self::STATE_PUBLISHED_ID => self::STATE_PUBLISHED,
]; ];
/** private int $id;
* @var int private string $name;
*/
private $id;
/**
* @var string
*/
private $name;
public static function fromInt(int $statusId) public static function fromInt(int $statusId)
{ {
@@ -39,8 +34,13 @@ class PostStatus
public static function fromString(string $status) public static function fromString(string $status)
{ {
self::ensureIsValidName($status); self::ensureIsValidName($status);
$state = array_search($status, self::$validStates);
return new self(array_search($status, self::$validStates), $status); if ($state === false) {
throw new InvalidArgumentException('Invalid state given!');
}
return new self($state, $status);
} }
private function __construct(int $id, string $name) private function __construct(int $id, string $name)
@@ -66,7 +66,7 @@ class PostStatus
private static function ensureIsValidId(int $status) private static function ensureIsValidId(int $status)
{ {
if (!in_array($status, array_keys(self::$validStates), true)) { if (!in_array($status, array_keys(self::$validStates), true)) {
throw new \InvalidArgumentException('Invalid status id given'); throw new InvalidArgumentException('Invalid status id given');
} }
} }
@@ -74,7 +74,7 @@ class PostStatus
private static function ensureIsValidName(string $status) private static function ensureIsValidName(string $status)
{ {
if (!in_array($status, self::$validStates, true)) { if (!in_array($status, self::$validStates, true)) {
throw new \InvalidArgumentException('Invalid status name given'); throw new InvalidArgumentException('Invalid status name given');
} }
} }
} }

View File

@@ -2,17 +2,12 @@
namespace DesignPatterns\More\Repository; namespace DesignPatterns\More\Repository;
use OutOfBoundsException;
class InMemoryPersistence implements Persistence class InMemoryPersistence implements Persistence
{ {
/** private array $data = [];
* @var array private int $lastId = 0;
*/
private $data = [];
/**
* @var int
*/
private $lastId = 0;
public function generateId(): int public function generateId(): int
{ {
@@ -29,7 +24,7 @@ class InMemoryPersistence implements Persistence
public function retrieve(int $id): array public function retrieve(int $id): array
{ {
if (!isset($this->data[$id])) { if (!isset($this->data[$id])) {
throw new \OutOfBoundsException(sprintf('No data found for ID %d', $id)); throw new OutOfBoundsException(sprintf('No data found for ID %d', $id));
} }
return $this->data[$id]; return $this->data[$id];
@@ -38,7 +33,7 @@ class InMemoryPersistence implements Persistence
public function delete(int $id) public function delete(int $id)
{ {
if (!isset($this->data[$id])) { if (!isset($this->data[$id])) {
throw new \OutOfBoundsException(sprintf('No data found for ID %d', $id)); throw new OutOfBoundsException(sprintf('No data found for ID %d', $id));
} }
unset($this->data[$id]); unset($this->data[$id]);

View File

@@ -2,6 +2,7 @@
namespace DesignPatterns\More\Repository; namespace DesignPatterns\More\Repository;
use OutOfBoundsException;
use DesignPatterns\More\Repository\Domain\Post; use DesignPatterns\More\Repository\Domain\Post;
use DesignPatterns\More\Repository\Domain\PostId; use DesignPatterns\More\Repository\Domain\PostId;
@@ -16,10 +17,7 @@ use DesignPatterns\More\Repository\Domain\PostId;
*/ */
class PostRepository class PostRepository
{ {
/** private Persistence $persistence;
* @var Persistence
*/
private $persistence;
public function __construct(Persistence $persistence) public function __construct(Persistence $persistence)
{ {
@@ -35,8 +33,8 @@ class PostRepository
{ {
try { try {
$arrayData = $this->persistence->retrieve($id->toInt()); $arrayData = $this->persistence->retrieve($id->toInt());
} catch (\OutOfBoundsException $e) { } catch (OutOfBoundsException $e) {
throw new \OutOfBoundsException(sprintf('Post with id %d does not exist', $id->toInt()), 0, $e); throw new OutOfBoundsException(sprintf('Post with id %d does not exist', $id->toInt()), 0, $e);
} }
return Post::fromState($arrayData); return Post::fromState($arrayData);

View File

@@ -2,6 +2,7 @@
namespace DesignPatterns\More\Repository\Tests; namespace DesignPatterns\More\Repository\Tests;
use OutOfBoundsException;
use DesignPatterns\More\Repository\Domain\PostId; use DesignPatterns\More\Repository\Domain\PostId;
use DesignPatterns\More\Repository\Domain\PostStatus; use DesignPatterns\More\Repository\Domain\PostStatus;
use DesignPatterns\More\Repository\InMemoryPersistence; use DesignPatterns\More\Repository\InMemoryPersistence;
@@ -11,10 +12,7 @@ use PHPUnit\Framework\TestCase;
class PostRepositoryTest extends TestCase class PostRepositoryTest extends TestCase
{ {
/** private PostRepository $repository;
* @var PostRepository
*/
private $repository;
protected function setUp(): void protected function setUp(): void
{ {
@@ -28,7 +26,7 @@ class PostRepositoryTest extends TestCase
public function testThrowsExceptionWhenTryingToFindPostWhichDoesNotExist() public function testThrowsExceptionWhenTryingToFindPostWhichDoesNotExist()
{ {
$this->expectException(\OutOfBoundsException::class); $this->expectException(OutOfBoundsException::class);
$this->expectExceptionMessage('Post with id 42 does not exist'); $this->expectExceptionMessage('Post with id 42 does not exist');
$this->repository->findById(PostId::fromInt(42)); $this->repository->findById(PostId::fromInt(42));

View File

@@ -2,17 +2,20 @@
namespace DesignPatterns\More\ServiceLocator; namespace DesignPatterns\More\ServiceLocator;
use OutOfRangeException;
use InvalidArgumentException;
class ServiceLocator class ServiceLocator
{ {
/** /**
* @var string[][] * @var string[][]
*/ */
private $services = []; private array $services = [];
/** /**
* @var Service[] * @var Service[]
*/ */
private $instantiated = []; private array $instantiated = [];
public function addInstance(string $class, Service $service) public function addInstance(string $class, Service $service)
{ {
@@ -51,11 +54,11 @@ class ServiceLocator
$object = new $class($args[0], $args[1], $args[2]); $object = new $class($args[0], $args[1], $args[2]);
break; break;
default: default:
throw new \OutOfRangeException('Too many arguments given'); throw new OutOfRangeException('Too many arguments given');
} }
if (!$object instanceof Service) { if (!$object instanceof Service) {
throw new \InvalidArgumentException('Could not register service: is no instance of Service'); throw new InvalidArgumentException('Could not register service: is no instance of Service');
} }
$this->instantiated[$class] = $object; $this->instantiated[$class] = $object;

View File

@@ -8,10 +8,7 @@ use PHPUnit\Framework\TestCase;
class ServiceLocatorTest extends TestCase class ServiceLocatorTest extends TestCase
{ {
/** private ServiceLocator $serviceLocator;
* @var ServiceLocator
*/
private $serviceLocator;
public function setUp(): void public function setUp(): void
{ {

View File

@@ -8,14 +8,8 @@ namespace DesignPatterns\Structural\Adapter;
*/ */
class EBookAdapter implements Book class EBookAdapter implements Book
{ {
/** protected EBook $eBook;
* @var EBook
*/
protected $eBook;
/**
* @param EBook $eBook
*/
public function __construct(EBook $eBook) public function __construct(EBook $eBook)
{ {
$this->eBook = $eBook; $this->eBook = $eBook;
@@ -37,8 +31,6 @@ class EBookAdapter implements Book
/** /**
* notice the adapted behavior here: EBook::getPage() will return two integers, but Book * notice the adapted behavior here: EBook::getPage() will return two integers, but Book
* supports only a current page getter, so we adapt the behavior here * supports only a current page getter, so we adapt the behavior here
*
* @return int
*/ */
public function getPage(): int public function getPage(): int
{ {

View File

@@ -8,15 +8,8 @@ namespace DesignPatterns\Structural\Adapter;
*/ */
class Kindle implements EBook class Kindle implements EBook
{ {
/** private int $page = 1;
* @var int private int $totalPages = 100;
*/
private $page = 1;
/**
* @var int
*/
private $totalPages = 100;
public function pressNext() public function pressNext()
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Adapter;
class PaperBook implements Book class PaperBook implements Book
{ {
/** private int $page;
* @var int
*/
private $page;
public function open() public function open()
{ {

View File

@@ -4,22 +4,13 @@ namespace DesignPatterns\Structural\Bridge;
abstract class Service abstract class Service
{ {
/** protected Formatter $implementation;
* @var Formatter
*/
protected $implementation;
/**
* @param Formatter $printer
*/
public function __construct(Formatter $printer) public function __construct(Formatter $printer)
{ {
$this->implementation = $printer; $this->implementation = $printer;
} }
/**
* @param Formatter $printer
*/
public function setImplementation(Formatter $printer) public function setImplementation(Formatter $printer)
{ {
$this->implementation = $printer; $this->implementation = $printer;

View File

@@ -11,15 +11,13 @@ class Form implements Renderable
/** /**
* @var Renderable[] * @var Renderable[]
*/ */
private $elements; private array $elements;
/** /**
* runs through all elements and calls render() on them, then returns the complete representation * runs through all elements and calls render() on them, then returns the complete representation
* of the form. * of the form.
* *
* from the outside, one will not see this and the form will act like a single object instance * from the outside, one will not see this and the form will act like a single object instance
*
* @return string
*/ */
public function render(): string public function render(): string
{ {
@@ -34,9 +32,6 @@ class Form implements Renderable
return $formCode; return $formCode;
} }
/**
* @param Renderable $element
*/
public function addElement(Renderable $element) public function addElement(Renderable $element)
{ {
$this->elements[] = $element; $this->elements[] = $element;

View File

@@ -2,19 +2,21 @@
namespace DesignPatterns\Structural\Composite\Tests; namespace DesignPatterns\Structural\Composite\Tests;
use DesignPatterns\Structural\Composite; use DesignPatterns\Structural\Composite\Form;
use DesignPatterns\Structural\Composite\TextElement;
use DesignPatterns\Structural\Composite\InputElement;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class CompositeTest extends TestCase class CompositeTest extends TestCase
{ {
public function testRender() public function testRender()
{ {
$form = new Composite\Form(); $form = new Form();
$form->addElement(new Composite\TextElement('Email:')); $form->addElement(new TextElement('Email:'));
$form->addElement(new Composite\InputElement()); $form->addElement(new InputElement());
$embed = new Composite\Form(); $embed = new Form();
$embed->addElement(new Composite\TextElement('Password:')); $embed->addElement(new TextElement('Password:'));
$embed->addElement(new Composite\InputElement()); $embed->addElement(new InputElement());
$form->addElement($embed); $form->addElement($embed);
// This is just an example, in a real world scenario it is important to remember that web browsers do not // This is just an example, in a real world scenario it is important to remember that web browsers do not

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Composite;
class TextElement implements Renderable class TextElement implements Renderable
{ {
/** private string $text;
* @var string
*/
private $text;
public function __construct(string $text) public function __construct(string $text)
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\DataMapper;
class StorageAdapter class StorageAdapter
{ {
/** private array $data = [];
* @var array
*/
private $data = [];
public function __construct(array $data) public function __construct(array $data)
{ {

View File

@@ -2,6 +2,7 @@
namespace DesignPatterns\Structural\DataMapper\Tests; namespace DesignPatterns\Structural\DataMapper\Tests;
use InvalidArgumentException;
use DesignPatterns\Structural\DataMapper\StorageAdapter; use DesignPatterns\Structural\DataMapper\StorageAdapter;
use DesignPatterns\Structural\DataMapper\User; use DesignPatterns\Structural\DataMapper\User;
use DesignPatterns\Structural\DataMapper\UserMapper; use DesignPatterns\Structural\DataMapper\UserMapper;
@@ -21,7 +22,7 @@ class DataMapperTest extends TestCase
public function testWillNotMapInvalidData() public function testWillNotMapInvalidData()
{ {
$this->expectException(\InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
$storage = new StorageAdapter([]); $storage = new StorageAdapter([]);
$mapper = new UserMapper($storage); $mapper = new UserMapper($storage);

View File

@@ -4,15 +4,8 @@ namespace DesignPatterns\Structural\DataMapper;
class User class User
{ {
/** private string $username;
* @var string private string $email;
*/
private $username;
/**
* @var string
*/
private $email;
public static function fromState(array $state): User public static function fromState(array $state): User
{ {
@@ -32,18 +25,12 @@ class User
$this->email = $email; $this->email = $email;
} }
/** public function getUsername(): string
* @return string
*/
public function getUsername()
{ {
return $this->username; return $this->username;
} }
/** public function getEmail(): string
* @return string
*/
public function getEmail()
{ {
return $this->email; return $this->email;
} }

View File

@@ -2,16 +2,12 @@
namespace DesignPatterns\Structural\DataMapper; namespace DesignPatterns\Structural\DataMapper;
use InvalidArgumentException;
class UserMapper class UserMapper
{ {
/** private StorageAdapter $adapter;
* @var StorageAdapter
*/
private $adapter;
/**
* @param StorageAdapter $storage
*/
public function __construct(StorageAdapter $storage) public function __construct(StorageAdapter $storage)
{ {
$this->adapter = $storage; $this->adapter = $storage;
@@ -22,17 +18,13 @@ class UserMapper
* in memory. Normally this kind of logic will be implemented using the Repository pattern. * in memory. Normally this kind of logic will be implemented using the Repository pattern.
* However the important part is in mapRowToUser() below, that will create a business object from the * However the important part is in mapRowToUser() below, that will create a business object from the
* data fetched from storage * data fetched from storage
*
* @param int $id
*
* @return User
*/ */
public function findById(int $id): User public function findById(int $id): User
{ {
$result = $this->adapter->find($id); $result = $this->adapter->find($id);
if ($result === null) { if ($result === null) {
throw new \InvalidArgumentException("User #$id not found"); throw new InvalidArgumentException("User #$id not found");
} }
return $this->mapRowToUser($result); return $this->mapRowToUser($result);

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Decorator;
abstract class BookingDecorator implements Booking abstract class BookingDecorator implements Booking
{ {
/** protected Booking $booking;
* @var Booking
*/
protected $booking;
public function __construct(Booking $booking) public function __construct(Booking $booking)
{ {

View File

@@ -4,25 +4,10 @@ namespace DesignPatterns\Structural\DependencyInjection;
class DatabaseConfiguration class DatabaseConfiguration
{ {
/** private string $host;
* @var string private int $port;
*/ private string $username;
private $host; private string $password;
/**
* @var int
*/
private $port;
/**
* @var string
*/
private $username;
/**
* @var string
*/
private $password;
public function __construct(string $host, int $port, string $username, string $password) public function __construct(string $host, int $port, string $username, string $password)
{ {

View File

@@ -4,14 +4,8 @@ namespace DesignPatterns\Structural\DependencyInjection;
class DatabaseConnection class DatabaseConnection
{ {
/** private DatabaseConfiguration $configuration;
* @var DatabaseConfiguration
*/
private $configuration;
/**
* @param DatabaseConfiguration $config
*/
public function __construct(DatabaseConfiguration $config) public function __construct(DatabaseConfiguration $config)
{ {
$this->configuration = $config; $this->configuration = $config;

View File

@@ -4,20 +4,9 @@ namespace DesignPatterns\Structural\Facade;
class Facade class Facade
{ {
/** private OperatingSystem $os;
* @var OperatingSystem private Bios $bios;
*/
private $os;
/**
* @var Bios
*/
private $bios;
/**
* @param Bios $bios
* @param OperatingSystem $os
*/
public function __construct(Bios $bios, OperatingSystem $os) public function __construct(Bios $bios, OperatingSystem $os)
{ {
$this->bios = $bios; $this->bios = $bios;

View File

@@ -4,20 +4,9 @@ namespace DesignPatterns\Structural\FluentInterface;
class Sql class Sql
{ {
/** private array $fields = [];
* @var array private array $from = [];
*/ private array $where = [];
private $fields = [];
/**
* @var array
*/
private $from = [];
/**
* @var array
*/
private $where = [];
public function select(array $fields): Sql public function select(array $fields): Sql
{ {

View File

@@ -11,10 +11,8 @@ class Character implements Text
/** /**
* Any state stored by the concrete flyweight must be independent of its context. * Any state stored by the concrete flyweight must be independent of its context.
* For flyweights representing characters, this is usually the corresponding character code. * For flyweights representing characters, this is usually the corresponding character code.
*
* @var string
*/ */
private $name; private string $name;
public function __construct(string $name) public function __construct(string $name)
{ {

View File

@@ -7,9 +7,10 @@ use PHPUnit\Framework\TestCase;
class FlyweightTest extends TestCase class FlyweightTest extends TestCase
{ {
private $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', private array $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
private $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica'];
private array $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica'];
public function testFlyweight() public function testFlyweight()
{ {

View File

@@ -2,16 +2,18 @@
namespace DesignPatterns\Structural\Flyweight; namespace DesignPatterns\Structural\Flyweight;
use Countable;
/** /**
* A factory manages shared flyweights. Clients should not instantiate them directly, * A factory manages shared flyweights. Clients should not instantiate them directly,
* but let the factory take care of returning existing objects or creating new ones. * but let the factory take care of returning existing objects or creating new ones.
*/ */
class TextFactory implements \Countable class TextFactory implements Countable
{ {
/** /**
* @var Text[] * @var Text[]
*/ */
private $charPool = []; private array $charPool = [];
public function get(string $name): Text public function get(string $name): Text
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Flyweight;
class Word implements Text class Word implements Text
{ {
/** private string $name;
* @var string
*/
private $name;
public function __construct(string $name) public function __construct(string $name)
{ {

View File

@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Proxy;
class BankAccountProxy extends HeavyBankAccount implements BankAccount class BankAccountProxy extends HeavyBankAccount implements BankAccount
{ {
/** private ?int $balance = null;
* @var int
*/
private $balance;
public function getBalance(): int public function getBalance(): int
{ {

View File

@@ -7,7 +7,7 @@ class HeavyBankAccount implements BankAccount
/** /**
* @var int[] * @var int[]
*/ */
private $transactions = []; private array $transactions = [];
public function deposit(int $amount) public function deposit(int $amount)
{ {

View File

@@ -2,6 +2,8 @@
namespace DesignPatterns\Structural\Registry; namespace DesignPatterns\Structural\Registry;
use InvalidArgumentException;
abstract class Registry abstract class Registry
{ {
const LOGGER = 'logger'; const LOGGER = 'logger';
@@ -12,19 +14,16 @@ abstract class Registry
* *
* @var Service[] * @var Service[]
*/ */
private static $services = []; private static array $services = [];
/** private static array $allowedKeys = [
* @var array
*/
private static $allowedKeys = [
self::LOGGER, self::LOGGER,
]; ];
public static function set(string $key, Service $value) public static function set(string $key, Service $value)
{ {
if (!in_array($key, self::$allowedKeys)) { if (!in_array($key, self::$allowedKeys)) {
throw new \InvalidArgumentException('Invalid key given'); throw new InvalidArgumentException('Invalid key given');
} }
self::$services[$key] = $value; self::$services[$key] = $value;
@@ -33,7 +32,7 @@ abstract class Registry
public static function get(string $key): Service public static function get(string $key): Service
{ {
if (!in_array($key, self::$allowedKeys) || !isset(self::$services[$key])) { if (!in_array($key, self::$allowedKeys) || !isset(self::$services[$key])) {
throw new \InvalidArgumentException('Invalid key given'); throw new InvalidArgumentException('Invalid key given');
} }
return self::$services[$key]; return self::$services[$key];

View File

@@ -2,6 +2,7 @@
namespace DesignPatterns\Structural\Registry\Tests; namespace DesignPatterns\Structural\Registry\Tests;
use InvalidArgumentException;
use DesignPatterns\Structural\Registry\Registry; use DesignPatterns\Structural\Registry\Registry;
use DesignPatterns\Structural\Registry\Service; use DesignPatterns\Structural\Registry\Service;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
@@ -9,7 +10,10 @@ use PHPUnit\Framework\TestCase;
class RegistryTest extends TestCase class RegistryTest extends TestCase
{ {
private $service; /**
* @var Service
*/
private MockObject $service;
protected function setUp(): void protected function setUp(): void
{ {
@@ -18,7 +22,6 @@ class RegistryTest extends TestCase
public function testSetAndGetLogger() public function testSetAndGetLogger()
{ {
/** @noinspection PhpParamsInspection */
Registry::set(Registry::LOGGER, $this->service); Registry::set(Registry::LOGGER, $this->service);
$this->assertSame($this->service, Registry::get(Registry::LOGGER)); $this->assertSame($this->service, Registry::get(Registry::LOGGER));
@@ -26,7 +29,7 @@ class RegistryTest extends TestCase
public function testThrowsExceptionWhenTryingToSetInvalidKey() public function testThrowsExceptionWhenTryingToSetInvalidKey()
{ {
$this->expectException(\InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
Registry::set('foobar', $this->service); Registry::set('foobar', $this->service);
} }
@@ -40,7 +43,7 @@ class RegistryTest extends TestCase
*/ */
public function testThrowsExceptionWhenTryingToGetNotSetKey() public function testThrowsExceptionWhenTryingToGetNotSetKey()
{ {
$this->expectException(\InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
Registry::get(Registry::LOGGER); Registry::get(Registry::LOGGER);
} }

View File

@@ -1,6 +1,7 @@
{ {
"name": "domnikl/design-patterns-php", "name": "domnikl/design-patterns-php",
"description": "Sample code for several design patterns in PHP", "description": "Sample code for several design patterns in PHP",
"license": ["MIT"],
"authors": [ "authors": [
{ {
"name": "Dominik Liebler", "name": "Dominik Liebler",
@@ -9,7 +10,7 @@
], ],
"minimum-stability": "stable", "minimum-stability": "stable",
"require": { "require": {
"php": ">=7.2", "php": ">=7.4",
"psr/http-message": "^1.0", "psr/http-message": "^1.0",
"ext-json": "*" "ext-json": "*"
}, },
@@ -18,11 +19,10 @@
"squizlabs/php_codesniffer": "^3", "squizlabs/php_codesniffer": "^3",
"flyeralarm/php-code-validator": "^2.2", "flyeralarm/php-code-validator": "^2.2",
"vimeo/psalm": "^3.4", "vimeo/psalm": "^3.4",
"psalm/plugin-phpunit": "^0.7.0" "psalm/plugin-phpunit": "^0.7.0",
"rector/rector": "^0.6.1"
}, },
"autoload": { "autoload": {
"psr-4": { "classmap": ["Behavioral", "Creational", "Structural", "More"]
"DesignPatterns\\": ""
}
} }
} }

2388
composer.lock generated

File diff suppressed because it is too large Load Diff