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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Iterators/CachingIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
* @property-read bool $empty
* @property-read bool $odd
* @property-read bool $even
* @property-read int $counter
* @property-read int<0,max> $counter
* @property-read TKey $nextKey
* @property-read TValue $nextValue
*/
class CachingIterator extends \CachingIterator implements \Countable
{
use Nette\SmartObject;

/** @var int<0, max> */
private int $counter = 0;


Expand Down Expand Up @@ -78,6 +79,7 @@ public function isEven(): bool
}


/** @return int<0, max> */
public function getCounter(): int
{
return $this->counter;
Expand Down
1 change: 1 addition & 0 deletions src/Utils/ArrayHash.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function &getIterator(): \Iterator
}


/** @return int<0, max> */
public function count(): int
{
return count((array) $this);
Expand Down
1 change: 1 addition & 0 deletions src/Utils/ArrayList.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function &getIterator(): \Iterator
}


/** @return int<0, max> */
public function count(): int
{
return count($this->list);
Expand Down
14 changes: 9 additions & 5 deletions src/Utils/Arrays.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,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
* @return ?int<0, max>
*/
public static function getKeyOffset(array $array, string|int $key): ?int
{
Expand All @@ -104,6 +105,7 @@ public static function getKeyOffset(array $array, string|int $key): ?int

/**
* @param array<mixed> $array
* @return ?int<0, max>
* @deprecated use getKeyOffset()
*/
public static function searchKey(array $array, string|int $key): ?int
Expand Down Expand Up @@ -253,8 +255,9 @@ public static function renameKey(array &$array, string|int $oldKey, string|int $

/**
* Returns only those array items, which matches a regular expression $pattern.
* @param string[] $array
* @return string[]
* @template K of array-key
* @param array<K, string> $array
* @return array<K, string>
*/
public static function grep(
array $array,
Expand All @@ -271,7 +274,7 @@ public static function grep(
/**
* Transforms multidimensional array to flat array.
* @param array<mixed> $array
* @return array<mixed>
* @return ($preserveKeys is true ? array<mixed> : list<mixed>)
*/
public static function flatten(array $array, bool $preserveKeys = false): array
{
Expand Down Expand Up @@ -557,8 +560,9 @@ public static function toKey(mixed $value): int|string

/**
* Returns a copy of $array where every item is cast to string and wrapped with $prefix and $suffix.
* @param string[] $array
* @return string[]
* @template K of array-key
* @param array<K, string> $array
* @return array<K, string>
*/
public static function wrap(array $array, string $prefix = '', string $suffix = ''): array
{
Expand Down
1 change: 1 addition & 0 deletions src/Utils/Random.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ final class Random
/**
* Generates a random string of given length from characters specified in second argument.
* Supports intervals, such as `0-9` or `A-Z`.
* @return non-empty-string
*/
public static function generate(int $length = 10, string $charlist = '0-9a-z'): string
{
Expand Down
8 changes: 8 additions & 0 deletions src/Utils/Strings.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ public static function indent(string $s, int $level = 1, string $chars = "\t"):

/**
* Converts all characters of UTF-8 string to lower case.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function lower(string $s): string
{
Expand All @@ -301,6 +302,7 @@ public static function lower(string $s): string

/**
* Converts the first character of a UTF-8 string to lower case and leaves the other characters unchanged.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function firstLower(string $s): string
{
Expand All @@ -310,6 +312,7 @@ public static function firstLower(string $s): string

/**
* Converts all characters of a UTF-8 string to upper case.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function upper(string $s): string
{
Expand All @@ -319,6 +322,7 @@ public static function upper(string $s): string

/**
* Converts the first character of a UTF-8 string to upper case and leaves the other characters unchanged.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function firstUpper(string $s): string
{
Expand All @@ -328,6 +332,7 @@ public static function firstUpper(string $s): string

/**
* Converts the first character of every word of a UTF-8 string to upper case and the others to lower case.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function capitalize(string $s): string
{
Expand Down Expand Up @@ -389,6 +394,7 @@ public static function findPrefix(array $strings): string
/**
* Returns number of characters (not bytes) in UTF-8 string.
* That is the number of Unicode code points which may differ from the number of graphemes.
* @return ($s is non-empty-string ? int<1, max> : 0)
*/
public static function length(string $s): int
{
Expand Down Expand Up @@ -436,6 +442,7 @@ public static function padRight(string $s, int $length, string $pad = ' '): stri

/**
* Reverses UTF-8 string.
* @return ($s is non-empty-string ? non-empty-string : string)
*/
public static function reverse(string $s): string
{
Expand Down Expand Up @@ -479,6 +486,7 @@ public static function after(string $haystack, string $needle, int $nth = 1): ?s
/**
* Returns position in characters of $nth occurence of $needle in $haystack or null if the $needle was not found.
* Negative value of `$nth` means searching from the end.
* @return ?int<0, max>
*/
public static function indexOf(string $haystack, string $needle, int $nth = 1): ?int
{
Expand Down
1 change: 1 addition & 0 deletions src/Utils/Validators.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ public static function isCallable(mixed $value): bool

/**
* Checks if the value is a valid UTF-8 string.
* @phpstan-assert-if-true string $value
*/
public static function isUnicode(mixed $value): bool
{
Expand Down
14 changes: 14 additions & 0 deletions tests/Iterators/CachingIterator.basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,17 @@ test('', function () {
Assert::same(0, $iterator->getCounter());
Assert::true($iterator->isEmpty());
});


test('magic properties', function () {
$iterator = new Iterators\CachingIterator(['a' => 'Nette', 'b' => 'Framework']);
$iterator->rewind();
Assert::true($iterator->first);
Assert::false($iterator->last);
Assert::false($iterator->empty);
Assert::true($iterator->odd);
Assert::false($iterator->even);
Assert::same(1, $iterator->counter);
Assert::same('b', $iterator->nextKey);
Assert::same('Framework', $iterator->nextValue);
});
86 changes: 85 additions & 1 deletion tests/types/utils-types.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

use Nette\Iterators\CachingIterator;
use Nette\Utils\{ArrayHash, Arrays, Helpers, Html, Iterables, Type, Validators};
use Nette\Utils\{ArrayHash, ArrayList, Arrays, Helpers, Html, Iterables, Random, Strings, Type, Validators};
use function PHPStan\Testing\assertType;


Expand Down Expand Up @@ -252,3 +252,87 @@ function testIterablesFirstKeyWithElse(iterable $iterable): void
{
assertType('string', Iterables::firstKey($iterable, else: fn() => 'default'));
}


/** @param non-empty-string $nonEmpty */
function testStringsLength(string $string, string $nonEmpty): void
{
assertType('int<1, max>', Strings::length('abc'));
assertType('int<1, max>', Strings::length($nonEmpty));
assertType('0', Strings::length(''));
assertType('int<0, max>', Strings::length($string));
}


/** @param non-empty-string $nonEmpty */
function testStringsCaseConversion(string $string, string $nonEmpty): void
{
assertType('non-empty-string', Strings::lower($nonEmpty));
assertType('non-empty-string', Strings::firstLower($nonEmpty));
assertType('non-empty-string', Strings::upper('abc'));
assertType('non-empty-string', Strings::firstUpper($nonEmpty));
assertType('non-empty-string', Strings::capitalize($nonEmpty));
assertType('non-empty-string', Strings::reverse($nonEmpty));
assertType('string', Strings::lower($string));
assertType('string', Strings::reverse($string));
}


function testStringsIndexOf(string $string): void
{
assertType('int<0, max>|null', Strings::indexOf($string, 'x'));
}


function testRandomGenerate(int $length): void
{
assertType('non-empty-string', Random::generate());
assertType('non-empty-string', Random::generate($length, 'a-z'));
}


/** @param array<string, mixed> $array */
function testArraysGetKeyOffset(array $array): void
{
assertType('int<0, max>|null', Arrays::getKeyOffset($array, 'key'));
}


/** @param array<string, string> $array */
function testArraysGrepAndWrap(array $array): void
{
assertType('array<string, string>', Arrays::grep($array, '#x#'));
assertType('array<string, string>', Arrays::wrap($array, '<', '>'));
assertType('array<3|5, string>', Arrays::wrap([3 => 'a', 5 => 'b']));
}


/** @param array<string, mixed> $array */
function testArraysFlatten(array $array, bool $preserveKeys): void
{
assertType('list<mixed>', Arrays::flatten($array));
assertType('array<mixed>', Arrays::flatten($array, preserveKeys: true));
assertType('array<mixed>', Arrays::flatten($array, $preserveKeys));
}


/**
* @param ArrayHash<int> $hash
* @param ArrayList<int> $list
* @param CachingIterator<int, string> $iterator
*/
function testCounts(ArrayHash $hash, ArrayList $list, CachingIterator $iterator): void
{
assertType('int<0, max>', $hash->count());
assertType('int<0, max>', $list->count());
assertType('int<0, max>', $iterator->getCounter());
assertType('int<0, max>', $iterator->counter);
}


function testValidatorsIsUnicode(mixed $value): void
{
if (Validators::isUnicode($value)) {
assertType('string', $value);
}
}
Loading