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