Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Symfony Console application and annotation commands in Drush #2103

Merged
merged 1 commit into from
May 7, 2016

Conversation

greg-1-anderson
Copy link
Member

@greg-1-anderson greg-1-anderson commented Mar 29, 2016

CONTINUED IN #2175.

Setting the DRUSH_SYMFONY environment variable makes the Symfony Console Application the main command runner. Otherwise, the original Drush command dispatcher is used first, and the Symfony Console Application is used as a backup.

There's a lot of work needed here before Drush will be fully functional under the Symfony Console Application. One interesting thing about Symfony Console is that option processing is not fully done until $application->run() is called. This means that work like site selection must be done via event listeners.

The list below enumerates what needs to be done, cross-referenced to other issues, PRs or commits that are relevant. Items that have existing code are checked off, but nothing should be considered to be "done" until reviewed, discussed and merged.

@weitzman weitzman added this to the drush9 milestone Mar 30, 2016
@weitzman
Copy link
Member

Nifty. It I like annotation classes as commands.

Great checklist - lots of work to do! Maybe we should split out the major ones into their own issues and link from there. Lets use the drush9 milestone to collect such issues.

This notice is noisy: Notice: Undefined index: default-value in /Users/moshe.weitzman/c/h/drush/includes/preflight.inc on line 266

@jhedstrom
Copy link
Member

Awesome to see this taking shape!

@Chi-teck
Copy link
Collaborator

Decide how to find and load module cli commands

You might find this useful:

Drupal Console discovers commands though name conventions.
https://github.com/hechoendrupal/DrupalConsole/blob/master/src/Helper/CommandDiscoveryHelper.php

DCG discovers commands using PHP reflection.
https://github.com/Chi-teck/drupal-code-generator/blob/master/src/GeneratorDiscovery.php

There is core conversation about Symfony Console integration with some interesting points about command discovery.
https://www.drupal.org/node/2242947

@weitzman
Copy link
Member

Thanks a lot for those links. Will read up on command discovery.

I just played with DCG and reviewed the code. Terrific work!

@greg-1-anderson
Copy link
Member Author

Thanks for the references; I was unaware of DCG.

I am ambivalent about the DCG discovery technique vs the DrupalConsole discovery technique. Being able to use instanceof is clearly a good thing; however, DCG at its core is still using filesystem iteration to discover classes, and furthemore it instantiates classes it does not need in order to use instanceof.

In the balance, I think I prefer the model that commandfiles must conform to some naming convention in their filenames, e.g. *Command.php, as DrupalConsole does.

@Chi-teck
Copy link
Collaborator

*Command.php

There should be a way to distinguish Drush commands from Drupal Console commands and other types of commands. Perhaps *DrushCommand.php or Drush/*Command.php

@greg-1-anderson
Copy link
Member Author

Actually, it is my goal to make it possible to write a Drupal 8 module cli tool that is loadable by both DrupalConsole and Drush. So, we'll instantiate any *Command.php, but will ignore anything that is an instanceof Symfony Console. Drush will only support annotation commands (and legacy procedural Drush commands, of course); DrupalConsole will use instanceof to distinguish between annotation commands and native Drupal Console commands. I'm working on the Drupal Console PR right now; I will cross-reference here when it is ready.

UPDATE: See hechoendrupal/drupal-console#2081 below.

@greg-1-anderson
Copy link
Member Author

Converted one command as a proof-of-concept, and got the tests to pass. Still a lot of work remaining, but a good milestone.


use Drush\Log\LogLevel;

class InitCommand extends \Robo\Tasks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the @option annotations below on the individual methods, but should there be an annotation on the class too for command discovery? Or are those intended to be discovered by other means?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commandfile discovery hasn't been designed yet, exactly. The basic mechanism is similar to what Drush does today: find all commandfiles, and then register all of the commands they define. Note that annotations on the class, or using instanceof are both possibilities for secondary techniques for command discovery / selection; however, there needs to be an additional initial filter function as well, as we would not want to load every class file available just to determine which are commandfiles.

DrupalConsole searches for files called *Command.php (in certain paths), and registers all of those. We should probably do something similar. Suggestions / PRs welcome.

@greg-1-anderson
Copy link
Member Author

Hooks and formatters are now working; I think the next step is to actually load a commandfile provided by a module, and see if we can make that work.

n.b. Module commandfiles will invariantly given a full bootstrap. We'll support allowing global and site commands to set their bootstrap level later.

@greg-1-anderson
Copy link
Member Author

I decided that Chi-teck was right, above; annotation commandfiles should use different filename patterns than Symfony commands. Discussion at consolidation/annotated-command#12

@greg-1-anderson
Copy link
Member Author

I renamed consolidation/annotation-command to consolidation/annotated-command. GitHub will automatically redirect the old links above to their new location in the new project name.

*/
public function phpEval($php, $options =
[
'format' => 'var_export',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does an annotation command specify @default-format and $options['format']? Also, I have not seen this use of use of an associative array as default value. Is that new in PHP?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put in both @default-format and 'format' => 'var_export' because I was experimenting; only one is needed on any given command. If you are using a Symfony Console command (whose parameters are always InputInterface, OutputInterface), then you must use @default-format.

The associative array as a default value, as far as I know, has always worked in php, but I have only verified this as far back as php 5.4. Its use in this context -- to define the default values for your options -- originated in Robo.

@greg-1-anderson
Copy link
Member Author

greg-1-anderson commented May 3, 2016

Going to investigate service tags, similar to what was done in an earlier Drush PR. See: tags example and the compiler pass.

Actually, it looks like it won't be necessary to use a compiler pass here. (UPDATE: It was necessary to use a compiler pass here.)

@@ -0,0 +1 @@
WootCommands.php
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this .gitignore really needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than make two copies of the same 'WootCommands', my scripts copy or symlink the Drupal 8 version into the Drupal 7 test module directory. I don't want this test artifact to be accidentally committed. It might also be a good idea to just erase the duplicate after the test runs.

@greg-1-anderson
Copy link
Member Author

I merged in #2169, so this PR now uses tagged services to find commands in Drupal 8 modules. In order for this to work, we need to create a subclass of DrupalKernel. A core patch that adds the functionality we need is here: https://www.drupal.org/node/2718933

@greg-1-anderson greg-1-anderson force-pushed the symfony-annotation-command branch from 4591667 to 6c09849 Compare May 6, 2016 23:23
@greg-1-anderson
Copy link
Member Author

I squashed and rebased this with the master branch.

@greg-1-anderson
Copy link
Member Author

Continued in #2843.

@weitzman weitzman deleted the symfony-annotation-command branch July 17, 2018 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants