Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 72 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3150,7 +3150,7 @@ wp post get <id> [--field=<field>] [--fields=<fields>] [--format=<format>]
Gets a list of posts.

~~~
wp post list [--<field>=<value>] [--field=<field>] [--fields=<fields>] [--format=<format>]
wp post list [--<field>=<value>] [--p=<id>|ID] [--title=<title>|post_title] [--name=<slug>|post_name] [--author=<author>|post_author] [--author_name=<author_name>] [--post_type=<post_type>] [--post_status=<post_status>] [--post_parent=<post_parent>] [--post_mime_type=<post_mime_type>] [--menu_order=<menu_order>] [--comment_status=<comment_status>] [--ping_status=<ping_status>] [--comment_count=<comment_count>] [--s=<string>] [--year=<year>] [--monthnum=<monthnum>] [--day=<day>] [--m=<yearmonth>] [--w=<week>] [--field=<field>] [--fields=<fields>] [--format=<format>]
~~~

Display posts based on all arguments supported by [WP_Query()](https://developer.wordpress.org/reference/classes/wp_query/).
Expand All @@ -3159,7 +3159,77 @@ Only shows post types marked as post by default.
**OPTIONS**

[--<field>=<value>]
One or more args to pass to WP_Query.
One or more args to pass to WP_Query. The arguments below are the ones
that filter on what this command displays; anything else WP_Query accepts
still works and is documented with WP_Query itself.

[--p=<id>|ID]
Filter by post ID. `--ID` is the name of the column this filters and is
accepted as an alias.

[--title=<title>|post_title]
Filter by post title, matched in full. `--post_title` is the name of the
column this filters and is accepted as an alias.

[--name=<slug>|post_name]
Filter by post slug. `--post_name` is the name of the column this filters
and is accepted as an alias.
Note: this makes the query a single-post one, and WP_Query returns a draft
from one of those only to a user who can edit it. WP-CLI runs as no user
unless the global `--user` argument says otherwise, so pass that to filter
drafts by slug.

[--author=<author>|post_author]
Filter by the ID of the post's author. `--post_author` is the name of the
column this filters and is accepted as an alias.

[--author_name=<author_name>]
Filter by the 'user_nicename' of the post's author.

[--post_type=<post_type>]
Filter by post type. Defaults to 'post'. Accepts a comma-separated list,
or 'any' for every type registered without 'exclude_from_search'.

[--post_status=<post_status>]
Filter by post status. Defaults to 'any', which is every status
registered without 'exclude_from_search' - so trashed and auto-draft posts
are left out until asked for by name, e.g. `--post_status=trash`.

[--post_parent=<post_parent>]
Filter by the ID of the parent post.

[--post_mime_type=<post_mime_type>]
Filter by MIME type. Only attachments carry one.

[--menu_order=<menu_order>]
Filter by menu order.

[--comment_status=<comment_status>]
Filter by comment status. Accepts 'open' or 'closed'.

[--ping_status=<ping_status>]
Filter by ping status. Accepts 'open' or 'closed'.

[--comment_count=<comment_count>]
Filter by number of comments.

[--s=<string>]
Only list the posts matching this search term.

[--year=<year>]
Filter by four-digit year, e.g. 2024.

[--monthnum=<monthnum>]
Filter by month number, 1 to 12.

[--day=<day>]
Filter by day of the month, 1 to 31.

[--m=<yearmonth>]
Filter by year and month together, e.g. 202401.

[--w=<week>]
Filter by week of the year, 0 to 53.

[--field=<field>]
Prints the value of a single field for each post.
Expand Down
97 changes: 97 additions & 0 deletions features/post.feature
Original file line number Diff line number Diff line change
Expand Up @@ -591,3 +591,100 @@ Feature: Manage WordPress posts
"""
{"block_version":1}
"""

Scenario: Filtering by the wp_posts column names
When I run `wp post create --post_title='Alpha' --post_status=publish --porcelain`
Then STDOUT should be a number

# 'title', 'name' and 'author' are WP_Query's names for these filters. The
# columns they filter on are spelled differently, and passing the column
# name used to reach WP_Query as an argument it does not know: it was
# dropped, and every post came back. They are aliases now.
When I run `wp post list --title='Hello world!' --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --post_title='Hello world!' --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --name=alpha --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --post_name=alpha --format=count`
Then STDOUT should be:
"""
1
"""

# Only the bundled post matches: a post created by WP-CLI has author 0,
# because WP-CLI runs as no user unless told otherwise.
When I run `wp post list --author=1 --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --post_author=1 --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --p=1 --format=count`
Then STDOUT should be:
"""
1
"""

When I run `wp post list --ID=1 --format=count`
Then STDOUT should be:
"""
1
"""

Scenario: Filtering drafts by slug needs a user
When I run `wp post create --post_title='Beta' --post_name=beta --post_status=draft --porcelain`
Then STDOUT should be a number

# '--name' makes this a single-post query, and WP_Query hands a draft from
# one of those only to a user who can edit it. WP-CLI is no user by default.
When I run `wp post list --name=beta --field=ID`
Then STDOUT should be empty

# The global '--user' argument is what makes it reachable.
When I run `wp post list --name=beta --user=1 --field=ID`
Then STDOUT should not be empty

Scenario: Trashed posts need their status named
When I run `wp post create --post_title='Doomed' --post_status=publish --porcelain`
Then STDOUT should be a number
And save STDOUT as {DOOMED_ID}

When I run `wp post delete {DOOMED_ID}`
Then STDOUT should contain:
"""
Success: Trashed post
"""

# This command defaults post_status to 'any', and WP_Query reads 'any' as
# every status registered without 'exclude_from_search' - which leaves out
# 'trash' and 'auto-draft'.
When I run `wp post list --field=ID`
Then STDOUT should not contain:
"""
{DOOMED_ID}
"""

When I run `wp post list --post_status=trash --field=ID`
Then STDOUT should contain:
"""
{DOOMED_ID}
"""
72 changes: 71 additions & 1 deletion src/Post_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,77 @@ protected function delete_callback( $post_id, $assoc_args ) {
* ## OPTIONS
*
* [--<field>=<value>]
* : One or more args to pass to WP_Query.
* : One or more args to pass to WP_Query. The arguments below are the ones
* that filter on what this command displays; anything else WP_Query accepts
* still works and is documented with WP_Query itself.
*
* [--p=<id>|ID]
* : Filter by post ID. `--ID` is the name of the column this filters and is
* accepted as an alias.
*
* [--title=<title>|post_title]
* : Filter by post title, matched in full. `--post_title` is the name of the
* column this filters and is accepted as an alias.
*
* [--name=<slug>|post_name]
* : Filter by post slug. `--post_name` is the name of the column this filters
* and is accepted as an alias.
* Note: this makes the query a single-post one, and WP_Query returns a draft
* from one of those only to a user who can edit it. WP-CLI runs as no user
* unless the global `--user` argument says otherwise, so pass that to filter
* drafts by slug.
*
* [--author=<author>|post_author]
* : Filter by the ID of the post's author. `--post_author` is the name of the
* column this filters and is accepted as an alias.
*
* [--author_name=<author_name>]
* : Filter by the 'user_nicename' of the post's author.
*
* [--post_type=<post_type>]
* : Filter by post type. Defaults to 'post'. Accepts a comma-separated list,
* or 'any' for every type registered without 'exclude_from_search'.
*
* [--post_status=<post_status>]
* : Filter by post status. Defaults to 'any', which is every status
* registered without 'exclude_from_search' - so trashed and auto-draft posts
* are left out until asked for by name, e.g. `--post_status=trash`.
*
* [--post_parent=<post_parent>]
* : Filter by the ID of the parent post.
*
* [--post_mime_type=<post_mime_type>]
* : Filter by MIME type. Only attachments carry one.
*
* [--menu_order=<menu_order>]
* : Filter by menu order.
*
* [--comment_status=<comment_status>]
* : Filter by comment status. Accepts 'open' or 'closed'.
*
* [--ping_status=<ping_status>]
* : Filter by ping status. Accepts 'open' or 'closed'.
*
* [--comment_count=<comment_count>]
* : Filter by number of comments.
*
* [--s=<string>]
* : Only list the posts matching this search term.
*
* [--year=<year>]
* : Filter by four-digit year, e.g. 2024.
*
* [--monthnum=<monthnum>]
* : Filter by month number, 1 to 12.
*
* [--day=<day>]
* : Filter by day of the month, 1 to 31.
*
* [--m=<yearmonth>]
* : Filter by year and month together, e.g. 202401.
*
* [--w=<week>]
* : Filter by week of the year, 0 to 53.
*
* [--field=<field>]
* : Prints the value of a single field for each post.
Expand Down