4
4
5
5
use Interop \Container \ContainerInterface ;
6
6
use PhpSchool \PhpWorkshop \Event \EventDispatcher ;
7
+ use PhpSchool \PhpWorkshop \Event \ContainerListenerHelper ;
7
8
use PhpSchool \PhpWorkshop \Exception \InvalidArgumentException ;
8
- use PhpSchool \PhpWorkshop \Listener \CodePatchListener ;
9
- use PhpSchool \PhpWorkshop \Listener \PrepareSolutionListener ;
10
- use PhpSchool \PhpWorkshop \Listener \SelfCheckListener ;
11
9
use PhpSchool \PhpWorkshop \ResultAggregator ;
10
+ use PhpSchool \PhpWorkshop \Utils \Collection ;
12
11
13
12
/**
14
13
* Class EventDispatcherFactory
@@ -27,36 +26,59 @@ public function __invoke(ContainerInterface $container)
27
26
{
28
27
$ dispatcher = new EventDispatcher ($ container ->get (ResultAggregator::class));
29
28
30
- $ prepareSolutionListener = $ container ->get (PrepareSolutionListener::class);
31
- $ dispatcher ->listen ('verify.start ' , $ prepareSolutionListener );
32
- $ dispatcher ->listen ('run.start ' , $ prepareSolutionListener );
33
-
34
- $ codePatcherListener = $ container ->get (CodePatchListener::class);
35
- $ dispatcher ->listen ('verify.pre.execute ' , [$ codePatcherListener , 'patch ' ]);
36
- $ dispatcher ->listen ('verify.post.execute ' , [$ codePatcherListener , 'revert ' ]);
37
- $ dispatcher ->listen ('run.start ' , [$ codePatcherListener , 'patch ' ]);
38
- $ dispatcher ->listen ('run.finish ' , [$ codePatcherListener , 'revert ' ]);
39
-
40
- $ dispatcher ->listen ('verify.post.check ' , $ container ->get (SelfCheckListener::class));
41
-
42
29
//add listeners from config
43
30
$ eventListeners = $ container ->has ('eventListeners ' ) ? $ container ->get ('eventListeners ' ) : [];
44
31
45
32
if (!is_array ($ eventListeners )) {
46
33
throw InvalidArgumentException::typeMisMatch ('array ' , $ eventListeners );
47
34
}
48
-
49
- array_walk ($ eventListeners , function ($ listeners , $ eventName ) use ( $ dispatcher , $ container ) {
50
- if (!is_array ($ listeners )) {
51
- throw InvalidArgumentException::typeMisMatch ('array ' , $ listeners );
35
+
36
+ array_walk ($ eventListeners , function ($ events ) {
37
+ if (!is_array ($ events )) {
38
+ throw InvalidArgumentException::typeMisMatch ('array ' , $ events );
52
39
}
40
+ });
53
41
42
+ $ eventListeners = $ this ->mergeListenerGroups ($ eventListeners );
43
+
44
+ array_walk ($ eventListeners , function ($ listeners , $ eventName ) use ($ dispatcher , $ container ) {
54
45
$ this ->attachListeners ($ eventName , $ listeners , $ container , $ dispatcher );
55
46
});
56
47
57
48
return $ dispatcher ;
58
49
}
59
50
51
+ /**
52
+ * @param array $listeners
53
+ * @return array
54
+ */
55
+ private function mergeListenerGroups (array $ listeners )
56
+ {
57
+ $ listeners = new Collection ($ listeners );
58
+
59
+ return $ listeners
60
+ ->keys ()
61
+ ->reduce (function (Collection $ carry , $ listenerGroup ) use ($ listeners ) {
62
+ $ events = new Collection ($ listeners ->get ($ listenerGroup ));
63
+
64
+ return $ events
65
+ ->keys ()
66
+ ->reduce (function (Collection $ carry , $ event ) use ($ events ) {
67
+ $ listeners = $ events ->get ($ event );
68
+
69
+ if (!is_array ($ listeners )) {
70
+ throw InvalidArgumentException::typeMisMatch ('array ' , $ listeners );
71
+ }
72
+
73
+ return $ carry ->set (
74
+ $ event ,
75
+ array_merge ($ carry ->get ($ event , []), $ listeners )
76
+ );
77
+ }, $ carry );
78
+ }, new Collection )
79
+ ->getArrayCopy ();
80
+ }
81
+
60
82
/**
61
83
* @param string $eventName
62
84
* @param array $listeners
@@ -71,26 +93,32 @@ private function attachListeners(
71
93
EventDispatcher $ dispatcher
72
94
) {
73
95
array_walk ($ listeners , function ($ listener ) use ($ eventName , $ dispatcher , $ container ) {
74
- if (is_callable ($ listener )) {
75
- return $ dispatcher ->listen ($ eventName , $ listener );
96
+ if ($ listener instanceof ContainerListenerHelper) {
97
+ if (!$ container ->has ($ listener ->getService ())) {
98
+ throw new InvalidArgumentException (
99
+ sprintf ('Container has no entry named: "%s" ' , $ listener ->getService ())
100
+ );
101
+ }
102
+
103
+ return $ dispatcher ->listen ($ eventName , function (...$ args ) use ($ container , $ listener ) {
104
+ $ service = $ container ->get ($ listener ->getService ());
105
+
106
+ if (!method_exists ($ service , $ listener ->getMethod ())) {
107
+ throw new InvalidArgumentException (
108
+ sprintf ('Method "%s" does not exist on "%s" ' , $ listener ->getMethod (), get_class ($ service ))
109
+ );
110
+ }
111
+
112
+ $ service ->{$ listener ->getMethod ()}(...$ args );
113
+ });
76
114
}
77
115
78
- if (!is_string ($ listener )) {
116
+ if (!is_callable ($ listener )) {
79
117
throw new InvalidArgumentException (
80
118
sprintf ('Listener must be a callable or a container entry for a callable service. ' )
81
119
);
82
120
}
83
121
84
- if (!$ container ->has ($ listener )) {
85
- throw new InvalidArgumentException (sprintf ('Container has no entry named: "%s" ' , $ listener ));
86
- }
87
-
88
- $ listener = $ container ->get ($ listener );
89
-
90
- if (!is_callable ($ listener )) {
91
- throw InvalidArgumentException::typeMisMatch ('callable ' , $ listener );
92
- }
93
-
94
122
return $ dispatcher ->listen ($ eventName , $ listener );
95
123
});
96
124
}
0 commit comments