Skip to content

Commit 05fd7f2

Browse files
authored
Fix newly reported PHPStan errors (#6385)
1 parent 847a2c1 commit 05fd7f2

4 files changed

Lines changed: 73 additions & 19 deletions

File tree

‎php/WP_CLI/Formatter.php‎

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use cli\Colors;
66
use cli\Table;
7-
use Iterator;
87
use Mustangostang\Spyc;
8+
use Traversable;
99
use WP_CLI;
1010

1111
/**
@@ -377,16 +377,16 @@ public function __get( $key ) {
377377
/**
378378
* Display multiple items according to the output arguments.
379379
*
380-
* @param iterable<int, array<string, mixed>|object> $items The items to display.
381-
* @param bool|array<int, bool> $ascii_pre_colorized Optional. A boolean or an array of booleans to pass to `format()` if items in the table are pre-colorized. Default false.
380+
* @param iterable<mixed> $items The items to display.
381+
* @param bool|array<int, bool> $ascii_pre_colorized Optional. A boolean or an array of booleans to pass to `format()` if items in the table are pre-colorized. Default false.
382382
* @return void
383383
*/
384384
public function display_items( $items, $ascii_pre_colorized = false ) {
385385
if ( $this->args['field'] ) {
386386
$this->show_single_field( $items, $this->args['field'] );
387387
} else {
388-
// Convert iterator to array early to avoid consumption issues and enable validation
389-
if ( $items instanceof Iterator ) {
388+
// Convert Traversable to array early to avoid consumption issues and enable validation
389+
if ( $items instanceof Traversable ) {
390390
$items = iterator_to_array( $items );
391391
}
392392

@@ -404,7 +404,7 @@ public function display_items( $items, $ascii_pre_colorized = false ) {
404404
}
405405

406406
if ( in_array( $this->args['format'], [ 'table', 'csv' ], true ) ) {
407-
/** @var array<int, array<string, mixed>|object> $transformed */
407+
/** @var array<int, mixed> $transformed */
408408
$transformed = array_map(
409409
function ( $item ) {
410410
return $this->transform_item_values_to_json( is_object( $item ) ? clone $item : $item );
@@ -455,8 +455,8 @@ public function display_item( $item, $ascii_pre_colorized = false ) {
455455
/**
456456
* Format items according to arguments.
457457
*
458-
* @param iterable<int, array<string, mixed>|object> $items Items.
459-
* @param bool|array<int, bool> $ascii_pre_colorized Optional. A boolean or an array of booleans to pass to `show_table()` if items in the table are pre-colorized. Default false.
458+
* @param iterable<mixed> $items Items.
459+
* @param bool|array<int, bool> $ascii_pre_colorized Optional. A boolean or an array of booleans to pass to `show_table()` if items in the table are pre-colorized. Default false.
460460
*/
461461
private function format( $items, $ascii_pre_colorized = false ): void {
462462
$fields = $this->args['fields'];
@@ -480,13 +480,16 @@ private function format( $items, $ascii_pre_colorized = false ): void {
480480
if ( is_array( $item ) || is_object( $item ) ) {
481481
$formatted_items[] = Utils\pick_fields( $item, $fields );
482482
} else {
483-
WP_CLI::debug( 'Skipping item that is neither array nor object in format handler.', 'formatter' );
483+
$formatted_items[] = $item;
484484
}
485485
}
486486

487487
// Truncate cell values exactly once for table/CSV output
488488
if ( in_array( $this->args['format'], [ 'table', 'csv' ], true ) ) {
489489
foreach ( $formatted_items as &$row ) {
490+
if ( ! is_array( $row ) && ! is_object( $row ) ) {
491+
continue;
492+
}
490493
foreach ( $row as $key => $value ) {
491494
if ( is_string( $value ) && strlen( $value ) > self::MAX_CELL_WIDTH ) {
492495
$row[ $key ] = substr( $value, 0, self::MAX_CELL_WIDTH ) . '...';
@@ -509,8 +512,8 @@ private function format( $items, $ascii_pre_colorized = false ): void {
509512
/**
510513
* Show a single field from a list of items.
511514
*
512-
* @param iterable<int, array<string, mixed>|object> $items Array of objects to show fields from
513-
* @param string $field The field to show
515+
* @param iterable<mixed> $items An iterable of items to show fields from.
516+
* @param string $field The field to show
514517
*/
515518
private function show_single_field( $items, $field ): void {
516519
$key = null;
@@ -559,7 +562,7 @@ private function show_single_field( $items, $field ): void {
559562
* Warns if a field doesn't exist in any item.
560563
* Also resolves field names to their actual keys (including prefixes).
561564
*
562-
* @param iterable<int, array<string, mixed>|object> $items Items to validate
565+
* @param iterable<mixed> $items Items to validate
563566
*/
564567
private function validate_fields( $items ): void {
565568
// Track which fields have been found and their resolved keys
@@ -633,9 +636,9 @@ private function is_object_property_accessible( $item, $key ): bool {
633636
* Find an object's key.
634637
* If $prefix is set, a key with that prefix will be prioritized.
635638
*
636-
* @param array<string, mixed>|object $item
637-
* @param string $field
638-
* @param bool $lenient If true, return null instead of erroring when field is not found.
639+
* @param mixed $item
640+
* @param string $field
641+
* @param bool $lenient If true, return null instead of erroring when field is not found.
639642
* @return string|null
640643
*/
641644
private function find_item_key( $item, $field, $lenient = false ) {
@@ -784,10 +787,14 @@ private function assoc_array_to_rows( $fields ) {
784787
* - Objects and arrays are converted to JSON strings
785788
* - Booleans are converted to "true" or "false"
786789
*
787-
* @param array<string, mixed>|object $item
790+
* @param mixed $item
788791
* @return mixed
789792
*/
790793
public function transform_item_values_to_json( $item ) {
794+
if ( ! is_object( $item ) && ! is_array( $item ) ) {
795+
return $item;
796+
}
797+
791798
foreach ( $this->args['fields'] as $field ) {
792799
$true_field = $this->find_item_key( $item, $field, true );
793800
if ( null === $true_field ) {

‎php/class-wp-cli.php‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,8 +1509,6 @@ public static function get_php_binary() {
15091509
* @param string $key Config parameter key to check.
15101510
*
15111511
* @return bool
1512-
*
1513-
* @phpstan-assert-if-true key-of<GlobalConfig> $key
15141512
*/
15151513
public static function has_config( $key ) {
15161514
return array_key_exists( $key, self::get_runner()->config );

‎tests/ConfiguratorTest.php‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ public function testNullGetConfig(): void {
131131
$logger = new Loggers\Execution();
132132
WP_CLI::set_logger( $logger );
133133

134-
// @phpstan-ignore staticMethod.alreadyNarrowedType
135134
$has_config = WP_CLI::has_config( 'url' );
136135
$get_config = WP_CLI::get_config( 'url' );
137136

‎tests/FormatterTest.php‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,4 +412,54 @@ public function __isset( $name ) {
412412

413413
$this->assertSame( '{"protected_prop":"protected_val"}', $output );
414414
}
415+
416+
public function test_display_items_with_traversable(): void {
417+
Formatter::register_builtin_formats();
418+
419+
$items = new \ArrayObject(
420+
[
421+
[
422+
'name' => 'Alice',
423+
'role' => 'admin',
424+
],
425+
[
426+
'name' => 'Bob',
427+
'role' => 'editor',
428+
],
429+
]
430+
);
431+
432+
$assoc_args = [ 'format' => 'json' ];
433+
$formatter = new Formatter( $assoc_args, [ 'name', 'role' ] );
434+
435+
ob_start();
436+
$formatter->display_items( $items );
437+
$output = ob_get_clean();
438+
439+
$this->assertSame( '[{"name":"Alice","role":"admin"},{"name":"Bob","role":"editor"}]', $output );
440+
}
441+
442+
public function test_display_items_scalar_items_in_json_and_yaml(): void {
443+
Formatter::register_builtin_formats();
444+
445+
$items = [ 1, 2, 3 ];
446+
447+
$assoc_args = [ 'format' => 'json' ];
448+
$formatter = new Formatter( $assoc_args );
449+
450+
ob_start();
451+
$formatter->display_items( $items );
452+
$output = ob_get_clean();
453+
454+
$this->assertSame( '[1,2,3]', $output );
455+
456+
$assoc_args = [ 'format' => 'yaml' ];
457+
$formatter = new Formatter( $assoc_args );
458+
459+
ob_start();
460+
$formatter->display_items( $items );
461+
$output = ob_get_clean();
462+
463+
$this->assertSame( "---\n- 1\n- 2\n- 3", trim( (string) $output ) );
464+
}
415465
}

0 commit comments

Comments
 (0)