Skip to content

Commit d0c9a83

Browse files
committed
Make tests pass
1 parent 3e986b2 commit d0c9a83

18 files changed

+139
-157
lines changed

composer.lock

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpstan.neon

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
parameters:
22
treatPhpDocTypesAsCertain: false
33
ignoreErrors:
4-
-
5-
message: '#PhpSchool\\PhpWorkshop\\ExerciseRunner\\CliRunner\:\:preserveOldArgFormat\(\) should return#'
6-
path: src/ExerciseRunner/CliRunner.php
74
-
85
message: '#Call to an undefined method PhpParser\\Node\\Expr\|PhpParser\\Node\\Name\:\:__toString\(\)#'
96
path: src/Check/FunctionRequirementsCheck.php

src/Event/CliExecuteEvent.php

+7-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpSchool\PhpWorkshop\Event;
66

77
use PhpSchool\PhpWorkshop\Utils\ArrayObject;
8+
use PhpSchool\PhpWorkshop\Utils\Collection;
89

910
/**
1011
* An event to represent events which occur throughout the verification and running process in
@@ -13,16 +14,16 @@
1314
class CliExecuteEvent extends Event
1415
{
1516
/**
16-
* @var ArrayObject<int, string>
17+
* @var Collection<int, string>
1718
*/
18-
private $args;
19+
private Collection $args;
1920

2021
/**
2122
* @param string $name The event name.
22-
* @param ArrayObject<int, string> $args The arguments that should be/have been passed to the program.
23+
* @param Collection<int, string> $args The arguments that should be/have been passed to the program.
2324
* @param array<mixed> $parameters The event parameters.
2425
*/
25-
public function __construct(string $name, ArrayObject $args, array $parameters = [])
26+
public function __construct(string $name, Collection $args, array $parameters = [])
2627
{
2728
$parameters['args'] = $args;
2829
parent::__construct($name, $parameters);
@@ -52,9 +53,9 @@ public function appendArg(string $arg): void
5253
/**
5354
* Get the arguments to be passed to the program.
5455
*
55-
* @return ArrayObject<int, string>
56+
* @return Collection<int, string>
5657
*/
57-
public function getArgs(): ArrayObject
58+
public function getArgs(): Collection
5859
{
5960
return $this->args;
6061
}

src/ExerciseRunner/CgiRunner.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,16 @@ private function getProcess(string $fileName, RequestInterface $request): Proces
195195
$env = $this->getDefaultEnv();
196196
$env += [
197197
'REQUEST_METHOD' => $request->getMethod(),
198-
'SCRIPT_FILENAME' => '/solution/' . basename($fileName), // TODO: Figure out this path in the container
199-
'REDIRECT_STATUS' => 302,
198+
//'SCRIPT_FILENAME' => '/solution/' . basename($fileName), // TODO: Figure out this path in the container
199+
'SCRIPT_FILENAME' => $fileName,
200+
'REDIRECT_STATUS' => '302',
200201
'QUERY_STRING' => $request->getUri()->getQuery(),
201202
'REQUEST_URI' => $request->getUri()->getPath(),
202203
'XDEBUG_MODE' => 'off',
203204
];
204205

205206
$content = $request->getBody()->__toString();
206-
$env['CONTENT_LENGTH'] = $request->getBody()->getSize();
207+
$env['CONTENT_LENGTH'] = (string) $request->getBody()->getSize();
207208
$env['CONTENT_TYPE'] = $request->getHeaderLine('Content-Type');
208209

209210
foreach ($request->getHeaders() as $name => $values) {

src/ExerciseRunner/CliRunner.php

+14-29
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use PhpSchool\PhpWorkshop\Result\Cli\ResultInterface as CliResultInterface;
2727
use PhpSchool\PhpWorkshop\Result\ResultInterface;
2828
use PhpSchool\PhpWorkshop\Utils\ArrayObject;
29+
use PhpSchool\PhpWorkshop\Utils\Collection;
2930
use Psr\Container\ContainerInterface;
3031
use RuntimeException;
3132
use Symfony\Component\Process\ExecutableFinder;
@@ -100,11 +101,11 @@ public function getRequiredChecks(): array
100101

101102
/**
102103
* @param string $fileName
103-
* @param ArrayObject<int, string> $args
104+
* @param Collection<int, string> $args
104105
* @param string $type
105106
* @return string
106107
*/
107-
private function executePhpFile(string $fileName, ArrayObject $args, string $type): string
108+
private function executePhpFile(string $fileName, Collection $args, string $type): string
108109
{
109110
$process = $this->getPhpProcess($fileName, $args);
110111

@@ -121,13 +122,13 @@ private function executePhpFile(string $fileName, ArrayObject $args, string $typ
121122

122123
/**
123124
* @param string $fileName
124-
* @param ArrayObject<int, string> $args
125+
* @param Collection<int, string> $args
125126
*
126127
* @return Process
127128
*/
128-
private function getPhpProcess(string $fileName, ArrayObject $args): Process
129+
private function getPhpProcess(string $fileName, Collection $args): Process
129130
{
130-
return $this->processFactory->phpCli(dirname($fileName), $args->getArrayCopy());
131+
return $this->processFactory->phpCli($fileName, $args);
131132
}
132133

133134
/**
@@ -151,33 +152,14 @@ public function verify(Input $input): ResultInterface
151152
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.verify.start', $this->exercise, $input));
152153
$result = new CliResult(
153154
array_map(
154-
function (array $args) use ($input) {
155-
return $this->doVerify($args, $input);
156-
},
157-
$this->preserveOldArgFormat($this->exercise->getArgs())
155+
fn(array $args) => $this->doVerify($args, $input),
156+
$this->exercise->getArgs()
158157
)
159158
);
160159
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.verify.finish', $this->exercise, $input));
161160
return $result;
162161
}
163162

164-
/**
165-
* BC - getArgs only returned 1 set of args in v1 instead of multiple sets of args in v2
166-
*
167-
* @param array<int, array<string>>|array<int, string> $args
168-
* @return array<int, array<string>>
169-
*/
170-
private function preserveOldArgFormat(array $args): array
171-
{
172-
if (isset($args[0]) && !is_array($args[0])) {
173-
$args = [$args];
174-
} elseif (count($args) === 0) {
175-
$args = [[]];
176-
}
177-
178-
return $args;
179-
}
180-
181163
/**
182164
* @param array<string> $args
183165
* @param Input $input
@@ -186,7 +168,8 @@ private function preserveOldArgFormat(array $args): array
186168
private function doVerify(array $args, Input $input): CliResultInterface
187169
{
188170
//arrays are not pass-by-ref
189-
$args = new ArrayObject($args);
171+
$args = new Collection($args);
172+
/** @var Collection<int,string> $args */
190173

191174
try {
192175
/** @var CliExecuteEvent $event */
@@ -236,10 +219,12 @@ public function run(Input $input, OutputInterface $output): bool
236219
{
237220
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.run.start', $this->exercise, $input));
238221
$success = true;
239-
foreach ($this->preserveOldArgFormat($this->exercise->getArgs()) as $i => $args) {
222+
foreach ($this->exercise->getArgs() as $i => $args) {
223+
/** @var Collection<int, string> $argsCollection */
224+
$argsCollection = new Collection($args);
240225
/** @var CliExecuteEvent $event */
241226
$event = $this->eventDispatcher->dispatch(
242-
new CliExecuteEvent('cli.run.student-execute.pre', new ArrayObject($args))
227+
new CliExecuteEvent('cli.run.student-execute.pre', $argsCollection)
243228
);
244229

245230
$args = $event->getArgs();

src/Listener/PrepareSolutionListener.php

+16-40
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,9 @@ class PrepareSolutionListener
2121

2222
public function __construct(ProcessFactory $processFactory)
2323
{
24-
$this->processFactory = $processFactory;
24+
$this->processFactory = $processFactory;
2525
}
2626

27-
/**
28-
* Locations for composer executable
29-
*
30-
* @var array<string>
31-
*/
32-
private static $composerLocations = [
33-
'composer',
34-
'composer.phar',
35-
'/usr/local/bin/composer',
36-
__DIR__ . '/../../vendor/bin/composer',
37-
];
38-
3927
/**
4028
* @param ExerciseRunnerEvent $event
4129
*/
@@ -49,37 +37,25 @@ public function __invoke(ExerciseRunnerEvent $event): void
4937

5038
$solution = $exercise->getSolution();
5139

52-
if ($solution->hasComposerFile()) {
53-
//prepare composer deps
54-
//only install if composer.lock file not available
40+
if (!$solution->hasComposerFile()) {
41+
return;
42+
}
5543

56-
if (!file_exists(sprintf('%s/vendor', $solution->getBaseDirectory()))) {
57-
$process = $this->processFactory->composer(
58-
$solution->getBaseDirectory(),
59-
'install',
60-
['--no-interaction']
61-
);
44+
//prepare composer deps
45+
//only install if composer.lock file not available
6246

63-
try {
64-
$process->mustRun();
65-
} catch (\Symfony\Component\Process\Exception\RuntimeException $e) {
66-
throw new RuntimeException('Composer dependencies could not be installed', 0, $e);
67-
}
68-
}
69-
}
70-
}
47+
if (!file_exists(sprintf('%s/vendor', $solution->getBaseDirectory()))) {
48+
$process = $this->processFactory->composer(
49+
$solution->getBaseDirectory(),
50+
'install',
51+
['--no-interaction']
52+
);
7153

72-
/**
73-
* @return string
74-
*/
75-
public static function locateComposer(): string
76-
{
77-
foreach (self::$composerLocations as $location) {
78-
if (file_exists($location) && is_executable($location)) {
79-
return $location;
54+
try {
55+
$process->mustRun();
56+
} catch (\Symfony\Component\Process\Exception\RuntimeException $e) {
57+
throw new RuntimeException('Composer dependencies could not be installed', 0, $e);
8058
}
8159
}
82-
83-
throw new RuntimeException('Composer could not be located on the system');
8460
}
8561
}

src/Process/DockerProcessFactory.php

+15-11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpSchool\PhpWorkshop\Process;
66

7+
use PhpSchool\PhpWorkshop\Utils\Collection;
78
use Symfony\Component\Process\ExecutableFinder;
89
use Symfony\Component\Process\Process;
910

@@ -20,30 +21,33 @@ public function __construct(string $basePath, string $dockerBinaryPath, string $
2021
$this->projectName = $projectName;
2122
}
2223

24+
/**
25+
* @return array<string>
26+
*/
2327
private function baseComposeCommand(): array
2428
{
25-
return [
26-
$this->docker,
27-
'compose',
28-
'-p', $this->projectName,
29-
'-f', '.docker/runtime/docker-compose.yml',
30-
'run',
31-
'--rm'
32-
];
29+
return [
30+
$this->docker,
31+
'compose',
32+
'-p', $this->projectName,
33+
'-f', '.docker/runtime/docker-compose.yml',
34+
'run',
35+
'--rm'
36+
];
3337
}
3438

35-
public function composer(string $solitionPath, string $composerCommand, array $composerArgs): Process
39+
public function composer(string $solutionPath, string $composerCommand, array $composerArgs): Process
3640
{
3741
return new Process(
38-
[...$this->baseComposeCommand(), 'runtime', ...$composerCommand, ...$composerArgs],
42+
[...$this->baseComposeCommand(), 'runtime', $composerCommand, ...$composerArgs],
3943
$this->basePath,
4044
['SOLUTION' => $solutionPath],
4145
null,
4246
60
4347
);
4448
}
4549

46-
public function phpCli(string $fileName, array $args): Process
50+
public function phpCli(string $fileName, Collection $args): Process
4751
{
4852
return new Process(
4953
[...$this->baseComposeCommand(), 'runtime', 'php', '/solution/' . basename($fileName), ...$args],

0 commit comments

Comments
 (0)