-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventType.php
More file actions
73 lines (62 loc) · 3.08 KB
/
EventType.php
File metadata and controls
73 lines (62 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
declare( strict_types = 1 );
namespace TheWebSolver\Codegarage\Container\Event;
use Closure;
use TheWebSolver\Codegarage\Container\Container;
use Psr\EventDispatcher\EventDispatcherInterface;
use TheWebSolver\Codegarage\Container\Data\SharedBinding;
use TheWebSolver\Codegarage\Container\Error\LogicalError;
use TheWebSolver\Codegarage\Container\Event\Manager\EventManager;
use TheWebSolver\Codegarage\Container\Interfaces\ListenerRegistry;
use TheWebSolver\Codegarage\Container\Event\Provider\BuildingListenerProvider;
use TheWebSolver\Codegarage\Container\Event\Provider\AfterBuildListenerProvider;
use TheWebSolver\Codegarage\Container\Event\Provider\BeforeBuildListenerProvider;
enum EventType: string {
case BeforeBuild = BeforeBuildEvent::class;
case Building = BuildingEvent::class;
case AfterBuild = AfterBuildEvent::class;
public static function registerDispatchersTo( EventManager $manager ): EventManager {
foreach ( self::cases() as $eventType ) {
$manager->setDispatcher( $eventType->getDispatcher(), $eventType );
}
return $manager;
}
public function getDispatcher(): EventDispatcherInterface&ListenerRegistry {
return match ( $this ) {
self::BeforeBuild => new EventDispatcher( new BeforeBuildListenerProvider() ),
self::Building => new EventDispatcher( new BuildingListenerProvider() ),
self::AfterBuild => new EventDispatcher( new AfterBuildListenerProvider() )
};
}
/**
* @param Container $app
* @param string $id The id can be one of the following based on `EventType`:
* - `EventType::BeforeBuild`
* - `EventType::AfterBuild` -> The `$id` value of `Container::get()` method if no container binding.
* Entry/alias of `Container::set()` method if has container binding.
* - `EventType::Building` -> The parameter type-hint (string, EventBuilder, etc).
* @param string $paramName The type-hinted parameter name to auto-wire the param value
* when `EventType::Building` the given {@param $id} type.
* @throws LogicalError When param name not passed for `EventType::Building`.
* When concrete is a Closure for `EventType::AfterBuild`.
*/
public function getKeyFrom( Container $app, string $id, ?string $paramName ): string {
$entry = $app->getEntryFrom( $id );
return match ( $this ) {
EventType::BeforeBuild => $entry,
EventType::Building => self::assertParamNameProvided( $entry, $paramName ),
EventType::AfterBuild => self::assertConcreteIsString( $app, $entry )
};
}
private static function assertParamNameProvided( string $entry, ?string $paramName ): string {
return $paramName ? "$entry:$paramName" : throw LogicalError::duringBuildEventNeedsParamName( $entry );
}
private static function assertConcreteIsString( Container $app, string $entry ): string {
if ( ! ( $bound = $app->getBinding( $entry ) ) || $bound instanceof SharedBinding ) {
return $entry;
}
return ! ( $classname = $bound->material ) instanceof Closure
? $classname
: throw LogicalError::afterBuildEventEntryMustBeClassname( $entry );
}
}