update lock clucknut
All checks were successful
All checks were successful
This commit is contained in:
9
vendor/nette/utils/composer.json
vendored
9
vendor/nette/utils/composer.json
vendored
@@ -20,7 +20,9 @@
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.5",
|
||||
"tracy/tracy": "^2.9",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"phpstan/phpstan": "^2.1@stable",
|
||||
"phpstan/extension-installer": "^1.4@stable",
|
||||
"nette/phpstan-rules": "^1.0",
|
||||
"jetbrains/phpstorm-attributes": "^1.2"
|
||||
},
|
||||
"conflict": {
|
||||
@@ -50,5 +52,10 @@
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"phpstan/extension-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
vendor/nette/utils/src/HtmlStringable.php
vendored
5
vendor/nette/utils/src/HtmlStringable.php
vendored
@@ -10,10 +10,13 @@
|
||||
namespace Nette;
|
||||
|
||||
|
||||
/**
|
||||
* Represents object convertible to HTML string.
|
||||
*/
|
||||
interface HtmlStringable
|
||||
{
|
||||
/**
|
||||
* Returns string in HTML format
|
||||
* Returns string in HTML format.
|
||||
*/
|
||||
function __toString(): string;
|
||||
}
|
||||
|
||||
@@ -13,16 +13,19 @@
|
||||
|
||||
|
||||
/**
|
||||
* Smarter caching iterator.
|
||||
* Enhanced caching iterator with first/last/counter tracking.
|
||||
*
|
||||
* @template TKey
|
||||
* @template TValue
|
||||
* @extends \CachingIterator<TKey, TValue, \Iterator<TKey, TValue>>
|
||||
* @property-read bool $first
|
||||
* @property-read bool $last
|
||||
* @property-read bool $empty
|
||||
* @property-read bool $odd
|
||||
* @property-read bool $even
|
||||
* @property-read int $counter
|
||||
* @property-read mixed $nextKey
|
||||
* @property-read mixed $nextValue
|
||||
* @property-read TKey $nextKey
|
||||
* @property-read TValue $nextValue
|
||||
*/
|
||||
class CachingIterator extends \CachingIterator implements \Countable
|
||||
{
|
||||
@@ -31,6 +34,7 @@ class CachingIterator extends \CachingIterator implements \Countable
|
||||
private int $counter = 0;
|
||||
|
||||
|
||||
/** @param iterable<TKey, TValue>|\stdClass $iterable */
|
||||
public function __construct(iterable|\stdClass $iterable)
|
||||
{
|
||||
$iterable = $iterable instanceof \stdClass
|
||||
@@ -58,45 +62,30 @@ public function isLast(?int $gridWidth = null): bool
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the iterator empty?
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->counter === 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the counter odd?
|
||||
*/
|
||||
public function isOdd(): bool
|
||||
{
|
||||
return $this->counter % 2 === 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the counter even?
|
||||
*/
|
||||
public function isEven(): bool
|
||||
{
|
||||
return $this->counter % 2 === 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the counter.
|
||||
*/
|
||||
public function getCounter(): int
|
||||
{
|
||||
return $this->counter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the count of elements.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
$inner = $this->getInnerIterator();
|
||||
@@ -131,18 +120,14 @@ public function rewind(): void
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next key.
|
||||
*/
|
||||
/** @return TKey */
|
||||
public function getNextKey(): mixed
|
||||
{
|
||||
return $this->getInnerIterator()->key();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next element.
|
||||
*/
|
||||
/** @return TValue */
|
||||
public function getNextValue(): mixed
|
||||
{
|
||||
return $this->getInnerIterator()->current();
|
||||
|
||||
5
vendor/nette/utils/src/Iterators/Mapper.php
vendored
5
vendor/nette/utils/src/Iterators/Mapper.php
vendored
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
class Mapper extends \IteratorIterator
|
||||
{
|
||||
/** @var callable */
|
||||
private $callback;
|
||||
private \Closure $callback;
|
||||
|
||||
|
||||
public function __construct(\Traversable $iterator, callable $callback)
|
||||
{
|
||||
parent::__construct($iterator);
|
||||
$this->callback = $callback;
|
||||
$this->callback = $callback(...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
3
vendor/nette/utils/src/SmartObject.php
vendored
3
vendor/nette/utils/src/SmartObject.php
vendored
@@ -22,6 +22,7 @@
|
||||
trait SmartObject
|
||||
{
|
||||
/**
|
||||
* @param mixed[] $args
|
||||
* @return mixed
|
||||
* @throws MemberAccessException
|
||||
*/
|
||||
@@ -47,6 +48,8 @@ public function __call(string $name, array $args)
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed[] $args
|
||||
* @return never
|
||||
* @throws MemberAccessException
|
||||
*/
|
||||
public static function __callStatic(string $name, array $args)
|
||||
|
||||
2
vendor/nette/utils/src/StaticClass.php
vendored
2
vendor/nette/utils/src/StaticClass.php
vendored
@@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Static class.
|
||||
* Prevents instantiation.
|
||||
*/
|
||||
trait StaticClass
|
||||
{
|
||||
|
||||
2
vendor/nette/utils/src/Translator.php
vendored
2
vendor/nette/utils/src/Translator.php
vendored
@@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Translator adapter.
|
||||
* Translation provider.
|
||||
*/
|
||||
interface Translator
|
||||
{
|
||||
|
||||
6
vendor/nette/utils/src/Utils/ArrayHash.php
vendored
6
vendor/nette/utils/src/Utils/ArrayHash.php
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Provides objects to work as array.
|
||||
* Array-like object with property access.
|
||||
* @template T
|
||||
* @implements \IteratorAggregate<array-key, T>
|
||||
* @implements \ArrayAccess<array-key, T>
|
||||
@@ -39,7 +39,6 @@ public static function from(array $array, bool $recursive = true): static
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator over all items.
|
||||
* @return \Iterator<array-key, T>
|
||||
*/
|
||||
public function &getIterator(): \Iterator
|
||||
@@ -50,9 +49,6 @@ public function &getIterator(): \Iterator
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns items count.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count((array) $this);
|
||||
|
||||
9
vendor/nette/utils/src/Utils/ArrayList.php
vendored
9
vendor/nette/utils/src/Utils/ArrayList.php
vendored
@@ -14,13 +14,14 @@
|
||||
|
||||
|
||||
/**
|
||||
* Provides the base class for a generic list (items can be accessed by index).
|
||||
* Generic list with integer indices.
|
||||
* @template T
|
||||
* @implements \IteratorAggregate<int, T>
|
||||
* @implements \ArrayAccess<int, T>
|
||||
*/
|
||||
class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
{
|
||||
/** @var list<T> */
|
||||
private array $list = [];
|
||||
|
||||
|
||||
@@ -41,7 +42,6 @@ public static function from(array $array): static
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator over all items.
|
||||
* @return \Iterator<int, T>
|
||||
*/
|
||||
public function &getIterator(): \Iterator
|
||||
@@ -52,9 +52,6 @@ public function &getIterator(): \Iterator
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns items count.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->list);
|
||||
@@ -63,7 +60,7 @@ public function count(): int
|
||||
|
||||
/**
|
||||
* Replaces or appends an item.
|
||||
* @param int|null $index
|
||||
* @param ?int $index
|
||||
* @param T $value
|
||||
* @throws Nette\OutOfRangeException
|
||||
*/
|
||||
|
||||
43
vendor/nette/utils/src/Utils/Arrays.php
vendored
43
vendor/nette/utils/src/Utils/Arrays.php
vendored
@@ -79,7 +79,7 @@ public static function &getRef(array &$array, string|int|array $key): mixed
|
||||
* @template T2
|
||||
* @param array<T1> $array1
|
||||
* @param array<T2> $array2
|
||||
* @return array<T1|T2>
|
||||
* @return array<T1|T2|array<mixed>>
|
||||
*/
|
||||
public static function mergeTree(array $array1, array $array2): array
|
||||
{
|
||||
@@ -96,6 +96,7 @@ public static function mergeTree(array $array1, array $array2): array
|
||||
|
||||
/**
|
||||
* Returns zero-indexed position of given array key. Returns null if key is not found.
|
||||
* @param array<mixed> $array
|
||||
*/
|
||||
public static function getKeyOffset(array $array, string|int $key): ?int
|
||||
{
|
||||
@@ -104,9 +105,10 @@ public static function getKeyOffset(array $array, string|int $key): ?int
|
||||
|
||||
|
||||
/**
|
||||
* @param array<mixed> $array
|
||||
* @deprecated use getKeyOffset()
|
||||
*/
|
||||
public static function searchKey(array $array, $key): ?int
|
||||
public static function searchKey(array $array, string|int $key): ?int
|
||||
{
|
||||
return self::getKeyOffset($array, $key);
|
||||
}
|
||||
@@ -114,10 +116,11 @@ public static function searchKey(array $array, $key): ?int
|
||||
|
||||
/**
|
||||
* Tests an array for the presence of value.
|
||||
* @param array<mixed> $array
|
||||
*/
|
||||
public static function contains(array $array, mixed $value): bool
|
||||
{
|
||||
return in_array($value, $array, true);
|
||||
return in_array($value, $array, strict: true);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,9 +128,11 @@ public static function contains(array $array, mixed $value): bool
|
||||
* Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
||||
* @template K of int|string
|
||||
* @template V
|
||||
* @template E
|
||||
* @param array<K, V> $array
|
||||
* @param ?callable(V, K, array<K, V>): bool $predicate
|
||||
* @return ?V
|
||||
* @param ?callable(): E $else
|
||||
* @return ($else is null ? ?V : V|E)
|
||||
*/
|
||||
public static function first(array $array, ?callable $predicate = null, ?callable $else = null): mixed
|
||||
{
|
||||
@@ -142,9 +147,11 @@ public static function first(array $array, ?callable $predicate = null, ?callabl
|
||||
* Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
||||
* @template K of int|string
|
||||
* @template V
|
||||
* @template E
|
||||
* @param array<K, V> $array
|
||||
* @param ?callable(V, K, array<K, V>): bool $predicate
|
||||
* @return ?V
|
||||
* @param ?callable(): E $else
|
||||
* @return ($else is null ? ?V : V|E)
|
||||
*/
|
||||
public static function last(array $array, ?callable $predicate = null, ?callable $else = null): mixed
|
||||
{
|
||||
@@ -196,6 +203,8 @@ public static function lastKey(array $array, ?callable $predicate = null): int|s
|
||||
/**
|
||||
* Inserts the contents of the $inserted array into the $array immediately after the $key.
|
||||
* If $key is null (or does not exist), it is inserted at the beginning.
|
||||
* @param array<mixed> $array
|
||||
* @param array<mixed> $inserted
|
||||
*/
|
||||
public static function insertBefore(array &$array, string|int|null $key, array $inserted): void
|
||||
{
|
||||
@@ -209,6 +218,8 @@ public static function insertBefore(array &$array, string|int|null $key, array $
|
||||
/**
|
||||
* Inserts the contents of the $inserted array into the $array before the $key.
|
||||
* If $key is null (or does not exist), it is inserted at the end.
|
||||
* @param array<mixed> $array
|
||||
* @param array<mixed> $inserted
|
||||
*/
|
||||
public static function insertAfter(array &$array, string|int|null $key, array $inserted): void
|
||||
{
|
||||
@@ -224,6 +235,7 @@ public static function insertAfter(array &$array, string|int|null $key, array $i
|
||||
|
||||
/**
|
||||
* Renames key in array.
|
||||
* @param array<mixed> $array
|
||||
*/
|
||||
public static function renameKey(array &$array, string|int $oldKey, string|int $newKey): bool
|
||||
{
|
||||
@@ -260,6 +272,8 @@ public static function grep(
|
||||
|
||||
/**
|
||||
* Transforms multidimensional array to flat array.
|
||||
* @param array<mixed> $array
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function flatten(array $array, bool $preserveKeys = false): array
|
||||
{
|
||||
@@ -284,16 +298,18 @@ public static function isList(mixed $value): bool
|
||||
|
||||
/**
|
||||
* Reformats table to associative tree. Path looks like 'field|field[]field->field=field'.
|
||||
* @param string|string[] $path
|
||||
* @param array<mixed> $array
|
||||
* @param string|list<string> $path
|
||||
* @return array<mixed>|\stdClass
|
||||
*/
|
||||
public static function associate(array $array, $path): array|\stdClass
|
||||
public static function associate(array $array, string|array $path): array|\stdClass
|
||||
{
|
||||
$parts = is_array($path)
|
||||
? $path
|
||||
: preg_split('#(\[\]|->|=|\|)#', $path, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
if (!$parts || $parts === ['->'] || $parts[0] === '=' || $parts[0] === '|') {
|
||||
throw new Nette\InvalidArgumentException("Invalid path '$path'.");
|
||||
throw new Nette\InvalidArgumentException("Invalid path '" . (is_array($path) ? implode('', $path) : $path) . "'.");
|
||||
}
|
||||
|
||||
$res = $parts[0] === '->' ? new \stdClass : [];
|
||||
@@ -312,6 +328,8 @@ public static function associate(array $array, $path): array|\stdClass
|
||||
$x = $row[$parts[$i]];
|
||||
$row = null;
|
||||
}
|
||||
break; // '=' is always the final operation
|
||||
|
||||
} elseif ($part === '->') {
|
||||
if (isset($parts[++$i])) {
|
||||
if ($x === null) {
|
||||
@@ -338,6 +356,8 @@ public static function associate(array $array, $path): array|\stdClass
|
||||
|
||||
/**
|
||||
* Normalizes array to associative array. Replace numeric keys with their values, the new value will be $filling.
|
||||
* @param array<mixed> $array
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function normalize(array $array, mixed $filling = null): array
|
||||
{
|
||||
@@ -481,8 +501,9 @@ public static function mapWithKeys(array $array, callable $transformer): array
|
||||
/**
|
||||
* Invokes all callbacks and returns array of results.
|
||||
* @param callable[] $callbacks
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function invoke(iterable $callbacks, ...$args): array
|
||||
public static function invoke(iterable $callbacks, mixed ...$args): array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($callbacks as $k => $cb) {
|
||||
@@ -496,8 +517,9 @@ public static function invoke(iterable $callbacks, ...$args): array
|
||||
/**
|
||||
* Invokes method on every object in an array and returns array of results.
|
||||
* @param object[] $objects
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function invokeMethod(iterable $objects, string $method, ...$args): array
|
||||
public static function invokeMethod(iterable $objects, string $method, mixed ...$args): array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($objects as $k => $obj) {
|
||||
@@ -511,6 +533,7 @@ public static function invokeMethod(iterable $objects, string $method, ...$args)
|
||||
/**
|
||||
* Copies the elements of the $array array to the $object object and then returns it.
|
||||
* @template T of object
|
||||
* @param iterable<mixed> $array
|
||||
* @param T $object
|
||||
* @return T
|
||||
*/
|
||||
|
||||
19
vendor/nette/utils/src/Utils/Callback.php
vendored
19
vendor/nette/utils/src/Utils/Callback.php
vendored
@@ -22,21 +22,24 @@ final class Callback
|
||||
|
||||
/**
|
||||
* Invokes internal PHP function with own error handler.
|
||||
* @param callable-string $function
|
||||
* @param list<mixed> $args
|
||||
* @param callable(string, int): (bool|void|null) $onError
|
||||
*/
|
||||
public static function invokeSafe(string $function, array $args, callable $onError): mixed
|
||||
{
|
||||
$prev = set_error_handler(function ($severity, $message, $file) use ($onError, &$prev, $function): ?bool {
|
||||
$prev = set_error_handler(function (int $severity, string $message, string $file, int $line) use ($onError, &$prev, $function): bool {
|
||||
if ($file === __FILE__) {
|
||||
$msg = ini_get('html_errors')
|
||||
? Html::htmlToText($message)
|
||||
: $message;
|
||||
$msg = preg_replace("#^$function\\(.*?\\): #", '', $msg);
|
||||
$msg = (string) preg_replace("#^$function\\(.*?\\): #", '', $msg);
|
||||
if ($onError($msg, $severity) !== false) {
|
||||
return null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $prev ? $prev(...func_get_args()) : false;
|
||||
return $prev ? $prev(...func_get_args()) !== false : false;
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -53,7 +56,7 @@ public static function invokeSafe(string $function, array $args, callable $onErr
|
||||
* @return callable
|
||||
* @throws Nette\InvalidArgumentException
|
||||
*/
|
||||
public static function check(mixed $callable, bool $syntax = false)
|
||||
public static function check(mixed $callable, bool $syntax = false): mixed
|
||||
{
|
||||
if (!is_callable($callable, $syntax)) {
|
||||
throw new Nette\InvalidArgumentException(
|
||||
@@ -87,7 +90,7 @@ public static function toString(mixed $callable): string
|
||||
* @param callable $callable type check is escalated to ReflectionException
|
||||
* @throws \ReflectionException if callback is not valid
|
||||
*/
|
||||
public static function toReflection($callable): \ReflectionMethod|\ReflectionFunction
|
||||
public static function toReflection(mixed $callable): \ReflectionMethod|\ReflectionFunction
|
||||
{
|
||||
if ($callable instanceof \Closure) {
|
||||
$callable = self::unwrap($callable);
|
||||
@@ -100,6 +103,7 @@ public static function toReflection($callable): \ReflectionMethod|\ReflectionFun
|
||||
} elseif (is_object($callable) && !$callable instanceof \Closure) {
|
||||
return new ReflectionMethod($callable, '__invoke');
|
||||
} else {
|
||||
assert($callable instanceof \Closure || is_string($callable));
|
||||
return new \ReflectionFunction($callable);
|
||||
}
|
||||
}
|
||||
@@ -116,8 +120,9 @@ public static function isStatic(callable $callable): bool
|
||||
|
||||
/**
|
||||
* Unwraps closure created by Closure::fromCallable().
|
||||
* @return callable|array{object|class-string, string}|string
|
||||
*/
|
||||
public static function unwrap(\Closure $closure): callable|array
|
||||
public static function unwrap(\Closure $closure): callable|array|string
|
||||
{
|
||||
$r = new \ReflectionFunction($closure);
|
||||
$class = $r->getClosureScopeClass()?->name;
|
||||
|
||||
2
vendor/nette/utils/src/Utils/DateTime.php
vendored
2
vendor/nette/utils/src/Utils/DateTime.php
vendored
@@ -142,7 +142,7 @@ public static function relativeToSeconds(string $relativeTime): int
|
||||
}
|
||||
|
||||
|
||||
private function apply(string $datetime, $timezone = null, bool $ctr = false): void
|
||||
private function apply(string $datetime, ?\DateTimeZone $timezone = null, bool $ctr = false): void
|
||||
{
|
||||
$relPart = '';
|
||||
$absPart = preg_replace_callback(
|
||||
|
||||
12
vendor/nette/utils/src/Utils/FileInfo.php
vendored
12
vendor/nette/utils/src/Utils/FileInfo.php
vendored
@@ -19,14 +19,12 @@
|
||||
*/
|
||||
final class FileInfo extends \SplFileInfo
|
||||
{
|
||||
private readonly string $relativePath;
|
||||
|
||||
|
||||
public function __construct(string $file, string $relativePath = '')
|
||||
{
|
||||
public function __construct(
|
||||
string $file,
|
||||
private readonly string $relativePath = '',
|
||||
) {
|
||||
parent::__construct($file);
|
||||
$this->setInfoClass(static::class);
|
||||
$this->relativePath = $relativePath;
|
||||
$this->setInfoClass(self::class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
7
vendor/nette/utils/src/Utils/FileSystem.php
vendored
7
vendor/nette/utils/src/Utils/FileSystem.php
vendored
@@ -52,14 +52,15 @@ public static function copy(string $origin, string $target, bool $overwrite = tr
|
||||
} elseif (is_dir($origin)) {
|
||||
static::createDir($target);
|
||||
foreach (new \FilesystemIterator($target) as $item) {
|
||||
\assert($item instanceof \SplFileInfo);
|
||||
static::delete($item->getPathname());
|
||||
}
|
||||
|
||||
foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($origin, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
|
||||
if ($item->isDir()) {
|
||||
static::createDir($target . '/' . $iterator->getSubPathName());
|
||||
static::createDir($target . '/' . $iterator->getSubPathname());
|
||||
} else {
|
||||
static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathName());
|
||||
static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathname());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -112,6 +113,7 @@ public static function delete(string $path): void
|
||||
}
|
||||
} elseif (is_dir($path)) {
|
||||
foreach (new \FilesystemIterator($path) as $item) {
|
||||
\assert($item instanceof \SplFileInfo);
|
||||
static::delete($item->getPathname());
|
||||
}
|
||||
|
||||
@@ -251,6 +253,7 @@ public static function makeWritable(string $path, int $dirMode = 0o777, int $fil
|
||||
}
|
||||
} elseif (is_dir($path)) {
|
||||
foreach (new \FilesystemIterator($path) as $item) {
|
||||
\assert($item instanceof \SplFileInfo);
|
||||
static::makeWritable($item->getPathname(), $dirMode, $fileMode);
|
||||
}
|
||||
|
||||
|
||||
35
vendor/nette/utils/src/Utils/Finder.php
vendored
35
vendor/nette/utils/src/Utils/Finder.php
vendored
@@ -32,24 +32,25 @@ class Finder implements \IteratorAggregate
|
||||
/** @var string[] */
|
||||
private array $in = [];
|
||||
|
||||
/** @var \Closure[] */
|
||||
/** @var array<\Closure(FileInfo): bool> */
|
||||
private array $filters = [];
|
||||
|
||||
/** @var \Closure[] */
|
||||
/** @var array<\Closure(FileInfo): bool> */
|
||||
private array $descentFilters = [];
|
||||
|
||||
/** @var array<string|self> */
|
||||
private array $appends = [];
|
||||
private bool $childFirst = false;
|
||||
|
||||
/** @var ?callable */
|
||||
private $sort;
|
||||
/** @var ?(\Closure(FileInfo, FileInfo): int) */
|
||||
private ?\Closure $sort = null;
|
||||
private int $maxDepth = -1;
|
||||
private bool $ignoreUnreadableDirs = true;
|
||||
|
||||
|
||||
/**
|
||||
* Begins search for files and directories matching mask.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public static function find(string|array $masks = ['*']): static
|
||||
{
|
||||
@@ -60,6 +61,7 @@ public static function find(string|array $masks = ['*']): static
|
||||
|
||||
/**
|
||||
* Begins search for files matching mask.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public static function findFiles(string|array $masks = ['*']): static
|
||||
{
|
||||
@@ -70,6 +72,7 @@ public static function findFiles(string|array $masks = ['*']): static
|
||||
|
||||
/**
|
||||
* Begins search for directories matching mask.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public static function findDirectories(string|array $masks = ['*']): static
|
||||
{
|
||||
@@ -80,6 +83,7 @@ public static function findDirectories(string|array $masks = ['*']): static
|
||||
|
||||
/**
|
||||
* Finds files matching the specified masks.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public function files(string|array $masks = ['*']): static
|
||||
{
|
||||
@@ -89,6 +93,7 @@ public function files(string|array $masks = ['*']): static
|
||||
|
||||
/**
|
||||
* Finds directories matching the specified masks.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public function directories(string|array $masks = ['*']): static
|
||||
{
|
||||
@@ -96,6 +101,7 @@ public function directories(string|array $masks = ['*']): static
|
||||
}
|
||||
|
||||
|
||||
/** @param list<string> $masks */
|
||||
private function addMask(array $masks, string $mode): static
|
||||
{
|
||||
foreach ($masks as $mask) {
|
||||
@@ -117,6 +123,7 @@ private function addMask(array $masks, string $mode): static
|
||||
|
||||
/**
|
||||
* Searches in the given directories. Wildcards are allowed.
|
||||
* @param string|list<string> $paths
|
||||
*/
|
||||
public function in(string|array $paths): static
|
||||
{
|
||||
@@ -128,6 +135,7 @@ public function in(string|array $paths): static
|
||||
|
||||
/**
|
||||
* Searches recursively from the given directories. Wildcards are allowed.
|
||||
* @param string|list<string> $paths
|
||||
*/
|
||||
public function from(string|array $paths): static
|
||||
{
|
||||
@@ -137,6 +145,7 @@ public function from(string|array $paths): static
|
||||
}
|
||||
|
||||
|
||||
/** @param list<string> $paths */
|
||||
private function addLocation(array $paths, string $ext): void
|
||||
{
|
||||
foreach ($paths as $path) {
|
||||
@@ -175,7 +184,7 @@ public function ignoreUnreadableDirs(bool $state = true): static
|
||||
*/
|
||||
public function sortBy(callable $callback): static
|
||||
{
|
||||
$this->sort = $callback;
|
||||
$this->sort = $callback(...);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -192,6 +201,7 @@ public function sortByName(): static
|
||||
|
||||
/**
|
||||
* Adds the specified paths or appends a new finder that returns.
|
||||
* @param string|list<string>|null $paths
|
||||
*/
|
||||
public function append(string|array|null $paths = null): static
|
||||
{
|
||||
@@ -209,6 +219,7 @@ public function append(string|array|null $paths = null): static
|
||||
|
||||
/**
|
||||
* Skips entries that matches the given masks relative to the ones defined with the in() or from() methods.
|
||||
* @param string|list<string> $masks
|
||||
*/
|
||||
public function exclude(string|array $masks): static
|
||||
{
|
||||
@@ -239,7 +250,7 @@ public function exclude(string|array $masks): static
|
||||
*/
|
||||
public function filter(callable $callback): static
|
||||
{
|
||||
$this->filters[] = \Closure::fromCallable($callback);
|
||||
$this->filters[] = $callback(...);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -250,7 +261,7 @@ public function filter(callable $callback): static
|
||||
*/
|
||||
public function descentFilter(callable $callback): static
|
||||
{
|
||||
$this->descentFilters[] = \Closure::fromCallable($callback);
|
||||
$this->descentFilters[] = $callback(...);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -267,6 +278,7 @@ public function limitDepth(?int $depth): static
|
||||
|
||||
/**
|
||||
* Restricts the search by size. $operator accepts "[operator] [size] [unit]" example: >=10kB
|
||||
* @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator or predicate string
|
||||
*/
|
||||
public function size(string $operator, ?int $size = null): static
|
||||
{
|
||||
@@ -277,7 +289,7 @@ public function size(string $operator, ?int $size = null): static
|
||||
|
||||
[, $operator, $size, $unit] = $matches;
|
||||
$units = ['' => 1, 'k' => 1e3, 'm' => 1e6, 'g' => 1e9];
|
||||
$size *= $units[strtolower($unit)];
|
||||
$size = (float) $size * $units[strtolower($unit)];
|
||||
$operator = $operator ?: '=';
|
||||
}
|
||||
|
||||
@@ -287,6 +299,7 @@ public function size(string $operator, ?int $size = null): static
|
||||
|
||||
/**
|
||||
* Restricts the search by modified time. $operator accepts "[operator] [date]" example: >1978-01-23
|
||||
* @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator or predicate string
|
||||
*/
|
||||
public function date(string $operator, string|int|\DateTimeInterface|null $date = null): static
|
||||
{
|
||||
@@ -401,6 +414,7 @@ private function traverseDir(string $dir, array $searches, array $subdirs = []):
|
||||
}
|
||||
|
||||
|
||||
/** @param iterable<string> $pathNames */
|
||||
private function convertToFiles(iterable $pathNames, string $relativePath, bool $absolute): \Generator
|
||||
{
|
||||
foreach ($pathNames as $pathName) {
|
||||
@@ -413,6 +427,10 @@ private function convertToFiles(iterable $pathNames, string $relativePath, bool
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param (\Closure(FileInfo): bool)[] $filters
|
||||
* @param array<int, bool> $cache
|
||||
*/
|
||||
private function proveFilters(array $filters, FileInfo $file, array &$cache): bool
|
||||
{
|
||||
foreach ($filters as $filter) {
|
||||
@@ -468,6 +486,7 @@ private function buildPlan(): array
|
||||
|
||||
/**
|
||||
* Since glob() does not know ** wildcard, we divide the path into a part for glob and a part for manual traversal.
|
||||
* @return array{string, string, bool}
|
||||
*/
|
||||
private static function splitRecursivePart(string $path): array
|
||||
{
|
||||
|
||||
8
vendor/nette/utils/src/Utils/Helpers.php
vendored
8
vendor/nette/utils/src/Utils/Helpers.php
vendored
@@ -14,6 +14,9 @@
|
||||
use const PHP_OS_FAMILY;
|
||||
|
||||
|
||||
/**
|
||||
* Miscellaneous utilities.
|
||||
*/
|
||||
class Helpers
|
||||
{
|
||||
public const IsWindows = PHP_OS_FAMILY === 'Windows';
|
||||
@@ -21,6 +24,7 @@ class Helpers
|
||||
|
||||
/**
|
||||
* Executes a callback and returns the captured output as a string.
|
||||
* @param callable(): void $func
|
||||
*/
|
||||
public static function capture(callable $func): string
|
||||
{
|
||||
@@ -37,7 +41,7 @@ public static function capture(callable $func): string
|
||||
|
||||
/**
|
||||
* Returns the last occurred PHP error or an empty string if no error occurred. Unlike error_get_last(),
|
||||
* it is nit affected by the PHP directive html_errors and always returns text, not HTML.
|
||||
* it is not affected by the PHP directive html_errors and always returns text, not HTML.
|
||||
*/
|
||||
public static function getLastError(): string
|
||||
{
|
||||
@@ -59,6 +63,7 @@ public static function falseToNull(mixed $value): mixed
|
||||
|
||||
/**
|
||||
* Returns value clamped to the inclusive range of min and max.
|
||||
* @return ($value is float ? float : ($min is float ? float : ($max is float ? float : int)))
|
||||
*/
|
||||
public static function clamp(int|float $value, int|float $min, int|float $max): int|float
|
||||
{
|
||||
@@ -91,6 +96,7 @@ public static function getSuggestion(array $possibilities, string $value): ?stri
|
||||
|
||||
/**
|
||||
* Compares two values in the same way that PHP does. Recognizes operators: >, >=, <, <=, =, ==, ===, !=, !==, <>
|
||||
* @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator
|
||||
*/
|
||||
public static function compare(mixed $left, string $operator, mixed $right): bool
|
||||
{
|
||||
|
||||
241
vendor/nette/utils/src/Utils/Html.php
vendored
241
vendor/nette/utils/src/Utils/Html.php
vendored
@@ -17,113 +17,113 @@
|
||||
/**
|
||||
* HTML helper.
|
||||
*
|
||||
* @property string|null $accept
|
||||
* @property string|null $accesskey
|
||||
* @property string|null $action
|
||||
* @property string|null $align
|
||||
* @property string|null $allow
|
||||
* @property string|null $alt
|
||||
* @property bool|null $async
|
||||
* @property string|null $autocapitalize
|
||||
* @property string|null $autocomplete
|
||||
* @property bool|null $autofocus
|
||||
* @property bool|null $autoplay
|
||||
* @property string|null $charset
|
||||
* @property bool|null $checked
|
||||
* @property string|null $cite
|
||||
* @property string|null $class
|
||||
* @property int|null $cols
|
||||
* @property int|null $colspan
|
||||
* @property string|null $content
|
||||
* @property bool|null $contenteditable
|
||||
* @property bool|null $controls
|
||||
* @property string|null $coords
|
||||
* @property string|null $crossorigin
|
||||
* @property string|null $data
|
||||
* @property string|null $datetime
|
||||
* @property string|null $decoding
|
||||
* @property bool|null $default
|
||||
* @property bool|null $defer
|
||||
* @property string|null $dir
|
||||
* @property string|null $dirname
|
||||
* @property bool|null $disabled
|
||||
* @property bool|null $download
|
||||
* @property string|null $draggable
|
||||
* @property string|null $dropzone
|
||||
* @property string|null $enctype
|
||||
* @property string|null $for
|
||||
* @property string|null $form
|
||||
* @property string|null $formaction
|
||||
* @property string|null $formenctype
|
||||
* @property string|null $formmethod
|
||||
* @property bool|null $formnovalidate
|
||||
* @property string|null $formtarget
|
||||
* @property string|null $headers
|
||||
* @property int|null $height
|
||||
* @property bool|null $hidden
|
||||
* @property float|null $high
|
||||
* @property string|null $href
|
||||
* @property string|null $hreflang
|
||||
* @property string|null $id
|
||||
* @property string|null $integrity
|
||||
* @property string|null $inputmode
|
||||
* @property bool|null $ismap
|
||||
* @property string|null $itemprop
|
||||
* @property string|null $kind
|
||||
* @property string|null $label
|
||||
* @property string|null $lang
|
||||
* @property string|null $list
|
||||
* @property bool|null $loop
|
||||
* @property float|null $low
|
||||
* @property float|null $max
|
||||
* @property int|null $maxlength
|
||||
* @property int|null $minlength
|
||||
* @property string|null $media
|
||||
* @property string|null $method
|
||||
* @property float|null $min
|
||||
* @property bool|null $multiple
|
||||
* @property bool|null $muted
|
||||
* @property string|null $name
|
||||
* @property bool|null $novalidate
|
||||
* @property bool|null $open
|
||||
* @property float|null $optimum
|
||||
* @property string|null $pattern
|
||||
* @property string|null $ping
|
||||
* @property string|null $placeholder
|
||||
* @property string|null $poster
|
||||
* @property string|null $preload
|
||||
* @property string|null $radiogroup
|
||||
* @property bool|null $readonly
|
||||
* @property string|null $rel
|
||||
* @property bool|null $required
|
||||
* @property bool|null $reversed
|
||||
* @property int|null $rows
|
||||
* @property int|null $rowspan
|
||||
* @property string|null $sandbox
|
||||
* @property string|null $scope
|
||||
* @property bool|null $selected
|
||||
* @property string|null $shape
|
||||
* @property int|null $size
|
||||
* @property string|null $sizes
|
||||
* @property string|null $slot
|
||||
* @property int|null $span
|
||||
* @property string|null $spellcheck
|
||||
* @property string|null $src
|
||||
* @property string|null $srcdoc
|
||||
* @property string|null $srclang
|
||||
* @property string|null $srcset
|
||||
* @property int|null $start
|
||||
* @property float|null $step
|
||||
* @property string|null $style
|
||||
* @property int|null $tabindex
|
||||
* @property string|null $target
|
||||
* @property string|null $title
|
||||
* @property string|null $translate
|
||||
* @property string|null $type
|
||||
* @property string|null $usemap
|
||||
* @property string|null $value
|
||||
* @property int|null $width
|
||||
* @property string|null $wrap
|
||||
* @property ?string $accept
|
||||
* @property ?string $accesskey
|
||||
* @property ?string $action
|
||||
* @property ?string $align
|
||||
* @property ?string $allow
|
||||
* @property ?string $alt
|
||||
* @property ?bool $async
|
||||
* @property ?string $autocapitalize
|
||||
* @property ?string $autocomplete
|
||||
* @property ?bool $autofocus
|
||||
* @property ?bool $autoplay
|
||||
* @property ?string $charset
|
||||
* @property ?bool $checked
|
||||
* @property ?string $cite
|
||||
* @property ?string $class
|
||||
* @property ?int $cols
|
||||
* @property ?int $colspan
|
||||
* @property ?string $content
|
||||
* @property ?bool $contenteditable
|
||||
* @property ?bool $controls
|
||||
* @property ?string $coords
|
||||
* @property ?string $crossorigin
|
||||
* @property ?string $data
|
||||
* @property ?string $datetime
|
||||
* @property ?string $decoding
|
||||
* @property ?bool $default
|
||||
* @property ?bool $defer
|
||||
* @property ?string $dir
|
||||
* @property ?string $dirname
|
||||
* @property ?bool $disabled
|
||||
* @property ?bool $download
|
||||
* @property ?string $draggable
|
||||
* @property ?string $dropzone
|
||||
* @property ?string $enctype
|
||||
* @property ?string $for
|
||||
* @property ?string $form
|
||||
* @property ?string $formaction
|
||||
* @property ?string $formenctype
|
||||
* @property ?string $formmethod
|
||||
* @property ?bool $formnovalidate
|
||||
* @property ?string $formtarget
|
||||
* @property ?string $headers
|
||||
* @property ?int $height
|
||||
* @property ?bool $hidden
|
||||
* @property ?float $high
|
||||
* @property ?string $href
|
||||
* @property ?string $hreflang
|
||||
* @property ?string $id
|
||||
* @property ?string $integrity
|
||||
* @property ?string $inputmode
|
||||
* @property ?bool $ismap
|
||||
* @property ?string $itemprop
|
||||
* @property ?string $kind
|
||||
* @property ?string $label
|
||||
* @property ?string $lang
|
||||
* @property ?string $list
|
||||
* @property ?bool $loop
|
||||
* @property ?float $low
|
||||
* @property ?float $max
|
||||
* @property ?int $maxlength
|
||||
* @property ?int $minlength
|
||||
* @property ?string $media
|
||||
* @property ?string $method
|
||||
* @property ?float $min
|
||||
* @property ?bool $multiple
|
||||
* @property ?bool $muted
|
||||
* @property ?string $name
|
||||
* @property ?bool $novalidate
|
||||
* @property ?bool $open
|
||||
* @property ?float $optimum
|
||||
* @property ?string $pattern
|
||||
* @property ?string $ping
|
||||
* @property ?string $placeholder
|
||||
* @property ?string $poster
|
||||
* @property ?string $preload
|
||||
* @property ?string $radiogroup
|
||||
* @property ?bool $readonly
|
||||
* @property ?string $rel
|
||||
* @property ?bool $required
|
||||
* @property ?bool $reversed
|
||||
* @property ?int $rows
|
||||
* @property ?int $rowspan
|
||||
* @property ?string $sandbox
|
||||
* @property ?string $scope
|
||||
* @property ?bool $selected
|
||||
* @property ?string $shape
|
||||
* @property ?int $size
|
||||
* @property ?string $sizes
|
||||
* @property ?string $slot
|
||||
* @property ?int $span
|
||||
* @property ?string $spellcheck
|
||||
* @property ?string $src
|
||||
* @property ?string $srcdoc
|
||||
* @property ?string $srclang
|
||||
* @property ?string $srcset
|
||||
* @property ?int $start
|
||||
* @property ?float $step
|
||||
* @property ?string $style
|
||||
* @property ?int $tabindex
|
||||
* @property ?string $target
|
||||
* @property ?string $title
|
||||
* @property ?string $translate
|
||||
* @property ?string $type
|
||||
* @property ?string $usemap
|
||||
* @property ?string $value
|
||||
* @property ?int $width
|
||||
* @property ?string $wrap
|
||||
*
|
||||
* @method self accept(?string $val)
|
||||
* @method self accesskey(?string $val, bool $state = null)
|
||||
@@ -230,20 +230,23 @@
|
||||
* @method self value(?string $val)
|
||||
* @method self width(?int $val)
|
||||
* @method self wrap(?string $val)
|
||||
*
|
||||
* @implements \IteratorAggregate<int, self|string>
|
||||
* @implements \ArrayAccess<int, self|string>
|
||||
*/
|
||||
class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringable
|
||||
{
|
||||
/** @var array<string, mixed> element's attributes */
|
||||
public array $attrs = [];
|
||||
|
||||
/** void elements */
|
||||
/** @var array<string, int> void elements */
|
||||
public static array $emptyElements = [
|
||||
'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1,
|
||||
'source' => 1, 'base' => 1, 'col' => 1, 'link' => 1, 'param' => 1, 'basefont' => 1, 'frame' => 1,
|
||||
'isindex' => 1, 'wbr' => 1, 'command' => 1, 'track' => 1,
|
||||
];
|
||||
|
||||
/** @var array<int, HtmlStringable|string> nodes */
|
||||
/** @var array<int, self|string> nodes */
|
||||
protected array $children = [];
|
||||
|
||||
/** element's name */
|
||||
@@ -254,7 +257,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab
|
||||
|
||||
/**
|
||||
* Constructs new HTML element.
|
||||
* @param array|string $attrs element's attributes or plain text content
|
||||
* @param array<string, mixed>|string|null $attrs element's attributes or plain text content
|
||||
*/
|
||||
public static function el(?string $name = null, array|string|null $attrs = null): static
|
||||
{
|
||||
@@ -355,6 +358,7 @@ final public function isEmpty(): bool
|
||||
|
||||
/**
|
||||
* Sets multiple attributes.
|
||||
* @param array<string, mixed> $attrs
|
||||
*/
|
||||
public function addAttributes(array $attrs): static
|
||||
{
|
||||
@@ -417,6 +421,7 @@ public function removeAttribute(string $name): static
|
||||
|
||||
/**
|
||||
* Unsets element's attributes.
|
||||
* @param list<string> $attributes
|
||||
*/
|
||||
public function removeAttributes(array $attributes): static
|
||||
{
|
||||
@@ -466,6 +471,7 @@ final public function __unset(string $name): void
|
||||
|
||||
/**
|
||||
* Overloaded setter for element's attribute.
|
||||
* @param mixed[] $args
|
||||
*/
|
||||
final public function __call(string $m, array $args): mixed
|
||||
{
|
||||
@@ -496,6 +502,7 @@ final public function __call(string $m, array $args): mixed
|
||||
|
||||
/**
|
||||
* Special setter for element's attribute.
|
||||
* @param array<string, mixed> $query
|
||||
*/
|
||||
final public function href(string $path, array $query = []): static
|
||||
{
|
||||
@@ -594,6 +601,7 @@ public function addText(\Stringable|string|int|null $text): static
|
||||
|
||||
/**
|
||||
* Creates and adds a new Html child.
|
||||
* @param array<string, mixed>|string|null $attrs
|
||||
*/
|
||||
final public function create(string $name, array|string|null $attrs = null): static
|
||||
{
|
||||
@@ -621,7 +629,7 @@ public function insert(?int $index, HtmlStringable|string $child, bool $replace
|
||||
|
||||
/**
|
||||
* Inserts (replaces) child node (\ArrayAccess implementation).
|
||||
* @param int|null $index position or null for appending
|
||||
* @param ?int $index position or null for appending
|
||||
* @param Html|string $child Html node or raw HTML string
|
||||
*/
|
||||
final public function offsetSet($index, $child): void
|
||||
@@ -634,7 +642,7 @@ final public function offsetSet($index, $child): void
|
||||
* Returns child node (\ArrayAccess implementation).
|
||||
* @param int $index
|
||||
*/
|
||||
final public function offsetGet($index): HtmlStringable|string
|
||||
final public function offsetGet($index): self|string
|
||||
{
|
||||
return $this->children[$index];
|
||||
}
|
||||
@@ -682,7 +690,7 @@ public function removeChildren(): void
|
||||
|
||||
/**
|
||||
* Iterates over elements.
|
||||
* @return \ArrayIterator<int, HtmlStringable|string>
|
||||
* @return \ArrayIterator<int, self|string>
|
||||
*/
|
||||
final public function getIterator(): \ArrayIterator
|
||||
{
|
||||
@@ -692,6 +700,7 @@ final public function getIterator(): \ArrayIterator
|
||||
|
||||
/**
|
||||
* Returns all children.
|
||||
* @return array<int, self|string>
|
||||
*/
|
||||
final public function getChildren(): array
|
||||
{
|
||||
@@ -764,10 +773,6 @@ final public function endTag(): string
|
||||
*/
|
||||
final public function attributes(): string
|
||||
{
|
||||
if (!is_array($this->attrs)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = '';
|
||||
$attrs = $this->attrs;
|
||||
foreach ($attrs as $key => $value) {
|
||||
@@ -780,7 +785,7 @@ final public function attributes(): string
|
||||
continue;
|
||||
|
||||
} elseif (is_array($value)) {
|
||||
if (strncmp($key, 'data-', 5) === 0) {
|
||||
if (str_starts_with($key, 'data-')) {
|
||||
$value = Json::encode($value);
|
||||
|
||||
} else {
|
||||
|
||||
126
vendor/nette/utils/src/Utils/Image.php
vendored
126
vendor/nette/utils/src/Utils/Image.php
vendored
@@ -24,7 +24,7 @@
|
||||
* $image->send();
|
||||
* </code>
|
||||
*
|
||||
* @method Image affine(array $affine, ?array $clip = null)
|
||||
* @method Image affine(array<int, float|int> $affine, ?array{x: int, y: int, width: int, height: int} $clip = null)
|
||||
* @method void alphaBlending(bool $enable)
|
||||
* @method void antialias(bool $enable)
|
||||
* @method void arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color)
|
||||
@@ -41,51 +41,51 @@
|
||||
* @method int colorResolve(int $red, int $green, int $blue)
|
||||
* @method int colorResolveAlpha(int $red, int $green, int $blue, int $alpha)
|
||||
* @method void colorSet(int $index, int $red, int $green, int $blue, int $alpha = 0)
|
||||
* @method array colorsForIndex(int $color)
|
||||
* @method array{red: int, green: int, blue: int, alpha: int} colorsForIndex(int $color)
|
||||
* @method int colorsTotal()
|
||||
* @method int colorTransparent(?int $color = null)
|
||||
* @method void convolution(array $matrix, float $div, float $offset)
|
||||
* @method void convolution(array<int, array<int, float>> $matrix, float $div, float $offset)
|
||||
* @method void copy(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH)
|
||||
* @method void copyMerge(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH, int $pct)
|
||||
* @method void copyMergeGray(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH, int $pct)
|
||||
* @method void copyResampled(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $dstW, int $dstH, int $srcW, int $srcH)
|
||||
* @method void copyResized(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $dstW, int $dstH, int $srcW, int $srcH)
|
||||
* @method Image cropAuto(int $mode = IMG_CROP_DEFAULT, float $threshold = .5, ?ImageColor $color = null)
|
||||
* @method Image cropAuto(int $mode = 0, float $threshold = .5, ?ImageColor $color = null)
|
||||
* @method void ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color)
|
||||
* @method void fill(int $x, int $y, ImageColor $color)
|
||||
* @method void filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style)
|
||||
* @method void filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color)
|
||||
* @method void filledPolygon(array $points, ImageColor $color)
|
||||
* @method void filledPolygon(array<int, int> $points, ImageColor $color)
|
||||
* @method void filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color)
|
||||
* @method void fillToBorder(int $x, int $y, ImageColor $borderColor, ImageColor $color)
|
||||
* @method void filter(int $filter, ...$args)
|
||||
* @method void flip(int $mode)
|
||||
* @method array ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options = [])
|
||||
* @method array<int, int> ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array<string, mixed> $options = [])
|
||||
* @method void gammaCorrect(float $inputgamma, float $outputgamma)
|
||||
* @method array getClip()
|
||||
* @method array{int, int, int, int} getClip()
|
||||
* @method int getInterpolation()
|
||||
* @method int interlace(?bool $enable = null)
|
||||
* @method bool isTrueColor()
|
||||
* @method void layerEffect(int $effect)
|
||||
* @method void line(int $x1, int $y1, int $x2, int $y2, ImageColor $color)
|
||||
* @method void openPolygon(array $points, ImageColor $color)
|
||||
* @method void openPolygon(array<int, int> $points, ImageColor $color)
|
||||
* @method void paletteCopy(Image $source)
|
||||
* @method void paletteToTrueColor()
|
||||
* @method void polygon(array $points, ImageColor $color)
|
||||
* @method void polygon(array<int, int> $points, ImageColor $color)
|
||||
* @method void rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color)
|
||||
* @method mixed resolution(?int $resolutionX = null, ?int $resolutionY = null)
|
||||
* @method Image rotate(float $angle, ImageColor $backgroundColor)
|
||||
* @method void saveAlpha(bool $enable)
|
||||
* @method Image scale(int $newWidth, int $newHeight = -1, int $mode = IMG_BILINEAR_FIXED)
|
||||
* @method Image scale(int $newWidth, int $newHeight = -1, int $mode = 3)
|
||||
* @method void setBrush(Image $brush)
|
||||
* @method void setClip(int $x1, int $y1, int $x2, int $y2)
|
||||
* @method void setInterpolation(int $method = IMG_BILINEAR_FIXED)
|
||||
* @method void setInterpolation(int $method = 3)
|
||||
* @method void setPixel(int $x, int $y, ImageColor $color)
|
||||
* @method void setStyle(array $style)
|
||||
* @method void setStyle(array<int, int> $style)
|
||||
* @method void setThickness(int $thickness)
|
||||
* @method void setTile(Image $tile)
|
||||
* @method void trueColorToPalette(bool $dither, int $ncolors)
|
||||
* @method array ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontfile, string $text, array $options = [])
|
||||
* @method array<int, int> ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontfile, string $text, array<string, mixed> $options = [])
|
||||
* @property-read positive-int $width
|
||||
* @property-read positive-int $height
|
||||
* @property-read \GdImage $imageResource
|
||||
@@ -146,6 +146,7 @@ class Image
|
||||
/**
|
||||
* Returns RGB color (0..255) and transparency (0..127).
|
||||
* @deprecated use ImageColor::rgb()
|
||||
* @return array{red: int, green: int, blue: int, alpha: int}
|
||||
*/
|
||||
public static function rgb(int $red, int $green, int $blue, int $transparency = 0): array
|
||||
{
|
||||
@@ -192,6 +193,7 @@ public static function fromString(string $s, ?int &$type = null): static
|
||||
}
|
||||
|
||||
|
||||
/** @param callable-string $func */
|
||||
private static function invokeSafe(string $func, string $arg, string $message, string $callee): static
|
||||
{
|
||||
$errors = [];
|
||||
@@ -213,6 +215,7 @@ private static function invokeSafe(string $func, string $arg, string $message, s
|
||||
* Creates a new true color image of the given dimensions. The default color is black.
|
||||
* @param positive-int $width
|
||||
* @param positive-int $height
|
||||
* @param ImageColor|array{red: int, green: int, blue: int, alpha?: int}|null $color
|
||||
* @throws Nette\NotSupportedException if gd extension is not loaded
|
||||
*/
|
||||
public static function fromBlank(int $width, int $height, ImageColor|array|null $color = null): static
|
||||
@@ -224,9 +227,9 @@ public static function fromBlank(int $width, int $height, ImageColor|array|null
|
||||
|
||||
$image = new static(imagecreatetruecolor($width, $height));
|
||||
if ($color) {
|
||||
$image->alphablending(false);
|
||||
$image->filledrectangle(0, 0, $width - 1, $height - 1, $color);
|
||||
$image->alphablending(true);
|
||||
$image->alphaBlending(false);
|
||||
$image->filledRectangle(0, 0, $width - 1, $height - 1, self::normalizeColor($color));
|
||||
$image->alphaBlending(true);
|
||||
}
|
||||
|
||||
return $image;
|
||||
@@ -235,9 +238,11 @@ public static function fromBlank(int $width, int $height, ImageColor|array|null
|
||||
|
||||
/**
|
||||
* Returns the type of image from file.
|
||||
* @return ImageType::*|null
|
||||
* @param-out ?int $width
|
||||
* @param-out ?int $height
|
||||
* @return ?ImageType::*
|
||||
*/
|
||||
public static function detectTypeFromFile(string $file, &$width = null, &$height = null): ?int
|
||||
public static function detectTypeFromFile(string $file, mixed &$width = null, mixed &$height = null): ?int
|
||||
{
|
||||
[$width, $height, $type] = Helpers::falseToNull(@getimagesize($file)); // @ - files smaller than 12 bytes causes read error
|
||||
return $type && isset(self::Formats[$type]) ? $type : null;
|
||||
@@ -246,9 +251,11 @@ public static function detectTypeFromFile(string $file, &$width = null, &$height
|
||||
|
||||
/**
|
||||
* Returns the type of image from string.
|
||||
* @return ImageType::*|null
|
||||
* @param-out ?int $width
|
||||
* @param-out ?int $height
|
||||
* @return ?ImageType::*
|
||||
*/
|
||||
public static function detectTypeFromString(string $s, &$width = null, &$height = null): ?int
|
||||
public static function detectTypeFromString(string $s, mixed &$width = null, mixed &$height = null): ?int
|
||||
{
|
||||
[$width, $height, $type] = Helpers::falseToNull(@getimagesizefromstring($s)); // @ - strings smaller than 12 bytes causes read error
|
||||
return $type && isset(self::Formats[$type]) ? $type : null;
|
||||
@@ -314,7 +321,7 @@ public static function isTypeSupported(int $type): bool
|
||||
}
|
||||
|
||||
|
||||
/** @return ImageType[] */
|
||||
/** @return ImageType::*[] */
|
||||
public static function getSupportedTypes(): array
|
||||
{
|
||||
self::ensureExtension();
|
||||
@@ -386,6 +393,10 @@ public function getImageResource(): \GdImage
|
||||
public function resize(int|string|null $width, int|string|null $height, int $mode = self::OrSmaller): static
|
||||
{
|
||||
if ($mode & self::Cover) {
|
||||
if ($width === null || $height === null) {
|
||||
throw new Nette\InvalidArgumentException('Both width and height must be set for Cover mode.');
|
||||
}
|
||||
|
||||
return $this->resize($width, $height, self::OrBigger)->crop('50%', '50%', $width, $height);
|
||||
}
|
||||
|
||||
@@ -419,12 +430,13 @@ public function resize(int|string|null $width, int|string|null $height, int $mod
|
||||
/**
|
||||
* Calculates dimensions of resized image. Width and height accept pixels or percent.
|
||||
* @param int-mask-of<self::OrSmaller|self::OrBigger|self::Stretch|self::Cover|self::ShrinkOnly> $mode
|
||||
* @return array{int<1, max>, int<1, max>}
|
||||
*/
|
||||
public static function calculateSize(
|
||||
int $srcWidth,
|
||||
int $srcHeight,
|
||||
$newWidth,
|
||||
$newHeight,
|
||||
int|string|null $newWidth,
|
||||
int|string|null $newHeight,
|
||||
int $mode = self::OrSmaller,
|
||||
): array
|
||||
{
|
||||
@@ -468,19 +480,19 @@ public static function calculateSize(
|
||||
}
|
||||
|
||||
if ($mode & self::OrBigger) {
|
||||
$scale = [max($scale)];
|
||||
$scale = [max($scale ?: [1])];
|
||||
}
|
||||
|
||||
if ($mode & self::ShrinkOnly) {
|
||||
$scale[] = 1;
|
||||
}
|
||||
|
||||
$scale = min($scale);
|
||||
$scale = min($scale ?: [1]);
|
||||
$newWidth = (int) round($srcWidth * $scale);
|
||||
$newHeight = (int) round($srcHeight * $scale);
|
||||
}
|
||||
|
||||
return [max($newWidth, 1), max($newHeight, 1)];
|
||||
return [max((int) $newWidth, 1), max((int) $newHeight, 1)];
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +507,7 @@ public function crop(int|string $left, int|string $top, int|string $width, int|s
|
||||
$this->image = imagecrop($this->image, $r);
|
||||
imagesavealpha($this->image, true);
|
||||
} else {
|
||||
$newImage = static::fromBlank($r['width'], $r['height'], ImageColor::rgb(0, 0, 0, 0))->getImageResource();
|
||||
$newImage = static::fromBlank(max(1, $r['width']), max(1, $r['height']), ImageColor::rgb(0, 0, 0, 0))->getImageResource();
|
||||
imagecopy($newImage, $this->image, 0, 0, $r['x'], $r['y'], $r['width'], $r['height']);
|
||||
$this->image = $newImage;
|
||||
}
|
||||
@@ -506,6 +518,7 @@ public function crop(int|string $left, int|string $top, int|string $width, int|s
|
||||
|
||||
/**
|
||||
* Calculates dimensions of cutout in image. Arguments accepts pixels or percent.
|
||||
* @return array{int, int, int, int}
|
||||
*/
|
||||
public static function calculateCutout(
|
||||
int $srcWidth,
|
||||
@@ -516,21 +529,10 @@ public static function calculateCutout(
|
||||
int|string $newHeight,
|
||||
): array
|
||||
{
|
||||
if (self::isPercent($newWidth)) {
|
||||
$newWidth = (int) round($srcWidth / 100 * $newWidth);
|
||||
}
|
||||
|
||||
if (self::isPercent($newHeight)) {
|
||||
$newHeight = (int) round($srcHeight / 100 * $newHeight);
|
||||
}
|
||||
|
||||
if (self::isPercent($left)) {
|
||||
$left = (int) round(($srcWidth - $newWidth) / 100 * $left);
|
||||
}
|
||||
|
||||
if (self::isPercent($top)) {
|
||||
$top = (int) round(($srcHeight - $newHeight) / 100 * $top);
|
||||
}
|
||||
$newWidth = (int) (self::isPercent($newWidth) ? round($srcWidth / 100 * $newWidth) : $newWidth);
|
||||
$newHeight = (int) (self::isPercent($newHeight) ? round($srcHeight / 100 * $newHeight) : $newHeight);
|
||||
$left = (int) (self::isPercent($left) ? round(($srcWidth - $newWidth) / 100 * $left) : $left);
|
||||
$top = (int) (self::isPercent($top) ? round(($srcHeight - $newHeight) / 100 * $top) : $top);
|
||||
|
||||
if ($left < 0) {
|
||||
$newWidth += $left;
|
||||
@@ -575,14 +577,8 @@ public function place(self $image, int|string $left = 0, int|string $top = 0, in
|
||||
|
||||
$width = $image->getWidth();
|
||||
$height = $image->getHeight();
|
||||
|
||||
if (self::isPercent($left)) {
|
||||
$left = (int) round(($this->getWidth() - $width) / 100 * $left);
|
||||
}
|
||||
|
||||
if (self::isPercent($top)) {
|
||||
$top = (int) round(($this->getHeight() - $height) / 100 * $top);
|
||||
}
|
||||
$left = (int) (self::isPercent($left) ? round(($this->getWidth() - $width) / 100 * $left) : $left);
|
||||
$top = (int) (self::isPercent($top) ? round(($this->getHeight() - $height) / 100 * $top) : $top);
|
||||
|
||||
$output = $input = $image->image;
|
||||
if ($opacity < 100) {
|
||||
@@ -595,7 +591,7 @@ public function place(self $image, int|string $left = 0, int|string $top = 0, in
|
||||
imagealphablending($output, false);
|
||||
if (!$image->isTrueColor()) {
|
||||
$input = $output;
|
||||
imagefilledrectangle($output, 0, 0, $width, $height, imagecolorallocatealpha($output, 0, 0, 0, 127));
|
||||
imagefilledrectangle($output, 0, 0, $width, $height, (int) imagecolorallocatealpha($output, 0, 0, 0, 127));
|
||||
imagecopy($output, $image->image, 0, 0, 0, 0, $width, $height);
|
||||
}
|
||||
|
||||
@@ -626,6 +622,8 @@ public function place(self $image, int|string $left = 0, int|string $top = 0, in
|
||||
|
||||
/**
|
||||
* Calculates the bounding box for a TrueType text. Returns keys left, top, width and height.
|
||||
* @param array<string, mixed> $options
|
||||
* @return array{left: int, top: int, width: int, height: int}
|
||||
*/
|
||||
public static function calculateTextBox(
|
||||
string $text,
|
||||
@@ -670,7 +668,7 @@ public function filledRectangleWH(int $x, int $y, int $width, int $height, Image
|
||||
|
||||
/**
|
||||
* Saves image to the file. Quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9).
|
||||
* @param ImageType::*|null $type
|
||||
* @param ?ImageType::* $type
|
||||
* @throws ImageException
|
||||
*/
|
||||
public function save(string $file, ?int $quality = null, ?int $type = null): void
|
||||
@@ -746,6 +744,7 @@ private function output(int $type, ?int $quality, ?string $file = null): void
|
||||
|
||||
/**
|
||||
* Call to undefined method.
|
||||
* @param mixed[] $args
|
||||
* @throws Nette\MemberAccessException
|
||||
*/
|
||||
public function __call(string $name, array $args): mixed
|
||||
@@ -760,6 +759,7 @@ public function __call(string $name, array $args): mixed
|
||||
$args[$key] = $value->getImageResource();
|
||||
|
||||
} elseif ($value instanceof ImageColor || (is_array($value) && isset($value['red']))) {
|
||||
/** @var ImageColor|array{red: int, green: int, blue: int, alpha?: int} $value */
|
||||
$args[$key] = $this->resolveColor($value);
|
||||
}
|
||||
}
|
||||
@@ -775,10 +775,11 @@ public function __clone()
|
||||
{
|
||||
ob_start(fn() => '');
|
||||
imagepng($this->image, null, 0);
|
||||
$this->setImageResource(imagecreatefromstring(ob_get_clean()));
|
||||
$this->setImageResource(imagecreatefromstring(ob_get_clean()) ?: throw new Nette\ShouldNotHappenException);
|
||||
}
|
||||
|
||||
|
||||
/** @param-out int|float $num */
|
||||
private static function isPercent(int|string &$num): bool
|
||||
{
|
||||
if (is_string($num) && str_ends_with($num, '%')) {
|
||||
@@ -802,13 +803,30 @@ public function __serialize(): array
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ImageColor|array{red: int, green: int, blue: int, alpha?: int} $color
|
||||
*/
|
||||
public function resolveColor(ImageColor|array $color): int
|
||||
{
|
||||
$color = $color instanceof ImageColor ? $color->toRGBA() : array_values($color);
|
||||
$color = self::normalizeColor($color)->toRGBA();
|
||||
return imagecolorallocatealpha($this->image, ...$color) ?: imagecolorresolvealpha($this->image, ...$color);
|
||||
}
|
||||
|
||||
|
||||
/** @param ImageColor|array{red: int, green: int, blue: int, alpha?: int} $color */
|
||||
private static function normalizeColor(ImageColor|array $color): ImageColor
|
||||
{
|
||||
return $color instanceof ImageColor
|
||||
? $color
|
||||
: ImageColor::rgb(
|
||||
$color['red'],
|
||||
$color['green'],
|
||||
$color['blue'],
|
||||
(127 - ($color['alpha'] ?? 0)) / 127,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static function ensureExtension(): void
|
||||
{
|
||||
if (!extension_loaded('gd')) {
|
||||
|
||||
4
vendor/nette/utils/src/Utils/ImageColor.php
vendored
4
vendor/nette/utils/src/Utils/ImageColor.php
vendored
@@ -64,6 +64,10 @@ private function __construct(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns GD-compatible color array [R, G, B, alpha].
|
||||
* @return array{int<0, 255>, int<0, 255>, int<0, 255>, int<0, 127>}
|
||||
*/
|
||||
public function toRGBA(): array
|
||||
{
|
||||
return [
|
||||
|
||||
24
vendor/nette/utils/src/Utils/Iterables.php
vendored
24
vendor/nette/utils/src/Utils/Iterables.php
vendored
@@ -22,6 +22,7 @@ final class Iterables
|
||||
|
||||
/**
|
||||
* Tests for the presence of value.
|
||||
* @param iterable<mixed> $iterable
|
||||
*/
|
||||
public static function contains(iterable $iterable, mixed $value): bool
|
||||
{
|
||||
@@ -36,6 +37,7 @@ public static function contains(iterable $iterable, mixed $value): bool
|
||||
|
||||
/**
|
||||
* Tests for the presence of key.
|
||||
* @param iterable<mixed> $iterable
|
||||
*/
|
||||
public static function containsKey(iterable $iterable, mixed $key): bool
|
||||
{
|
||||
@@ -52,9 +54,11 @@ public static function containsKey(iterable $iterable, mixed $key): bool
|
||||
* Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
||||
* @template K
|
||||
* @template V
|
||||
* @template E
|
||||
* @param iterable<K, V> $iterable
|
||||
* @param ?callable(V, K, iterable<K, V>): bool $predicate
|
||||
* @return ?V
|
||||
* @param ?callable(): E $else
|
||||
* @return ($else is null ? ?V : V|E)
|
||||
*/
|
||||
public static function first(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed
|
||||
{
|
||||
@@ -71,9 +75,11 @@ public static function first(iterable $iterable, ?callable $predicate = null, ?c
|
||||
* Returns the key of first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
||||
* @template K
|
||||
* @template V
|
||||
* @template E
|
||||
* @param iterable<K, V> $iterable
|
||||
* @param ?callable(V, K, iterable<K, V>): bool $predicate
|
||||
* @return ?K
|
||||
* @param ?callable(): E $else
|
||||
* @return ($else is null ? ?K : K|E)
|
||||
*/
|
||||
public static function firstKey(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed
|
||||
{
|
||||
@@ -161,11 +167,11 @@ public static function map(iterable $iterable, callable $transformer): \Generato
|
||||
* Iterator that transforms keys and values by calling $transformer. If it returns null, the element is skipped.
|
||||
* @template K
|
||||
* @template V
|
||||
* @template ResV
|
||||
* @template ResK
|
||||
* @template ResV
|
||||
* @param iterable<K, V> $iterable
|
||||
* @param callable(V, K, iterable<K, V>): ?array{ResV, ResK} $transformer
|
||||
* @return \Generator<ResV, ResK>
|
||||
* @param callable(V, K, iterable<K, V>): ?array{ResK, ResV} $transformer
|
||||
* @return \Generator<ResK, ResV>
|
||||
*/
|
||||
public static function mapWithKeys(iterable $iterable, callable $transformer): \Generator
|
||||
{
|
||||
@@ -188,9 +194,10 @@ public static function mapWithKeys(iterable $iterable, callable $transformer): \
|
||||
*/
|
||||
public static function repeatable(callable $factory): \IteratorAggregate
|
||||
{
|
||||
return new class ($factory) implements \IteratorAggregate {
|
||||
return new class ($factory(...)) implements \IteratorAggregate {
|
||||
public function __construct(
|
||||
private $factory,
|
||||
/** @var \Closure(): iterable<mixed, mixed> */
|
||||
private \Closure $factory,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -215,7 +222,8 @@ public static function memoize(iterable $iterable): \IteratorAggregate
|
||||
{
|
||||
return new class (self::toIterator($iterable)) implements \IteratorAggregate {
|
||||
public function __construct(
|
||||
private \Iterator $iterator,
|
||||
private readonly \Iterator $iterator,
|
||||
/** @var array<array{mixed, mixed}> */
|
||||
private array $cache = [],
|
||||
) {
|
||||
}
|
||||
|
||||
53
vendor/nette/utils/src/Utils/Paginator.php
vendored
53
vendor/nette/utils/src/Utils/Paginator.php
vendored
@@ -17,17 +17,17 @@
|
||||
*
|
||||
* @property int $page
|
||||
* @property-read int $firstPage
|
||||
* @property-read int|null $lastPage
|
||||
* @property-read ?int $lastPage
|
||||
* @property-read int<0,max> $firstItemOnPage
|
||||
* @property-read int<0,max> $lastItemOnPage
|
||||
* @property int $base
|
||||
* @property-read bool $first
|
||||
* @property-read bool $last
|
||||
* @property-read int<0,max>|null $pageCount
|
||||
* @property-read ?int<0,max> $pageCount
|
||||
* @property positive-int $itemsPerPage
|
||||
* @property int<0,max>|null $itemCount
|
||||
* @property ?int<0,max> $itemCount
|
||||
* @property-read int<0,max> $offset
|
||||
* @property-read int<0,max>|null $countdownOffset
|
||||
* @property-read ?int<0,max> $countdownOffset
|
||||
* @property-read int<0,max> $length
|
||||
*/
|
||||
class Paginator
|
||||
@@ -41,13 +41,10 @@ class Paginator
|
||||
|
||||
private int $page = 1;
|
||||
|
||||
/** @var int<0, max>|null */
|
||||
/** @var ?int<0, max> */
|
||||
private ?int $itemCount = null;
|
||||
|
||||
|
||||
/**
|
||||
* Sets current page number.
|
||||
*/
|
||||
public function setPage(int $page): static
|
||||
{
|
||||
$this->page = $page;
|
||||
@@ -55,27 +52,18 @@ public function setPage(int $page): static
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns current page number.
|
||||
*/
|
||||
public function getPage(): int
|
||||
{
|
||||
return $this->base + $this->getPageIndex();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns first page number.
|
||||
*/
|
||||
public function getFirstPage(): int
|
||||
{
|
||||
return $this->base;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns last page number.
|
||||
*/
|
||||
public function getLastPage(): ?int
|
||||
{
|
||||
return $this->itemCount === null
|
||||
@@ -106,9 +94,6 @@ public function getLastItemOnPage(): int
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets first page (base) number.
|
||||
*/
|
||||
public function setBase(int $base): static
|
||||
{
|
||||
$this->base = $base;
|
||||
@@ -116,9 +101,6 @@ public function setBase(int $base): static
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns first page (base) number.
|
||||
*/
|
||||
public function getBase(): int
|
||||
{
|
||||
return $this->base;
|
||||
@@ -138,18 +120,12 @@ protected function getPageIndex(): int
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the current page the first one?
|
||||
*/
|
||||
public function isFirst(): bool
|
||||
{
|
||||
return $this->getPageIndex() === 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the current page the last one?
|
||||
*/
|
||||
public function isLast(): bool
|
||||
{
|
||||
return $this->itemCount === null
|
||||
@@ -159,20 +135,16 @@ public function isLast(): bool
|
||||
|
||||
|
||||
/**
|
||||
* Returns the total number of pages.
|
||||
* @return int<0, max>|null
|
||||
* @return ?int<0, max>
|
||||
*/
|
||||
public function getPageCount(): ?int
|
||||
{
|
||||
return $this->itemCount === null
|
||||
? null
|
||||
: (int) ceil($this->itemCount / $this->itemsPerPage);
|
||||
: max(0, (int) ceil($this->itemCount / $this->itemsPerPage));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the number of items to display on a single page.
|
||||
*/
|
||||
public function setItemsPerPage(int $itemsPerPage): static
|
||||
{
|
||||
$this->itemsPerPage = max(1, $itemsPerPage);
|
||||
@@ -181,7 +153,6 @@ public function setItemsPerPage(int $itemsPerPage): static
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of items to display on a single page.
|
||||
* @return positive-int
|
||||
*/
|
||||
public function getItemsPerPage(): int
|
||||
@@ -190,9 +161,6 @@ public function getItemsPerPage(): int
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the total number of items.
|
||||
*/
|
||||
public function setItemCount(?int $itemCount = null): static
|
||||
{
|
||||
$this->itemCount = $itemCount === null ? null : max(0, $itemCount);
|
||||
@@ -201,8 +169,7 @@ public function setItemCount(?int $itemCount = null): static
|
||||
|
||||
|
||||
/**
|
||||
* Returns the total number of items.
|
||||
* @return int<0, max>|null
|
||||
* @return ?int<0, max>
|
||||
*/
|
||||
public function getItemCount(): ?int
|
||||
{
|
||||
@@ -222,7 +189,7 @@ public function getOffset(): int
|
||||
|
||||
/**
|
||||
* Returns the absolute index of the first item on current page in countdown paging.
|
||||
* @return int<0, max>|null
|
||||
* @return ?int<0, max>
|
||||
*/
|
||||
public function getCountdownOffset(): ?int
|
||||
{
|
||||
@@ -240,6 +207,6 @@ public function getLength(): int
|
||||
{
|
||||
return $this->itemCount === null
|
||||
? $this->itemsPerPage
|
||||
: min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage);
|
||||
: max(0, min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage));
|
||||
}
|
||||
}
|
||||
|
||||
24
vendor/nette/utils/src/Utils/Reflection.php
vendored
24
vendor/nette/utils/src/Utils/Reflection.php
vendored
@@ -38,7 +38,7 @@ public static function isClassKeyword(string $name): bool
|
||||
public static function getParameterDefaultValue(\ReflectionParameter $param): mixed
|
||||
{
|
||||
if ($param->isDefaultValueConstant()) {
|
||||
$const = $orig = $param->getDefaultValueConstantName();
|
||||
$const = $orig = $param->getDefaultValueConstantName() ?? throw new Nette\ShouldNotHappenException;
|
||||
$pair = explode('::', $const);
|
||||
if (isset($pair[1])) {
|
||||
$pair[0] = Type::resolve($pair[0], $param);
|
||||
@@ -68,6 +68,7 @@ public static function getParameterDefaultValue(\ReflectionParameter $param): mi
|
||||
|
||||
/**
|
||||
* Returns a reflection of a class or trait that contains a declaration of given property. Property can also be declared in the trait.
|
||||
* @return \ReflectionClass<object>
|
||||
*/
|
||||
public static function getPropertyDeclaringClass(\ReflectionProperty $prop): \ReflectionClass
|
||||
{
|
||||
@@ -151,6 +152,7 @@ public static function toString(\Reflector $ref): string
|
||||
/**
|
||||
* Expands the name of the class to full name in the given context of given class.
|
||||
* Thus, it returns how the PHP parser would understand $name if it were written in the body of the class $context.
|
||||
* @param \ReflectionClass<object> $context
|
||||
* @throws Nette\InvalidArgumentException
|
||||
*/
|
||||
public static function expandClassName(string $name, \ReflectionClass $context): string
|
||||
@@ -189,7 +191,10 @@ public static function expandClassName(string $name, \ReflectionClass $context):
|
||||
}
|
||||
|
||||
|
||||
/** @return array<string, class-string> of [alias => class] */
|
||||
/**
|
||||
* @param \ReflectionClass<object> $class
|
||||
* @return array<string, class-string> of [alias => class]
|
||||
*/
|
||||
public static function getUseStatements(\ReflectionClass $class): array
|
||||
{
|
||||
if ($class->isAnonymous()) {
|
||||
@@ -201,7 +206,7 @@ public static function getUseStatements(\ReflectionClass $class): array
|
||||
if ($class->isInternal()) {
|
||||
$cache[$name] = [];
|
||||
} else {
|
||||
$code = file_get_contents($class->getFileName());
|
||||
$code = (string) file_get_contents((string) $class->getFileName());
|
||||
$cache = self::parseUseStatements($code, $name) + $cache;
|
||||
}
|
||||
}
|
||||
@@ -212,6 +217,7 @@ public static function getUseStatements(\ReflectionClass $class): array
|
||||
|
||||
/**
|
||||
* Parses PHP code to [class => [alias => class, ...]]
|
||||
* @return array<string, array<string, string>>
|
||||
*/
|
||||
private static function parseUseStatements(string $code, ?string $forClass = null): array
|
||||
{
|
||||
@@ -256,8 +262,8 @@ private static function parseUseStatements(string $code, ?string $forClass = nul
|
||||
$name = ltrim($name, '\\');
|
||||
if (self::fetch($tokens, '{')) {
|
||||
while ($suffix = self::fetch($tokens, $nameTokens)) {
|
||||
if (self::fetch($tokens, T_AS)) {
|
||||
$uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
|
||||
if (self::fetch($tokens, T_AS) && ($alias = self::fetch($tokens, T_STRING))) {
|
||||
$uses[$alias] = $name . $suffix;
|
||||
} else {
|
||||
$tmp = explode('\\', $suffix);
|
||||
$uses[end($tmp)] = $name . $suffix;
|
||||
@@ -267,8 +273,8 @@ private static function parseUseStatements(string $code, ?string $forClass = nul
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif (self::fetch($tokens, T_AS)) {
|
||||
$uses[self::fetch($tokens, T_STRING)] = $name;
|
||||
} elseif (self::fetch($tokens, T_AS) && ($alias = self::fetch($tokens, T_STRING))) {
|
||||
$uses[$alias] = $name;
|
||||
|
||||
} else {
|
||||
$tmp = explode('\\', $name);
|
||||
@@ -301,6 +307,10 @@ private static function parseUseStatements(string $code, ?string $forClass = nul
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \PhpToken[] $tokens
|
||||
* @param string|int|int[] $take
|
||||
*/
|
||||
private static function fetch(array &$tokens, string|int|array $take): ?string
|
||||
{
|
||||
$res = null;
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
*/
|
||||
final class ReflectionMethod extends \ReflectionMethod
|
||||
{
|
||||
private \ReflectionClass $originalClass;
|
||||
/** @var \ReflectionClass<object> */
|
||||
private readonly \ReflectionClass $originalClass;
|
||||
|
||||
|
||||
/** @param class-string|object $objectOrMethod */
|
||||
public function __construct(object|string $objectOrMethod, ?string $method = null)
|
||||
{
|
||||
if (is_string($objectOrMethod) && str_contains($objectOrMethod, '::')) {
|
||||
@@ -31,6 +33,7 @@ public function __construct(object|string $objectOrMethod, ?string $method = nul
|
||||
}
|
||||
|
||||
|
||||
/** @return \ReflectionClass<object> */
|
||||
public function getOriginalClass(): \ReflectionClass
|
||||
{
|
||||
return $this->originalClass;
|
||||
|
||||
63
vendor/nette/utils/src/Utils/Strings.php
vendored
63
vendor/nette/utils/src/Utils/Strings.php
vendored
@@ -59,7 +59,8 @@ public static function chr(int $code): string
|
||||
throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.');
|
||||
}
|
||||
|
||||
return iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code));
|
||||
$res = iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code));
|
||||
return $res === false ? throw new Nette\ShouldNotHappenException : $res;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,11 +74,11 @@ public static function ord(string $c): int
|
||||
}
|
||||
|
||||
$tmp = iconv('UTF-8', 'UTF-32BE//IGNORE', $c);
|
||||
if (!$tmp) {
|
||||
if ($tmp === false || $tmp === '') {
|
||||
throw new Nette\InvalidArgumentException('Invalid UTF-8 character "' . ($c === '' ? '' : '\x' . strtoupper(bin2hex($c))) . '".');
|
||||
}
|
||||
|
||||
return unpack('N', $tmp)[1];
|
||||
return unpack('N', $tmp)[1] ?? throw new Nette\ShouldNotHappenException;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +125,8 @@ public static function substring(string $s, int $start, ?int $length = null): st
|
||||
$start += self::length($s); // unifies iconv_substr behavior with mb_substr
|
||||
}
|
||||
|
||||
return iconv_substr($s, $start, $length, 'UTF-8');
|
||||
$res = iconv_substr($s, $start, $length, 'UTF-8');
|
||||
return $res === false ? throw new Nette\InvalidStateException('iconv_substr() failed.') : $res;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +137,7 @@ public static function substring(string $s, int $start, ?int $length = null): st
|
||||
public static function normalize(string $s): string
|
||||
{
|
||||
// convert to compressed normal form (NFC)
|
||||
if (class_exists('Normalizer', false) && ($n = \Normalizer::normalize($s, \Normalizer::FORM_C)) !== false) {
|
||||
if (class_exists('Normalizer', autoload: false) && ($n = \Normalizer::normalize($s, \Normalizer::FORM_C)) !== false) {
|
||||
$s = $n;
|
||||
}
|
||||
|
||||
@@ -201,14 +203,23 @@ public static function toAscii(string $s): string
|
||||
$s = strtr($s, ["\u{AE}" => '(R)', "\u{A9}" => '(c)', "\u{2026}" => '...', "\u{AB}" => '<<', "\u{BB}" => '>>', "\u{A3}" => 'lb', "\u{A5}" => 'yen', "\u{B2}" => '^2', "\u{B3}" => '^3', "\u{B5}" => 'u', "\u{B9}" => '^1', "\u{BA}" => 'o', "\u{BF}" => '?', "\u{2CA}" => "'", "\u{2CD}" => '_', "\u{2DD}" => '"', "\u{1FEF}" => '', "\u{20AC}" => 'EUR', "\u{2122}" => 'TM', "\u{212E}" => 'e', "\u{2190}" => '<-', "\u{2191}" => '^', "\u{2192}" => '->', "\u{2193}" => 'V', "\u{2194}" => '<->']); // ® © … « » £ ¥ ² ³ µ ¹ º ¿ ˊ ˍ ˝ ` € ™ ℮ ← ↑ → ↓ ↔
|
||||
}
|
||||
|
||||
$s = \Transliterator::create('Any-Latin; Latin-ASCII')->transliterate($s);
|
||||
$s = \Transliterator::create('Any-Latin; Latin-ASCII')?->transliterate($s)
|
||||
?? throw new Nette\InvalidStateException('Transliterator::transliterate() failed.');
|
||||
|
||||
// use iconv because The transliterator leaves some characters out of ASCII, eg → ʾ
|
||||
if ($iconv === 'glibc') {
|
||||
$s = strtr($s, '?', "\x01"); // temporarily hide ? to distinguish them from the garbage that iconv creates
|
||||
$s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
|
||||
if ($s === false) {
|
||||
throw new Nette\InvalidStateException('iconv() failed.');
|
||||
}
|
||||
|
||||
$s = str_replace(['?', "\x01"], ['', '?'], $s); // remove garbage and restore ? characters
|
||||
} elseif ($iconv === 'libiconv') {
|
||||
$s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
|
||||
if ($s === false) {
|
||||
throw new Nette\InvalidStateException('iconv() failed.');
|
||||
}
|
||||
} else { // null or 'unknown' (#216)
|
||||
$s = self::pcre('preg_replace', ['#[^\x00-\x7F]++#', '', $s]); // remove non-ascii chars
|
||||
}
|
||||
@@ -323,7 +334,7 @@ public static function capitalize(string $s): string
|
||||
*/
|
||||
public static function compare(string $left, string $right, ?int $length = null): bool
|
||||
{
|
||||
if (class_exists('Normalizer', false)) {
|
||||
if (class_exists('Normalizer', autoload: false)) {
|
||||
$left = \Normalizer::normalize($left, \Normalizer::FORM_D); // form NFD is faster
|
||||
$right = \Normalizer::normalize($right, \Normalizer::FORM_D); // form NFD is faster
|
||||
}
|
||||
@@ -347,6 +358,10 @@ public static function compare(string $left, string $right, ?int $length = null)
|
||||
public static function findPrefix(array $strings): string
|
||||
{
|
||||
$first = array_shift($strings);
|
||||
if ($first === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
for ($i = 0; $i < strlen($first); $i++) {
|
||||
foreach ($strings as $s) {
|
||||
if (!isset($s[$i]) || $first[$i] !== $s[$i]) {
|
||||
@@ -370,8 +385,8 @@ public static function findPrefix(array $strings): string
|
||||
public static function length(string $s): int
|
||||
{
|
||||
return match (true) {
|
||||
extension_loaded('mbstring') => mb_strlen($s, 'UTF-8'),
|
||||
extension_loaded('iconv') => iconv_strlen($s, 'UTF-8'),
|
||||
extension_loaded('mbstring') => (int) mb_strlen($s, 'UTF-8'),
|
||||
extension_loaded('iconv') => (int) iconv_strlen($s, 'UTF-8'),
|
||||
default => strlen(@utf8_decode($s)), // deprecated
|
||||
};
|
||||
}
|
||||
@@ -420,7 +435,10 @@ public static function reverse(string $s): string
|
||||
throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.');
|
||||
}
|
||||
|
||||
return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', $s)));
|
||||
$tmp = iconv('UTF-8', 'UTF-32BE', $s);
|
||||
return $tmp === false
|
||||
? throw new Nette\InvalidStateException('iconv() failed.')
|
||||
: (string) iconv('UTF-32LE', 'UTF-8', strrev($tmp));
|
||||
}
|
||||
|
||||
|
||||
@@ -499,6 +517,7 @@ private static function pos(string $haystack, string $needle, int $nth = 1): ?in
|
||||
|
||||
/**
|
||||
* Divides the string into arrays according to the regular expression. Expressions in parentheses will be captured and returned as well.
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function split(
|
||||
string $subject,
|
||||
@@ -525,6 +544,7 @@ public static function split(
|
||||
/**
|
||||
* Searches the string for the part matching the regular expression and returns
|
||||
* an array with the found expression and individual subexpressions, or `null`.
|
||||
* @return ?array<string>
|
||||
*/
|
||||
public static function match(
|
||||
string $subject,
|
||||
@@ -545,6 +565,7 @@ public static function match(
|
||||
$pattern .= 'u';
|
||||
}
|
||||
|
||||
$m = [];
|
||||
if ($offset > strlen($subject)) {
|
||||
return null;
|
||||
} elseif (!self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])) {
|
||||
@@ -560,7 +581,7 @@ public static function match(
|
||||
/**
|
||||
* Searches the string for all occurrences matching the regular expression and
|
||||
* returns an array of arrays containing the found expression and each subexpression.
|
||||
* @return ($lazy is true ? \Generator<int, array> : array[])
|
||||
* @return ($lazy is true ? \Generator<int, array<string>> : list<array<string>>)
|
||||
*/
|
||||
public static function matchAll(
|
||||
string $subject,
|
||||
@@ -583,10 +604,12 @@ public static function matchAll(
|
||||
$flags = PREG_OFFSET_CAPTURE | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0);
|
||||
return (function () use ($utf8, $captureOffset, $flags, $subject, $pattern, $offset) {
|
||||
$counter = 0;
|
||||
$m = [];
|
||||
while (
|
||||
$offset <= strlen($subject) - ($counter ? 1 : 0)
|
||||
&& self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])
|
||||
) {
|
||||
/** @var list<array{string, int}> $m */
|
||||
$offset = $m[0][1] + max(1, strlen($m[0][0]));
|
||||
if (!$captureOffset) {
|
||||
$m = array_map(fn($item) => $item[0], $m);
|
||||
@@ -606,6 +629,7 @@ public static function matchAll(
|
||||
? $captureOffset
|
||||
: ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0) | ($patternOrder ? PREG_PATTERN_ORDER : 0);
|
||||
|
||||
$m = [];
|
||||
self::pcre('preg_match_all', [
|
||||
$pattern, $subject, &$m,
|
||||
($flags & PREG_PATTERN_ORDER) ? $flags : ($flags | PREG_SET_ORDER),
|
||||
@@ -619,6 +643,7 @@ public static function matchAll(
|
||||
|
||||
/**
|
||||
* Replaces all occurrences matching regular expression $pattern which can be string or array in the form `pattern => replacement`.
|
||||
* @param string|array<string, string> $pattern
|
||||
*/
|
||||
public static function replace(
|
||||
string $subject,
|
||||
@@ -638,7 +663,7 @@ public static function replace(
|
||||
|
||||
$flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0);
|
||||
if ($utf8) {
|
||||
$pattern .= 'u';
|
||||
$pattern = is_array($pattern) ? array_map(fn($item) => $item . 'u', $pattern) : $pattern . 'u';
|
||||
if ($captureOffset) {
|
||||
$replacement = fn($m) => $replacement(self::bytesToChars($subject, [$m])[0]);
|
||||
}
|
||||
@@ -659,6 +684,10 @@ public static function replace(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param list<array<array{string, int}>> $groups
|
||||
* @return list<array<array{string, int}>>
|
||||
*/
|
||||
private static function bytesToChars(string $s, array $groups): array
|
||||
{
|
||||
$lastBytes = $lastChars = 0;
|
||||
@@ -679,8 +708,12 @@ private static function bytesToChars(string $s, array $groups): array
|
||||
}
|
||||
|
||||
|
||||
/** @internal */
|
||||
public static function pcre(string $func, array $args)
|
||||
/**
|
||||
* @param callable-string $func
|
||||
* @param list<mixed> $args
|
||||
* @internal
|
||||
*/
|
||||
public static function pcre(string $func, array $args): mixed
|
||||
{
|
||||
$res = Callback::invokeSafe($func, $args, function (string $message) use ($args): void {
|
||||
// compile-time error, not detectable by preg_last_error
|
||||
@@ -688,7 +721,7 @@ public static function pcre(string $func, array $args)
|
||||
});
|
||||
|
||||
if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars
|
||||
&& ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], true))
|
||||
&& ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], strict: true))
|
||||
) {
|
||||
throw new RegexpException(preg_last_error_msg()
|
||||
. ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code);
|
||||
|
||||
68
vendor/nette/utils/src/Utils/Type.php
vendored
68
vendor/nette/utils/src/Utils/Type.php
vendored
@@ -10,7 +10,7 @@
|
||||
namespace Nette\Utils;
|
||||
|
||||
use Nette;
|
||||
use function array_map, array_search, array_splice, count, explode, implode, is_a, is_resource, is_string, strcasecmp, strtolower, substr, trim;
|
||||
use function array_map, array_search, array_splice, array_values, count, explode, implode, is_a, is_resource, is_string, strcasecmp, strtolower, substr, trim;
|
||||
|
||||
|
||||
/**
|
||||
@@ -18,9 +18,9 @@
|
||||
*/
|
||||
final readonly class Type
|
||||
{
|
||||
/** @var array<int, string|self> */
|
||||
/** @var list<string|self> */
|
||||
private array $types;
|
||||
private bool $simple;
|
||||
private ?string $singleName;
|
||||
private string $kind; // | &
|
||||
|
||||
|
||||
@@ -40,7 +40,12 @@ public static function fromReflection(
|
||||
}
|
||||
|
||||
|
||||
private static function fromReflectionType(\ReflectionType $type, $of, bool $asObject): self|string
|
||||
/** @return ($asObject is true ? self : self|string) */
|
||||
private static function fromReflectionType(
|
||||
\ReflectionType $type,
|
||||
\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $of,
|
||||
bool $asObject,
|
||||
): self|string
|
||||
{
|
||||
if ($type instanceof \ReflectionNamedType) {
|
||||
$name = self::resolve($type->getName(), $of);
|
||||
@@ -107,34 +112,40 @@ public static function fromValue(mixed $value): self
|
||||
*/
|
||||
public static function resolve(
|
||||
string $type,
|
||||
\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $of,
|
||||
\ReflectionFunction|\ReflectionMethod|\ReflectionParameter|\ReflectionProperty $of,
|
||||
): string
|
||||
{
|
||||
$lower = strtolower($type);
|
||||
if ($of instanceof \ReflectionFunction) {
|
||||
return $type;
|
||||
}
|
||||
|
||||
$class = $of->getDeclaringClass();
|
||||
if ($class === null) {
|
||||
return $type;
|
||||
} elseif ($lower === 'self') {
|
||||
return $of->getDeclaringClass()->name;
|
||||
return $class->name;
|
||||
} elseif ($lower === 'static') {
|
||||
return ($of instanceof ReflectionMethod ? $of->getOriginalClass() : $of->getDeclaringClass())->name;
|
||||
} elseif ($lower === 'parent' && $of->getDeclaringClass()->getParentClass()) {
|
||||
return $of->getDeclaringClass()->getParentClass()->name;
|
||||
return ($of instanceof ReflectionMethod ? $of->getOriginalClass() : $class)->name;
|
||||
} elseif ($lower === 'parent' && $class->getParentClass()) {
|
||||
return $class->getParentClass()->name;
|
||||
} else {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @param array<string|self> $types */
|
||||
private function __construct(array $types, string $kind = '|')
|
||||
{
|
||||
$o = array_search('null', $types, strict: true);
|
||||
if ($o !== false) { // null as last
|
||||
array_splice($types, $o, 1);
|
||||
array_splice($types, (int) $o, 1);
|
||||
$types[] = 'null';
|
||||
}
|
||||
|
||||
$this->types = $types;
|
||||
$this->simple = is_string($types[0]) && ($types[1] ?? 'null') === 'null';
|
||||
$this->types = array_values($types);
|
||||
$this->singleName = is_string($types[0]) && ($types[1] ?? 'null') === 'null' ? $types[0] : null;
|
||||
$this->kind = count($types) > 1 ? $kind : '';
|
||||
}
|
||||
|
||||
@@ -142,8 +153,8 @@ private function __construct(array $types, string $kind = '|')
|
||||
public function __toString(): string
|
||||
{
|
||||
$multi = count($this->types) > 1;
|
||||
if ($this->simple) {
|
||||
return ($multi ? '?' : '') . $this->types[0];
|
||||
if ($this->singleName !== null) {
|
||||
return ($multi ? '?' : '') . $this->singleName;
|
||||
}
|
||||
|
||||
$res = [];
|
||||
@@ -173,7 +184,7 @@ public function with(string|self $type): self
|
||||
|
||||
/**
|
||||
* Returns the array of subtypes that make up the compound type as strings.
|
||||
* @return array<int, string|string[]>
|
||||
* @return list<string|array<string|array<mixed>>>
|
||||
*/
|
||||
public function getNames(): array
|
||||
{
|
||||
@@ -182,8 +193,8 @@ public function getNames(): array
|
||||
|
||||
|
||||
/**
|
||||
* Returns the array of subtypes that make up the compound type as Type objects:
|
||||
* @return self[]
|
||||
* Returns the array of subtypes that make up the compound type as Type objects.
|
||||
* @return list<self>
|
||||
*/
|
||||
public function getTypes(): array
|
||||
{
|
||||
@@ -196,9 +207,7 @@ public function getTypes(): array
|
||||
*/
|
||||
public function getSingleName(): ?string
|
||||
{
|
||||
return $this->simple
|
||||
? $this->types[0]
|
||||
: null;
|
||||
return $this->singleName;
|
||||
}
|
||||
|
||||
|
||||
@@ -225,14 +234,14 @@ public function isIntersection(): bool
|
||||
*/
|
||||
public function isSimple(): bool
|
||||
{
|
||||
return $this->simple;
|
||||
return $this->singleName !== null;
|
||||
}
|
||||
|
||||
|
||||
#[\Deprecated('use isSimple()')]
|
||||
public function isSingle(): bool
|
||||
{
|
||||
return $this->simple;
|
||||
return $this->singleName !== null;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +250,7 @@ public function isSingle(): bool
|
||||
*/
|
||||
public function isBuiltin(): bool
|
||||
{
|
||||
return $this->simple && Validators::isBuiltinType($this->types[0]);
|
||||
return $this->singleName !== null && Validators::isBuiltinType($this->singleName);
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +259,7 @@ public function isBuiltin(): bool
|
||||
*/
|
||||
public function isClass(): bool
|
||||
{
|
||||
return $this->simple && !Validators::isBuiltinType($this->types[0]);
|
||||
return $this->singleName !== null && !Validators::isBuiltinType($this->singleName);
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +268,7 @@ public function isClass(): bool
|
||||
*/
|
||||
public function isClassKeyword(): bool
|
||||
{
|
||||
return $this->simple && Validators::isClassKeyword($this->types[0]);
|
||||
return $this->singleName !== null && Validators::isClassKeyword($this->singleName);
|
||||
}
|
||||
|
||||
|
||||
@@ -279,6 +288,7 @@ public function allows(string|self $type): bool
|
||||
}
|
||||
|
||||
|
||||
/** @param array<string> $givenTypes */
|
||||
private function allowsAny(array $givenTypes): bool
|
||||
{
|
||||
return $this->isUnion()
|
||||
@@ -287,13 +297,17 @@ private function allowsAny(array $givenTypes): bool
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array<string> $ourTypes
|
||||
* @param array<string> $givenTypes
|
||||
*/
|
||||
private function allowsAll(array $ourTypes, array $givenTypes): bool
|
||||
{
|
||||
return Arrays::every(
|
||||
$ourTypes,
|
||||
fn($ourType) => Arrays::some(
|
||||
fn(string $ourType) => Arrays::some(
|
||||
$givenTypes,
|
||||
fn($givenType) => Validators::isBuiltinType($ourType)
|
||||
fn(string $givenType) => Validators::isBuiltinType($ourType)
|
||||
? strcasecmp($ourType, $givenType) === 0
|
||||
: is_a($givenType, $ourType, allow_string: true),
|
||||
),
|
||||
|
||||
15
vendor/nette/utils/src/Utils/Validators.php
vendored
15
vendor/nette/utils/src/Utils/Validators.php
vendored
@@ -26,7 +26,7 @@ class Validators
|
||||
'never' => 1, 'true' => 1,
|
||||
];
|
||||
|
||||
/** @var array<string,?callable> */
|
||||
/** @var array<string, ?(callable(mixed): bool)> */
|
||||
protected static $validators = [
|
||||
// PHP types
|
||||
'array' => 'is_array',
|
||||
@@ -76,7 +76,7 @@ class Validators
|
||||
'type' => [self::class, 'isType'],
|
||||
];
|
||||
|
||||
/** @var array<string,callable> */
|
||||
/** @var array<string, callable(mixed): int> */
|
||||
protected static $counters = [
|
||||
'string' => 'strlen',
|
||||
'unicode' => [Strings::class, 'length'],
|
||||
@@ -120,16 +120,16 @@ public static function assert(mixed $value, string $expected, string $label = 'v
|
||||
*/
|
||||
public static function assertField(
|
||||
array $array,
|
||||
$key,
|
||||
int|string $key,
|
||||
?string $expected = null,
|
||||
string $label = "item '%' in array",
|
||||
): void
|
||||
{
|
||||
if (!array_key_exists($key, $array)) {
|
||||
throw new AssertionException('Missing ' . str_replace('%', $key, $label) . '.');
|
||||
throw new AssertionException('Missing ' . str_replace('%', (string) $key, $label) . '.');
|
||||
|
||||
} elseif ($expected) {
|
||||
static::assert($array[$key], $expected, str_replace('%', $key, $label));
|
||||
static::assert($array[$key], $expected, str_replace('%', (string) $key, $label));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public static function is(mixed $value, string $expected): bool
|
||||
if (!static::$validators[$type]($value)) {
|
||||
continue;
|
||||
}
|
||||
} catch (\TypeError $e) {
|
||||
} catch (\TypeError) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($type === 'pattern') {
|
||||
@@ -261,7 +261,7 @@ public static function isUnicode(mixed $value): bool
|
||||
|
||||
/**
|
||||
* Checks if the value is 0, '', false or null.
|
||||
* @return ($value is 0|''|false|null ? true : false)
|
||||
* @return ($value is 0|0.0|''|false|null ? true : false)
|
||||
*/
|
||||
public static function isNone(mixed $value): bool
|
||||
{
|
||||
@@ -290,6 +290,7 @@ public static function isList(mixed $value): bool
|
||||
/**
|
||||
* Checks if the value is in the given range [min, max], where the upper or lower limit can be omitted (null).
|
||||
* Numbers, strings and DateTime objects can be compared.
|
||||
* @param array{int|float|string|\DateTimeInterface|null, int|float|string|\DateTimeInterface|null} $range
|
||||
*/
|
||||
public static function isInRange(mixed $value, array $range): bool
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user