From 05f28947e767d3a5b312ee840e70538f1fadb9be Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Thu, 19 Aug 2021 12:43:03 +0000 Subject: [PATCH] Media: Check the return type of `_get_cron_array()` in `WP_Media_List_Table::prepare_items()`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following warnings could, in very select circumstances, be shown: {{{ // PHP 8.0 and higher: Warning: foreach() argument must be of type array|object, bool given // PHP 5.6 – 7.4 Warning: Invalid argument supplied for foreach() }}} In `WP_Media_List_Table::prepare_items()`, the cron info array is retrieved via a call to `_get_cron_array()`, but as the documentation (correctly) states, the return type of that function is `array|false`, where `false` is returned for a virgin site, with no cron jobs scheduled yet. However, no type check is done on the return value, and the method just blindly continues by using it in a `foreach`. Fixed by adding validation for the returned value from `_get_cron_array()` and only running the `foreach` when the returned value is an array. Reference: [https://developer.wordpress.org/reference/functions/_get_cron_array/ WordPress Developer Resources: _get_cron_array()] Follow-up to [48417]. Props jrf, hellofromTonya, mukesh27. Fixes #53949. git-svn-id: https://develop.svn.wordpress.org/trunk@51638 602fd350-edb4-49c9-b593-d223f7449a82 --- .../includes/class-wp-media-list-table.php | 14 ++++-- .../tests/admin/includesMediaListTable.php | 50 +++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 tests/phpunit/tests/admin/includesMediaListTable.php diff --git a/src/wp-admin/includes/class-wp-media-list-table.php b/src/wp-admin/includes/class-wp-media-list-table.php index b3eb0b32cc..275d07caca 100644 --- a/src/wp-admin/includes/class-wp-media-list-table.php +++ b/src/wp-admin/includes/class-wp-media-list-table.php @@ -78,12 +78,16 @@ class WP_Media_List_Table extends WP_List_Table { */ $not_in = array(); - foreach ( _get_cron_array() as $cron ) { - if ( isset( $cron['upgrader_scheduled_cleanup'] ) ) { - $details = reset( $cron['upgrader_scheduled_cleanup'] ); + $crons = _get_cron_array(); - if ( ! empty( $details['args'][0] ) ) { - $not_in[] = (int) $details['args'][0]; + if ( is_array( $crons ) ) { + foreach ( $crons as $cron ) { + if ( isset( $cron['upgrader_scheduled_cleanup'] ) ) { + $details = reset( $cron['upgrader_scheduled_cleanup'] ); + + if ( ! empty( $details['args'][0] ) ) { + $not_in[] = (int) $details['args'][0]; + } } } } diff --git a/tests/phpunit/tests/admin/includesMediaListTable.php b/tests/phpunit/tests/admin/includesMediaListTable.php new file mode 100644 index 0000000000..da0aef19f2 --- /dev/null +++ b/tests/phpunit/tests/admin/includesMediaListTable.php @@ -0,0 +1,50 @@ +getMockBuilder( WP_Media_List_Table::class ) + ->disableOriginalConstructor() + ->disallowMockingUnknownTypes() + ->setMethods( array( 'set_pagination_args' ) ) + ->getMock(); + + $mock->expects( $this->once() ) + ->method( 'set_pagination_args' ); + + $wp_query->query_vars['posts_per_page'] = 10; + delete_option( 'cron' ); + + // Verify that the cause of the error is in place. + $this->assertFalse( _get_cron_array(), '_get_cron_array() does not return false' ); + + // If this test does not error out due to the PHP warning, we're good. + $mock->prepare_items(); + } +}