Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ There are many classes in this package. Almost all are extending from `nette/uti
- [Fields](#fields)
- [FileSystem](#filesystem)
- [Strings](#strings)
- [Caster](#caster)
- [Emptiness](#emptiness)
- [Urls](#urls)
- [System](#system)
- [TextString](#textstring)
- [UserAgents](#useragents)
- [Uuid](#uuid)
- [Validators](#validators)
- [CSV](#csv)
- [Collections](#collections)
Expand Down Expand Up @@ -81,12 +87,64 @@ Collection of extra functions:
- `Strings::dashless($s)`
- `Strings::slashless($s)`

## `Caster`

Collection of casting helpers:

- `Caster::stringOrNull($value)`
- `Caster::ensureString($value)`
- `Caster::forceString($value)`
- `Caster::intOrNull($value)`
- `Caster::ensureInt($value)`
- `Caster::forceInt($value)`
- `Caster::floatOrNull($value)`
- `Caster::ensureFloat($value)`
- `Caster::forceFloat($value)`
- `Caster::boolOrNull($value)`
- `Caster::ensureBool($value)`
- `Caster::forceBool($value)`
- `Caster::ensureArray($value)`
- `Caster::forceArray($value)`

## `Emptiness`

Helpers for strict empty checks:

- `Emptiness::empty($value)`
- `Emptiness::notEmpty($value)`

## `Urls`

Collection of extra functions:

- `Urls::hasFragment($url)`

## `System`

Helpers for runtime diagnostics:

- `System::memoryUsage()`
- `System::memoryPeakUsage()`
- `System::timer($name)`

## `TextString`

Value object implementing `Stringable` for explicit text wrapping.

## `UserAgents`

Utility for rotating and randomizing user agents:

- `UserAgents::get()`
- `UserAgents::random()`

## `Uuid`

UUID v4 generation and validation:

- `Uuid::v4()`
- `Uuid::validateV4($uuid)`

## `Validators`

Collection of extra functions:
Expand Down
158 changes: 158 additions & 0 deletions src/Caster.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

use Contributte\Utils\Exception\LogicalException;

final class Caster
{

public static function stringOrNull(mixed $value): string|null
{
if ($value === null) {
return null;
}

if (!is_scalar($value)) {
throw new LogicalException('Given value must be scalar or null');
}

return (string) $value;
}

public static function ensureString(mixed $value): string
{
return self::stringOrNull($value) ?? '';
}

public static function forceString(mixed $value): string
{
if (!is_scalar($value)) {
throw new LogicalException('Given value must be scalar');
}

return (string) $value;
}

public static function intOrNull(mixed $value): int|null
{
if ($value === null) {
return null;
}

if (!Validators::isNumericInt($value)) {
throw new LogicalException('Given value must be integer or null');
}

return (int) $value; // @phpstan-ignore-line
}

public static function ensureInt(mixed $value): int
{
return self::intOrNull($value) ?? 0;
}

public static function forceInt(mixed $value): int
{
if (!Validators::isNumericInt($value)) {
throw new LogicalException('Given value must be integer');
}

return (int) $value; // @phpstan-ignore-line
}

public static function floatOrNull(mixed $value): float|null
{
if ($value === null) {
return null;
}

if (!Validators::isNumeric($value)) {
throw new LogicalException('Given value must be float or null');
}

return (float) $value; // @phpstan-ignore-line
}

public static function ensureFloat(mixed $value): float
{
return self::floatOrNull($value) ?? 0.0;
}

public static function forceFloat(mixed $value): float
{
if (!Validators::isNumeric($value)) {
throw new LogicalException('Given value must be float');
}

return (float) $value; // @phpstan-ignore-line
}

public static function boolOrNull(mixed $value): bool|null
{
if ($value === null) {
return null;
}

if ($value === true || $value === false) {
return $value;
}

if (!is_scalar($value)) {
return null;
}

return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
}

public static function ensureBool(mixed $value): bool
{
return self::boolOrNull($value) ?? false;
}

public static function forceBool(mixed $value): bool
{
if (!is_bool($value)) {
throw new LogicalException('Given value must be boolean');
}

return $value;
}

/**
* @template T
* @param T|T[]|null $value
* @return T[]
*/
public static function ensureArray(mixed $value): array
{
if (is_array($value)) {
return $value;
}

if ($value === null) {
return [];
}

if (is_scalar($value)) {
return [$value];
}

throw new LogicalException('Given value must be array, scalar or null');
}

/**
* @template T
* @param T|T[] $value
* @return T[]
*/
public static function forceArray(mixed $value): array
{
if (!is_array($value)) {
throw new LogicalException('Given value must be array');
}

return $value;
}

}
18 changes: 18 additions & 0 deletions src/Emptiness.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

final class Emptiness
{

public static function empty(mixed $value): bool
{
return $value === null || $value === '' || $value === [];
}

public static function notEmpty(mixed $value): bool
{
return !self::empty($value);
}

}
43 changes: 43 additions & 0 deletions src/System.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

class System
{

/** @var array<string, float> */
public static array $timers = [];

public static function memoryUsage(): string
{
return sprintf(
'%dKB / %dMB',
round(memory_get_usage(true) / 1024),
round(memory_get_usage(true) / 1024 / 1024)
);
}

public static function memoryPeakUsage(): string
{
return sprintf(
'%dKB / %dMB',
round(memory_get_peak_usage(true) / 1024),
round(memory_get_peak_usage(true) / 1024 / 1024)
);
}

public static function timer(string $timer): float|null
{
if (isset(self::$timers[$timer])) {
$time = microtime(true) - self::$timers[$timer];
unset(self::$timers[$timer]);

return $time;
}

self::$timers[$timer] = microtime(true);

return null;
}

}
21 changes: 21 additions & 0 deletions src/TextString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

use Stringable;

final class TextString implements Stringable
{

public function __construct(
private string $text,
)
{
}

public function __toString(): string
{
return $this->text;
}

}
38 changes: 38 additions & 0 deletions src/UserAgents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

final class UserAgents
{

public const USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edg/138.0.0.0 Safari/537.36',
'Go-http-client/1.1',
'okhttp/4.12.0',
];

private static int $usedCursor = 0;

public static function get(): string
{
$agent = self::USER_AGENTS[self::$usedCursor];
self::$usedCursor = (self::$usedCursor + 1) % count(self::USER_AGENTS);

return $agent;
}

public static function random(): string
{
$index = array_rand(self::USER_AGENTS);

return self::USER_AGENTS[$index];
}

}
26 changes: 26 additions & 0 deletions src/Uuid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

namespace Contributte\Utils;

final class Uuid
{

/**
* @see https://stackoverflow.com/a/15875555
*/
public static function v4(): string
{
$data = random_bytes(16);

$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);

return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

public static function validateV4(string $uuid): bool
{
return preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $uuid) === 1;
}

}
Loading