Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added character generator/group abstraction
Signed-off-by: Rob Frawley 2nd <rmf@src.run>
- Loading branch information
1 parent
03fdac0
commit 8022208
Showing
4 changed files
with
863 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the `src-run/web-app-v1` project. | ||
* | ||
* (c) Rob Frawley 2nd <rmf@src.run> | ||
* | ||
* For the full copyright and license information, please view the LICENSE.md | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace SR\Utilities\Characters; | ||
|
||
use SR\Utilities\Characters\Group\CharactersGroup; | ||
|
||
class AsciiCharacters implements \Countable, \IteratorAggregate | ||
{ | ||
use CharactersTrait; | ||
|
||
/** | ||
* @var CharactersGroup[] | ||
*/ | ||
private $sets; | ||
|
||
public function __construct() | ||
{ | ||
$this->bytes = $this->mergedCharactersGroup( | ||
$this->numbers(), $this->letters(), $this->symbols() | ||
)->bytes(); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
public function numbers(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [range(48, 57)]; | ||
}); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
public function letters(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [ | ||
$this->lettersLower()->bytes(), | ||
$this->lettersUpper()->bytes(), | ||
]; | ||
}); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
public function lettersUpper(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [range(65, 90)]; | ||
}); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
public function lettersLower(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [range(97, 122)]; | ||
}); | ||
} | ||
|
||
/** | ||
* @param bool $readable | ||
* | ||
* @return CharactersGroup | ||
*/ | ||
public function symbols(bool $readable = false): CharactersGroup | ||
{ | ||
return $readable ? $this->symbolsSel() : $this->symbolsAll(); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
public function passwords(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [ | ||
$this->numbers()->bytes(), | ||
$this->letters()->bytes(), | ||
$this->symbols(true)->bytes(), | ||
]; | ||
}); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
private function symbolsAll(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [ | ||
range(32, 47), | ||
range(58, 64), | ||
range(91, 96), | ||
range(123, 126), | ||
]; | ||
}); | ||
} | ||
|
||
/** | ||
* @return CharactersGroup | ||
*/ | ||
private function symbolsSel(): CharactersGroup | ||
{ | ||
return $this->cachedCharactersGroup(__FUNCTION__, function (): array { | ||
return [[ | ||
33, // exclamation mark | ||
35, // number sign | ||
36, // dollar sign | ||
37, // percent sign | ||
38, // ampersand | ||
40, // parentheses (opening) | ||
41, // parentheses (closing) | ||
42, // asterisk | ||
43, // plus sign | ||
45, // hyphen-minus | ||
58, // colon | ||
59, // semicolon | ||
61, // equal sign | ||
63, // question mark | ||
64, // at sign | ||
91, // square bracket (opening) | ||
93, // square bracket (closing) | ||
94, // circumflex accent | ||
95, // underscore | ||
123,// curly bracket (opening) | ||
124,// vertical bar | ||
125,// curly bracket (closing) | ||
126 // tilde | ||
]]; | ||
}); | ||
} | ||
|
||
/** | ||
* @param CharactersGroup ...$groups | ||
* | ||
* @return CharactersGroup | ||
*/ | ||
private function mergedCharactersGroup(CharactersGroup ...$groups): CharactersGroup | ||
{ | ||
return $this->createCharacterGroup(...array_map(function (CharactersGroup $set): array { | ||
return $set->bytes(); | ||
}, $groups)); | ||
} | ||
|
||
/** | ||
* @param string $name | ||
* @param \Closure $provider | ||
* | ||
* @return CharactersGroup | ||
*/ | ||
private function cachedCharactersGroup(string $name, \Closure $provider): CharactersGroup | ||
{ | ||
return isset($this->sets[$name]) | ||
? $this->sets[$name] | ||
: $this->sets[$name] = $this->createCharacterGroup(...$provider()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the `src-run/web-app-v1` project. | ||
* | ||
* (c) Rob Frawley 2nd <rmf@src.run> | ||
* | ||
* For the full copyright and license information, please view the LICENSE.md | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace SR\Utilities\Characters; | ||
|
||
use SR\Utilities\Characters\Group\CharactersGroup; | ||
|
||
trait CharactersTrait | ||
{ | ||
/** | ||
* @var int[] | ||
*/ | ||
private $bytes = []; | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function __toString(): string | ||
{ | ||
return self::arrayToString($this->chars()); | ||
} | ||
|
||
/** | ||
* @return int[] | ||
*/ | ||
public function bytes(): array | ||
{ | ||
return $this->bytes; | ||
} | ||
|
||
/** | ||
* @return string[] | ||
*/ | ||
public function chars(): array | ||
{ | ||
return array_map(function (int $byte): string { | ||
return $this->byteToChar($byte); | ||
}, $this->bytes()); | ||
} | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function count(): int | ||
{ | ||
return count($this->bytes); | ||
} | ||
|
||
/** | ||
* @return \ArrayIterator | ||
*/ | ||
public function getIterator(): \ArrayIterator | ||
{ | ||
return new \ArrayIterator( | ||
array_combine($this->bytes(), $this->chars()) | ||
); | ||
} | ||
|
||
/** | ||
* @param int $byte | ||
* | ||
* @return bool | ||
*/ | ||
public function isValidByte(int $byte): bool | ||
{ | ||
return in_array($byte, $this->bytes, true) || ($byte >= 0 && $byte <= 255); | ||
} | ||
|
||
/** | ||
* @param string $char | ||
* | ||
* @return bool | ||
*/ | ||
public function isValidChar(string $char): bool | ||
{ | ||
if (1 !== strlen($char)) { | ||
throw new \InvalidArgumentException(sprintf( | ||
'Provided value "%s" must be a single character (input length of %d provided).', $char, strlen($char) | ||
)); | ||
} | ||
|
||
return $this->isValidByte($this->charToByte($char)); | ||
} | ||
|
||
/** | ||
* @param string $char | ||
* | ||
* @return int|null | ||
*/ | ||
public function charToByte(string $char): ?int | ||
{ | ||
if (1 !== strlen($char)) { | ||
throw new \InvalidArgumentException(sprintf( | ||
'Provided value "%s" must be a single character.', $char | ||
)); | ||
} | ||
|
||
return $this->isValidByte($byte = ord($char)) ? $byte : null; | ||
} | ||
|
||
/** | ||
* @param int $byte | ||
* | ||
* @return string|null | ||
*/ | ||
public function byteToChar(int $byte): ?string | ||
{ | ||
return $this->isValidByte($byte) ? chr($byte) : null; | ||
} | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function randomByte(): int | ||
{ | ||
return $this->bytes[random_int(0, count($this->bytes) - 1)]; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function randomChar(): string | ||
{ | ||
return $this->byteToChar($this->randomByte()); | ||
} | ||
|
||
/** | ||
* @param int $length | ||
* | ||
* @return CharactersGroup | ||
*/ | ||
public function randomGroup(int $length = 12): CharactersGroup | ||
{ | ||
return $this->createCharacterGroup(array_map(function (): int { | ||
return $this->randomByte(); | ||
}, 0 === $length ? [] : range(1, $length))); | ||
} | ||
|
||
/** | ||
* @param int $length | ||
* | ||
* @return string | ||
*/ | ||
public function randomString(int $length = 12): string | ||
{ | ||
return $this->randomGroup($length)->__toString(); | ||
} | ||
|
||
/** | ||
* @param array $array | ||
* | ||
* @return string | ||
*/ | ||
private static function arrayToString(array $array): string | ||
{ | ||
return implode('', $array); | ||
} | ||
|
||
/** | ||
* @param array[] $byteSets | ||
* | ||
* @return CharactersGroup | ||
*/ | ||
private function createCharacterGroup(array ...$byteSets): CharactersGroup | ||
{ | ||
return new CharactersGroup(...array_reduce($byteSets, function (array $all, $set): array { | ||
return array_merge($all, $set); | ||
}, [])); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the `src-run/web-app-v1` project. | ||
* | ||
* (c) Rob Frawley 2nd <rmf@src.run> | ||
* | ||
* For the full copyright and license information, please view the LICENSE.md | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace SR\Utilities\Characters\Group; | ||
|
||
use SR\Utilities\Characters\CharactersTrait; | ||
|
||
final class CharactersGroup implements \Countable, \IteratorAggregate | ||
{ | ||
use CharactersTrait; | ||
|
||
/** | ||
* @param int ...$decimals | ||
*/ | ||
public function __construct(int ...$decimals) | ||
{ | ||
$this->bytes = $decimals; | ||
} | ||
} |
Oops, something went wrong.