- Add test for property hooks preservation and invocation after __clone - Add test for private/protected/readonly property scope handling in clone-with - Add test for trait method scope usage inside clone-with operations - Update documentation to reflect completed clone-with implementation coverage - Remove pending classification for clone-with scoped/readonly/hooked properties - Remove TODO comment about property handlers preservation in clone-with operationmaster
parent
795a8e0a1d
commit
b2246cd456
6 changed files with 154 additions and 8 deletions
@ -0,0 +1,71 @@ |
||||
--TEST-- |
||||
PHP 8.5 clone-with preserves TypePHP property handlers and invokes hooks after __clone |
||||
--SKIPIF-- |
||||
<?php |
||||
if (PHP_VERSION_ID < 80500) { |
||||
die('skip requires PHP 8.5'); |
||||
} |
||||
?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class CloneWithHookValue |
||||
{ |
||||
public int $value { |
||||
get => $this->value * 2; |
||||
set { |
||||
echo 'set:', $value, "\n"; |
||||
if ($value < 0) { |
||||
throw new InvalidArgumentException('negative value'); |
||||
} |
||||
$this->value = $value + 1; |
||||
} |
||||
} |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->value = 1; |
||||
} |
||||
|
||||
public function __clone(): void |
||||
{ |
||||
echo '__clone:', $this->value, "\n"; |
||||
} |
||||
|
||||
public function withValue(int $value): self |
||||
{ |
||||
return clone($this, ['value' => $value]); |
||||
} |
||||
} |
||||
|
||||
class CloneWithHookChild extends CloneWithHookValue {} |
||||
|
||||
function read_clone_hook_dynamically(mixed $object): int |
||||
{ |
||||
return $object->value; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$source = new CloneWithHookChild(); |
||||
$copy = $source->withValue(5); |
||||
|
||||
var_dump(read_clone_hook_dynamically($source)); |
||||
var_dump(read_clone_hook_dynamically($copy)); |
||||
|
||||
try { |
||||
$source->withValue(-1); |
||||
} catch (InvalidArgumentException $error) { |
||||
echo $error->getMessage(), "\n"; |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
set:1 |
||||
__clone:4 |
||||
set:5 |
||||
int(4) |
||||
int(12) |
||||
__clone:4 |
||||
set:-1 |
||||
negative value |
||||
@ -0,0 +1,45 @@ |
||||
--TEST-- |
||||
PHP 8.5 clone-with uses the consuming class scope inside trait methods |
||||
--SKIPIF-- |
||||
<?php |
||||
if (PHP_VERSION_ID < 80500) { |
||||
die('skip requires PHP 8.5'); |
||||
} |
||||
?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
trait CloneWithTraitScope |
||||
{ |
||||
private int $traitPrivate = 1; |
||||
|
||||
public function withTraitPrivate(int $value): self |
||||
{ |
||||
return clone($this, ['traitPrivate' => $value]); |
||||
} |
||||
|
||||
public function traitPrivate(): int |
||||
{ |
||||
return $this->traitPrivate; |
||||
} |
||||
} |
||||
|
||||
class CloneWithTraitBase |
||||
{ |
||||
use CloneWithTraitScope; |
||||
} |
||||
|
||||
class CloneWithTraitChild extends CloneWithTraitBase {} |
||||
|
||||
function main(): void |
||||
{ |
||||
$source = new CloneWithTraitChild(); |
||||
$copy = $source->withTraitPrivate(9); |
||||
|
||||
var_dump($source->traitPrivate()); |
||||
var_dump($copy->traitPrivate()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(1) |
||||
int(9) |
||||
Loading…
Reference in new issue