-
Notifications
You must be signed in to change notification settings - Fork 25
Migrate to symfony/console #23
Migrate to symfony/console #23
Conversation
4e522be
to
f05fd4d
Compare
This patch migrates the tooling to use symfony/console instead of zend-stdlib's `ConsoleHelper`. The reasons are: - We were needing to write argument parsing routines for each and every command, and each differed. - We were needing to write "help" functionality for each command. - We were creating a plethora of entry points. We should have one, with many commands available. - While we could use zf-deploy, using symfony/console will likely get more contributors to the project, due to its ubiquity in the PHP ecosystem. In the end, I also discovered that I ended up writing less code overall in order to create commands, and had better, simpler options for re-use when re-purposing existing command endpoints to re-use the same commands as used by the main entry point. All existing commands continue to work. I have updated the `expressive` tool to use the following patterns: - `migrate:*`: the various tools dedicated to migration. - `module:*`: the various tools dedicated to module manipulation. - `middleware:*`: the tools dedicated to middleware manipulation (currently only creation).
f05fd4d
to
791864d
Compare
- Removed obsolete `Command` and `Help` tests - Re-arranged `Module` tests and updated namespaces and class names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like update to symfony/console
! Many things is already done there so it simplify our library :) Couple of things to change and should be fine. Of course updating tests as you pointed is needed. Thanks!
src/Module/CreateCommand.php
Outdated
} catch (Exception\RuntimeException $e) { | ||
$console = $this->getErrorConsole($output); | ||
$console->writeln('<error>Error during execution:</error>', true, STDERR); | ||
$console->writeln(sprintf(' <error>%s</error>', $ex->getMessage()), true, STDERR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ex
is not defined. Here should be $e
or variable in catch should be renamed (I'd prefer to use $ex
for exception)
src/Module/CreateCommand.php
Outdated
$output->writeln(sprintf('<info>%s</info>', $message)); | ||
} catch (Exception\RuntimeException $e) { | ||
$console = $this->getErrorConsole($output); | ||
$console->writeln('<error>Error during execution:</error>', true, STDERR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we have different signature of writeln
method - from symfony, so there are two params: $messages
and $options
.
src/Module/DeregisterCommand.php
Outdated
$disable = new Disable($this->projectDir, $modulesPath, $composer); | ||
$disable->process($module); | ||
} catch (RuntimeException $ex) { | ||
$console = $this->getErrorConsole(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should be called with parameter. It's missing here.
src/Module/RegisterCommand.php
Outdated
$enable->setMoveModuleClass(false); | ||
$enable->process($module); | ||
} catch (RuntimeException $ex) { | ||
$console = $this->getErrorConsole(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above - missing required param.
@@ -34,9 +34,9 @@ class Scanner implements Countable, IteratorAggregate | |||
|
|||
/** | |||
* @param string $path | |||
* @param ConsoleHelper $console | |||
* @param OutputInterface $console |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same should be changed also in line 21.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
This patch updates all tests as follows: - Removes obsolete `Command` and `Help` tests. - Adds tests for new symfony/console commands. - Fixes test setup and expectations for classes that now depend on a symfony/console `OutputInterface` instance. - Fixes issues found during testing, including several also reported by @webimpress.
All tests updated and/or new tests written; doing so addressed most of the feedback from @webimpress, and I've updated a property typehint per his feedback as well. |
use Zend\Stdlib\ConsoleHelper; | ||
use Symfony\Component\Console\Application; | ||
|
||
const VERSION = '%version%'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cough PackageVersions cough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cough PHP 5.6 cough
bin/expressive
Outdated
$return = $command->process(array_slice($argv, 1)); | ||
exit($return); | ||
$application = new Application('expressive', VERSION); | ||
$application->add(new CreateMiddleware\CreateMiddlewareCommand('middleware:create')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, wasn't aware of that one!
$command = new Command($argv[0], new ConsoleHelper()); | ||
$return = $command->process(array_slice($argv, 1)); | ||
exit($return); | ||
$application = new Application('expressive-migrate-original-messages', VERSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can include the main CLI app, then set the default command instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a BC measure; the goal is to eventually remove it.
Also note that the command names differ between the main expressive
script and this one.
bin/expressive-module
Outdated
$return = $command->process(array_slice($argv, 1)); | ||
exit($return); | ||
$application = new Application('expressive-module', VERSION); | ||
$application->add(new CreateCommand('create')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this done just to keep the command names BC compliance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Since we already have documented migration steps, I cannot break how these original scripts worked; hence the difference between command names and what commands are exposed.
bin/expressive-pipeline-from-config
Outdated
$command = new Command($argv[0], new ConsoleHelper()); | ||
$return = $command->process(array_slice($argv, 1)); | ||
exit($return); | ||
$application = new Application('expressive-pipeline-from-config', VERSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: main app, set default command in this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above; this is a BC measure.
'<error>Unable to determine src directory: %s</error>', | ||
$e->getMessage() | ||
)); | ||
return 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let exceptions bubble up. If the exception message is meaningful, no additional code is needed
src/Module/CreateCommand.php
Outdated
$creation = new Create(); | ||
$message = $creation->process($module, $modulesPath, $this->projectDir); | ||
$output->writeln(sprintf('<info>%s</info>', $message)); | ||
} catch (Exception\RuntimeException $e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove, let it bubble up
src/Module/DeregisterCommand.php
Outdated
try { | ||
$disable = new Disable($this->projectDir, $modulesPath, $composer); | ||
$disable->process($module); | ||
} catch (RuntimeException $ex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove, let it bubble up
src/Module/RegisterCommand.php
Outdated
$enable = new Enable($this->projectDir, $modulesPath, $composer); | ||
$enable->setMoveModuleClass(false); | ||
$enable->process($module); | ||
} catch (RuntimeException $ex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
{ | ||
try { | ||
$src = $this->getSrcDir($input); | ||
} catch (ArgvException $e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
Per @Ocramius, it's simpler to allow exceptions to bubble up, as symfony/console will report the exception message always, and, when verbosity is enabled, more details including the stack trace.
@Ocramius I've incorporated your feedback; thanks a ton! |
Combines the entry for zendframework#22 with zendframework#23.
Have it invoke `to` with a fixed `version` argument.
return 1; | ||
} | ||
$generator = new Generator($output); | ||
$generator->projectDir = $this->projectDir; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh... Missed this before, why is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually... no longer necessary. It was necessary before I started mocking the various internal classes, but now it isn't. I'll nuke it in the various *Command
classes.
It's still necessary for the internal classes that do filesystem operations, though I may be able to move that to constructor arguments. I'll review.
src/Module/CommandCommonTrait.php
Outdated
/** | ||
* Add default arguments and options used by all commands. | ||
*/ | ||
private function addDefaultOptionsAndArguments() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a public static function
, referenced by classes using it.
src/Module/CommandCommonTrait.php
Outdated
* @param InputInterface $input | ||
* @return string | ||
*/ | ||
private function getModulesPath(InputInterface $input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a public static function
, referenced by classes using it.
src/Module/CommandCommonTrait.php
Outdated
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Input\InputOption; | ||
|
||
trait CommandCommonTrait |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be moved to a static class and marked as @internal
, since we really don't want to distribute this as public/reusable API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough; I'll make that change (and the ones you suggest below) momentarily.
This includes all commands, though a few, where we needed to test path existence, required the ability to inject a path, which is now handled by a setter; when the setter is not called, `getcwd()` is then assumed. For internal classes, this is now handled as either a passed argument, or via a constructor argument.
🚢 |
This patch migrates the tooling to use symfony/console instead of zend-stdlib's
ConsoleHelper
. The reasons are:All existing commands continue to work. I have updated the
expressive
tool to use the following patterns:migrate:*
: the various tools dedicated to migration.module:*
: the various tools dedicated to module manipulation.middleware:*
: the tools dedicated to middleware manipulation(currently only creation).
TODO