@vituum/vite-plugin-latte 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/vendor/autoload.php +1 -1
- package/vendor/composer/autoload_real.php +4 -4
- package/vendor/composer/autoload_static.php +2 -2
- package/vendor/composer/installed.json +21 -20
- package/vendor/composer/installed.php +8 -8
- package/vendor/latte/latte/composer.json +6 -5
- package/vendor/latte/latte/readme.md +27 -9
- package/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml +4 -1
- package/vendor/latte/latte/src/Latte/Compiler/TagLexer.php +1 -1
- package/vendor/latte/latte/src/Latte/Compiler/TagParserData.php +129 -129
- package/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php +1 -1
- package/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php +1 -1
- package/vendor/latte/latte/src/Latte/Engine.php +22 -2
- package/vendor/latte/latte/src/Latte/Essential/CachingIterator.php +2 -3
- package/vendor/latte/latte/src/Latte/Essential/CoreExtension.php +9 -1
- package/vendor/latte/latte/src/Latte/Essential/Filters.php +110 -10
- package/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php +8 -2
- package/vendor/latte/latte/src/Latte/Essential/Nodes/VarNode.php +14 -18
- package/vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php +1 -1
- package/vendor/latte/latte/src/Latte/Loaders/FileLoader.php +5 -4
- package/vendor/latte/latte/src/Latte/Runtime/Template.php +1 -1
- package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php +0 -1
- package/vendor/nette/utils/composer.json +1 -1
- package/vendor/nette/utils/readme.md +25 -26
- package/vendor/nette/utils/src/Iterators/CachingIterator.php +5 -19
- package/vendor/nette/utils/src/Iterators/Mapper.php +1 -2
- package/vendor/nette/utils/src/Utils/Arrays.php +59 -28
- package/vendor/nette/utils/src/Utils/Callback.php +1 -1
- package/vendor/nette/utils/src/Utils/Image.php +14 -12
- package/vendor/nette/utils/src/Utils/Iterables.php +99 -20
- package/vendor/nette/utils/src/Utils/Reflection.php +5 -3
- package/vendor/nette/utils/src/Utils/Strings.php +26 -6
|
@@ -23,6 +23,9 @@ use function is_array, is_string, count, strlen;
|
|
|
23
23
|
*/
|
|
24
24
|
final class Filters
|
|
25
25
|
{
|
|
26
|
+
public ?string $locale = null;
|
|
27
|
+
|
|
28
|
+
|
|
26
29
|
/**
|
|
27
30
|
* Converts HTML to plain text.
|
|
28
31
|
*/
|
|
@@ -35,7 +38,7 @@ final class Filters
|
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
|
-
* Removes tags from HTML (but remains HTML
|
|
41
|
+
* Removes tags from HTML (but remains HTML entities).
|
|
39
42
|
*/
|
|
40
43
|
public static function stripTags(FilterInfo $info, $s): string
|
|
41
44
|
{
|
|
@@ -168,14 +171,11 @@ final class Filters
|
|
|
168
171
|
*/
|
|
169
172
|
public static function date(string|int|\DateTimeInterface|\DateInterval|null $time, ?string $format = null): ?string
|
|
170
173
|
{
|
|
174
|
+
$format ??= Latte\Runtime\Filters::$dateFormat;
|
|
171
175
|
if ($time == null) { // intentionally ==
|
|
172
176
|
return null;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
$format ??= Latte\Runtime\Filters::$dateFormat;
|
|
176
|
-
if ($time instanceof \DateInterval) {
|
|
177
|
+
} elseif ($time instanceof \DateInterval) {
|
|
177
178
|
return $time->format($format);
|
|
178
|
-
|
|
179
179
|
} elseif (is_numeric($time)) {
|
|
180
180
|
$time = (new \DateTime)->setTimestamp((int) $time);
|
|
181
181
|
} elseif (!$time instanceof \DateTimeInterface) {
|
|
@@ -194,10 +194,75 @@ final class Filters
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Date/time formatting according to locale.
|
|
199
|
+
*/
|
|
200
|
+
public function localDate(
|
|
201
|
+
string|int|\DateTimeInterface|null $value,
|
|
202
|
+
?string $format = null,
|
|
203
|
+
?string $date = null,
|
|
204
|
+
?string $time = null,
|
|
205
|
+
): ?string
|
|
206
|
+
{
|
|
207
|
+
if ($this->locale === null) {
|
|
208
|
+
throw new Latte\RuntimeException('Filter |localDate requires the locale to be set using Engine::setLocale()');
|
|
209
|
+
} elseif ($value == null) { // intentionally ==
|
|
210
|
+
return null;
|
|
211
|
+
} elseif (is_numeric($value)) {
|
|
212
|
+
$value = (new \DateTime)->setTimestamp((int) $value);
|
|
213
|
+
} elseif (!$value instanceof \DateTimeInterface) {
|
|
214
|
+
$value = new \DateTime($value);
|
|
215
|
+
$errors = \DateTime::getLastErrors();
|
|
216
|
+
if (!empty($errors['warnings'])) {
|
|
217
|
+
throw new \InvalidArgumentException(reset($errors['warnings']));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if ($format === null) {
|
|
222
|
+
$xlt = ['' => \IntlDateFormatter::NONE, 'full' => \IntlDateFormatter::FULL, 'long' => \IntlDateFormatter::LONG, 'medium' => \IntlDateFormatter::MEDIUM, 'short' => \IntlDateFormatter::SHORT,
|
|
223
|
+
'relative-full' => \IntlDateFormatter::RELATIVE_FULL, 'relative-long' => \IntlDateFormatter::RELATIVE_LONG, 'relative-medium' => \IntlDateFormatter::RELATIVE_MEDIUM, 'relative-short' => \IntlDateFormatter::RELATIVE_SHORT];
|
|
224
|
+
$date ??= $time === null ? 'long' : null;
|
|
225
|
+
$formatter = new \IntlDateFormatter($this->locale, $xlt[$date], $xlt[$time]);
|
|
226
|
+
} else {
|
|
227
|
+
$formatter = new \IntlDateFormatter($this->locale, pattern: (new \IntlDatePatternGenerator($this->locale))->getBestPattern($format));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
$res = $formatter->format($value);
|
|
231
|
+
$res = preg_replace('~(\d\.) ~', "\$1\u{a0}", $res);
|
|
232
|
+
return $res;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Formats a number with grouped thousands and optionally decimal digits according to locale.
|
|
238
|
+
*/
|
|
239
|
+
public function number(
|
|
240
|
+
float $number,
|
|
241
|
+
string|int $patternOrDecimals = 0,
|
|
242
|
+
string $decimalSeparator = '.',
|
|
243
|
+
string $thousandsSeparator = ',',
|
|
244
|
+
): string
|
|
245
|
+
{
|
|
246
|
+
if (is_int($patternOrDecimals) && $patternOrDecimals < 0) {
|
|
247
|
+
throw new Latte\RuntimeException('Filter |number: the number of decimal must not be negative');
|
|
248
|
+
} elseif ($this->locale === null || func_num_args() > 2) {
|
|
249
|
+
return number_format($number, $patternOrDecimals, $decimalSeparator, $thousandsSeparator);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
$formatter = new \NumberFormatter($this->locale, \NumberFormatter::DECIMAL);
|
|
253
|
+
if (is_string($patternOrDecimals)) {
|
|
254
|
+
$formatter->setPattern($patternOrDecimals);
|
|
255
|
+
} else {
|
|
256
|
+
$formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $patternOrDecimals);
|
|
257
|
+
}
|
|
258
|
+
return $formatter->format($number);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
|
|
197
262
|
/**
|
|
198
263
|
* Converts to human-readable file size.
|
|
199
264
|
*/
|
|
200
|
-
public
|
|
265
|
+
public function bytes(float $bytes, int $precision = 2): string
|
|
201
266
|
{
|
|
202
267
|
$bytes = round($bytes);
|
|
203
268
|
$units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
|
|
@@ -209,7 +274,15 @@ final class Filters
|
|
|
209
274
|
$bytes /= 1024;
|
|
210
275
|
}
|
|
211
276
|
|
|
212
|
-
|
|
277
|
+
if ($this->locale === null) {
|
|
278
|
+
$bytes = (string) round($bytes, $precision);
|
|
279
|
+
} else {
|
|
280
|
+
$formatter = new \NumberFormatter($this->locale, \NumberFormatter::DECIMAL);
|
|
281
|
+
$formatter->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $precision);
|
|
282
|
+
$bytes = $formatter->format($bytes);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return $bytes . ' ' . $unit;
|
|
213
286
|
}
|
|
214
287
|
|
|
215
288
|
|
|
@@ -455,7 +528,7 @@ final class Filters
|
|
|
455
528
|
* @param iterable<K, V> $data
|
|
456
529
|
* @return iterable<K, V>
|
|
457
530
|
*/
|
|
458
|
-
public
|
|
531
|
+
public function sort(
|
|
459
532
|
iterable $data,
|
|
460
533
|
?\Closure $comparison = null,
|
|
461
534
|
string|int|\Closure|null $by = null,
|
|
@@ -469,7 +542,16 @@ final class Filters
|
|
|
469
542
|
$by = $byKey === true ? null : $byKey;
|
|
470
543
|
}
|
|
471
544
|
|
|
472
|
-
|
|
545
|
+
if ($comparison) {
|
|
546
|
+
} elseif ($this->locale === null) {
|
|
547
|
+
$comparison = fn($a, $b) => $a <=> $b;
|
|
548
|
+
} else {
|
|
549
|
+
$collator = new \Collator($this->locale);
|
|
550
|
+
$comparison = fn($a, $b) => is_string($a) && is_string($b)
|
|
551
|
+
? $collator->compare($a, $b)
|
|
552
|
+
: $a <=> $b;
|
|
553
|
+
}
|
|
554
|
+
|
|
473
555
|
$comparison = match (true) {
|
|
474
556
|
$by === null => $comparison,
|
|
475
557
|
$by instanceof \Closure => fn($a, $b) => $comparison($by($a), $by($b)),
|
|
@@ -524,6 +606,24 @@ final class Filters
|
|
|
524
606
|
}
|
|
525
607
|
|
|
526
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Filters elements according to a given $predicate. Maintains original keys.
|
|
611
|
+
* @template K
|
|
612
|
+
* @template V
|
|
613
|
+
* @param iterable<K, V> $iterable
|
|
614
|
+
* @param callable(V, K, iterable<K, V>): bool $predicate
|
|
615
|
+
* @return iterable<K, V>
|
|
616
|
+
*/
|
|
617
|
+
public static function filter(iterable $iterable, callable $predicate): iterable
|
|
618
|
+
{
|
|
619
|
+
foreach ($iterable as $k => $v) {
|
|
620
|
+
if ($predicate($v, $k, $iterable)) {
|
|
621
|
+
yield $k => $v;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
|
|
527
627
|
/**
|
|
528
628
|
* Returns value clamped to the inclusive range of min and max.
|
|
529
629
|
*/
|
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
|
|
9
9
|
|
|
10
10
|
namespace Latte\Essential\Nodes;
|
|
11
11
|
|
|
12
|
+
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
|
|
12
13
|
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
13
14
|
use Latte\Compiler\Nodes\StatementNode;
|
|
14
15
|
use Latte\Compiler\PrintContext;
|
|
@@ -16,11 +17,12 @@ use Latte\Compiler\Tag;
|
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
|
-
* {import "file"}
|
|
20
|
+
* {import "file"[, args]}
|
|
20
21
|
*/
|
|
21
22
|
class ImportNode extends StatementNode
|
|
22
23
|
{
|
|
23
24
|
public ExpressionNode $file;
|
|
25
|
+
public ArrayNode $args;
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
public static function create(Tag $tag): static
|
|
@@ -28,6 +30,8 @@ class ImportNode extends StatementNode
|
|
|
28
30
|
$tag->expectArguments();
|
|
29
31
|
$node = new static;
|
|
30
32
|
$node->file = $tag->parser->parseUnquotedStringOrExpression();
|
|
33
|
+
$tag->parser->stream->tryConsume(',');
|
|
34
|
+
$node->args = $tag->parser->parseArguments();
|
|
31
35
|
return $node;
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -35,8 +39,9 @@ class ImportNode extends StatementNode
|
|
|
35
39
|
public function print(PrintContext $context): string
|
|
36
40
|
{
|
|
37
41
|
return $context->format(
|
|
38
|
-
'$this->createTemplate(%node, $this->params, "import")->render() %line;',
|
|
42
|
+
'$this->createTemplate(%node, %node? + $this->params, "import")->render() %line;',
|
|
39
43
|
$this->file,
|
|
44
|
+
$this->args,
|
|
40
45
|
$this->position,
|
|
41
46
|
);
|
|
42
47
|
}
|
|
@@ -45,5 +50,6 @@ class ImportNode extends StatementNode
|
|
|
45
50
|
public function &getIterator(): \Generator
|
|
46
51
|
{
|
|
47
52
|
yield $this->file;
|
|
53
|
+
yield $this->args;
|
|
48
54
|
}
|
|
49
55
|
}
|
|
@@ -10,8 +10,10 @@ declare(strict_types=1);
|
|
|
10
10
|
namespace Latte\Essential\Nodes;
|
|
11
11
|
|
|
12
12
|
use Latte\Compiler\Nodes\Php\Expression\AssignNode;
|
|
13
|
+
use Latte\Compiler\Nodes\Php\Expression\AssignOpNode;
|
|
14
|
+
use Latte\Compiler\Nodes\Php\Expression\AuxiliaryNode;
|
|
15
|
+
use Latte\Compiler\Nodes\Php\Expression\TernaryNode;
|
|
13
16
|
use Latte\Compiler\Nodes\Php\Expression\VariableNode;
|
|
14
|
-
use Latte\Compiler\Nodes\Php\ExpressionNode;
|
|
15
17
|
use Latte\Compiler\Nodes\Php\Scalar\NullNode;
|
|
16
18
|
use Latte\Compiler\Nodes\StatementNode;
|
|
17
19
|
use Latte\Compiler\PrintContext;
|
|
@@ -67,25 +69,19 @@ class VarNode extends StatementNode
|
|
|
67
69
|
public function print(PrintContext $context): string
|
|
68
70
|
{
|
|
69
71
|
$res = [];
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
foreach ($this->assignments as $assign) {
|
|
73
|
+
if ($this->default) {
|
|
72
74
|
assert($assign->var instanceof VariableNode);
|
|
73
|
-
|
|
74
|
-
$
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
$assign = new AssignOpNode(
|
|
76
|
+
$assign->var,
|
|
77
|
+
'??',
|
|
78
|
+
new TernaryNode(
|
|
79
|
+
new AuxiliaryNode(fn() => 'array_key_exists(' . $context->encodeString($assign->var->name) . ', get_defined_vars())'),
|
|
80
|
+
new NullNode,
|
|
81
|
+
$assign->expr,
|
|
82
|
+
),
|
|
83
|
+
);
|
|
79
84
|
}
|
|
80
|
-
|
|
81
|
-
return $context->format(
|
|
82
|
-
'extract([%raw], EXTR_SKIP) %line;',
|
|
83
|
-
implode(', ', $res),
|
|
84
|
-
$this->position,
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
foreach ($this->assignments as $assign) {
|
|
89
85
|
$res[] = $assign->print($context);
|
|
90
86
|
}
|
|
91
87
|
|
|
@@ -50,7 +50,7 @@ final class TranslatorExtension extends Latte\Extension
|
|
|
50
50
|
public function getFilters(): array
|
|
51
51
|
{
|
|
52
52
|
return [
|
|
53
|
-
'translate' => fn(Latte\Runtime\FilterInfo $fi, ...$args)
|
|
53
|
+
'translate' => fn(Latte\Runtime\FilterInfo $fi, ...$args) => $this->translator
|
|
54
54
|
? ($this->translator)(...$args)
|
|
55
55
|
: $args[0],
|
|
56
56
|
];
|
|
@@ -59,7 +59,7 @@ class FileLoader implements Latte\Loader
|
|
|
59
59
|
*/
|
|
60
60
|
public function getReferredName(string $file, string $referringFile): string
|
|
61
61
|
{
|
|
62
|
-
if ($this->baseDir || !preg_match('#/|\\\\|[a-z]
|
|
62
|
+
if ($this->baseDir || !preg_match('#/|\\\\|[a-z]:|phar:#iA', $file)) {
|
|
63
63
|
$file = $this->normalizePath($referringFile . '/../' . $file);
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -78,15 +78,16 @@ class FileLoader implements Latte\Loader
|
|
|
78
78
|
|
|
79
79
|
protected static function normalizePath(string $path): string
|
|
80
80
|
{
|
|
81
|
+
preg_match('#^([a-z]:|phar://.+?/)?(.*)#i', $path, $m);
|
|
81
82
|
$res = [];
|
|
82
|
-
foreach (explode('/', strtr($
|
|
83
|
-
if ($part === '..' && $res && end($res) !== '..') {
|
|
83
|
+
foreach (explode('/', strtr($m[2], '\\', '/')) as $part) {
|
|
84
|
+
if ($part === '..' && $res && end($res) !== '..' && end($res) !== '') {
|
|
84
85
|
array_pop($res);
|
|
85
86
|
} elseif ($part !== '.') {
|
|
86
87
|
$res[] = $part;
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
return implode(DIRECTORY_SEPARATOR, $res);
|
|
91
|
+
return $m[1] . implode(DIRECTORY_SEPARATOR, $res);
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -138,7 +138,7 @@ class Template
|
|
|
138
138
|
|
|
139
139
|
$params = $this->prepare();
|
|
140
140
|
|
|
141
|
-
if ($this->parentName === null && isset($this->global->coreParentFinder)) {
|
|
141
|
+
if ($this->parentName === null && !$this->referringTemplate && isset($this->global->coreParentFinder)) {
|
|
142
142
|
$this->parentName = ($this->global->coreParentFinder)($this);
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
Nette
|
|
2
|
-
=====================
|
|
1
|
+
[](https://doc.nette.org/en/utils)
|
|
3
2
|
|
|
4
3
|
[](https://packagist.org/packages/nette/utils)
|
|
5
4
|
[](https://github.com/nette/utils/actions)
|
|
@@ -11,25 +10,27 @@ Nette Utility Classes
|
|
|
11
10
|
Introduction
|
|
12
11
|
------------
|
|
13
12
|
|
|
14
|
-
In package nette/utils you will find a set of
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
13
|
+
In package nette/utils you will find a set of useful classes for everyday use:
|
|
14
|
+
|
|
15
|
+
✅ [Arrays](https://doc.nette.org/utils/arrays)<br>
|
|
16
|
+
✅ [Callback](https://doc.nette.org/utils/callback) - PHP callbacks<br>
|
|
17
|
+
✅ [Filesystem](https://doc.nette.org/utils/filesystem) - copying, renaming, …<br>
|
|
18
|
+
✅ [Finder](https://doc.nette.org/utils/finder) - finds files and directories<br>
|
|
19
|
+
✅ [Floats](https://doc.nette.org/utils/floats) - floating point numbers<br>
|
|
20
|
+
✅ [Helper Functions](https://doc.nette.org/utils/helpers)<br>
|
|
21
|
+
✅ [HTML elements](https://doc.nette.org/utils/html-elements) - generate HTML<br>
|
|
22
|
+
✅ [Images](https://doc.nette.org/utils/images) - crop, resize, rotate images<br>
|
|
23
|
+
✅ [Iterables](https://doc.nette.org/utils/iterables) <br>
|
|
24
|
+
✅ [JSON](https://doc.nette.org/utils/json) - encoding and decoding<br>
|
|
25
|
+
✅ [Generating Random Strings](https://doc.nette.org/utils/random)<br>
|
|
26
|
+
✅ [Paginator](https://doc.nette.org/utils/paginator) - pagination math<br>
|
|
27
|
+
✅ [PHP Reflection](https://doc.nette.org/utils/reflection)<br>
|
|
28
|
+
✅ [Strings](https://doc.nette.org/utils/strings) - useful text functions<br>
|
|
29
|
+
✅ [SmartObject](https://doc.nette.org/utils/smartobject) - PHP object enhancements<br>
|
|
30
|
+
✅ [Type](https://doc.nette.org/utils/type) - PHP data type<br>
|
|
31
|
+
✅ [Validation](https://doc.nette.org/utils/validators) - validate inputs<br>
|
|
32
|
+
|
|
33
|
+
<!---->
|
|
33
34
|
|
|
34
35
|
Installation
|
|
35
36
|
------------
|
|
@@ -40,11 +41,9 @@ The recommended way to install is via Composer:
|
|
|
40
41
|
composer require nette/utils
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- Nette Utils 3.0 is compatible with PHP 7.1 to 8.0
|
|
47
|
-
- Nette Utils 2.5 is compatible with PHP 5.6 to 8.0
|
|
44
|
+
Nette Utils 4.0 is compatible with PHP 8.0 to 8.4.
|
|
45
|
+
|
|
46
|
+
<!---->
|
|
48
47
|
|
|
49
48
|
[Support Me](https://github.com/sponsors/dg)
|
|
50
49
|
--------------------------------------------
|
|
@@ -31,26 +31,12 @@ class CachingIterator extends \CachingIterator implements \Countable
|
|
|
31
31
|
private int $counter = 0;
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
public function __construct($
|
|
34
|
+
public function __construct(iterable|\stdClass $iterable)
|
|
35
35
|
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
do {
|
|
41
|
-
$iterator = $iterator->getIterator();
|
|
42
|
-
} while ($iterator instanceof \IteratorAggregate);
|
|
43
|
-
|
|
44
|
-
assert($iterator instanceof \Iterator);
|
|
45
|
-
|
|
46
|
-
} elseif ($iterator instanceof \Iterator) {
|
|
47
|
-
} elseif ($iterator instanceof \Traversable) {
|
|
48
|
-
$iterator = new \IteratorIterator($iterator);
|
|
49
|
-
} else {
|
|
50
|
-
throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to %s; array or Traversable expected, %s given.', self::class, get_debug_type($iterator)));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
parent::__construct($iterator, 0);
|
|
36
|
+
$iterable = $iterable instanceof \stdClass
|
|
37
|
+
? new \ArrayIterator($iterable)
|
|
38
|
+
: Nette\Utils\Iterables::toIterator($iterable);
|
|
39
|
+
parent::__construct($iterable, 0);
|
|
54
40
|
}
|
|
55
41
|
|
|
56
42
|
|
|
@@ -122,10 +122,11 @@ class Arrays
|
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
|
125
|
-
*
|
|
126
|
-
* @template
|
|
127
|
-
* @param array<
|
|
128
|
-
* @
|
|
125
|
+
* @template K of int|string
|
|
126
|
+
* @template V
|
|
127
|
+
* @param array<K, V> $array
|
|
128
|
+
* @param ?callable(V, K, array<K, V>): bool $predicate
|
|
129
|
+
* @return ?V
|
|
129
130
|
*/
|
|
130
131
|
public static function first(array $array, ?callable $predicate = null, ?callable $else = null): mixed
|
|
131
132
|
{
|
|
@@ -138,10 +139,11 @@ class Arrays
|
|
|
138
139
|
|
|
139
140
|
/**
|
|
140
141
|
* Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null.
|
|
141
|
-
*
|
|
142
|
-
* @template
|
|
143
|
-
* @param array<
|
|
144
|
-
* @
|
|
142
|
+
* @template K of int|string
|
|
143
|
+
* @template V
|
|
144
|
+
* @param array<K, V> $array
|
|
145
|
+
* @param ?callable(V, K, array<K, V>): bool $predicate
|
|
146
|
+
* @return ?V
|
|
145
147
|
*/
|
|
146
148
|
public static function last(array $array, ?callable $predicate = null, ?callable $else = null): mixed
|
|
147
149
|
{
|
|
@@ -154,7 +156,11 @@ class Arrays
|
|
|
154
156
|
|
|
155
157
|
/**
|
|
156
158
|
* Returns the key of first item (matching the specified predicate if given) or null if there is no such item.
|
|
157
|
-
*
|
|
159
|
+
* @template K of int|string
|
|
160
|
+
* @template V
|
|
161
|
+
* @param array<K, V> $array
|
|
162
|
+
* @param ?callable(V, K, array<K, V>): bool $predicate
|
|
163
|
+
* @return ?K
|
|
158
164
|
*/
|
|
159
165
|
public static function firstKey(array $array, ?callable $predicate = null): int|string|null
|
|
160
166
|
{
|
|
@@ -172,7 +178,11 @@ class Arrays
|
|
|
172
178
|
|
|
173
179
|
/**
|
|
174
180
|
* Returns the key of last item (matching the specified predicate if given) or null if there is no such item.
|
|
175
|
-
*
|
|
181
|
+
* @template K of int|string
|
|
182
|
+
* @template V
|
|
183
|
+
* @param array<K, V> $array
|
|
184
|
+
* @param ?callable(V, K, array<K, V>): bool $predicate
|
|
185
|
+
* @return ?K
|
|
176
186
|
*/
|
|
177
187
|
public static function lastKey(array $array, ?callable $predicate = null): int|string|null
|
|
178
188
|
{
|
|
@@ -368,12 +378,11 @@ class Arrays
|
|
|
368
378
|
|
|
369
379
|
|
|
370
380
|
/**
|
|
371
|
-
* Tests whether at least one element in the array passes the test implemented by the provided function
|
|
372
|
-
*
|
|
373
|
-
* @template K
|
|
381
|
+
* Tests whether at least one element in the array passes the test implemented by the provided function.
|
|
382
|
+
* @template K of int|string
|
|
374
383
|
* @template V
|
|
375
|
-
* @param
|
|
376
|
-
* @param callable(V, K,
|
|
384
|
+
* @param array<K, V> $array
|
|
385
|
+
* @param callable(V, K, array<K, V>): bool $predicate
|
|
377
386
|
*/
|
|
378
387
|
public static function some(iterable $array, callable $predicate): bool
|
|
379
388
|
{
|
|
@@ -388,12 +397,11 @@ class Arrays
|
|
|
388
397
|
|
|
389
398
|
|
|
390
399
|
/**
|
|
391
|
-
* Tests whether all elements in the array pass the test implemented by the provided function
|
|
392
|
-
*
|
|
393
|
-
* @template K
|
|
400
|
+
* Tests whether all elements in the array pass the test implemented by the provided function.
|
|
401
|
+
* @template K of int|string
|
|
394
402
|
* @template V
|
|
395
|
-
* @param
|
|
396
|
-
* @param callable(V, K,
|
|
403
|
+
* @param array<K, V> $array
|
|
404
|
+
* @param callable(V, K, array<K, V>): bool $predicate
|
|
397
405
|
*/
|
|
398
406
|
public static function every(iterable $array, callable $predicate): bool
|
|
399
407
|
{
|
|
@@ -409,11 +417,10 @@ class Arrays
|
|
|
409
417
|
|
|
410
418
|
/**
|
|
411
419
|
* Returns a new array containing all key-value pairs matching the given $predicate.
|
|
412
|
-
*
|
|
413
|
-
* @template K of array-key
|
|
420
|
+
* @template K of int|string
|
|
414
421
|
* @template V
|
|
415
|
-
* @param array<K, V>
|
|
416
|
-
* @param callable(V, K, array<K, V>): bool
|
|
422
|
+
* @param array<K, V> $array
|
|
423
|
+
* @param callable(V, K, array<K, V>): bool $predicate
|
|
417
424
|
* @return array<K, V>
|
|
418
425
|
*/
|
|
419
426
|
public static function filter(array $array, callable $predicate): array
|
|
@@ -430,12 +437,11 @@ class Arrays
|
|
|
430
437
|
|
|
431
438
|
/**
|
|
432
439
|
* Returns an array containing the original keys and results of applying the given transform function to each element.
|
|
433
|
-
*
|
|
434
|
-
* @template K of array-key
|
|
440
|
+
* @template K of int|string
|
|
435
441
|
* @template V
|
|
436
442
|
* @template R
|
|
437
|
-
* @param
|
|
438
|
-
* @param callable(V, K,
|
|
443
|
+
* @param array<K, V> $array
|
|
444
|
+
* @param callable(V, K, array<K, V>): R $transformer
|
|
439
445
|
* @return array<K, R>
|
|
440
446
|
*/
|
|
441
447
|
public static function map(iterable $array, callable $transformer): array
|
|
@@ -449,6 +455,31 @@ class Arrays
|
|
|
449
455
|
}
|
|
450
456
|
|
|
451
457
|
|
|
458
|
+
/**
|
|
459
|
+
* Returns an array containing new keys and values generated by applying the given transform function to each element.
|
|
460
|
+
* If the function returns null, the element is skipped.
|
|
461
|
+
* @template K of int|string
|
|
462
|
+
* @template V
|
|
463
|
+
* @template ResK of int|string
|
|
464
|
+
* @template ResV
|
|
465
|
+
* @param array<K, V> $array
|
|
466
|
+
* @param callable(V, K, array<K, V>): ?array{ResK, ResV} $transformer
|
|
467
|
+
* @return array<ResK, ResV>
|
|
468
|
+
*/
|
|
469
|
+
public static function mapWithKeys(array $array, callable $transformer): array
|
|
470
|
+
{
|
|
471
|
+
$res = [];
|
|
472
|
+
foreach ($array as $k => $v) {
|
|
473
|
+
$pair = $transformer($v, $k, $array);
|
|
474
|
+
if ($pair) {
|
|
475
|
+
$res[$pair[0]] = $pair[1];
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return $res;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
|
|
452
483
|
/**
|
|
453
484
|
* Invokes all callbacks and returns array of results.
|
|
454
485
|
* @param callable[] $callbacks
|
|
@@ -94,7 +94,7 @@ final class Callback
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (is_string($callable) && str_contains($callable, '::')) {
|
|
97
|
-
return new ReflectionMethod($callable);
|
|
97
|
+
return new ReflectionMethod(...explode('::', $callable, 2));
|
|
98
98
|
} elseif (is_array($callable)) {
|
|
99
99
|
return new ReflectionMethod($callable[0], $callable[1]);
|
|
100
100
|
} elseif (is_object($callable) && !$callable instanceof \Closure) {
|