Skip to content

Commit d0587ce

Browse files
committed
Introduce Input object
1 parent c905eb1 commit d0587ce

File tree

5 files changed

+238
-32
lines changed

5 files changed

+238
-32
lines changed

app/config.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
new CommandDefinition('credits', [], CreditsCommand::class)
9090
],
9191
'menu',
92+
$c->get(EventDispatcher::class),
9293
$c
9394
);
9495
},

src/CommandRouter.php

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
namespace PhpSchool\PhpWorkshop;
44

5+
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
56
use PhpSchool\PhpWorkshop\Exception\CliRouteNotExistsException;
67
use PhpSchool\PhpWorkshop\Exception\MissingArgumentException;
78
use Interop\Container\ContainerInterface;
9+
use PhpSchool\PhpWorkshop\Input\Input;
810
use SebastianBergmann\Environment\Runtime;
911

1012
/**
@@ -28,6 +30,11 @@ class CommandRouter
2830
*/
2931
private $defaultCommand;
3032

33+
/**
34+
* @var EventDispatcher
35+
*/
36+
private $eventDispatcher;
37+
3138
/**
3239
* @var ContainerInterface
3340
*/
@@ -42,10 +49,15 @@ class CommandRouter
4249
*
4350
* @param CommandDefinition[] $commands An array of command definitions
4451
* @param string $default The default command to use (if the workshop was invoked with no arguments)
52+
* @param EventDispatcher $eventDispatcher
4553
* @param ContainerInterface $container An instance of the container
4654
*/
47-
public function __construct(array $commands, $default, ContainerInterface $container)
48-
{
55+
public function __construct(
56+
array $commands,
57+
$default,
58+
EventDispatcher $eventDispatcher,
59+
ContainerInterface $container
60+
) {
4961
foreach ($commands as $command) {
5062
$this->addCommand($command);
5163
}
@@ -54,6 +66,7 @@ public function __construct(array $commands, $default, ContainerInterface $conta
5466
throw new \InvalidArgumentException(sprintf('Default command: "%s" is not available', $default));
5567
}
5668
$this->defaultCommand = $default;
69+
$this->eventDispatcher = $eventDispatcher;
5770
$this->container = $container;
5871
}
5972

@@ -88,40 +101,47 @@ private function addCommand(CommandDefinition $c)
88101
*/
89102
public function route(array $args = null)
90103
{
104+
91105
if (null === $args) {
92106
$args = isset($_SERVER['argv']) ? $_SERVER['argv'] : [];
93107
}
94108

95109
$appName = array_shift($args);
96110

97111
if (empty($args)) {
98-
return $this->resolveCallable($this->commands[$this->defaultCommand], array_merge([$appName], $args));
112+
return $this->resolveCallable($this->commands[$this->defaultCommand], new Input($appName));
99113
}
100114

101115
$commandName = array_shift($args);
102116
if (!isset($this->commands[$commandName])) {
103117
$command = $this->findNearestCommand($commandName, $this->commands);
104-
118+
105119
if (false === $command) {
106120
throw new CliRouteNotExistsException($commandName);
107121
}
108-
122+
109123
$commandName = $command;
110124
}
111125
$command = $this->commands[$commandName];
112126

113-
$this->checkRequiredArgs($commandName, $command->getRequiredArgs(), $args);
127+
$this->eventDispatcher->dispatch(new Event\Event('route.pre.resolve.args', ['command' => $command]));
114128

115-
return $this->resolveCallable($command, array_merge([$appName], $args));
129+
$input = $this->parseArgs($commandName, $command->getRequiredArgs(), $appName, $args);
130+
131+
return $this->resolveCallable($command, $input);
116132
}
117133

118134
/**
119135
* @param string $commandName
120-
* @param array $definitionArgs
136+
* @param CommandArgument[] $definitionArgs
137+
* @param string $appName
121138
* @param array $givenArgs
139+
* @return Input
122140
*/
123-
private function checkRequiredArgs($commandName, array $definitionArgs, array $givenArgs)
141+
private function parseArgs($commandName, array $definitionArgs, $appName, array $givenArgs)
124142
{
143+
$parsedArgs = [];
144+
125145
while (null !== ($definitionArg = array_shift($definitionArgs))) {
126146
$arg = array_shift($givenArgs);
127147

@@ -130,7 +150,11 @@ private function checkRequiredArgs($commandName, array $definitionArgs, array $g
130150
return $argument->getName();
131151
}, array_merge([$definitionArg], $definitionArgs)));
132152
}
153+
154+
$parsedArgs[$definitionArg->getName()] = $arg;
133155
}
156+
157+
return new Input($appName, $parsedArgs);
134158
}
135159

136160
/**
@@ -147,29 +171,29 @@ private function findNearestCommand($commandName, array $commands)
147171
foreach (array_keys($commands) as $command) {
148172
$distances[$command] = levenshtein($commandName, $command);
149173
}
150-
174+
151175
$distances = array_filter(array_unique($distances), function ($distance) {
152176
return $distance <= 3;
153177
});
154-
178+
155179
if (empty($distances)) {
156180
return false;
157181
}
158-
182+
159183
return array_search(min($distances), $distances);
160184
}
161185

162186
/**
163187
* @param CommandDefinition $command
164-
* @param array $args
188+
* @param Input $input
165189
* @return int
166190
*/
167-
private function resolveCallable(CommandDefinition $command, array $args)
191+
private function resolveCallable(CommandDefinition $command, Input $input)
168192
{
169193
$commandCallable = $command->getCommandCallable();
170194

171195
if (is_callable($commandCallable)) {
172-
return $this->callCommand($commandCallable, $args);
196+
return $this->callCommand($command, $commandCallable, $input);
173197
}
174198

175199
if (!is_string($commandCallable)) {
@@ -186,7 +210,7 @@ private function resolveCallable(CommandDefinition $command, array $args)
186210
throw new \RuntimeException(sprintf('Container entry: "%s" not callable', $commandCallable));
187211
}
188212

189-
$return = $this->callCommand($callable, $args);
213+
$return = $this->callCommand($command, $callable, $input);
190214

191215
if (is_int($return)) {
192216
return $return;
@@ -196,12 +220,16 @@ private function resolveCallable(CommandDefinition $command, array $args)
196220
}
197221

198222
/**
199-
* @param callable $command
200-
* @param array $arguments
223+
* @param CommandDefinition $command
224+
* @param callable $callable
225+
* @param Input $input
201226
* @return int
202227
*/
203-
private function callCommand(callable $command, array $arguments)
228+
private function callCommand(CommandDefinition $command, callable $callable, Input $input)
204229
{
205-
return $command(...$arguments);
230+
$this->eventDispatcher->dispatch(new Event\Event('route.pre.invoke'));
231+
$this->eventDispatcher->dispatch(new Event\Event(sprintf('route.pre.invoke.%s', $command->getName())));
232+
233+
return $callable($input);
206234
}
207235
}

src/Input/Input.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace PhpSchool\PhpWorkshop\Input;
4+
5+
use PhpSchool\PhpWorkshop\CommandDefinition;
6+
use PhpSchool\PhpWorkshop\Exception\InvalidArgumentException;
7+
8+
/**
9+
* @author Aydin Hassan <aydin@hotmail.co.uk>
10+
*/
11+
class Input
12+
{
13+
/**
14+
* @var string
15+
*/
16+
private $appName;
17+
18+
/**
19+
* @var array
20+
*/
21+
private $arguments = [];
22+
23+
/**
24+
* Input constructor.
25+
* @param $appName
26+
* @param array $arguments
27+
*/
28+
public function __construct($appName, array $arguments = [])
29+
{
30+
$this->appName = $appName;
31+
$this->arguments = $arguments;
32+
}
33+
34+
/**
35+
* @return string
36+
*/
37+
public function getAppName()
38+
{
39+
return $this->appName;
40+
}
41+
42+
/**
43+
* @param string $name
44+
* @return bool
45+
*/
46+
public function hasArgument($name)
47+
{
48+
return isset($this->arguments[$name]);
49+
}
50+
51+
/**
52+
* @param string $name
53+
* @return string
54+
* @throws InvalidArgumentException
55+
*/
56+
public function getArgument($name)
57+
{
58+
if (!$this->hasArgument($name)) {
59+
throw new InvalidArgumentException(sprintf('Argument with name: "%s" does not exist', $name));
60+
}
61+
62+
return $this->arguments[$name];
63+
}
64+
65+
/**
66+
* @param string $name
67+
* @param string $value
68+
*/
69+
public function setArgument($name, $value)
70+
{
71+
$this->arguments[$name] = $value;
72+
}
73+
}

0 commit comments

Comments
 (0)