Skip to content

Commit ba183d7

Browse files
committed
Merge branch 'main' into fix/network-meta
2 parents a52134a + 22bcd45 commit ba183d7

File tree

7 files changed

+248
-95
lines changed

7 files changed

+248
-95
lines changed

README.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,7 +2781,7 @@ wp post create [--post_author=<post_author>] [--post_date=<post_date>] [--post_d
27812781
[--tax_input=<tax_input>]
27822782
Array of taxonomy terms keyed by their taxonomy name. Default empty.
27832783

2784-
Note: In WordPress core, this normally requires a user context to satisfy capability checks. WP-CLI bypasses this for convenience. See https://core.trac.wordpress.org/ticket/19373
2784+
Note: In WordPress core, this normally requires a user context to satisfy capability checks. WP-CLI bypasses this for convenience. See https://core.trac.wordpress.org/ticket/19373
27852785

27862786
[--meta_input=<meta_input>]
27872787
Array in JSON format of post meta values keyed by their post meta key. Default empty.
@@ -2790,22 +2790,21 @@ wp post create [--post_author=<post_author>] [--post_date=<post_date>] [--post_d
27902790
Read post content from <file>. If this value is present, the
27912791
`--post_content` argument will be ignored.
27922792

2793-
Passing `-` as the filename will cause post content to
2794-
be read from STDIN.
2793+
Passing `-` as the filename will cause post content to
2794+
be read from STDIN.
27952795

27962796
[--<field>=<value>]
27972797
Associative args for the new post. See wp_insert_post().
27982798

27992799
[--edit]
28002800
Immediately open system's editor to write or edit post content.
28012801

2802-
If content is read from a file, from STDIN, or from the `--post_content`
2803-
argument, that text will be loaded into the editor.
2802+
If content is read from a file, from STDIN, or from the `--post_content`
2803+
argument, that text will be loaded into the editor.
28042804

28052805
[--porcelain]
28062806
Output just the new post id.
28072807

2808-
28092808
**EXAMPLES**
28102809

28112810
# Create post and schedule for future
@@ -3839,7 +3838,7 @@ wp post update <id>... [--post_author=<post_author>] [--post_date=<post_date>] [
38393838
[--tax_input=<tax_input>]
38403839
Array of taxonomy terms keyed by their taxonomy name. Default empty.
38413840

3842-
Note: In WordPress core, this normally requires a user context to satisfy capability checks. WP-CLI bypasses this for convenience. See https://core.trac.wordpress.org/ticket/19373
3841+
Note: In WordPress core, this normally requires a user context to satisfy capability checks. WP-CLI bypasses this for convenience. See https://core.trac.wordpress.org/ticket/19373
38433842

38443843
[--meta_input=<meta_input>]
38453844
Array in JSON format of post meta values keyed by their post meta key. Default empty.
@@ -3848,8 +3847,8 @@ wp post update <id>... [--post_author=<post_author>] [--post_date=<post_date>] [
38483847
Read post content from <file>. If this value is present, the
38493848
`--post_content` argument will be ignored.
38503849

3851-
Passing `-` as the filename will cause post content to
3852-
be read from STDIN.
3850+
Passing `-` as the filename will cause post content to
3851+
be read from STDIN.
38533852

38543853
--<field>=<value>
38553854
One or more fields to update. See wp_insert_post().
@@ -5218,17 +5217,18 @@ wp site delete [<site-id>] [--slug=<slug>] [--yes] [--keep-tables]
52185217

52195218
### wp site empty
52205219

5221-
Empties a site of its content (posts, comments, terms, and meta).
5220+
Empties a site of its content (posts, comments, terms, links, and meta).
52225221

52235222
~~~
52245223
wp site empty [--uploads] [--yes]
52255224
~~~
52265225

5227-
Truncates posts, comments, and terms tables to empty a site of its
5226+
Truncates posts, comments, terms, and links tables to empty a site of its
52285227
content. Doesn't affect site configuration (options) or users.
52295228

5230-
If running a persistent object cache, make sure to flush the cache
5231-
after emptying the site, as the cache values will be invalid otherwise.
5229+
Flushes the object cache after emptying the site to ensure stale data
5230+
is not served. On a Multisite installation, this will flush the cache
5231+
for all sites.
52325232

52335233
To also empty custom database tables, you'll need to hook into command
52345234
execution:
@@ -8967,6 +8967,10 @@ Want to contribute a new feature? Please first [open a new issue](https://github
89678967

89688968
Once you've decided to commit the time to seeing your pull request through, [please follow our guidelines for creating a pull request](https://make.wordpress.org/cli/handbook/pull-requests/) to make sure it's a pleasant experience. See "[Setting up](https://make.wordpress.org/cli/handbook/pull-requests/#setting-up)" for details specific to working on this package locally.
89698969

8970+
### License
8971+
8972+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
8973+
89708974
## Support
89718975

89728976
GitHub issues aren't for general support questions, but there are other venues you can try: https://wp-cli.org/#support

features/menu-item.feature

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,52 @@ Feature: Manage WordPress menu items
195195
| custom | First | 1 | https://first.com |
196196
| custom | Third | 2 | https://third.com |
197197

198+
Scenario: Menu order is recalculated on update
199+
When I run `wp menu create "Sidebar Menu"`
200+
Then STDOUT should not be empty
201+
202+
When I run `wp menu item add-custom sidebar-menu Alpha https://alpha.com --porcelain`
203+
Then save STDOUT as {ITEM_ID_1}
204+
205+
When I run `wp menu item add-custom sidebar-menu Beta https://beta.com --porcelain`
206+
Then save STDOUT as {ITEM_ID_2}
207+
208+
When I run `wp menu item add-custom sidebar-menu Gamma https://gamma.com --porcelain`
209+
Then save STDOUT as {ITEM_ID_3}
210+
211+
When I run `wp menu item list sidebar-menu --fields=type,title,position,link`
212+
Then STDOUT should be a table containing rows:
213+
| type | title | position | link |
214+
| custom | Alpha | 1 | https://alpha.com |
215+
| custom | Beta | 2 | https://beta.com |
216+
| custom | Gamma | 3 | https://gamma.com |
217+
218+
When I run `wp menu item update {ITEM_ID_3} --position=1`
219+
Then STDOUT should be:
220+
"""
221+
Success: Menu item updated.
222+
"""
223+
224+
When I run `wp menu item list sidebar-menu --fields=type,title,position,link`
225+
Then STDOUT should be a table containing rows:
226+
| type | title | position | link |
227+
| custom | Gamma | 1 | https://gamma.com |
228+
| custom | Alpha | 2 | https://alpha.com |
229+
| custom | Beta | 3 | https://beta.com |
230+
231+
When I run `wp menu item update {ITEM_ID_1} --position=3`
232+
Then STDOUT should be:
233+
"""
234+
Success: Menu item updated.
235+
"""
236+
237+
When I run `wp menu item list sidebar-menu --fields=type,title,position,link`
238+
Then STDOUT should be a table containing rows:
239+
| type | title | position | link |
240+
| custom | Gamma | 1 | https://gamma.com |
241+
| custom | Beta | 2 | https://beta.com |
242+
| custom | Alpha | 3 | https://alpha.com |
243+
198244
Scenario: Get menu item details
199245
When I run `wp menu create "Sidebar Menu"`
200246
Then STDOUT should not be empty

features/site-empty.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Feature: Empty a WordPress site of its data
7272
When I run `wp site empty --yes`
7373
Then STDOUT should be:
7474
"""
75-
Success: The site at 'https://example.com' was emptied.
75+
Success: The site at 'http://example.com' was emptied.
7676
"""
7777
And the wp-content/uploads/large-image.jpg file should exist
7878

features/term-migrate.feature

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,66 @@ Feature: Migrate term custom fields
8787
"""
8888
Error: Taxonomy term 'peach' for taxonomy 'category' doesn't exist.
8989
"""
90+
91+
@require-wp-4.4
92+
Scenario: Migrate a term when posts have been migrated to a different post type that supports the destination taxonomy
93+
Given a WP install
94+
And a wp-content/mu-plugins/test-migrate.php file:
95+
"""
96+
<?php
97+
// Plugin Name: Test Migrate
98+
99+
add_action( 'init', function() {
100+
register_post_type( 'news', [ 'public' => true ] );
101+
register_taxonomy( 'topic', 'news', [ 'public' => true ] );
102+
} );
103+
"""
104+
105+
When I run `wp term create category grape`
106+
Then STDOUT should not be empty
107+
108+
When I run `wp post create --post_title='Test post' --post_type=post --porcelain`
109+
Then STDOUT should be a number
110+
And save STDOUT as {POST_ID}
111+
112+
When I run `wp post term set {POST_ID} category grape`
113+
Then STDOUT should not be empty
114+
115+
When I run `wp post update {POST_ID} --post_type=news`
116+
Then STDOUT should not be empty
117+
118+
When I run `wp term migrate grape --by=slug --from=category --to=topic`
119+
Then STDOUT should be:
120+
"""
121+
Term 'grape' assigned to post {POST_ID}.
122+
Term 'grape' migrated.
123+
Old instance of term 'grape' removed from its original taxonomy.
124+
Success: Migrated the term 'grape' from taxonomy 'category' to taxonomy 'topic' for 1 post.
125+
"""
126+
127+
@require-wp-4.4
128+
Scenario: Migrate a term warns when post type is not registered with destination taxonomy
129+
Given a WP install
130+
131+
When I run `wp term create category grape`
132+
Then STDOUT should not be empty
133+
134+
When I run `wp post create --post_title='Test post' --post_type=post --porcelain`
135+
Then STDOUT should be a number
136+
And save STDOUT as {POST_ID}
137+
138+
When I run `wp post term set {POST_ID} category grape`
139+
Then STDOUT should not be empty
140+
141+
When I run `wp post update {POST_ID} --post_type=page`
142+
Then STDOUT should not be empty
143+
144+
When I try `wp term migrate grape --by=slug --from=category --to=post_tag`
145+
Then STDERR should contain:
146+
"""
147+
Warning: Term 'grape' not assigned to post {POST_ID}. Post type 'page' is not registered with taxonomy 'post_tag'.
148+
"""
149+
And STDOUT should contain:
150+
"""
151+
Success: Migrated the term 'grape' from taxonomy 'category' to taxonomy 'post_tag' for 0 posts.
152+
"""

src/Menu_Item_Command.php

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,71 @@ private function add_or_update_item( $method, $type, $args, $assoc_args ) {
634634
}
635635

636636
$menu_item_args['menu-item-type'] = $type;
637-
$result = wp_update_nav_menu_item( $menu->term_id, $menu_item_db_id, $menu_item_args );
637+
$pending_menu_order_updates = [];
638+
639+
// Reorder other menu items when the position changes on update.
640+
if ( 'update' === $method ) {
641+
$new_position = (int) $menu_item_args['menu-item-position'];
642+
if ( $new_position > 0 ) {
643+
// Fetch all menu items sorted by their raw menu_order to determine
644+
// normalized (1-indexed) ranks, since wp_get_nav_menu_items(ARRAY_A)
645+
// normalises menu_order to 1,2,3… which may differ from the raw DB values.
646+
$sorted_item_ids = get_posts(
647+
[
648+
'post_type' => 'nav_menu_item',
649+
'numberposts' => -1,
650+
'orderby' => 'menu_order',
651+
'order' => 'ASC',
652+
'post_status' => 'any',
653+
'tax_query' => [
654+
[
655+
'taxonomy' => 'nav_menu',
656+
'field' => 'term_taxonomy_id',
657+
'terms' => $menu->term_taxonomy_id,
658+
],
659+
],
660+
'fields' => 'ids',
661+
]
662+
);
663+
664+
// Normalise to integers so that strict comparisons below work regardless of
665+
// whether $wpdb->get_col() returned strings or integers.
666+
$sorted_item_ids = array_map( 'intval', $sorted_item_ids );
667+
668+
// Clamp the requested position to the valid range of menu items.
669+
$max_position = count( $sorted_item_ids );
670+
if ( $max_position > 0 && $new_position > $max_position ) {
671+
// Treat out-of-range positions as "move to end", consistent with core behavior.
672+
$new_position = $max_position;
673+
}
674+
675+
// Find the 1-indexed normalized rank of the item being moved.
676+
$item_idx = array_search( (int) $menu_item_db_id, $sorted_item_ids, true );
677+
$old_position_normalized = ( false !== $item_idx ) ? $item_idx + 1 : 0;
678+
679+
if ( $old_position_normalized > 0 && $new_position !== $old_position_normalized ) {
680+
if ( $new_position < $old_position_normalized ) {
681+
// Moving up: items at 0-indexed [new_pos-1, old_pos-2] shift down by +1.
682+
for ( $i = $new_position - 1; $i <= $old_position_normalized - 2; $i++ ) {
683+
$pending_menu_order_updates[] = [
684+
'ID' => $sorted_item_ids[ $i ],
685+
'menu_order' => $i + 2,
686+
];
687+
}
688+
} else {
689+
// Moving down: items at 0-indexed [old_pos, new_pos-1] shift up by -1.
690+
for ( $i = $old_position_normalized; $i <= $new_position - 1; $i++ ) {
691+
$pending_menu_order_updates[] = [
692+
'ID' => $sorted_item_ids[ $i ],
693+
'menu_order' => $i,
694+
];
695+
}
696+
}
697+
}
698+
}
699+
}
700+
701+
$result = wp_update_nav_menu_item( $menu->term_id, $menu_item_db_id, $menu_item_args );
638702

639703
if ( is_wp_error( $result ) ) {
640704
WP_CLI::error( $result->get_error_message() );
@@ -645,6 +709,26 @@ private function add_or_update_item( $method, $type, $args, $assoc_args ) {
645709
WP_CLI::error( "Couldn't update menu item." );
646710
}
647711
} else {
712+
// Apply deferred reordering of other menu items only after a successful update.
713+
if ( ! empty( $pending_menu_order_updates ) ) {
714+
global $wpdb;
715+
716+
$ids_to_update = [];
717+
$case_clauses = '';
718+
foreach ( $pending_menu_order_updates as $update_args ) {
719+
$item_id = (int) $update_args['ID'];
720+
$ids_to_update[] = $item_id;
721+
$case_clauses .= $wpdb->prepare( ' WHEN %d THEN %d', $item_id, $update_args['menu_order'] );
722+
}
723+
724+
$ids_sql = implode( ',', $ids_to_update );
725+
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $case_clauses and $ids_sql are constructed from prepared/safe integer values.
726+
$wpdb->query( "UPDATE {$wpdb->posts} SET menu_order = CASE ID {$case_clauses} END WHERE ID IN ({$ids_sql})" );
727+
728+
foreach ( $ids_to_update as $id ) {
729+
clean_post_cache( $id );
730+
}
731+
}
648732

649733
if ( ( 'add' === $method ) && $menu_item_args['menu-item-position'] ) {
650734
$this->reorder_menu_items( $menu->term_id, $menu_item_args['menu-item-position'], +1, $result );

0 commit comments

Comments
 (0)