-
Notifications
You must be signed in to change notification settings - Fork 85
Fix output formats for the theme mod get command
#456
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
base: main
Are you sure you want to change the base?
Conversation
schlessera
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 ) { |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
| $mod_list | ||
| ), | ||
| function ( $item ) { | ||
| return ! empty( $item['value'] ); |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using empty( $item['value'] ) here will also filter out legitimate values like '0' or 0 from the CSV/YAML/JSON output, not just missing values. If the intent is to strip only items with no value, consider checking explicitly for null or an empty string instead of relying on empty(), so that falsy-but-meaningful values are still emitted.
| return ! empty( $item['value'] ); | |
| return $item['value'] !== '' && $item['value'] !== null; |
| @@ -1,5 +1,7 @@ | |||
| <?php | |||
|
|
|||
| use \WP_CLI\Utils; | |||
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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: