Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: nette/utils
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.0.3
Choose a base ref
...
head repository: nette/utils
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.0.4
Choose a head ref
  • 10 commits
  • 21 files changed
  • 2 contributors

Commits on Nov 21, 2023

  1. Copy the full SHA
    74618ab View commit details

Commits on Jan 17, 2024

  1. Copy the full SHA
    fba3961 View commit details
  2. Copy the full SHA
    fc8db11 View commit details
  3. added Image::getSupportedTypes()

    dg committed Jan 17, 2024
    Copy the full SHA
    9631bcf View commit details
  4. Arrays: improved phpDoc

    dg committed Jan 17, 2024
    Copy the full SHA
    662e524 View commit details
  5. added Arrays::filter()

    dg committed Jan 17, 2024
    Copy the full SHA
    a445024 View commit details
  6. Copy the full SHA
    c2cc29c View commit details
  7. Copy the full SHA
    526b40c View commit details
  8. Copy the full SHA
    4b3c27e View commit details
  9. added Iterables

    dg committed Jan 17, 2024
    Copy the full SHA
    d3ad0aa View commit details
2 changes: 1 addition & 1 deletion src/StaticClass.php
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ trait StaticClass
/**
* Class is static and cannot be instantiated.
*/
final private function __construct()
private function __construct()
{
}

99 changes: 79 additions & 20 deletions src/Utils/Arrays.php
Original file line number Diff line number Diff line change
@@ -121,26 +121,64 @@ public static function contains(array $array, mixed $value): bool


/**
* Returns the first item from the array or null if array is empty.
* Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
* The $predicate has the signature `function (mixed $value, int|string $key, array $array): bool`.
* @template T
* @param array<T> $array
* @return ?T
*/
public static function first(array $array): mixed
public static function first(array $array, ?callable $predicate = null, ?callable $else = null): mixed
{
return $array[array_key_first($array)] ?? null;
$key = self::firstKey($array, $predicate);
return $key === null
? ($else ? $else() : null)
: $array[$key];
}


/**
* Returns the last item from the array or null if array is empty.
* Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
* The $predicate has the signature `function (mixed $value, int|string $key, array $array): bool`.
* @template T
* @param array<T> $array
* @return ?T
*/
public static function last(array $array): mixed
public static function last(array $array, ?callable $predicate = null, ?callable $else = null): mixed
{
return $array[array_key_last($array)] ?? null;
$key = self::lastKey($array, $predicate);
return $key === null
? ($else ? $else() : null)
: $array[$key];
}


/**
* Returns the key of first item (matching the specified predicate if given) or null if there is no such item.
* The $predicate has the signature `function (mixed $value, int|string $key, array $array): bool`.
*/
public static function firstKey(array $array, ?callable $predicate = null): int|string|null
{
if (!$predicate) {
return array_key_first($array);
}
foreach ($array as $k => $v) {
if ($predicate($v, $k, $array)) {
return $k;
}
}
return null;
}


/**
* Returns the key of last item (matching the specified predicate if given) or null if there is no such item.
* The $predicate has the signature `function (mixed $value, int|string $key, array $array): bool`.
*/
public static function lastKey(array $array, ?callable $predicate = null): int|string|null
{
return $predicate
? self::firstKey(array_reverse($array, preserve_keys: true), $predicate)
: array_key_last($array);
}


@@ -217,7 +255,7 @@ public static function flatten(array $array, bool $preserveKeys = false): array
$res = [];
$cb = $preserveKeys
? function ($v, $k) use (&$res): void { $res[$k] = $v; }
: function ($v) use (&$res): void { $res[] = $v; };
: function ($v) use (&$res): void { $res[] = $v; };
array_walk_recursive($array, $cb);
return $res;
}
@@ -330,17 +368,17 @@ public static function pick(array &$array, string|int $key, mixed $default = nul


/**
* Tests whether at least one element in the array passes the test implemented by the
* provided callback with signature `function ($value, $key, array $array): bool`.
* Tests whether at least one element in the array passes the test implemented by the provided function,
* which has the signature `function ($value, $key, array $array): bool`.
* @template K
* @template V
* @param iterable<K, V> $array
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): bool $callback
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): bool $predicate
*/
public static function some(iterable $array, callable $callback): bool
public static function some(iterable $array, callable $predicate): bool
{
foreach ($array as $k => $v) {
if ($callback($v, $k, $array)) {
if ($predicate($v, $k, $array)) {
return true;
}
}
@@ -355,12 +393,12 @@ public static function some(iterable $array, callable $callback): bool
* @template K
* @template V
* @param iterable<K, V> $array
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): bool $callback
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): bool $predicate
*/
public static function every(iterable $array, callable $callback): bool
public static function every(iterable $array, callable $predicate): bool
{
foreach ($array as $k => $v) {
if (!$callback($v, $k, $array)) {
if (!$predicate($v, $k, $array)) {
return false;
}
}
@@ -370,20 +408,41 @@ public static function every(iterable $array, callable $callback): bool


/**
* Calls $callback on all elements in the array and returns the array of return values.
* The callback has the signature `function ($value, $key, array $array): bool`.
* Returns a new array containing all key-value pairs matching the given $predicate.
* The callback has the signature `function (mixed $value, int|string $key, array $array): bool`.
* @template K of array-key
* @template V
* @param array<K, V> $array
* @param callable(V, K, array<K, V>): bool $predicate
* @return array<K, V>
*/
public static function filter(array $array, callable $predicate): array
{
$res = [];
foreach ($array as $k => $v) {
if ($predicate($v, $k, $array)) {
$res[$k] = $v;
}
}
return $res;
}


/**
* Returns an array containing the original keys and results of applying the given transform function to each element.
* The function has signature `function ($value, $key, array $array): mixed`.
* @template K of array-key
* @template V
* @template R
* @param iterable<K, V> $array
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): R $callback
* @param callable(V, K, ($array is array ? array<K, V> : iterable<K, V>)): R $transformer
* @return array<K, R>
*/
public static function map(iterable $array, callable $callback): array
public static function map(iterable $array, callable $transformer): array
{
$res = [];
foreach ($array as $k => $v) {
$res[$k] = $callback($v, $k, $array);
$res[$k] = $transformer($v, $k, $array);
}

return $res;
15 changes: 15 additions & 0 deletions src/Utils/Image.php
Original file line number Diff line number Diff line change
@@ -320,6 +320,21 @@ public static function isTypeSupported(int $type): bool
}


/** @return ImageType[] */
public static function getSupportedTypes(): array
{
$flag = imagetypes();
return array_filter([
$flag & IMG_GIF ? ImageType::GIF : null,
$flag & IMG_JPG ? ImageType::JPEG : null,
$flag & IMG_PNG ? ImageType::PNG : null,
$flag & IMG_WEBP ? ImageType::WEBP : null,
$flag & 256 ? ImageType::AVIF : null, // IMG_AVIF
$flag & IMG_BMP ? ImageType::BMP : null,
]);
}


/**
* Wraps GD image.
*/
159 changes: 159 additions & 0 deletions src/Utils/Iterables.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Utils;

use Nette;


/**
* Utilities for iterables.
*/
final class Iterables
{
use Nette\StaticClass;

/**
* Tests for the presence of value.
*/
public static function contains(iterable $iterable, mixed $value): bool
{
foreach ($iterable as $v) {
if ($v === $value) {
return true;
}
}
return false;
}


/**
* Tests for the presence of key.
*/
public static function containsKey(iterable $iterable, mixed $key): bool
{
foreach ($iterable as $k => $v) {
if ($k === $key) {
return true;
}
}
return false;
}


/**
* Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
* The $predicate has the signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template T
* @param iterable<T> $iterable
* @return ?T
*/
public static function first(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed
{
foreach ($iterable as $k => $v) {
if (!$predicate || $predicate($v, $k, $iterable)) {
return $v;
}
}
return $else ? $else() : null;
}


/**
* 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.
* The $predicate has the signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template T
* @param iterable<T, mixed> $iterable
* @return ?T
*/
public static function firstKey(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed
{
foreach ($iterable as $k => $v) {
if (!$predicate || $predicate($v, $k, $iterable)) {
return $k;
}
}
return $else ? $else() : null;
}


/**
* Tests whether at least one element in the iterator passes the test implemented by the
* provided callback with signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template K
* @template V
* @param iterable<K, V> $iterable
* @param callable(V, K, iterable<K, V>): bool $predicate
*/
public static function some(iterable $iterable, callable $predicate): bool
{
foreach ($iterable as $k => $v) {
if ($predicate($v, $k, $iterable)) {
return true;
}
}
return false;
}


/**
* Tests whether all elements in the iterator pass the test implemented by the provided function,
* which has the signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template K
* @template V
* @param iterable<K, V> $iterable
* @param callable(V, K, iterable<K, V>): bool $predicate
*/
public static function every(iterable $iterable, callable $predicate): bool
{
foreach ($iterable as $k => $v) {
if (!$predicate($v, $k, $iterable)) {
return false;
}
}
return true;
}


/**
* Iterator that filters elements according to a given $predicate. Maintains original keys.
* The callback has the signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template K
* @template V
* @param iterable<K, V> $iterable
* @param callable(V, K, iterable<K, V>): bool $predicate
* @return \Generator<K, V>
*/
public static function filter(iterable $iterable, callable $predicate): \Generator
{
foreach ($iterable as $k => $v) {
if ($predicate($v, $k, $iterable)) {
yield $k => $v;
}
}
}


/**
* Iterator that transforms values by calling $transformer. Maintains original keys.
* The callback has the signature `function (mixed $value, mixed $key, iterable $iterable): bool`.
* @template K
* @template V
* @template R
* @param iterable<K, V> $iterable
* @param callable(V, K, iterable<K, V>): R $transformer
* @return \Generator<K, R>
*/
public static function map(iterable $iterable, callable $transformer): \Generator
{
foreach ($iterable as $k => $v) {
yield $k => $transformer($v, $k, $iterable);
}
}
}
3 changes: 3 additions & 0 deletions src/Utils/Random.php
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
namespace Nette\Utils;

use Nette;
use Random\Randomizer;


/**
@@ -37,6 +38,8 @@ public static function generate(int $length = 10, string $charlist = '0-9a-z'):
throw new Nette\InvalidArgumentException('Length must be greater than zero.');
} elseif ($chLen < 2) {
throw new Nette\InvalidArgumentException('Character list must contain at least two chars.');
} elseif (PHP_VERSION_ID >= 80300) {
return (new Randomizer)->getBytesFromString($charlist, $length);
}

$res = '';
2 changes: 1 addition & 1 deletion src/Utils/Strings.php
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ class Strings
{
use Nette\StaticClass;

public const TrimCharacters = " \t\n\r\0\x0B\u{A0}";
public const TrimCharacters = " \t\n\r\0\x0B\u{A0}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{200B}";

/** @deprecated use Strings::TrimCharacters */
public const TRIM_CHARACTERS = self::TrimCharacters;
Loading