Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
3 test implementations of PHP Attributes for Tukio
<?php
class ProviderBuilder {
public function addListenerService(string $serviceName, string $methodName, string $type, int $priority = 0, string $id = null): string
{
// ...
}
public function addSubscriber(string $class, string $serviceName): void
{
try {
$rClass = new \ReflectionClass($class);
$methods = array_filter($rClass->getMethods(\ReflectionMethod::IS_PUBLIC),
fn($rMethod) => strpos($rMethod->getName(), 'on') === 0);
$defs = array_map([$this, 'getDefinition'], $methods);
foreach ($defs as $def) {
$this->addListenerService($serviceName, $def->methodName, $def->type, $def->priority, $def->id);
}
} catch (\ReflectionException $e) {
throw new \RuntimeException('Type error registering subscriber.', 0, $e);
}
}
protected function getDefinition(ReflectionMethod $rMethod): Listener {
$annotations = array_map(
fn($rNote) => $rNote->getAsObject(),
$rMethod->getAttributes(Crell\Tukio\Annotation\Listener::class)
);
$note = $annotations[0] ?? new Listener();
$note->type ??= $rMethod->getParameters()[0]->getType()->getName();
$note->methodName = $rMethod->getName();
return $note;
}
}
class Listener {
public int $priority = 0;
public string $id= '';
public string $type = '';
public string $methodName;
public function __construct(int $priority = 0, string $id = '', string $type = '') { }
}
class MySubscriber {
<<Listener(5, 'some_id')>>
public function onThingHappened(MyEvent $event) {}
}
<?php
class ProviderBuilder {
public function addListenerService(string $serviceName, string $methodName, string $type, int $priority = 0, string $id = null): string
{
// ...
}
public function addSubscriber(string $class, string $serviceName): void
{
try {
$rClass = new \ReflectionClass($class);
$methods = array_filter($rClass->getMethods(\ReflectionMethod::IS_PUBLIC),
fn($rMethod) => strpos($rMethod->getName(), 'on') === 0);
$defs = array_map([$this, 'getDefinition'], $methods);
foreach ($defs as $def) {
$this->addListenerService($serviceName, $def->methodName, $def->type, $def->priority, $def->id);
}
} catch (\ReflectionException $e) {
throw new \RuntimeException('Type error registering subscriber.', 0, $e);
}
}
protected function getDefinition(ReflectionMethod $rMethod): Definition {
$annotations = array_map(
fn($rNote) => $rNote->getAsObject(),
$rMethod->getAttributes(Crell\Tukio\Annotation\Listener::class)
);
$def = new Definition($rMethod->getName(), $rMethod->getParameters()[0]->getType()->getName());
foreach ($annotations as $note) {
if ($note instanceof Listener\Priority) {
$def->priority ??= $note->priority;
}
elseif ($note instanceof Listener\Id) {
$def->id ??= $note->id;
}
elseif ($note instanceof Listener\Type) {
$def->type ??= $note->type;
}
}
return $def;
}
}
class Listener\Priority implements Listener {
public int $priority = 0;
public function __construct(int $priority = 0) { }
}
class Listener\Id implements Listener {
public string $id = '';
public function __construct(string $id = '') { }
}
class Listener\Type implements Listener {
public string $type = '';
public function __construct(string $type = '') { }
}
class Definition {
public int $priority = 0;
public string $id= '';
public ?string $type = null;
public string $methodName;
public function __construct(string $methodName, string $type = null) { }
}
class MySubscriber {
<<Listener\Priority(5)>>
<<Listener\Id('some_id')>>
<<Listener\Type(MyEvent::class)>>
public function onThingHappened(MyEvent $event) {}
}
<?php
class ProviderBuilder {
public function addListenerService(string $serviceName, string $methodName, string $type, int $priority = 0, string $id = null): string
{
// ...
}
public function addSubscriber(string $class, string $serviceName): void
{
try {
$rClass = new \ReflectionClass($class);
$methods = array_filter($rClass->getMethods(\ReflectionMethod::IS_PUBLIC),
fn($rMethod) => strpos($rMethod->getName(), 'on') === 0);
$defs = array_map([$this, 'getDefinition'], $methods);
foreach ($defs as $def) {
switch ($def->order()) {
case 'numeric':
$this->addListenerService($serviceName, $def->methodName, $def->type, $def->priority, $def->id);
break;
case 'before':
$this->addListenerServiceBefore($def->before, $serviceName, $def->methodName, $def->type, $def->priority, $def->id);
break;
case 'after':
$this->addListenerServiceAfter($def->after, $serviceName, $def->methodName, $def->type, $def->priority, $def->id);
break;
}
}
} catch (\ReflectionException $e) {
throw new \RuntimeException('Type error registering subscriber.', 0, $e);
}
}
protected function getDefinition(ReflectionMethod $rMethod): Listener {
$annotations = array_map(
fn($rNote) => $rNote->getAsObject(),
$rMethod->getAttributes(Crell\Tukio\Annotation\Listener::class)
);
$note = $annotations[0] ?? new Listener();
$note->type ??= $rMethod->getParameters()[0]->getType()->getName();
$note->methodName = $rMethod->getName();
return $note;
}
}
class Listener {
public int $priority = 0;
public string $id= '';
public string $type = '';
public string $methodName;
public function __construct(array $props = []) {
if (more than one of priority, before, or after is set) {
throw new RuntimeException();
}
}
}
class MySubscriber {
<<Listener([
'id' => 'some_id',
'type' => MyEvent::class,
'before' => 'other_id',
])>>
public function onThingHappened(MyEvent $event) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment