1818use  PhpSchool \PhpWorkshop \Exercise \ExerciseInterface ;
1919use  PhpSchool \PhpWorkshop \Input \Input ;
2020use  PhpSchool \PhpWorkshop \Output \OutputInterface ;
21+ use  PhpSchool \PhpWorkshop \Process \ProcessFactory ;
22+ use  PhpSchool \PhpWorkshop \Process \ProcessInput ;
2123use  PhpSchool \PhpWorkshop \Result \Cli \RequestFailure ;
2224use  PhpSchool \PhpWorkshop \Result \Cli \CliResult ;
2325use  PhpSchool \PhpWorkshop \Result \Cli \GenericFailure ;
2426use  PhpSchool \PhpWorkshop \Result \Cli \Success ;
2527use  PhpSchool \PhpWorkshop \Result \Cli \ResultInterface  as  CliResultInterface ;
2628use  PhpSchool \PhpWorkshop \Result \ResultInterface ;
2729use  PhpSchool \PhpWorkshop \Utils \ArrayObject ;
30+ use  PhpSchool \PhpWorkshop \Utils \Collection ;
2831use  RuntimeException ;
2932use  Symfony \Component \Process \ExecutableFinder ;
3033use  Symfony \Component \Process \Process ;
3942 */ 
4043class  CliRunner implements  ExerciseRunnerInterface
4144{
42-  /** 
43-  * @var CliExercise&ExerciseInterface 
44-  */ 
45-  private  $ exercise
46- 47-  /** 
48-  * @var EventDispatcher 
49-  */ 
50-  private  $ eventDispatcher
51- 52-  /** 
53-  * @var string 
54-  */ 
55-  private  $ phpLocation
56- 5745 /** 
5846 * @var array<class-string> 
5947 */ 
60-  private  static  $ requiredChecks
48+  private  static  array $ requiredChecks
6149 FileExistsCheck::class,
6250 CodeExistsCheck::class,
6351 PhpLintCheck::class,
@@ -67,24 +55,13 @@ class CliRunner implements ExerciseRunnerInterface
6755 /** 
6856 * Requires the exercise instance and an event dispatcher. 
6957 * 
70-  * @param CliExercise $exercise The exercise to be invoked. 
71-  * @param EventDispatcher $eventDispatcher The event dispatcher. 
58+  * @param CliExercise&ExerciseInterface $exercise The exercise to be invoked. 
7259 */ 
73-  public  function  __construct (CliExercise $ exerciseEventDispatcher $ eventDispatcher
74-  {
75-  $ phpnew  ExecutableFinder ())->find ('php ' );
76- 77-  if  (null  === $ php
78-  throw  new  RuntimeException (
79-  'Could not load php binary. Please install php using your package manager. ' 
80-  );
81-  }
82- 83-  $ this phpLocation  = $ php
84- 85-  /** @var CliExercise&ExerciseInterface $exercise */ 
86-  $ this eventDispatcher  = $ eventDispatcher
87-  $ this exercise  = $ exercise
60+  public  function  __construct (
61+  private  CliExercise $ exercise
62+  private  EventDispatcher $ eventDispatcher
63+  private  ProcessFactory $ processFactory
64+  ) {
8865 }
8966
9067 /** 
@@ -105,59 +82,6 @@ public function getRequiredChecks(): array
10582 return  self ::$ requiredChecks
10683 }
10784
108-  /** 
109-  * @param string $fileName 
110-  * @param ArrayObject<int, string> $args 
111-  * @param string $type 
112-  * @return string 
113-  */ 
114-  private  function  executePhpFile (string  $ fileNameArrayObject $ argsstring  $ typestring 
115-  {
116-  $ process$ this getPhpProcess ($ fileName$ args
117- 118-  $ processstart ();
119-  $ this eventDispatcher ->dispatch (new  CliExecuteEvent (sprintf ('cli.verify.%s.executing ' , $ type$ args
120-  $ processwait ();
121- 122-  if  (!$ processisSuccessful ()) {
123-  throw  CodeExecutionException::fromProcess ($ process
124-  }
125- 126-  return  $ processgetOutput ();
127-  }
128- 129-  /** 
130-  * @param string $fileName 
131-  * @param ArrayObject<int, string> $args 
132-  * 
133-  * @return Process 
134-  */ 
135-  private  function  getPhpProcess (string  $ fileNameArrayObject $ argsProcess 
136-  {
137-  return  new  Process (
138-  $ argsprepend ($ fileNameprepend ($ this phpLocation )->getArrayCopy (),
139-  dirname ($ fileName
140-  $ this getDefaultEnv () + ['XDEBUG_MODE '  => 'off ' ],
141-  null ,
142-  10 
143-  );
144-  }
145- 146-  /** 
147-  * We need to reset env entirely, because Symfony inherits it. We do that by setting all 
148-  * the current env vars to false 
149-  * 
150-  * @return array<string, false> 
151-  */ 
152-  private  function  getDefaultEnv (): array 
153-  {
154-  $ envarray_map (fn  () => false , $ _ENV 
155-  $ envarray_map (fn  () => false , $ _SERVER 
156- 157-  return  $ env
158-  }
159- 160- 16185 /** 
16286 * Verifies a solution by invoking PHP from the CLI passing the arguments gathered from the exercise 
16387 * as command line arguments to PHP. 
@@ -272,7 +196,12 @@ public function run(Input $input, OutputInterface $output): bool
272196
273197 $ args$ eventgetArgs ();
274198
275-  $ process$ this getPhpProcess ($ inputgetRequiredArgument ('program ' ), $ args
199+  $ process$ this getPhpProcess (
200+  dirname ($ inputgetRequiredArgument ('program ' )),
201+  $ inputgetRequiredArgument ('program ' ),
202+  $ args
203+  );
204+ 276205 $ processstart ();
277206 $ this eventDispatcher ->dispatch (
278207 new  CliExecuteEvent ('cli.run.student.executing ' , $ args'output '  => $ output
@@ -296,4 +225,32 @@ public function run(Input $input, OutputInterface $output): bool
296225 $ this eventDispatcher ->dispatch (new  ExerciseRunnerEvent ('cli.run.finish ' , $ this exercise , $ input
297226 return  $ success
298227 }
228+ 229+  /** 
230+  * @param ArrayObject<int, string> $args 
231+  */ 
232+  private  function  executePhpFile (string  $ fileNameArrayObject $ argsstring  $ typestring 
233+  {
234+  $ process$ this getPhpProcess (dirname ($ fileName$ fileName$ args
235+ 236+  $ processstart ();
237+  $ this eventDispatcher ->dispatch (new  CliExecuteEvent (sprintf ('cli.verify.%s.executing ' , $ type$ args
238+  $ processwait ();
239+ 240+  if  (!$ processisSuccessful ()) {
241+  throw  CodeExecutionException::fromProcess ($ process
242+  }
243+ 244+  return  $ processgetOutput ();
245+  }
246+ 247+  /** 
248+  * @param ArrayObject<int, string> $args 
249+  */ 
250+  private  function  getPhpProcess (string  $ workingDirectorystring  $ fileNameArrayObject $ argsProcess 
251+  {
252+  return  $ this processFactory ->create (
253+  new  ProcessInput ('php ' , [$ fileName$ argsgetArrayCopy ()], $ workingDirectory
254+  );
255+  }
299256}
0 commit comments