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

Add --filter to many commands #3718

Merged
merged 18 commits into from Oct 16, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5b35ff4
Add --filter to pm:list
greg-1-anderson Oct 4, 2018
5dc6984
Add filter-output to more commands
greg-1-anderson Oct 4, 2018
db64208
Add filter-output to example command and generated commands. Clean up…
greg-1-anderson Oct 4, 2018
0502032
Turn off validation for 'filter' in RoleCommands, since it might be a…
greg-1-anderson Oct 4, 2018
0da8fb5
Don't bother to install all of our dependencies; just install phpcs
greg-1-anderson Oct 4, 2018
5f7d975
Add filter default fields for other filterable commands. These are a …
greg-1-anderson Oct 5, 2018
1c5f908
Add a topic for output filters.
greg-1-anderson Oct 5, 2018
6e3c273
Merge branch 'master' into output-filter
greg-1-anderson Oct 5, 2018
40774ad
Make a combined topic about output formats, fields and filters.
greg-1-anderson Oct 6, 2018
b5c0345
Merge branch 'output-filter' of github.com:drush-ops/drush into outpu…
greg-1-anderson Oct 6, 2018
1bc647c
Make @filter-output annotaton implicit if @filter-default-field annot…
greg-1-anderson Oct 6, 2018
93283ad
Automatically add '@topics docs:output-formats-filters' to any comman…
greg-1-anderson Oct 7, 2018
25e92dc
[ci skip] Clarify the filter comparison operators = and *= are case-i…
greg-1-anderson Oct 7, 2018
0096318
[ci skip] Add a comparison between filters and grep in the output topic.
greg-1-anderson Oct 7, 2018
6bf87e1
Allow the 'site:alias' command to have selectable fields.
greg-1-anderson Oct 12, 2018
9dcf533
Update scenarios
greg-1-anderson Oct 15, 2018
86d9967
Use stable release of output-formatters with unstuctured data support…
greg-1-anderson Oct 16, 2018
9004ed9
Merge branch 'master' into output-filter
greg-1-anderson Oct 16, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -36,6 +36,7 @@
"composer/semver": "^1.4",
"consolidation/annotated-command": "^2.9.1",
"consolidation/config": "^1.1.0",
"consolidation/filter-via-dot-access-data": "^0.4",
"consolidation/output-formatters": "^3.1.12",
"consolidation/robo": "^1.1.5",
"consolidation/site-alias": "^1.1.5",
Expand Down
36 changes: 36 additions & 0 deletions docs/output-filters.md
@@ -0,0 +1,36 @@
Output Filters
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for writing this ... I have two thoughts. I don't know how to handle them though.

  1. Output filters sounds a lot like output formats which is a related but different concept. Everyone is going to mix them up.
  2. Might be worth saying how this feature differs from grep and when to use each.

==============

A number of Drush commands that output tabular data support a `--filter` option that allows rows from the output to be selected with simple logic expressions.

In its simplest form, the `--filter` option takes a simple string that indicates the value to filter by in the command's *default filter field*. For example, the `role:list` command's default filter field is `perms`; the output of the `role:list` command can be limited to only those roles that have a specified permission:
```
$ drush role:list --filter='post comments'
authenticated:
label: 'Authenticated user'
perms:
- 'access comments'
- 'access content'
- 'access shortcuts'
- 'access site-wide contact form'
- 'access user contact forms'
- 'post comments'
- 'search content'
- 'skip comment approval'
- 'use text format basic_html'
```
Note that not all commands have a default filter field.

Other fields in the output may be searched by using a simple expression in the `--filter` term. For example, to list only the enabled extensions with the `pm:list` command, you could run:
```
$ drush pm:list --filter='status=enabled'
```
To search for fields that contain a string using the operator `*=`, or match a regular expression with the `~=` operator. For example, to find all views whose machine name contains the word "content":
```
drush views:list --filter='machine-name*=content'
```
To use a regular expression to find any core requirement notice whose title contains either "php" or "gd"
```
drush core:requirements --filter='title~=#(php|gd)#i'
```
Finally, filter expressions may also use logical-and (`&&`) or logical-or (`||`) operations to separate multiple terms. Parenthesis are not supported.
2 changes: 2 additions & 0 deletions examples/Commands/ArtCommands.php
Expand Up @@ -65,6 +65,8 @@ public function art($art = '')
* path: Path
* @default-fields name,description
*
* @filter-output
* @filter-default-field name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function listArt($options = ['format' => 'table'])
Expand Down
5 changes: 3 additions & 2 deletions scenarios/isolation-phpunit4/composer.json
Expand Up @@ -67,8 +67,8 @@
"vendor-dir": "../../vendor"
},
"scripts": {
"cs": "phpcs -n --standard=PSR2 src tests examples",
"cbf": "phpcbf -n --standard=PSR2 src tests examples",
"cs": "phpcs",
"cbf": "phpcbf",
"lint": [
"find includes -name '*.inc' -print0 | xargs -0 -n1 php -l",
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
Expand All @@ -83,6 +83,7 @@
"api": "PATH=$HOME/bin:$PATH sami.phar --ansi update sami-config.php",
"sami-install": "mkdir -p $HOME/bin && curl --output $HOME/bin/sami.phar http://get.sensiolabs.org/sami.phar && chmod +x $HOME/bin/sami.phar",
"scenario": "scenarios/install",
"si-unish": "./drush site:install testing --uri=dev --sites-subdir=dev --db-url=mysql://root:password@mariadb/unish_dev -v",
"unit": "phpunit --colors=always",
"functional": "phpunit --colors=always --configuration tests",
"post-update-cmd": [
Expand Down
5 changes: 3 additions & 2 deletions scenarios/isolation/composer.json
Expand Up @@ -67,8 +67,8 @@
"vendor-dir": "../../vendor"
},
"scripts": {
"cs": "phpcs -n --standard=PSR2 src tests examples",
"cbf": "phpcbf -n --standard=PSR2 src tests examples",
"cs": "phpcs",
"cbf": "phpcbf",
"lint": [
"find includes -name '*.inc' -print0 | xargs -0 -n1 php -l",
"find src -name '*.php' -print0 | xargs -0 -n1 php -l",
Expand All @@ -83,6 +83,7 @@
"api": "PATH=$HOME/bin:$PATH sami.phar --ansi update sami-config.php",
"sami-install": "mkdir -p $HOME/bin && curl --output $HOME/bin/sami.phar http://get.sensiolabs.org/sami.phar && chmod +x $HOME/bin/sami.phar",
"scenario": "scenarios/install",
"si-unish": "./drush site:install testing --uri=dev --sites-subdir=dev --db-url=mysql://root:password@mariadb/unish_dev -v",
"unit": "phpunit --colors=always",
"functional": "phpunit --colors=always --configuration tests",
"post-update-cmd": [
Expand Down
3 changes: 2 additions & 1 deletion shippable.yml
Expand Up @@ -18,7 +18,8 @@ build:
- rm $HOME/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini
# Install / update our tools
- composer self-update
- composer install --no-interaction
- mkdir phpcs
- COMPOSER_BIN_DIR=$(pwd)/vendor/bin composer --working-dir=phpcs require "squizlabs/php_codesniffer:^2.7"
# Run code style and linting tools
- composer cs
- composer lint
1 change: 1 addition & 0 deletions src/Application.php
Expand Up @@ -316,6 +316,7 @@ public function configureAndRegisterCommands(InputInterface $input, OutputInterf

$discovery = $this->commandDiscovery();
$commandClasses = $discovery->discover($commandfileSearchpath, '\Drush');
$commandClasses[] = \Consolidation\Filter\Hooks\FilterHooks::class;

$this->loadCommandClasses($commandClasses);

Expand Down
2 changes: 2 additions & 0 deletions src/Commands/core/CoreCommands.php
Expand Up @@ -26,6 +26,8 @@ class CoreCommands extends DrushCommands implements SiteAliasManagerAwareInterfa
* @default-fields name,description
* @aliases core-global-options
*
* @filter-output
* @filter-default-field name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function globalOptions($options = ['format' => 'table'])
Expand Down
13 changes: 13 additions & 0 deletions src/Commands/core/DocsCommands.php
Expand Up @@ -77,6 +77,19 @@ public function configExport()
self::printFile(DRUSH_BASE_PATH. '/docs/config-exporting.md');
}

/**
* Explanation of how output filters work.
*
* @command docs:output-filters
* @aliases docs-output-filters
* @hidden
* @topic
*/
public function outputFilters()
{
self::printFile(DRUSH_BASE_PATH. '/docs/output-filters.md');
}

/**
* Creating site aliases for running Drush on remote sites.
*
Expand Down
2 changes: 2 additions & 0 deletions src/Commands/core/UpdateDBCommands.php
Expand Up @@ -112,6 +112,8 @@ public function entityUpdates($options = ['cache-clear' => true])
* description: Description
* type: Type
* @default-fields module,update_id,type,description
* @filter-output
* @filter-default-field module
weitzman marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

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

I think 'type' would be a better default field here.

* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function updatedbStatus($options = ['format'=> 'table', 'entity-updates' => true, 'post-updates' => true])
Expand Down
Expand Up @@ -31,6 +31,7 @@
* @command {{ machine_name }}:token
* @aliases token
*
* @filter-output
Copy link
Member

Choose a reason for hiding this comment

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

should declare a default field instead

Copy link
Member Author

Choose a reason for hiding this comment

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

How do we pick which field is the default field? Assume id and let the user change it?

Copy link
Member

Choose a reason for hiding this comment

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

In this case I would go with “name”. This is just an example method. It’s not dynamically adjusted or anything.

* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function token($options = ['format' => 'table']) {
Expand Down
2 changes: 2 additions & 0 deletions src/Commands/pm/SecurityUpdateCommands.php
Expand Up @@ -38,6 +38,8 @@ class SecurityUpdateCommands extends DrushCommands
* min-version: Suggested version
* @default-fields name,version,min-version
*
* @filter-output
* @filter-default-field name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*
* @throws \Exception
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/config/ConfigCommands.php
Expand Up @@ -221,6 +221,8 @@ public function delete($config_name, $key = null)
* state: State
* @default-fields name,state
* @aliases cst,config-status
* @filter-output
* @filter-default-field name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function status($options = ['state' => 'Only in DB,Only in sync dir,Different', 'prefix' => self::REQ, 'label' => self::REQ])
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/DrupalCommands.php
Expand Up @@ -84,6 +84,8 @@ public function cron()
* description: Description
* value: Summary
* @default-fields title,severity,value
* @filter-output
* @filter-default-field severity
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function requirements($options = ['format' => 'table', 'severity' => -1, 'ignore' => ''])
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/LanguageCommands.php
Expand Up @@ -102,6 +102,8 @@ public function add($langcode, $options = ['skip-translations' => false])
* default: Default
* locked: Locked
* @default-fields language,direction,default
* @filter-output
* @filter-default-field language
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function info()
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/QueueCommands.php
Expand Up @@ -98,6 +98,8 @@ public function run($name, $options = ['time-limit' => self::REQ])
* items: Items
* class: Class
*
* @filter-output
* @filter-default-field queue
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function qList($options = ['format' => 'table'])
Expand Down
9 changes: 3 additions & 6 deletions src/Drupal/Commands/core/RoleCommands.php
Expand Up @@ -106,8 +106,6 @@ public function roleRemovePerm($machine_name, $permissions)
* then all of the roles that have been granted that permission will be listed.
*
* @command role:list
* @validate-permissions filter
* @option filter Limits the list of roles to only those that have been assigned the specified permission.
* @usage drush role:list --filter='administer nodes'
* Display a list of roles that have the administer nodes permission assigned.
* @aliases rls,role-list
Expand All @@ -116,16 +114,15 @@ public function roleRemovePerm($machine_name, $permissions)
* label: Role Label
* perms: Permissions
*
* @filter-output
* @filter-default-field perms
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function roleList($options = ['format' => 'yaml', 'filter' => self::REQ])
public function roleList($options = ['format' => 'yaml'])
{
$rows = [];
$roles = Role::loadMultiple();
foreach ($roles as $role) {
if ($options['filter'] && !$role->hasPermission($options['filter'])) {
continue;
}
$rows[$role->id()] = [
'label' => $role->label(),
'perms' => $role->getPermissions(),
Expand Down
1 change: 1 addition & 0 deletions src/Drupal/Commands/core/TwigCommands.php
Expand Up @@ -64,6 +64,7 @@ public function __construct(TwigEnvironment $twig, ModuleHandlerInterface $modul
* template: Template
* compiled: Compiled
* @default-fields template,compiled
* @filter-output
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*
* @command twig:unused
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/UserCommands.php
Expand Up @@ -54,6 +54,8 @@ class UserCommands extends DrushCommands
* @table-style default
* @default-fields uid,name,mail,roles,user_status
*
* @filter-output
* @filter-default-field name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function information($names = '', $options = ['format' => 'table', 'uid' => self::REQ, 'mail' => self::REQ])
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/ViewsCommands.php
Expand Up @@ -140,6 +140,8 @@ public function dev()
* @aliases vl,views-list
* @validate-module-enabled views
*
* @filter-output
* @filter-default-field machine-name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function vlist($options = ['name' => self::REQ, 'tags' => self::REQ, 'status' => self::REQ, 'format' => 'table'])
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/WatchdogCommands.php
Expand Up @@ -45,6 +45,8 @@ class WatchdogCommands extends DrushCommands
* date: Date
* username: Username
* @default-fields wid,date,type,severity,message
* @filter-output
* @filter-default-field message
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function show($substring = '', $options = ['format' => 'table', 'count' => 10, 'severity' => self::REQ, 'type' => self::REQ, 'extended' => false])
Expand Down
2 changes: 2 additions & 0 deletions src/Drupal/Commands/pm/PmCommands.php
Expand Up @@ -151,6 +151,8 @@ public function validateUninstall(CommandData $commandData)
* version: Version
* @default-fields package,display_name,status,version
* @aliases pml,pm-list
* @filter-output
* @filter-default-field display_name
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
*/
public function pmList($options = ['format' => 'table', 'type' => 'module,theme', 'status' => 'enabled,disabled', 'package' => self::REQ, 'core' => false, 'no-core' => false])
Expand Down