parent
5ee74b2d9d
commit
cb03f9452c
4 changed files with 183 additions and 0 deletions
@ -0,0 +1,37 @@ |
||||
--TEST-- |
||||
Symfony pattern: callable variable converted to first-class callable |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeLogger |
||||
{ |
||||
private Closure $formatter; |
||||
|
||||
public function __construct(?callable $formatter = null) |
||||
{ |
||||
$this->formatter = null !== $formatter ? $formatter(...) : $this->format(...); |
||||
} |
||||
|
||||
public function log(string $level, string $message): string |
||||
{ |
||||
return ($this->formatter)($level, $message); |
||||
} |
||||
|
||||
private function format(string $level, string $message): string |
||||
{ |
||||
return strtoupper($level).': '.$message; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$default = new SymfonyLikeLogger(); |
||||
$custom = new SymfonyLikeLogger(static fn (string $level, string $message): string => $level.'|'.strrev($message)); |
||||
|
||||
var_dump($default->log('info', 'boot')); |
||||
var_dump($custom->log('debug', 'boot')); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(10) "INFO: boot" |
||||
string(10) "debug|toob" |
||||
@ -0,0 +1,48 @@ |
||||
--TEST-- |
||||
Symfony pattern: array_filter with dynamic instanceof class name |
||||
--XFAIL-- |
||||
Known AOT bug: objects filtered by dynamic instanceof can lose their precise class type before closure property reads. |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeControllerAttribute |
||||
{ |
||||
public function __construct(public string $name) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
class SymfonyLikeOtherAttribute |
||||
{ |
||||
} |
||||
|
||||
class SymfonyLikeControllerEvent |
||||
{ |
||||
public function __construct(private array $attributes) |
||||
{ |
||||
} |
||||
|
||||
public function getAttributes(string $className): array |
||||
{ |
||||
return array_values(array_filter($this->attributes, static fn ($attr) => $attr instanceof $className)); |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$event = new SymfonyLikeControllerEvent([ |
||||
new SymfonyLikeOtherAttribute(), |
||||
new SymfonyLikeControllerAttribute('template'), |
||||
new SymfonyLikeControllerAttribute('cache'), |
||||
]); |
||||
|
||||
var_dump(array_map(static fn ($attribute) => $attribute->name, $event->getAttributes(SymfonyLikeControllerAttribute::class))); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(2) { |
||||
[0]=> |
||||
string(8) "template" |
||||
[1]=> |
||||
string(5) "cache" |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
--TEST-- |
||||
Symfony pattern: error handler arrow function throws conditional exception |
||||
--ENV-- |
||||
USE_ZEND_ALLOC=0 |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeCompiledUrlMatcherDumper |
||||
{ |
||||
private RuntimeException $signalingException; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->signalingException = new RuntimeException('SIGNAL'); |
||||
} |
||||
|
||||
public function run(string $message): void |
||||
{ |
||||
set_error_handler(fn ($type, $errorMessage) => throw str_contains($errorMessage, $this->signalingException->getMessage()) ? $this->signalingException : new ErrorException($errorMessage)); |
||||
|
||||
try { |
||||
trigger_error($message, E_USER_WARNING); |
||||
} finally { |
||||
restore_error_handler(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$dumper = new SymfonyLikeCompiledUrlMatcherDumper(); |
||||
|
||||
foreach (['SIGNAL: stop', 'plain failure'] as $message) { |
||||
try { |
||||
$dumper->run($message); |
||||
} catch (Throwable $e) { |
||||
var_dump($e::class); |
||||
var_dump($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(16) "RuntimeException" |
||||
string(6) "SIGNAL" |
||||
string(14) "ErrorException" |
||||
string(13) "plain failure" |
||||
@ -0,0 +1,51 @@ |
||||
--TEST-- |
||||
Symfony pattern: uksort with priority fallback comparator |
||||
--XFAIL-- |
||||
Known AOT bug: uksort with captured arrays in a static arrow comparator can crash during shutdown. |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeRouteCollection |
||||
{ |
||||
private array $routes = []; |
||||
private array $priorities = []; |
||||
|
||||
public function add(string $name, string $path, int $priority = 0): void |
||||
{ |
||||
$this->routes[$name] = $path; |
||||
$this->priorities[$name] = $priority; |
||||
} |
||||
|
||||
public function all(): array |
||||
{ |
||||
$priorities = $this->priorities; |
||||
$keysOrder = array_flip(array_keys($this->routes)); |
||||
|
||||
uksort($this->routes, static fn ($n1, $n2) => (($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0)) ?: ($keysOrder[$n1] <=> $keysOrder[$n2])); |
||||
|
||||
return $this->routes; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$collection = new SymfonyLikeRouteCollection(); |
||||
$collection->add('fallback', '/fallback'); |
||||
$collection->add('admin', '/admin', 20); |
||||
$collection->add('api', '/api', 20); |
||||
$collection->add('home', '/', 10); |
||||
|
||||
var_dump(array_keys($collection->all())); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(4) { |
||||
[0]=> |
||||
string(5) "admin" |
||||
[1]=> |
||||
string(3) "api" |
||||
[2]=> |
||||
string(4) "home" |
||||
[3]=> |
||||
string(8) "fallback" |
||||
} |
||||
Loading…
Reference in new issue