18
18
use PhpSchool \PhpWorkshop \Exercise \ExerciseInterface ;
19
19
use PhpSchool \PhpWorkshop \Input \Input ;
20
20
use PhpSchool \PhpWorkshop \Output \OutputInterface ;
21
+ use PhpSchool \PhpWorkshop \Process \ProcessFactory ;
22
+ use PhpSchool \PhpWorkshop \Process \ProcessInput ;
21
23
use PhpSchool \PhpWorkshop \Result \Cli \RequestFailure ;
22
24
use PhpSchool \PhpWorkshop \Result \Cli \CliResult ;
23
25
use PhpSchool \PhpWorkshop \Result \Cli \GenericFailure ;
24
26
use PhpSchool \PhpWorkshop \Result \Cli \Success ;
25
27
use PhpSchool \PhpWorkshop \Result \Cli \ResultInterface as CliResultInterface ;
26
28
use PhpSchool \PhpWorkshop \Result \ResultInterface ;
27
29
use PhpSchool \PhpWorkshop \Utils \ArrayObject ;
30
+ use PhpSchool \PhpWorkshop \Utils \Collection ;
28
31
use RuntimeException ;
29
32
use Symfony \Component \Process \ExecutableFinder ;
30
33
use Symfony \Component \Process \Process ;
39
42
*/
40
43
class CliRunner implements ExerciseRunnerInterface
41
44
{
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
-
57
45
/**
58
46
* @var array<class-string>
59
47
*/
60
- private static $ requiredChecks = [
48
+ private static array $ requiredChecks = [
61
49
FileExistsCheck::class,
62
50
CodeExistsCheck::class,
63
51
PhpLintCheck::class,
@@ -67,24 +55,13 @@ class CliRunner implements ExerciseRunnerInterface
67
55
/**
68
56
* Requires the exercise instance and an event dispatcher.
69
57
*
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.
72
59
*/
73
- public function __construct (CliExercise $ exercise , EventDispatcher $ eventDispatcher )
74
- {
75
- $ php = (new 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
+ ) {
88
65
}
89
66
90
67
/**
@@ -105,59 +82,6 @@ public function getRequiredChecks(): array
105
82
return self ::$ requiredChecks ;
106
83
}
107
84
108
- /**
109
- * @param string $fileName
110
- * @param ArrayObject<int, string> $args
111
- * @param string $type
112
- * @return string
113
- */
114
- private function executePhpFile (string $ fileName , ArrayObject $ args , string $ type ): string
115
- {
116
- $ process = $ this ->getPhpProcess ($ fileName , $ args );
117
-
118
- $ process ->start ();
119
- $ this ->eventDispatcher ->dispatch (new CliExecuteEvent (sprintf ('cli.verify.%s.executing ' , $ type ), $ args ));
120
- $ process ->wait ();
121
-
122
- if (!$ process ->isSuccessful ()) {
123
- throw CodeExecutionException::fromProcess ($ process );
124
- }
125
-
126
- return $ process ->getOutput ();
127
- }
128
-
129
- /**
130
- * @param string $fileName
131
- * @param ArrayObject<int, string> $args
132
- *
133
- * @return Process
134
- */
135
- private function getPhpProcess (string $ fileName , ArrayObject $ args ): Process
136
- {
137
- return new Process (
138
- $ args ->prepend ($ fileName )->prepend ($ 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
- $ env = array_map (fn () => false , $ _ENV );
155
- $ env + array_map (fn () => false , $ _SERVER );
156
-
157
- return $ env ;
158
- }
159
-
160
-
161
85
/**
162
86
* Verifies a solution by invoking PHP from the CLI passing the arguments gathered from the exercise
163
87
* as command line arguments to PHP.
@@ -272,7 +196,12 @@ public function run(Input $input, OutputInterface $output): bool
272
196
273
197
$ args = $ event ->getArgs ();
274
198
275
- $ process = $ this ->getPhpProcess ($ input ->getRequiredArgument ('program ' ), $ args );
199
+ $ process = $ this ->getPhpProcess (
200
+ dirname ($ input ->getRequiredArgument ('program ' )),
201
+ $ input ->getRequiredArgument ('program ' ),
202
+ $ args
203
+ );
204
+
276
205
$ process ->start ();
277
206
$ this ->eventDispatcher ->dispatch (
278
207
new CliExecuteEvent ('cli.run.student.executing ' , $ args , ['output ' => $ output ])
@@ -296,4 +225,32 @@ public function run(Input $input, OutputInterface $output): bool
296
225
$ this ->eventDispatcher ->dispatch (new ExerciseRunnerEvent ('cli.run.finish ' , $ this ->exercise , $ input ));
297
226
return $ success ;
298
227
}
228
+
229
+ /**
230
+ * @param ArrayObject<int, string> $args
231
+ */
232
+ private function executePhpFile (string $ fileName , ArrayObject $ args , string $ type ): string
233
+ {
234
+ $ process = $ this ->getPhpProcess (dirname ($ fileName ), $ fileName , $ args );
235
+
236
+ $ process ->start ();
237
+ $ this ->eventDispatcher ->dispatch (new CliExecuteEvent (sprintf ('cli.verify.%s.executing ' , $ type ), $ args ));
238
+ $ process ->wait ();
239
+
240
+ if (!$ process ->isSuccessful ()) {
241
+ throw CodeExecutionException::fromProcess ($ process );
242
+ }
243
+
244
+ return $ process ->getOutput ();
245
+ }
246
+
247
+ /**
248
+ * @param ArrayObject<int, string> $args
249
+ */
250
+ private function getPhpProcess (string $ workingDirectory , string $ fileName , ArrayObject $ args ): Process
251
+ {
252
+ return $ this ->processFactory ->create (
253
+ new ProcessInput ('php ' , [$ fileName , ...$ args ->getArrayCopy ()], $ workingDirectory , [])
254
+ );
255
+ }
299
256
}
0 commit comments