Skip to content

Commit 3f93cad

Browse files
committed
Take the argument list from WP_Query::parse_query
Guessing at which arguments are worth writing down produced two that should not have been: 'has_password' and 'post_password' filter, but neither is a WP_Query argument. They are not in the docblock on WP_Query::parse_query, which is the list WP_Query actually documents, and they are gone again. Working from that docblock instead turned up the reverse problem, a lot of arguments left out for no reason. The list ones - post__in, author__in, category__in, tag__in and their relatives - were skipped on the belief that a comma-separated value would reach WP_Query as a string and quietly match its first entry alone. That was wrong: process_csv_arguments_to_arrays() already splits every argument whose name contains '__'. They work: wp post list --post__in=4,5 --format=count -> 2 wp post list --post_name__in=one,two -> 2 posts date_query, meta_query and tax_query were likewise already handled - list_() names all three for JSON decoding - and likewise undocumented. Sixty-three arguments are documented now, every one of them in the parse_query docblock. What is left out of that docblock is either internal bookkeeping, where a CLI user has no reason to reach ('cache_results', 'no_found_rows', 'suppress_filters', the cache-priming flags), or means something other than it appears to for a list ('page' paginates within a single post, 'comments_per_page' and 'posts_per_archive_page' are not about this query). Documenting a family by halves turned out to be worse than documenting all of it, measured against the near-match check in wp-cli/wp-cli#6392: documented set false positives before this commit 2 + the list arguments only 3 'tag_id' now looks like 'tag__in' + those and the id arguments 3 'paged' now looks like 'page_id' + those and pagination 2 everything here 2 Each partial step stranded a name whose neighbours had just been documented. The two that survive are 'feed' and 'tb', which are not filters at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SSZzqMJRDTiLiDxQEPYcL
1 parent 81f5b3e commit 3f93cad

3 files changed

Lines changed: 276 additions & 24 deletions

File tree

README.md

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,7 @@ wp post get <id> [--field=<field>] [--fields=<fields>] [--format=<format>]
31503150
Gets a list of posts.
31513151

31523152
~~~
3153-
wp post list [--<field>=<value>] [--p=<id>|ID] [--title=<title>|post_title] [--name=<slug>|post_name] [--author=<author>|post_author] [--author_name=<author_name>] [--cat=<cat>] [--category_name=<category_name>] [--tag=<tag>] [--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>] [--hour=<hour>] [--minute=<minute>] [--second=<second>] [--m=<yearmonth>] [--w=<week>] [--meta_key=<meta_key>] [--meta_value=<meta_value>] [--has_password=<has_password>] [--post_password=<post_password>] [--orderby=<orderby>] [--order=<order>] [--field=<field>] [--fields=<fields>] [--format=<format>]
3153+
wp post list [--<field>=<value>] [--p=<id>|ID] [--title=<title>|post_title] [--name=<slug>|post_name] [--author=<author>|post_author] [--author_name=<author_name>] [--cat=<cat>] [--category_name=<category_name>] [--tag=<tag>] [--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>] [--hour=<hour>] [--minute=<minute>] [--second=<second>] [--m=<yearmonth>] [--w=<week>] [--meta_key=<meta_key>] [--meta_value=<meta_value>] [--orderby=<orderby>] [--order=<order>] [--post__in=<ids>] [--post__not_in=<ids>] [--post_name__in=<slugs>] [--post_parent__in=<ids>] [--post_parent__not_in=<ids>] [--author__in=<ids>] [--author__not_in=<ids>] [--category__in=<ids>] [--category__and=<ids>] [--category__not_in=<ids>] [--tag_id=<tag_id>] [--tag__in=<ids>] [--tag__and=<ids>] [--tag__not_in=<ids>] [--tag_slug__in=<slugs>] [--tag_slug__and=<slugs>] [--page_id=<page_id>] [--pagename=<pagename>] [--attachment_id=<attachment_id>] [--date_query=<json>] [--meta_query=<json>] [--tax_query=<json>] [--meta_compare=<meta_compare>] [--sentence=<sentence>] [--exact=<exact>] [--search_columns=<columns>] [--perm=<perm>] [--posts_per_page=<number>] [--paged=<paged>] [--offset=<offset>] [--nopaging=<nopaging>] [--field=<field>] [--fields=<fields>] [--format=<format>]
31543154
~~~
31553155

31563156
Display posts based on all arguments supported by [WP_Query()](https://developer.wordpress.org/reference/classes/wp_query/).
@@ -3259,12 +3259,6 @@ Only shows post types marked as post by default.
32593259
Filter by this meta value. Needs `--meta_key` to say which key it
32603260
belongs to.
32613261

3262-
[--has_password=<has_password>]
3263-
Filter by whether the post has a password. Accepts 1 or 0.
3264-
3265-
[--post_password=<post_password>]
3266-
Filter by the post's password, matched in full.
3267-
32683262
[--orderby=<orderby>]
32693263
Order the results by this field. Accepts what WP_Query accepts, e.g.
32703264
'date', 'title', 'ID', 'menu_order', 'rand', or 'meta_value' alongside
@@ -3273,6 +3267,106 @@ Only shows post types marked as post by default.
32733267
[--order=<order>]
32743268
Direction to order by. Accepts 'ASC' or 'DESC'.
32753269

3270+
[--post__in=<ids>]
3271+
Only list the posts with these IDs (comma-separated).
3272+
3273+
[--post__not_in=<ids>]
3274+
Exclude the posts with these IDs (comma-separated).
3275+
3276+
[--post_name__in=<slugs>]
3277+
Only list the posts with these slugs (comma-separated). Unlike `--name`
3278+
this is not a single-post query, so it reaches drafts as well.
3279+
3280+
[--post_parent__in=<ids>]
3281+
Only list the posts whose parent is one of these IDs (comma-separated).
3282+
3283+
[--post_parent__not_in=<ids>]
3284+
Exclude the posts whose parent is one of these IDs (comma-separated).
3285+
3286+
[--author__in=<ids>]
3287+
Only list the posts by these author IDs (comma-separated).
3288+
3289+
[--author__not_in=<ids>]
3290+
Exclude the posts by these author IDs (comma-separated).
3291+
3292+
[--category__in=<ids>]
3293+
Only list the posts in these category IDs (comma-separated).
3294+
3295+
[--category__and=<ids>]
3296+
Only list the posts in all of these category IDs (comma-separated).
3297+
3298+
[--category__not_in=<ids>]
3299+
Exclude the posts in these category IDs (comma-separated).
3300+
3301+
[--tag_id=<tag_id>]
3302+
Filter by tag ID.
3303+
3304+
[--tag__in=<ids>]
3305+
Only list the posts with these tag IDs (comma-separated).
3306+
3307+
[--tag__and=<ids>]
3308+
Only list the posts with all of these tag IDs (comma-separated).
3309+
3310+
[--tag__not_in=<ids>]
3311+
Exclude the posts with these tag IDs (comma-separated).
3312+
3313+
[--tag_slug__in=<slugs>]
3314+
Only list the posts with these tag slugs (comma-separated).
3315+
3316+
[--tag_slug__and=<slugs>]
3317+
Only list the posts with all of these tag slugs (comma-separated).
3318+
3319+
[--page_id=<page_id>]
3320+
Filter by page ID. Needs `--post_type=page` to match anything.
3321+
3322+
[--pagename=<pagename>]
3323+
Filter by page slug. Needs `--post_type=page` to match anything.
3324+
3325+
[--attachment_id=<attachment_id>]
3326+
Filter by attachment ID. Needs `--post_type=attachment` to match
3327+
anything.
3328+
3329+
[--date_query=<json>]
3330+
Filter by a date query, given as JSON. See WP_Date_Query.
3331+
3332+
[--meta_query=<json>]
3333+
Filter by a meta query, given as JSON. See WP_Meta_Query.
3334+
3335+
[--tax_query=<json>]
3336+
Filter by a taxonomy query, given as JSON. See WP_Tax_Query.
3337+
3338+
[--meta_compare=<meta_compare>]
3339+
Operator to test `--meta_value` with, e.g. '=', '!=', '>' or 'LIKE'.
3340+
3341+
[--sentence=<sentence>]
3342+
Match `--s` as one phrase rather than as separate words. Accepts 1 or 0.
3343+
3344+
[--exact=<exact>]
3345+
Match `--s` against the whole column rather than part of it. Accepts 1
3346+
or 0.
3347+
3348+
[--search_columns=<columns>]
3349+
Comma-separated list of columns `--s` looks in. Accepts 'post_title',
3350+
'post_excerpt' and 'post_content'.
3351+
3352+
[--perm=<perm>]
3353+
Filter by what the current user may do with the post. Accepts
3354+
'readable' or 'editable'; pair it with the global `--user` argument,
3355+
since WP-CLI is no user by default.
3356+
3357+
[--posts_per_page=<number>]
3358+
How many posts to return. Defaults to -1, meaning every post.
3359+
3360+
[--paged=<paged>]
3361+
Which page of results to return, counted in `--posts_per_page` steps.
3362+
3363+
[--offset=<offset>]
3364+
How many posts to skip. Needs `--posts_per_page` set to something other
3365+
than -1, which otherwise takes precedence.
3366+
3367+
[--nopaging=<nopaging>]
3368+
Return every post, ignoring `--posts_per_page`. Accepts 1 or 0.
3369+
32763370
[--field=<field>]
32773371
Prints the value of a single field for each post.
32783372

features/post.feature

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ Feature: Manage WordPress posts
724724
1
725725
"""
726726

727-
Scenario: Filtering by meta, time of day, password and order
727+
Scenario: Filtering by meta, time of day and order
728728
When I run `wp post create --post_title='Timed' --post_status=publish --post_date='2020-03-04 05:06:07' --porcelain`
729729
Then STDOUT should be a number
730730
And save STDOUT as {TIMED_ID}
@@ -765,30 +765,94 @@ Feature: Manage WordPress posts
765765
0
766766
"""
767767

768-
When I run `wp post list --has_password=1 --field=post_title`
768+
When I run `wp post list --orderby=title --order=ASC --field=post_title`
769769
Then STDOUT should be:
770770
"""
771+
Hello world!
771772
Locked
773+
Timed
772774
"""
773775

774-
When I run `wp post list --post_password=secret --field=post_title`
776+
When I run `wp post list --orderby=title --order=DESC --field=post_title`
775777
Then STDOUT should be:
776778
"""
779+
Timed
777780
Locked
781+
Hello world!
778782
"""
779783

780-
When I run `wp post list --orderby=title --order=ASC --field=post_title`
784+
Scenario: Filtering by lists, JSON queries and search columns
785+
When I run `wp post create --post_title='Zebra Title' --post_content='nothing' --post_status=publish --porcelain`
786+
Then save STDOUT as {TITLED}
787+
788+
When I run `wp post create --post_title='Plain' --post_name=plain --post_content='zebra in body' --post_status=publish --porcelain`
789+
Then save STDOUT as {BODIED}
790+
791+
When I run `wp post meta add {TITLED} rank 5`
792+
Then STDOUT should not be empty
793+
794+
# Arguments carrying '__' are split on commas before they reach WP_Query,
795+
# which is what makes them usable from the command line at all.
796+
When I run `wp post list --post__in={TITLED},{BODIED} --format=count`
781797
Then STDOUT should be:
782798
"""
783-
Hello world!
784-
Locked
785-
Timed
799+
2
786800
"""
787801

788-
When I run `wp post list --orderby=title --order=DESC --field=post_title`
802+
When I run `wp post list --post__not_in={TITLED},{BODIED} --format=count`
789803
Then STDOUT should be:
790804
"""
791-
Timed
792-
Locked
793-
Hello world!
805+
1
806+
"""
807+
808+
# Unlike --name, this reaches a draft, because it is not a single-post query.
809+
When I run `wp post list --post_name__in=plain --field=post_title`
810+
Then STDOUT should be:
811+
"""
812+
Plain
813+
"""
814+
815+
# --s searches every column; --search_columns narrows it.
816+
When I run `wp post list --s=zebra --format=count`
817+
Then STDOUT should be:
818+
"""
819+
2
820+
"""
821+
822+
When I run `wp post list --s=zebra --search_columns=post_title --field=post_title`
823+
Then STDOUT should be:
824+
"""
825+
Zebra Title
826+
"""
827+
828+
When I run `wp post list --s=zebra --search_columns=post_title,post_content --format=count`
829+
Then STDOUT should be:
830+
"""
831+
2
832+
"""
833+
834+
# The nested queries are given as JSON, which this command decodes.
835+
When I run `wp post list --meta_query='[{"key":"rank","value":"5"}]' --field=post_title`
836+
Then STDOUT should be:
837+
"""
838+
Zebra Title
839+
"""
840+
841+
When I run `wp post list --meta_key=rank --meta_value=4 --meta_compare=">" --field=post_title`
842+
Then STDOUT should be:
843+
"""
844+
Zebra Title
845+
"""
846+
847+
# --offset only means anything once --posts_per_page is bounded.
848+
When I run `wp post list --posts_per_page=10 --offset=1 --format=count`
849+
Then STDOUT should be:
850+
"""
851+
2
852+
"""
853+
854+
When I run `wp post list --posts_per_page=1 --nopaging=1 --format=count`
855+
Then STDOUT should be:
856+
"""
857+
3
794858
"""

src/Post_Command.php

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -717,12 +717,6 @@ protected function delete_callback( $post_id, $assoc_args ) {
717717
* : Filter by this meta value. Needs `--meta_key` to say which key it
718718
* belongs to.
719719
*
720-
* [--has_password=<has_password>]
721-
* : Filter by whether the post has a password. Accepts 1 or 0.
722-
*
723-
* [--post_password=<post_password>]
724-
* : Filter by the post's password, matched in full.
725-
*
726720
* [--orderby=<orderby>]
727721
* : Order the results by this field. Accepts what WP_Query accepts, e.g.
728722
* 'date', 'title', 'ID', 'menu_order', 'rand', or 'meta_value' alongside
@@ -731,6 +725,106 @@ protected function delete_callback( $post_id, $assoc_args ) {
731725
* [--order=<order>]
732726
* : Direction to order by. Accepts 'ASC' or 'DESC'.
733727
*
728+
* [--post__in=<ids>]
729+
* : Only list the posts with these IDs (comma-separated).
730+
*
731+
* [--post__not_in=<ids>]
732+
* : Exclude the posts with these IDs (comma-separated).
733+
*
734+
* [--post_name__in=<slugs>]
735+
* : Only list the posts with these slugs (comma-separated). Unlike `--name`
736+
* this is not a single-post query, so it reaches drafts as well.
737+
*
738+
* [--post_parent__in=<ids>]
739+
* : Only list the posts whose parent is one of these IDs (comma-separated).
740+
*
741+
* [--post_parent__not_in=<ids>]
742+
* : Exclude the posts whose parent is one of these IDs (comma-separated).
743+
*
744+
* [--author__in=<ids>]
745+
* : Only list the posts by these author IDs (comma-separated).
746+
*
747+
* [--author__not_in=<ids>]
748+
* : Exclude the posts by these author IDs (comma-separated).
749+
*
750+
* [--category__in=<ids>]
751+
* : Only list the posts in these category IDs (comma-separated).
752+
*
753+
* [--category__and=<ids>]
754+
* : Only list the posts in all of these category IDs (comma-separated).
755+
*
756+
* [--category__not_in=<ids>]
757+
* : Exclude the posts in these category IDs (comma-separated).
758+
*
759+
* [--tag_id=<tag_id>]
760+
* : Filter by tag ID.
761+
*
762+
* [--tag__in=<ids>]
763+
* : Only list the posts with these tag IDs (comma-separated).
764+
*
765+
* [--tag__and=<ids>]
766+
* : Only list the posts with all of these tag IDs (comma-separated).
767+
*
768+
* [--tag__not_in=<ids>]
769+
* : Exclude the posts with these tag IDs (comma-separated).
770+
*
771+
* [--tag_slug__in=<slugs>]
772+
* : Only list the posts with these tag slugs (comma-separated).
773+
*
774+
* [--tag_slug__and=<slugs>]
775+
* : Only list the posts with all of these tag slugs (comma-separated).
776+
*
777+
* [--page_id=<page_id>]
778+
* : Filter by page ID. Needs `--post_type=page` to match anything.
779+
*
780+
* [--pagename=<pagename>]
781+
* : Filter by page slug. Needs `--post_type=page` to match anything.
782+
*
783+
* [--attachment_id=<attachment_id>]
784+
* : Filter by attachment ID. Needs `--post_type=attachment` to match
785+
* anything.
786+
*
787+
* [--date_query=<json>]
788+
* : Filter by a date query, given as JSON. See WP_Date_Query.
789+
*
790+
* [--meta_query=<json>]
791+
* : Filter by a meta query, given as JSON. See WP_Meta_Query.
792+
*
793+
* [--tax_query=<json>]
794+
* : Filter by a taxonomy query, given as JSON. See WP_Tax_Query.
795+
*
796+
* [--meta_compare=<meta_compare>]
797+
* : Operator to test `--meta_value` with, e.g. '=', '!=', '>' or 'LIKE'.
798+
*
799+
* [--sentence=<sentence>]
800+
* : Match `--s` as one phrase rather than as separate words. Accepts 1 or 0.
801+
*
802+
* [--exact=<exact>]
803+
* : Match `--s` against the whole column rather than part of it. Accepts 1
804+
* or 0.
805+
*
806+
* [--search_columns=<columns>]
807+
* : Comma-separated list of columns `--s` looks in. Accepts 'post_title',
808+
* 'post_excerpt' and 'post_content'.
809+
*
810+
* [--perm=<perm>]
811+
* : Filter by what the current user may do with the post. Accepts
812+
* 'readable' or 'editable'; pair it with the global `--user` argument,
813+
* since WP-CLI is no user by default.
814+
*
815+
* [--posts_per_page=<number>]
816+
* : How many posts to return. Defaults to -1, meaning every post.
817+
*
818+
* [--paged=<paged>]
819+
* : Which page of results to return, counted in `--posts_per_page` steps.
820+
*
821+
* [--offset=<offset>]
822+
* : How many posts to skip. Needs `--posts_per_page` set to something other
823+
* than -1, which otherwise takes precedence.
824+
*
825+
* [--nopaging=<nopaging>]
826+
* : Return every post, ignoring `--posts_per_page`. Accepts 1 or 0.
827+
*
734828
* [--field=<field>]
735829
* : Prints the value of a single field for each post.
736830
*

0 commit comments

Comments
 (0)