Fix output formats for the theme mod get command#456
Fix output formats for the theme mod get command#456philipjohn wants to merge 12 commits intowp-cli:mainfrom
theme mod get command#456Conversation
schlessera
left a comment
There was a problem hiding this comment.
Looks good, only minor nitpicks for the code. Also, it would be good to have at least 1 feature test covering this.
|
Oh, I will do tests by the way! Just probably not until after this week :) |
There was a problem hiding this comment.
Pull request overview
This PR refactors the wp theme mod get implementation to produce well-structured output across table, CSV, JSON, and YAML formats, particularly for nested option values, addressing malformed output reported in issue #96.
Changes:
- Introduces a recursive
mod_to_string()helper to flatten nested theme mod arrays/objects into a list of{ key, value }pairs, with special handling for booleans and empty arrays. - Adjusts table formatting to use indentation for nested keys and uses dot-notation for hierarchical keys in CSV/JSON/YAML formats, while filtering out items deemed to have “no value” in non-tabular formats.
- Updates usage of
WP_CLI\Utils\get_flag_value()via an importedUtilsalias and reuses the new formatter logic for bothgetandlist_subcommands.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // If specific mods are requested, filter out any that aren't requested. | ||
| $mods = ! empty( $args ) ? array_intersect_key( get_theme_mods(), array_flip( $args ) ) : get_theme_mods(); | ||
|
|
||
| // For unset mods, show blank value. | ||
| foreach ( $args as $mod ) { | ||
| if ( ! isset( $mods[ $mod ] ) ) { | ||
| $list[] = [ | ||
| 'key' => $mod, | ||
| 'value' => '', | ||
| ]; | ||
| // Generate the list of items ready for output. We use an initial separator that we can replace later depending on format. | ||
| $separator = '\t'; | ||
| array_walk( | ||
| $mods, | ||
| function ( $value, $key ) use ( &$mod_list, $separator ) { |
There was a problem hiding this comment.
The previous implementation added rows for requested mods that are not present in get_theme_mods() (see the old "For unset mods, show blank value." logic), which is relied on by the theme-mod.feature example for header_textcolor. With this new $mods construction and no subsequent pass over $args, requested-but-unset mods are now silently omitted from the output for all formats, changing the CLI behavior; to preserve backward compatibility you should add entries with an empty value for any requested mod that is not present in $mods (at least for the table format, and optionally for others).
| @@ -1,5 +1,7 @@ | |||
| <?php | |||
|
|
|||
| use \WP_CLI\Utils; | |||
There was a problem hiding this comment.
The import here uses a leading backslash, whereas other commands in this repository consistently use use WP_CLI\Utils; without it (for example, src/Theme_Command.php:5 and src/Plugin_Command.php:5). For consistency with established codebase conventions, it would be better to drop the leading backslash from this use statement.
| // For JSON, CSV, and YAML formats we use dot notation to show the hierarchy. | ||
| case 'csv': | ||
| case 'yaml': | ||
| case 'json': | ||
| $mod_list = array_filter( | ||
| array_map( | ||
| static function ( $item ) use ( $separator ) { | ||
| return [ | ||
| 'key' => str_replace( $separator, '.', $item['key'] ), | ||
| 'value' => $item['value'], | ||
| ]; | ||
| }, | ||
| $mod_list | ||
| ), | ||
| function ( $item ) { | ||
| return ! empty( $item['value'] ); | ||
| } | ||
| ); | ||
| break; |
There was a problem hiding this comment.
The new flattening and dot-notation logic for CSV/YAML/JSON formats introduces non-trivial behavior but currently has no dedicated acceptance tests (unlike features/theme-mod-list.feature, which covers those formats for the list subcommand). Given that issue #96 was caused by malformed non-tabular output, it would be valuable to add Behat coverage for wp theme mod get --all --format=csv|json|yaml with nested theme-mod structures to ensure this formatter behavior is exercised and guarded against regressions.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Fixes #96
I maintained but improved the space-indented formatting for the table format as folks might be using this (as per @schlessera's comment) and then fixed the other formats by using dot notation to represent each field, given the formatter needs arrays with
keyandvalue.For the table format, I opted to remove the
=>for the value to represent an array. I felt it was harder to read than simply leaving the value blank and letting the indent do the visual work.For other formats I stripped out anything without a value.
For all formats booleans and empty arrays are represented by a string (e.g.
[empty array]. There may be a better way to represent these, and I did considervar_export()but others may have better ideas.Here are some examples of the new output: