src/Generators/RandomWords.php
<?php
namespace GregorJ\CorrectHorse\Generators;
use Exception;
use GregorJ\CorrectHorse\RandomGeneratorInterface;
use function array_merge;
use function random_int;
use function shuffle;
/**
* Class RandomWords
* Generate random upper and lower case words.
*/
final class RandomWords implements RandomGeneratorInterface
{
/**
* @var RandomGeneratorInterface
*/
private $lowerCase;
/**
* @var RandomGeneratorInterface
*/
private $upperCase;
/**
* Initialize the generator with an upper case word dictionary and a lower case word dictionary.
* @param RandomWord $lowerCase
* @param RandomWord $upperCase
*/
public function __construct(RandomGeneratorInterface $lowerCase, RandomGeneratorInterface $upperCase)
{
$this->upperCase = $upperCase;
$this->lowerCase = $lowerCase;
}
/**
* Add a randomly generated item.
* @return void
* @throws Exception
*/
public function add(): void
{
if (random_int(0, 1) === 0) {
$this->lowerCase->add();
} else {
$this->upperCase->add();
}
}
/**
* Clear all generated items.
* @return void
*/
public function reset(): void
{
$this->upperCase->reset();
$this->lowerCase->reset();
}
/**
* Remove a random generated item.
* @return void
* @throws Exception
*/
public function remove(): void
{
if (!$this->upperCase->has() && $this->lowerCase->has()) {
$this->lowerCase->remove();
} elseif (!$this->lowerCase->has() && $this->upperCase->has()) {
$this->upperCase->remove();
} elseif ($this->upperCase->has() && $this->lowerCase->has()) {
if (random_int(0, 1) === 0) {
$this->lowerCase->remove();
} else {
$this->upperCase->remove();
}
}
}
/**
* Are there any randomly generated items?
* @return bool
*/
public function has(): bool
{
return $this->lowerCase->has() || $this->upperCase->has();
}
/**
* Get all randomly generated items in random order.
* @return array
* @throws Exception
*/
public function get(): array
{
/**
* Quit early in case there are no words.
*/
if (!$this->upperCase->has() && !$this->lowerCase->has()) {
return [];
}
/**
* Ensure that at least one upper case and one lower case word is present.
*/
if (!$this->upperCase->has() && count($this->lowerCase->get()) > 1) {
$this->lowerCase->remove();
$this->upperCase->add();
}
if (!$this->lowerCase->has() && count($this->upperCase->get()) > 1) {
$this->upperCase->remove();
$this->lowerCase->add();
}
$words = array_merge(
$this->upperCase->get(),
$this->lowerCase->get()
);
shuffle($words);
return $words;
}
}