44
55use Closure ;
66use ReflectionObject ;
7+ use RuntimeException ;
78use Zeus \Mock \Exceptions \InternalObjectException ;
89use Zeus \Mock \Exceptions \NamespaceNotFoundException ;
910use Zeus \Mock \Exceptions \OnceMockFunctionException ;
@@ -55,6 +56,12 @@ class ScopedFunctionMocker
5556 */
5657 private array $ calledCount = [];
5758
59+
60+ /**
61+ * @var callable[] $monitoringCallbacks
62+ */
63+ private array $ monitoringCallbacks = [];
64+
5865 /**
5966 *
6067 */
@@ -72,7 +79,7 @@ public function __construct()
7279 public function add (string $ name , mixed $ returnValue ): void
7380 {
7481 if ($ this ->onceMode && !in_array ($ name , $ this ->onceFunctions , true )) {
75- $ this ->onceFunctions [] = $ name ;
82+ $ this ->onceFunctions [] = $ name ;
7683 }
7784 if (!isset ($ this ->originalFunctions [$ name ]) && function_exists ($ name )) {
7885 $ this ->originalFunctions [$ name ] = $ name (...);
@@ -133,8 +140,9 @@ private function call(string $name, array $args): mixed
133140 }
134141 }
135142 return $ this ->executeWithEffect (
136- call_user_func ($ this ->functions [$ name ], ...$ args ),
137- fn () => $ this ->incrementCount ($ name )
143+ $ return =call_user_func ($ this ->functions [$ name ], ...$ args ),
144+ fn () => $ this ->incrementCount ($ name ),
145+ fn () => $ this ->invokeMonitoringCallbacks ($ name , $ args ,$ return )
138146 );
139147 }
140148
@@ -146,8 +154,9 @@ private function call(string $name, array $args): mixed
146154 private function callGlobalFunction (string $ name , mixed ...$ args ): mixed
147155 {
148156 return $ this ->executeWithEffect (
149- $ name (...$ args ),
150- fn () => $ this ->incrementCount ($ name )
157+ $ return = $ name (...$ args ),
158+ fn () => $ this ->incrementCount ($ name ),
159+ fn () => $ this ->invokeMonitoringCallbacks ($ name , $ args , $ return )
151160 );
152161 }
153162
@@ -194,12 +203,14 @@ private function generate(string $namespace): string
194203
195204 /**
196205 * @param mixed $returnValue
197- * @param Closure $effect
206+ * @param Closure ...$effects
198207 * @return mixed
199208 */
200- private function executeWithEffect (mixed $ returnValue , Closure $ effect ): mixed
209+ private function executeWithEffect (mixed $ returnValue , Closure ... $ effects ): mixed
201210 {
202- $ effect ();
211+ foreach ($ effects as $ effect ) {
212+ $ effect ();
213+ }
203214 return $ returnValue ;
204215 }
205216
@@ -310,12 +321,13 @@ public function runWithMock(object $object, Closure $closure): mixed
310321 }
311322
312323
313- public function once (Closure $ closure ):void
324+ public function once (Closure $ closure ): void
314325 {
315326 $ this ->onceMode = true ;
316327 $ closure ($ this );
317328 $ this ->onceMode = false ;
318329 }
330+
319331 /**
320332 * @param string $method
321333 * @param array $arguments
@@ -331,10 +343,63 @@ public static function __callStatic(string $method, array $arguments)
331343 };
332344 }
333345
334- public function addConsecutive (string $ name , array $ array ):void
346+ public function addConsecutive (string $ name , array $ array ): void
335347 {
336- $ this ->add ($ name ,function () use (&$ array ):mixed {
348+ $ this ->add ($ name , function () use (&$ array ): mixed {
337349 return array_shift ($ array );
338350 });
339351 }
352+
353+ /**
354+ * @param $name
355+ * @param array $arguments
356+ * @param mixed $return
357+ * @return void
358+ */
359+ private function invokeMonitoringCallbacks ($ name , array $ arguments , mixed $ return ): void
360+ {
361+ $ args = [
362+ 'function ' => $ name ,
363+ 'arguments ' => $ arguments ,
364+ 'return ' => $ return ,
365+ ];
366+ foreach ($ this ->monitoringCallbacks ?? [] as $ monitoringCallback ) {
367+ $ monitoringCallback ($ args );
368+ }
369+ }
370+
371+ /**
372+ * @param string $logFile
373+ * @return void
374+ */
375+ public function log (string $ logFile ): void
376+ {
377+ $ this ->monitoring (function (array $ args ) use ($ logFile ) {
378+
379+ $ logMessage = sprintf (
380+ "[%s] %s called with arguments: %s and returned: %s \n" ,
381+ date ('Y-m-d H:i:s ' ),
382+ $ args ['function ' ],
383+ json_encode ($ args ['arguments ' ], JSON_THROW_ON_ERROR ),
384+ json_encode ($ args ['return ' ], JSON_THROW_ON_ERROR )
385+ );
386+
387+ $ logDirectory = dirname ($ logFile );
388+
389+ if (!is_dir ($ logDirectory ) && !mkdir ($ logDirectory , 0755 , true ) && !is_dir ($ logDirectory )) {
390+ throw new RuntimeException (sprintf ('Directory "%s" was not created ' , $ logDirectory )); //NOSONAR
391+ }
392+
393+ file_put_contents ($ logFile , $ logMessage , FILE_APPEND | LOCK_EX );
394+ });
395+ }
396+
397+ /**
398+ * @param callable $handler
399+ * @return void
400+ */
401+ public function monitoring (callable $ handler ): void
402+ {
403+ $ this ->monitoringCallbacks [] = $ handler ;
404+ }
340405}
0 commit comments