Skip to content

Commit

Permalink
ArrayList support returning references (#289)
Browse files Browse the repository at this point in the history
$arrayList = ArrayList::form([['id'=>1],['id'=>2]]);
        // $arrayList => [['id'=>1],['id'=>2]]
        foreach($arrayList as &$item)
        {
            $item['id'] += 1;
        }
        unset($item);
        // $arrayList => [['id'=>2],['id'=>3]]
  • Loading branch information
duncanxia97 committed Jan 19, 2023
1 parent 46e8fe1 commit cc06620
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 36 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"jetbrains/phpstorm-attributes": "dev-master"
},
"conflict": {
"nette/finder": "<3"
"nette/finder": "<3",
"nette/schema": "<1.2.2"
},
"suggest": {
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
Expand Down
7 changes: 5 additions & 2 deletions src/Utils/ArrayList.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ public static function from(array $array): static
* Returns an iterator over all items.
* @return \ArrayIterator<int, T>
*/
public function getIterator(): \ArrayIterator
public function &getIterator(): \Iterator
{
return new \ArrayIterator($this->list);
foreach ($this->list as &$item) {
yield $item;
}
unset($item);
}


Expand Down
24 changes: 16 additions & 8 deletions src/Utils/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,12 @@ private static function fromReflectionType(\ReflectionType $type, $of, bool $asO
*/
public static function fromString(string $type): self
{
if (!preg_match('#(?:
\?([\w\\\\]+) |
(?: [\w\\\\]+ | \( [\w\\\\]+ (?:&[\w\\\\]+)+ \) ) (?: \| (?: [\w\\\\]+ | \( [\w\\\\]+ (?:&[\w\\\\]+)+ \) ) )* |
[\w\\\\]+ (?:&[\w\\\\]+)+
)()$#xAD', $type, $m)) {
if (!self::isValid($type)) {
throw new Nette\InvalidArgumentException("Invalid type '$type'.");
}

[, $nullable] = $m;
if ($nullable) {
return new self([$nullable, 'null']);
if ($type[0] === '?') {
return new self([substr($type, 1), 'null']);
}

$unions = [];
Expand All @@ -89,6 +84,19 @@ public static function fromString(string $type): self
}


/**
* Checks whether the given type is syntactically valid.
*/
public static function isValid(string $type): bool
{
return (bool) preg_match('#(?:
\?([\w\\\\]+) |
(?: [\w\\\\]+ | \( [\w\\\\]+ (?:&[\w\\\\]+)+ \) ) (?: \| (?: [\w\\\\]+ | \( [\w\\\\]+ (?:&[\w\\\\]+)+ \) ) )* |
[\w\\\\]+ (?:&[\w\\\\]+)+
)$#xAD', $type);
}


/**
* Resolves 'self', 'static' and 'parent' to the actual class name.
*/
Expand Down
46 changes: 21 additions & 25 deletions src/Utils/Validators.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ class Validators
'never' => 1,
];

private const ClassKeywords = [
'self' => 1, 'parent' => 1, 'static' => 1,
];

/** @var array<string,?callable> */
protected static $validators = [
// PHP types
Expand Down Expand Up @@ -320,13 +316,13 @@ public static function isEmail(string $value): bool
$atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
$alpha = "a-z\x80-\xFF"; // superset of IDN
return (bool) preg_match(<<<XX
(^
("([ !#-[\\]-~]*|\\\\[ -~])+"|$atom+(\\.$atom+)*) # quoted or unquoted
@
([0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)+ # domain - RFC 1034
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
$)Dix
XX, $value);
(^
("([ !#-[\\]-~]*|\\\\[ -~])+"|$atom+(\\.$atom+)*) # quoted or unquoted
@
([0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)+ # domain - RFC 1034
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
$)Dix
XX, $value);
}


Expand All @@ -337,19 +333,19 @@ public static function isUrl(string $value): bool
{
$alpha = "a-z\x80-\xFF";
return (bool) preg_match(<<<XX
(^
https?://(
(([-_0-9$alpha]+\\.)* # subdomain
[0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)? # domain
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} # IPv4
|\\[[0-9a-f:]{3,39}\\] # IPv6
)(:\\d{1,5})? # port
(/\\S*)? # path
(\\?\\S*)? # query
(\\#\\S*)? # fragment
$)Dix
XX, $value);
(^
https?://(
(([-_0-9$alpha]+\\.)* # subdomain
[0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)? # domain
[$alpha]([-0-9$alpha]{0,17}[$alpha])? # top domain
|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} # IPv4
|\\[[0-9a-f:]{3,39}\\] # IPv6
)(:\\d{1,5})? # port
(/\\S*)? # path
(\\?\\S*)? # query
(\\#\\S*)? # fragment
$)Dix
XX, $value);
}


Expand Down Expand Up @@ -394,6 +390,6 @@ public static function isBuiltinType(string $type): bool
*/
public static function isClassKeyword(string $name): bool
{
return isset(self::ClassKeywords[strtolower($name)]);
return (bool) preg_match('#^(self|parent|static)$#Di', $name);
}
}
27 changes: 27 additions & 0 deletions tests/Utils/Type.isValid.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* Test: Nette\Utils\Type
*/

declare(strict_types=1);

use Nette\Utils\Type;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


Assert::true(Type::isValid('string'));
Assert::true(Type::isValid('?string'));
Assert::true(Type::isValid('string|null'));
Assert::true(Type::isValid('(A&B&C)'));
Assert::true(Type::isValid('A&B&C'));
Assert::true(Type::isValid('(A&C)|(C&D)|true'));

Assert::false(Type::isValid('?string|null'));
Assert::false(Type::isValid('?'));
Assert::false(Type::isValid(''));
Assert::false(Type::isValid('|foo'));
Assert::false(Type::isValid('(A|B)'));
Assert::false(Type::isValid('A&B|C'));

0 comments on commit cc06620

Please sign in to comment.