- print_r: documentation ( source)
- sprintf: documentation ( source)
<?php
interface ICupboard {
public function getNextCup(): Cup;
public function haveCups(): bool;
}
class InfiniteCupBoard implements ICupboard {
public function getNextCup(): Cup {
return Cup::createEmpty();
}
public function haveCups(): bool {
return true;
}
}
interface ITap {
public function getWater(): Liquid;
}
class InfiniteTap implements ITap {
private int $waterVolumePerReuqest;
public function __construct(int $waterVolumePerReuqest) {
$this->waterVolumePerReuqest = $waterVolumePerReuqest;
}
public function getWater(): Liquid {
return Liquid::createVolume($this->waterVolumePerReuqest);
}
}
class Cup {
private Liquid $liquid;
private int $volume;
private function __construct(Liquid $liquid, int $volume = 300) {
$this->liquid = $liquid;
$this->volume = $volume;
}
public static function createEmpty(): self {
return new self(Liquid::createEmpty());
}
public function fill(Liquid $liquid): void {
if (false === $this->canAddLiquid($liquid)) {
throw new DomainException(
sprintf(
'Cannot hold liquid volume. Expected volume: %s. Current volume: %s. Provided volume: %s.',
$this->volume,
$this->liquid->getVolume(),
$liquid->getVolume()
)
);
}
$this->liquid = $this->liquid->add($liquid);
}
public function canAddLiquid(Liquid $liquid): bool {
return $this->volume >= $this->liquid->getVolume() + $liquid->getVolume();
}
}
class Liquid {
private int $volume;
private function __construct(int $volume) {
$this->volume = $volume;
}
public static function createEmpty(): self {
return new self(0);
}
public static function createVolume(int $volume): self {
return new self($volume);
}
public function add(Liquid $liquid): self {
return new self($this->volume + $liquid->volume);
}
public function getVolume(): int {
return $this->volume;
}
}
class FillCupsWithWater {
private ITap $tap;
private ICupboard $cupboard;
public function __construct(ITap $tap, ICupboard $cupboard) {
$this->tap = $tap;
$this->cupboard = $cupboard;
}
public function __invoke(int $cupsToFillCount): array {
$filledCups = [];
while($this->cupboard->haveCups() && $cupsToFillCount) {
$cup = $this->cupboard->getNextCup();
$water = $this->tap->getWater();
while($cup->canAddLiquid($water)) {
$cup->fill($water);
}
$filledCups[] = $cup;
$cupsToFillCount--;
}
return $filledCups;
}
}
$fillCupsWithWater = new FillCupsWithWater(new InfiniteTap(14), new InfiniteCupBoard);
print_r($fillCupsWithWater(4));