44
55use Interop \Container \ContainerInterface ;
66use PhpSchool \PhpWorkshop \Event \EventDispatcher ;
7+ use PhpSchool \PhpWorkshop \Event \ContainerListenerHelper ;
78use PhpSchool \PhpWorkshop \Exception \InvalidArgumentException ;
8- use PhpSchool \PhpWorkshop \Listener \CodePatchListener ;
9- use PhpSchool \PhpWorkshop \Listener \PrepareSolutionListener ;
10- use PhpSchool \PhpWorkshop \Listener \SelfCheckListener ;
119use PhpSchool \PhpWorkshop \ResultAggregator ;
10+ use PhpSchool \PhpWorkshop \Utils \Collection ;
1211
1312/**
1413 * Class EventDispatcherFactory
@@ -27,36 +26,59 @@ public function __invoke(ContainerInterface $container)
2726 {
2827 $ dispatcher = new EventDispatcher ($ container ->get (ResultAggregator::class));
2928
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-
4229 //add listeners from config
4330 $ eventListeners = $ container ->has ('eventListeners ' ) ? $ container ->get ('eventListeners ' ) : [];
4431
4532 if (!is_array ($ eventListeners )) {
4633 throw InvalidArgumentException::typeMisMatch ('array ' , $ eventListeners );
4734 }
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 );
5239 }
40+ });
5341
42+ $ eventListeners = $ this ->mergeListenerGroups ($ eventListeners );
43+
44+ array_walk ($ eventListeners , function ($ listeners , $ eventName ) use ($ dispatcher , $ container ) {
5445 $ this ->attachListeners ($ eventName , $ listeners , $ container , $ dispatcher );
5546 });
5647
5748 return $ dispatcher ;
5849 }
5950
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+
6082 /**
6183 * @param string $eventName
6284 * @param array $listeners
@@ -71,26 +93,32 @@ private function attachListeners(
7193 EventDispatcher $ dispatcher
7294 ) {
7395 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+ });
76114 }
77115
78- if (!is_string ($ listener )) {
116+ if (!is_callable ($ listener )) {
79117 throw new InvalidArgumentException (
80118 sprintf ('Listener must be a callable or a container entry for a callable service. ' )
81119 );
82120 }
83121
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-
94122 return $ dispatcher ->listen ($ eventName , $ listener );
95123 });
96124 }
0 commit comments