addListener('stdClass', function() use (&$order) { $order[] = 'low'; }, 0); $provider->addListener('stdClass', function() use (&$order) { $order[] = 'high'; }, 100); $provider->addListener('stdClass', function() use (&$order) { $order[] = 'medium'; }, 50); $listeners = $provider->getListenersForEvent(new \stdClass()); foreach ($listeners as $listener) { $listener(); } $this->assertEquals(['high', 'medium', 'low'], $order); } public function test_it_resolves_inheritance(): void { $provider = new ListenerProvider(); $called = []; $provider->addListener(ParentEvent::class, function() use (&$called) { $called[] = 'parent'; }); $provider->addListener(TestInterface::class, function() use (&$called) { $called[] = 'interface'; }); $provider->addListener(ChildEvent::class, function() use (&$called) { $called[] = 'child'; }); $listeners = $provider->getListenersForEvent(new ChildEvent()); foreach ($listeners as $listener) { $listener(); } $this->assertContains('parent', $called); $this->assertContains('interface', $called); $this->assertContains('child', $called); } public function test_it_respects_interface_resolution_toggle(): void { $provider = new ListenerProvider(); $provider->setResolveInterfaces(false); $called = []; $provider->addListener(TestInterface::class, function() use (&$called) { $called[] = 'interface'; }); $provider->addListener(ChildEvent::class, function() use (&$called) { $called[] = 'child'; }); $listeners = $provider->getListenersForEvent(new ChildEvent()); foreach ($listeners as $listener) { $listener(); } $this->assertNotContains('interface', $called); $this->assertContains('child', $called); } public function test_it_resolves_wildcards(): void { $provider = new ListenerProvider(); $called = []; $provider->addListener('Phred\Beacon\Tests\Unit\*', function() use (&$called) { $called[] = 'wildcard'; }); $listeners = $provider->getListenersForEvent(new ChildEvent()); foreach ($listeners as $listener) { $listener(); } $this->assertContains('wildcard', $called); } public function test_complex_priority_with_inheritance_and_wildcards(): void { $provider = new ListenerProvider(); $order = []; // Exact match (low priority) $provider->addListener(ChildEvent::class, function() use (&$order) { $order[] = 'exact'; }, 0); // Wildcard match (high priority) $provider->addListener('Phred\*', function() use (&$order) { $order[] = 'wildcard'; }, 100); // Interface match (medium priority) $provider->addListener(TestInterface::class, function() use (&$order) { $order[] = 'interface'; }, 50); $listeners = $provider->getListenersForEvent(new ChildEvent()); foreach ($listeners as $listener) { $listener(); } $this->assertEquals(['wildcard', 'interface', 'exact'], $order); } }