From bc6035ddb0aabb9c589b7c946b6915e3c96f1d42 Mon Sep 17 00:00:00 2001 From: Philip John Date: Thu, 5 Jun 2025 15:38:27 +0200 Subject: [PATCH 1/9] 96: Fix output formats for the `theme mod get` command --- src/Theme_Mod_Command.php | 122 ++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 32 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index 9aea4c87..e35decbe 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -85,51 +85,109 @@ public function get( $args = array(), $assoc_args = array() ) { $args = array(); } + // This array will hold the list of theme mods in a format suitable for the WP CLI Formatter. $list = array(); - $mods = get_theme_mods(); + + // 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(); if ( ! is_array( $mods ) ) { - // If no mods are set (perhaps new theme), make sure foreach still works. + // If no mods are set (perhaps new theme), make sure array_intersect_key still works. $mods = array(); } - foreach ( $mods as $k => $v ) { - // If mods were given, skip the others. - if ( ! empty( $args ) && ! in_array( $k, $args, true ) ) { - continue; - } - if ( is_array( $v ) ) { - $list[] = [ - 'key' => $k, - 'value' => '=>', - ]; - foreach ( $v as $_k => $_v ) { - $list[] = [ - 'key' => " $_k", - 'value' => $_v, - ]; - } - } else { - $list[] = [ - 'key' => $k, - 'value' => $v, - ]; + // Generate the list of items ready for output. We use an initial separator that we can replace later depending on format. + $separator = '!!!'; + array_walk( + $mods, + function( $value, $key ) use ( &$list, $separator ) { + $this->mod_to_string( $key, $value, $list, $separator ); } - } + ); - // For unset mods, show blank value. - foreach ( $args as $mod ) { - if ( ! isset( $mods[ $mod ] ) ) { - $list[] = [ - 'key' => $mod, - 'value' => '', - ]; - } + // Take our Formatter-friendly list and adjust it according to the requested format. + switch ( \WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) ) { + // For tables we use a double space to indent child items. + case 'table': + $list = array_map( + function( $item ) { + $parts = explode( '!!!', $item['key'] ); + $new_key = array_pop( $parts ); + if ( ! empty( $parts ) ) { + $new_key = str_repeat( ' ', count( $parts ) ) . $new_key; + } + return [ + 'key' => $new_key, + 'value' => $item['value'], + ]; + }, + $list + ); + break; + + // For JSON, CSV, and YAML formats we use dot notation to show the hierarchy. + case 'csv': + case 'yaml': + case 'json': + $list = array_filter( array_map( + function( $item ) { + return [ + 'key' => str_replace( '!!!', '.', $item['key'] ), + 'value' => $item['value'], + ]; + }, + $list + ), function( $item ) { + return ! empty( $item['value'] ); + } ); + break; } + // Output the list using the WP CLI Formatter. $formatter = new \WP_CLI\Formatter( $assoc_args, $this->fields, 'thememods' ); $formatter->display_items( $list ); } + /** + * Convert the theme mods to a flattened array with a string representation of the keys. + * + * @param string $key The mod key + * @param mixed $value The value of the mod. + * @param array $list The list so far, passed by reference. + * @param string $separator A string to separate keys to denote their place in the tree. + */ + private function mod_to_string( $key, $value, &$list, $separator ) { + if ( is_array( $value ) ){ + if ( empty( $value ) ) { + // Explicitly handle empty arrays to ensure they are displayed. + $list[] = array( + 'key' => $key, + 'value' => '[empty array]', + ); + return; + } + + // Arrays get their own entry in the list to allow for sensible table output. + $list[] = array( + 'key' => $key, + 'value' => '', + ); + + foreach ( $value as $child_key => $child_value ) { + $this->mod_to_string( $key . $separator . $child_key, $child_value, $list, $separator ); + } + } else { + // Explicitly handle false values to ensure they are displayed. + if ( false === $value ) { + $value = '[false]'; + } + + $list[] = array( + 'key' => $key, + 'value' => $value, + ); + } + } + /** * Gets a list of theme mods. * From 84891e74bcededdb7a2a033ba868d9ba150f2ee6 Mon Sep 17 00:00:00 2001 From: Philip John Date: Thu, 5 Jun 2025 15:48:26 +0200 Subject: [PATCH 2/9] 96: Handle both booleans --- src/Theme_Mod_Command.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index e35decbe..487cb79a 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -176,9 +176,9 @@ private function mod_to_string( $key, $value, &$list, $separator ) { $this->mod_to_string( $key . $separator . $child_key, $child_value, $list, $separator ); } } else { - // Explicitly handle false values to ensure they are displayed. - if ( false === $value ) { - $value = '[false]'; + // Explicitly handle boolean values to ensure they are displayed correctly. + if ( is_bool( $value ) ) { + $value = $value ? '[true]' : '[false]'; } $list[] = array( From d80db8f743e53eb8c1e1d60a2c6d61e6d535bf16 Mon Sep 17 00:00:00 2001 From: Philip John Date: Thu, 5 Jun 2025 15:57:58 +0200 Subject: [PATCH 3/9] 96: Handle objects --- src/Theme_Mod_Command.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index 487cb79a..31e42cd1 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -156,9 +156,12 @@ function( $item ) { * @param string $separator A string to separate keys to denote their place in the tree. */ private function mod_to_string( $key, $value, &$list, $separator ) { - if ( is_array( $value ) ){ + if ( is_array( $value ) || is_object( $value ) ) { + // Convert objects to arrays for easier handling. + $value = (array) $value; + + // Explicitly handle empty arrays to ensure they are displayed. if ( empty( $value ) ) { - // Explicitly handle empty arrays to ensure they are displayed. $list[] = array( 'key' => $key, 'value' => '[empty array]', From e3546141730b69538cf2640a4bef0e42c6179bdf Mon Sep 17 00:00:00 2001 From: Philip John Date: Thu, 5 Jun 2025 16:01:53 +0200 Subject: [PATCH 4/9] 96: Fix formatting and rename variable to please the CS Gods --- src/Theme_Mod_Command.php | 51 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index 31e42cd1..cb1f0f4e 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -86,7 +86,7 @@ public function get( $args = array(), $assoc_args = array() ) { } // This array will hold the list of theme mods in a format suitable for the WP CLI Formatter. - $list = array(); + $mod_list = array(); // 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(); @@ -99,8 +99,8 @@ public function get( $args = array(), $assoc_args = array() ) { $separator = '!!!'; array_walk( $mods, - function( $value, $key ) use ( &$list, $separator ) { - $this->mod_to_string( $key, $value, $list, $separator ); + function ( $value, $key ) use ( &$mod_list, $separator ) { + $this->mod_to_string( $key, $value, $mod_list, $separator ); } ); @@ -108,8 +108,8 @@ function( $value, $key ) use ( &$list, $separator ) { switch ( \WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) ) { // For tables we use a double space to indent child items. case 'table': - $list = array_map( - function( $item ) { + $mod_list = array_map( + function ( $item ) { $parts = explode( '!!!', $item['key'] ); $new_key = array_pop( $parts ); if ( ! empty( $parts ) ) { @@ -120,7 +120,7 @@ function( $item ) { 'value' => $item['value'], ]; }, - $list + $mod_list ); break; @@ -128,23 +128,26 @@ function( $item ) { case 'csv': case 'yaml': case 'json': - $list = array_filter( array_map( - function( $item ) { - return [ - 'key' => str_replace( '!!!', '.', $item['key'] ), - 'value' => $item['value'], - ]; - }, - $list - ), function( $item ) { - return ! empty( $item['value'] ); - } ); + $mod_list = array_filter( + array_map( + function ( $item ) { + return [ + 'key' => str_replace( '!!!', '.', $item['key'] ), + 'value' => $item['value'], + ]; + }, + $mod_list + ), + function ( $item ) { + return ! empty( $item['value'] ); + } + ); break; } // Output the list using the WP CLI Formatter. $formatter = new \WP_CLI\Formatter( $assoc_args, $this->fields, 'thememods' ); - $formatter->display_items( $list ); + $formatter->display_items( $mod_list ); } /** @@ -152,17 +155,17 @@ function( $item ) { * * @param string $key The mod key * @param mixed $value The value of the mod. - * @param array $list The list so far, passed by reference. + * @param array $mod_list The list so far, passed by reference. * @param string $separator A string to separate keys to denote their place in the tree. */ - private function mod_to_string( $key, $value, &$list, $separator ) { + private function mod_to_string( $key, $value, &$mod_list, $separator ) { if ( is_array( $value ) || is_object( $value ) ) { // Convert objects to arrays for easier handling. $value = (array) $value; // Explicitly handle empty arrays to ensure they are displayed. if ( empty( $value ) ) { - $list[] = array( + $mod_list[] = array( 'key' => $key, 'value' => '[empty array]', ); @@ -170,13 +173,13 @@ private function mod_to_string( $key, $value, &$list, $separator ) { } // Arrays get their own entry in the list to allow for sensible table output. - $list[] = array( + $mod_list[] = array( 'key' => $key, 'value' => '', ); foreach ( $value as $child_key => $child_value ) { - $this->mod_to_string( $key . $separator . $child_key, $child_value, $list, $separator ); + $this->mod_to_string( $key . $separator . $child_key, $child_value, $mod_list, $separator ); } } else { // Explicitly handle boolean values to ensure they are displayed correctly. @@ -184,7 +187,7 @@ private function mod_to_string( $key, $value, &$list, $separator ) { $value = $value ? '[true]' : '[false]'; } - $list[] = array( + $mod_list[] = array( 'key' => $key, 'value' => $value, ); From 561cfc862f7221b8fcd3dc7e99daf243ee0759ca Mon Sep 17 00:00:00 2001 From: Philip John Date: Fri, 6 Jun 2025 10:08:46 +0200 Subject: [PATCH 5/9] 96: Remove unnecessary array check already done by get_theme_mods() --- src/Theme_Mod_Command.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index cb1f0f4e..2eb32b75 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -90,10 +90,6 @@ public function get( $args = array(), $assoc_args = array() ) { // 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(); - if ( ! is_array( $mods ) ) { - // If no mods are set (perhaps new theme), make sure array_intersect_key still works. - $mods = array(); - } // Generate the list of items ready for output. We use an initial separator that we can replace later depending on format. $separator = '!!!'; From 4b0aa30f34e3226e289a858549b14373c2308efd Mon Sep 17 00:00:00 2001 From: Philip John Date: Fri, 6 Jun 2025 10:09:22 +0200 Subject: [PATCH 6/9] 96: Use tab character as separator --- src/Theme_Mod_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index 2eb32b75..aadfec9e 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -92,7 +92,7 @@ public function get( $args = array(), $assoc_args = array() ) { $mods = ! empty( $args ) ? array_intersect_key( get_theme_mods(), array_flip( $args ) ) : get_theme_mods(); // Generate the list of items ready for output. We use an initial separator that we can replace later depending on format. - $separator = '!!!'; + $separator = '\t'; array_walk( $mods, function ( $value, $key ) use ( &$mod_list, $separator ) { From 26b9affe6b88a799f2d5e58748f99f16c1e1eca4 Mon Sep 17 00:00:00 2001 From: Philip John Date: Fri, 6 Jun 2025 10:11:44 +0200 Subject: [PATCH 7/9] 96: Import Utils for much more handsome code --- src/Theme_Mod_Command.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index aadfec9e..bd136de4 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -1,5 +1,7 @@ Date: Fri, 6 Jun 2025 10:12:39 +0200 Subject: [PATCH 8/9] 96: Make the array_map callbacks static --- src/Theme_Mod_Command.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index bd136de4..d69ce35c 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -107,7 +107,7 @@ function ( $value, $key ) use ( &$mod_list, $separator ) { // For tables we use a double space to indent child items. case 'table': $mod_list = array_map( - function ( $item ) { + static function ( $item ) { $parts = explode( '!!!', $item['key'] ); $new_key = array_pop( $parts ); if ( ! empty( $parts ) ) { @@ -128,7 +128,7 @@ function ( $item ) { case 'json': $mod_list = array_filter( array_map( - function ( $item ) { + static function ( $item ) { return [ 'key' => str_replace( '!!!', '.', $item['key'] ), 'value' => $item['value'], From 76025d7074fe054697ee12f309af13ae3f23cd81 Mon Sep 17 00:00:00 2001 From: Philip John Date: Fri, 6 Jun 2025 10:13:55 +0200 Subject: [PATCH 9/9] 96: Set the separator once --- src/Theme_Mod_Command.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Theme_Mod_Command.php b/src/Theme_Mod_Command.php index d69ce35c..cbff4a5f 100644 --- a/src/Theme_Mod_Command.php +++ b/src/Theme_Mod_Command.php @@ -107,8 +107,8 @@ function ( $value, $key ) use ( &$mod_list, $separator ) { // For tables we use a double space to indent child items. case 'table': $mod_list = array_map( - static function ( $item ) { - $parts = explode( '!!!', $item['key'] ); + static function ( $item ) use ( $separator ) { + $parts = explode( $separator, $item['key'] ); $new_key = array_pop( $parts ); if ( ! empty( $parts ) ) { $new_key = str_repeat( ' ', count( $parts ) ) . $new_key; @@ -128,9 +128,9 @@ static function ( $item ) { case 'json': $mod_list = array_filter( array_map( - static function ( $item ) { + static function ( $item ) use ( $separator ) { return [ - 'key' => str_replace( '!!!', '.', $item['key'] ), + 'key' => str_replace( $separator, '.', $item['key'] ), 'value' => $item['value'], ]; },