diff --git a/bin/phpstan/filtered-functions.stub b/bin/phpstan/filtered-functions.stub index 410dcc7767..01cb75d5ed 100644 --- a/bin/phpstan/filtered-functions.stub +++ b/bin/phpstan/filtered-functions.stub @@ -29,3 +29,43 @@ * }|null Attachment metadata. Null on failure. */ function wp_get_attachment_metadata( int $attachment_id = 0, bool $unfiltered = false ): ?array {} + +/** + * Updates the attached file and image meta data when the original image was edited. + * + * @since 5.3.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * @access private + * + * @phpstan-param array{ + * width: int, + * height: int, + * path: string + * } $saved_data + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int + * } $image_meta + * @phpstan-return array{ + * width: int, + * height: int, + * file: string, + * sizes: array }>, + * image_meta: array, + * filesize: int, + * sources?: array, + * has_transparency?: bool, + * dominant_color?: string + * } + * + * @param array $saved_data The data returned from WP_Image_Editor after successfully saving an image. + * @param string $original_file Path to the original file. + * @param array $image_meta The image meta data. + * @param int $attachment_id The attachment post ID. + * @return array The updated image meta data. + */ +function _wp_image_meta_replace_original( $saved_data, $original_file, $image_meta, $attachment_id ): array {} diff --git a/composer.lock b/composer.lock index 174cb2a9e3..d012f92337 100644 --- a/composer.lock +++ b/composer.lock @@ -334,16 +334,16 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.5.2", + "version": "v6.5.3", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "379f17a90c01498d4c99a0d15aab6e7aa6a2c840" + "reference": "e611a83292d02055a25f83291a98fadd0c21e092" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/379f17a90c01498d4c99a0d15aab6e7aa6a2c840", - "reference": "379f17a90c01498d4c99a0d15aab6e7aa6a2c840", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/e611a83292d02055a25f83291a98fadd0c21e092", + "reference": "e611a83292d02055a25f83291a98fadd0c21e092", "shasum": "" }, "require-dev": { @@ -375,9 +375,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.5.2" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.5.3" }, - "time": "2024-04-14T17:30:14+00:00" + "time": "2024-05-08T02:12:31+00:00" }, { "name": "phpcompatibility/php-compatibility", @@ -521,16 +521,16 @@ }, { "name": "phpcsstandards/phpcsutils", - "version": "1.0.10", + "version": "1.0.11", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", - "reference": "51609a5b89f928e0c463d6df80eb38eff1eaf544" + "reference": "c457da9dabb60eb7106dd5e3c05132b1a6539c6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/51609a5b89f928e0c463d6df80eb38eff1eaf544", - "reference": "51609a5b89f928e0c463d6df80eb38eff1eaf544", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c457da9dabb60eb7106dd5e3c05132b1a6539c6a", + "reference": "c457da9dabb60eb7106dd5e3c05132b1a6539c6a", "shasum": "" }, "require": { @@ -605,7 +605,7 @@ "type": "open_collective" } ], - "time": "2024-03-17T23:44:50+00:00" + "time": "2024-04-24T11:47:18+00:00" }, { "name": "phpstan/extension-installer", @@ -685,16 +685,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.28.0", + "version": "1.29.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb" + "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", - "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/536889f2b340489d328f5ffb7b02bb6b183ddedc", + "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc", "shasum": "" }, "require": { @@ -726,22 +726,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.28.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.0" }, - "time": "2024-04-03T18:51:33+00:00" + "time": "2024-05-06T12:04:23+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.66", + "version": "1.10.67", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd" + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", "shasum": "" }, "require": { @@ -784,13 +784,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2024-03-28T16:17:31+00:00" + "time": "2024-04-16T07:22:02+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -2082,16 +2078,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.1", + "version": "3.9.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909" + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/267a4405fff1d9c847134db3a3c92f1ab7f77909", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", + "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", "shasum": "" }, "require": { @@ -2158,7 +2154,7 @@ "type": "open_collective" } ], - "time": "2024-03-31T21:03:09+00:00" + "time": "2024-04-23T20:25:34+00:00" }, { "name": "symfony/polyfill-php73", @@ -2416,16 +2412,16 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.5.2", + "version": "6.5.3", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", - "reference": "4368fd1dd37d0314cbaa9040be39d835616aeb17" + "reference": "ef2cb44c0d991ac0c3a7a3ed0d2d1cf3fe8d8f2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/4368fd1dd37d0314cbaa9040be39d835616aeb17", - "reference": "4368fd1dd37d0314cbaa9040be39d835616aeb17", + "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/ef2cb44c0d991ac0c3a7a3ed0d2d1cf3fe8d8f2f", + "reference": "ef2cb44c0d991ac0c3a7a3ed0d2d1cf3fe8d8f2f", "shasum": "" }, "type": "library", @@ -2460,7 +2456,7 @@ "issues": "https://github.com/wp-phpunit/issues", "source": "https://github.com/wp-phpunit/wp-phpunit" }, - "time": "2024-04-03T00:33:03+00:00" + "time": "2024-05-07T16:46:52+00:00" }, { "name": "yoast/phpunit-polyfills", diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 9717e0cc1d..a27c778e9b 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -60,6 +60,11 @@ function perflab_query_plugin_info( string $plugin_slug ) { set_transient( 'perflab_plugin_info_' . $plugin_slug, $plugin, HOUR_IN_SECONDS ); + /** + * Validated (mostly) plugin data. + * + * @var array{name: string, slug: string, short_description: string, requires: string|false, requires_php: string|false, requires_plugins: string[], download_link: string, version: string} $plugin + */ return $plugin; } diff --git a/includes/server-timing/class-perflab-server-timing.php b/includes/server-timing/class-perflab-server-timing.php index 8208c780b2..c190a2fe23 100644 --- a/includes/server-timing/class-perflab-server-timing.php +++ b/includes/server-timing/class-perflab-server-timing.php @@ -9,6 +9,11 @@ /** * Class controlling the Server-Timing header. * + * @phpstan-type MetricArguments array{ + * measure_callback: callable( Perflab_Server_Timing_Metric ): void, + * access_cap: string + * } + * * @since 1.8.0 */ class Perflab_Server_Timing { @@ -25,7 +30,8 @@ class Perflab_Server_Timing { * Map of registered metric slugs and their registered data. * * @since 1.8.0 - * @var array + * @phpstan-var array + * @var array */ private $registered_metrics_data = array(); @@ -36,8 +42,10 @@ class Perflab_Server_Timing { * * @since 1.8.0 * - * @param string $metric_slug The metric slug. - * @param array{measure_callback: callable, access_cap: string} $args { + * @phpstan-param MetricArguments $args + * + * @param string $metric_slug The metric slug. + * @param array $args { * Arguments for the metric. * * @type callable $measure_callback The callback that initiates calculating the metric value. It will receive @@ -94,6 +102,11 @@ public function register_metric( string $metric_slug, array $args ): void { ); return; } + /** + * Validated args. + * + * @var MetricArguments $args + */ $this->registered_metrics[ $metric_slug ] = new Perflab_Server_Timing_Metric( $metric_slug ); $this->registered_metrics_data[ $metric_slug ] = $args; diff --git a/includes/server-timing/defaults.php b/includes/server-timing/defaults.php index 32d883892c..f242f690f9 100644 --- a/includes/server-timing/defaults.php +++ b/includes/server-timing/defaults.php @@ -148,7 +148,7 @@ static function ( $passthrough = null ) { perflab_server_timing_register_metric( 'template', array( - 'measure_callback' => static function ( $metric ): void { + 'measure_callback' => static function ( Perflab_Server_Timing_Metric $metric ): void { $metric->measure_before(); add_action( 'perflab_server_timing_send_header', array( $metric, 'measure_after' ), PHP_INT_MAX ); }, diff --git a/includes/server-timing/load.php b/includes/server-timing/load.php index 6ae7a0bc2a..3c1ede6995 100644 --- a/includes/server-timing/load.php +++ b/includes/server-timing/load.php @@ -205,7 +205,7 @@ function perflab_sanitize_server_timing_setting( $value ): array { array_unique( array_filter( array_map( - static function ( $hook_name ) { + static function ( string $hook_name ): string { /* * Allow any characters except whitespace. * While most hooks use a limited set of characters, hook names in plugins are not @@ -227,5 +227,10 @@ static function ( $hook_name ) { $value['output_buffering'] = (bool) $value['output_buffering']; + /** + * Validated value. + * + * @var array{benchmarking_actions: string[], benchmarking_filters: string[], output_buffering: bool} $value + */ return $value; } diff --git a/includes/site-health/audit-enqueued-assets/helper.php b/includes/site-health/audit-enqueued-assets/helper.php index e0088c918a..ae826fd53a 100644 --- a/includes/site-health/audit-enqueued-assets/helper.php +++ b/includes/site-health/audit-enqueued-assets/helper.php @@ -22,7 +22,8 @@ function perflab_aea_enqueued_js_assets_test(): array { * If the test didn't run yet, deactivate. */ $enqueued_scripts = perflab_aea_get_total_enqueued_scripts(); - if ( false === $enqueued_scripts ) { + $bytes_enqueued = perflab_aea_get_total_size_bytes_enqueued_scripts(); + if ( false === $enqueued_scripts || false === $bytes_enqueued ) { // The return value is validated in JavaScript at: // // If the value lacks the required keys of test, label, and description then it is omitted. @@ -48,7 +49,7 @@ function perflab_aea_enqueued_js_assets_test(): array { 'performance-lab' ), $enqueued_scripts, - size_format( perflab_aea_get_total_size_bytes_enqueued_scripts() ) + size_format( $bytes_enqueued ) ) ) ), @@ -74,7 +75,7 @@ function perflab_aea_enqueued_js_assets_test(): array { */ $scripts_size_threshold = apply_filters( 'perflab_aea_enqueued_scripts_byte_size_threshold', 300000 ); - if ( $enqueued_scripts > $scripts_threshold || perflab_aea_get_total_size_bytes_enqueued_scripts() > $scripts_size_threshold ) { + if ( $enqueued_scripts > $scripts_threshold || $bytes_enqueued > $scripts_size_threshold ) { $result['status'] = 'recommended'; $result['description'] = sprintf( @@ -89,7 +90,7 @@ function perflab_aea_enqueued_js_assets_test(): array { 'performance-lab' ), $enqueued_scripts, - size_format( perflab_aea_get_total_size_bytes_enqueued_scripts() ) + size_format( $bytes_enqueued ) ) ) ); @@ -117,7 +118,8 @@ function perflab_aea_enqueued_js_assets_test(): array { function perflab_aea_enqueued_css_assets_test(): array { // Omit if the test didn't run yet, omit. $enqueued_styles = perflab_aea_get_total_enqueued_styles(); - if ( false === $enqueued_styles ) { + $bytes_enqueued = perflab_aea_get_total_size_bytes_enqueued_styles(); + if ( false === $enqueued_styles || false === $bytes_enqueued ) { // The return value is validated in JavaScript at: // // If the value lacks the required keys of test, label, and description then it is omitted. @@ -142,7 +144,7 @@ function perflab_aea_enqueued_css_assets_test(): array { 'performance-lab' ), $enqueued_styles, - size_format( perflab_aea_get_total_size_bytes_enqueued_styles() ) + size_format( $bytes_enqueued ) ) ) ), @@ -182,7 +184,7 @@ function perflab_aea_enqueued_css_assets_test(): array { 'performance-lab' ), $enqueued_styles, - size_format( perflab_aea_get_total_size_bytes_enqueued_styles() ) + size_format( $bytes_enqueued ) ) ) ); @@ -210,7 +212,7 @@ function perflab_aea_enqueued_css_assets_test(): array { function perflab_aea_get_total_enqueued_scripts() { $enqueued_scripts = false; $list_enqueued_scripts = get_transient( 'aea_enqueued_front_page_scripts' ); - if ( $list_enqueued_scripts ) { + if ( is_array( $list_enqueued_scripts ) ) { $enqueued_scripts = count( $list_enqueued_scripts ); } return $enqueued_scripts; @@ -226,10 +228,12 @@ function perflab_aea_get_total_enqueued_scripts() { function perflab_aea_get_total_size_bytes_enqueued_scripts() { $total_size = false; $list_enqueued_scripts = get_transient( 'aea_enqueued_front_page_scripts' ); - if ( $list_enqueued_scripts ) { + if ( is_array( $list_enqueued_scripts ) ) { $total_size = 0; foreach ( $list_enqueued_scripts as $enqueued_script ) { - $total_size += $enqueued_script['size']; + if ( is_array( $enqueued_script ) && array_key_exists( 'size', $enqueued_script ) && is_int( $enqueued_script['size'] ) ) { + $total_size += $enqueued_script['size']; + } } } return $total_size; @@ -261,10 +265,12 @@ function perflab_aea_get_total_enqueued_styles() { function perflab_aea_get_total_size_bytes_enqueued_styles() { $total_size = false; $list_enqueued_styles = get_transient( 'aea_enqueued_front_page_styles' ); - if ( $list_enqueued_styles ) { + if ( is_array( $list_enqueued_styles ) ) { $total_size = 0; foreach ( $list_enqueued_styles as $enqueued_style ) { - $total_size += $enqueued_style['size']; + if ( is_array( $enqueued_style ) && array_key_exists( 'size', $enqueued_style ) && is_int( $enqueued_style['size'] ) ) { + $total_size += $enqueued_style['size']; + } } } return $total_size; diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 31e9b13aab..31962d0e39 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,7 +1,7 @@ includes: - phar://phpstan.phar/conf/bleedingEdge.neon parameters: - level: 6 + level: 7 treatPhpDocTypesAsCertain: false paths: - load.php @@ -23,3 +23,41 @@ parameters: - bin/phpstan/filtered-functions.stub dynamicConstantNames: - PERFLAB_OBJECT_CACHE_DROPIN_VERSION + ignoreErrors: + - + # Ignore error related to PHP 8 using a GdImage but PHP 7 using a resource. + message: '/^Parameter .+? of function .+? expects resource, GdImage\|resource given\.$/' + path: plugins/dominant-color-images/*.php + + # The following ignored errors are all for tests. They are likely excessively strict and do not warrant being fixed. + # TODO: Use error identifiers instead of messages once PHPStan 1.11 is out: . + - + message: '/Parameter #\d.+given./' + path: tests/* + - + message: '/Cannot use array destructuring/' + path: tests/* + - + message: '/Call to an undefined method/' + path: tests/* + - + message: '/Offset .+ might not exist on array/' + path: tests/* + - + message: '/Part .+ of encapsed string cannot be cast to string/' + path: tests/* + - + message: '/Possibly invalid array key type/' + path: tests/* + - + message: '/Static property .+ does not accept .+/' + path: tests/* + - + message: '/Cannot call method format\(\) on DateTimeImmutable\|false/' + path: tests/* + - + message: '/Property .+ does not accept array.+/' + path: tests/* + - + message: '/Cannot cast .+ to string/' + path: tests/* diff --git a/plugins/dominant-color-images/class-dominant-color-image-editor-gd.php b/plugins/dominant-color-images/class-dominant-color-image-editor-gd.php index 5468198dee..a6106bf1f6 100644 --- a/plugins/dominant-color-images/class-dominant-color-image-editor-gd.php +++ b/plugins/dominant-color-images/class-dominant-color-image-editor-gd.php @@ -32,7 +32,12 @@ public function get_dominant_color() { } // The logic here is resize the image to 1x1 pixel, then get the color of that pixel. $shorted_image = imagecreatetruecolor( 1, 1 ); - imagecopyresampled( $shorted_image, $this->image, 0, 0, 0, 0, 1, 1, imagesx( $this->image ), imagesy( $this->image ) ); + $image_width = imagesx( $this->image ); + $image_height = imagesy( $this->image ); + if ( false === $shorted_image || false === $image_width || false === $image_height ) { + return new WP_Error( 'image_editor_dominant_color_error', __( 'Dominant color detection failed.', 'dominant-color-images' ) ); + } + imagecopyresampled( $shorted_image, $this->image, 0, 0, 0, 0, 1, 1, $image_width, $image_height ); $rgb = imagecolorat( $shorted_image, 0, 0 ); if ( false === $rgb ) { @@ -49,7 +54,6 @@ public function get_dominant_color() { return $hex; } - /** * Looks for transparent pixels in the image. * If there are none, it returns false. @@ -69,8 +73,14 @@ public function has_transparency() { $h = imagesy( $this->image ); for ( $x = 0; $x < $w; $x++ ) { for ( $y = 0; $y < $h; $y++ ) { - $rgb = imagecolorat( $this->image, $x, $y ); + $rgb = imagecolorat( $this->image, $x, $y ); + if ( false === $rgb ) { + return new WP_Error( 'unable_to_obtain_rgb_via_imagecolorat' ); + } $rgba = imagecolorsforindex( $this->image, $rgb ); + if ( ! is_array( $rgba ) ) { + return new WP_Error( 'unable_to_obtain_rgba_via_imagecolorsforindex' ); + } if ( $rgba['alpha'] > 0 ) { return true; } diff --git a/plugins/dominant-color-images/helper.php b/plugins/dominant-color-images/helper.php index b723250ece..ab5b1a5374 100644 --- a/plugins/dominant-color-images/helper.php +++ b/plugins/dominant-color-images/helper.php @@ -57,6 +57,9 @@ function dominant_color_get_dominant_color_data( int $attachment_id ) { if ( ! $file ) { $file = get_attached_file( $attachment_id ); } + if ( ! $file ) { + return new WP_Error( 'no_image_found', __( 'Unable to load image.', 'dominant-color-images' ) ); + } add_filter( 'wp_image_editors', 'dominant_color_set_image_editors' ); /** @@ -119,6 +122,9 @@ function dominant_color_get_attachment_file_path( int $attachment_id, string $si } $file = get_attached_file( $attachment_id ); + if ( ! $file ) { + return false; + } $filepath = str_replace( wp_basename( $file ), $imagedata['sizes'][ $size ]['file'], $file ); diff --git a/plugins/embed-optimizer/hooks.php b/plugins/embed-optimizer/hooks.php index 8625f814a9..2c54afdf60 100644 --- a/plugins/embed-optimizer/hooks.php +++ b/plugins/embed-optimizer/hooks.php @@ -81,7 +81,7 @@ function embed_optimizer_filter_oembed_html( string $html ): string { // by preventing links in the hidden iframe from receiving focus. if ( $html_processor->has_class( 'wp-embedded-content' ) ) { $style = $html_processor->get_attribute( 'style' ); - if ( $style ) { + if ( is_string( $style ) ) { // WordPress core injects this clip CSS property: // . $style = str_replace( 'clip: rect(1px, 1px, 1px, 1px);', 'visibility: hidden;', $style ); diff --git a/plugins/optimization-detective/class-od-html-tag-walker.php b/plugins/optimization-detective/class-od-html-tag-walker.php index 735dffd3d7..9f7092499e 100644 --- a/plugins/optimization-detective/class-od-html-tag-walker.php +++ b/plugins/optimization-detective/class-od-html-tag-walker.php @@ -220,7 +220,7 @@ public function open_tags(): Generator { if ( in_array( $tag_name, self::P_CLOSING_TAGS, true ) ) { $i = array_search( 'P', $this->open_stack_tags, true ); if ( false !== $i ) { - array_splice( $this->open_stack_tags, $i ); + array_splice( $this->open_stack_tags, (int) $i ); array_splice( $this->open_stack_indices, count( $this->open_stack_tags ) ); } } diff --git a/plugins/optimization-detective/class-od-url-metrics-group-collection.php b/plugins/optimization-detective/class-od-url-metrics-group-collection.php index a45ac011f5..4fa247c7c6 100644 --- a/plugins/optimization-detective/class-od-url-metrics-group-collection.php +++ b/plugins/optimization-detective/class-od-url-metrics-group-collection.php @@ -38,7 +38,12 @@ final class OD_URL_Metrics_Group_Collection implements Countable, IteratorAggreg /** * Breakpoints in max widths. * - * Valid values are from 1 to PHP_INT_MAX. + * Valid values are from 1 to PHP_INT_MAX - 1. This is because: + * + * 1. It doesn't make sense for there to be a viewport width of zero, so the first breakpoint (max width) must be at least 1. + * 2. After the last breakpoint, the final breakpoint group is set to be spanning one plus the last breakpoint max width up + * until PHP_INT_MAX. So a breakpoint cannot be PHP_INT_MAX because then the minimum viewport width for the final group + * would end up being larger than PHP_INT_MAX. * * @var int[] * @phpstan-var positive-int[] @@ -78,7 +83,7 @@ public function __construct( array $url_metrics, array $breakpoints, int $sample sort( $breakpoints ); $breakpoints = array_values( array_unique( $breakpoints, SORT_NUMERIC ) ); foreach ( $breakpoints as $breakpoint ) { - if ( $breakpoint <= 1 || PHP_INT_MAX === $breakpoint ) { + if ( ! is_int( $breakpoint ) || $breakpoint < 1 || PHP_INT_MAX === $breakpoint ) { throw new InvalidArgumentException( esc_html( sprintf( @@ -93,6 +98,11 @@ public function __construct( array $url_metrics, array $breakpoints, int $sample ); } } + /** + * Validated breakpoints. + * + * @var positive-int[] $breakpoints + */ $this->breakpoints = $breakpoints; // Set sample size. @@ -133,6 +143,8 @@ public function __construct( array $url_metrics, array $breakpoints, int $sample /** * Create groups. * + * @phpstan-return non-empty-array + * * @return OD_URL_Metrics_Group[] Groups. */ private function create_groups(): array { diff --git a/plugins/optimization-detective/optimization.php b/plugins/optimization-detective/optimization.php index 60c7e104b7..f24957ebf6 100644 --- a/plugins/optimization-detective/optimization.php +++ b/plugins/optimization-detective/optimization.php @@ -195,7 +195,7 @@ function od_is_response_html_content_type(): bool { ); foreach ( $headers_list as $header ) { $header_parts = preg_split( '/\s*[:;]\s*/', strtolower( $header ) ); - if ( count( $header_parts ) >= 2 && 'content-type' === $header_parts[0] ) { + if ( is_array( $header_parts ) && count( $header_parts ) >= 2 && 'content-type' === $header_parts[0] ) { $is_html_content_type = in_array( $header_parts[1], array( 'text/html', 'application/xhtml+xml' ), true ); } } @@ -279,7 +279,7 @@ function od_optimize_template_output_buffer( string $buffer ): string { && $walker->get_attribute( 'src' ) && - ! str_starts_with( $walker->get_attribute( 'src' ), 'data:' ) + ! str_starts_with( (string) $walker->get_attribute( 'src' ), 'data:' ) ); /* @@ -295,7 +295,7 @@ function od_optimize_template_output_buffer( string $buffer ): string { if ( $style && - preg_match( '/background(-image)?\s*:[^;]*?url\(\s*[\'"]?(?.+?)[\'"]?\s*\)/', $style, $matches ) + preg_match( '/background(-image)?\s*:[^;]*?url\(\s*[\'"]?(?.+?)[\'"]?\s*\)/', (string) $style, $matches ) && ! str_starts_with( $matches['background_image'], 'data:' ) ) { @@ -342,16 +342,20 @@ function od_optimize_template_output_buffer( string $buffer ): string { $img_attributes = array(); foreach ( array( 'src', 'srcset', 'sizes', 'crossorigin' ) as $attr_name ) { $value = $walker->get_attribute( $attr_name ); - if ( null !== $value ) { + if ( is_string( $value ) ) { $img_attributes[ $attr_name ] = $value; } } foreach ( $lcp_element_minimum_viewport_widths_by_xpath[ $xpath ] as $minimum_viewport_width ) { - $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ]['img_attributes'] = $img_attributes; + if ( is_array( $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ] ) ) { + $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ]['img_attributes'] = $img_attributes; + } } } elseif ( $background_image_url ) { foreach ( $lcp_element_minimum_viewport_widths_by_xpath[ $xpath ] as $minimum_viewport_width ) { - $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ]['background_image'] = $background_image_url; + if ( is_array( $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ] ) ) { + $lcp_elements_by_minimum_viewport_widths[ $minimum_viewport_width ]['background_image'] = $background_image_url; + } } } } diff --git a/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php b/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php index 1494b51d0b..38d34c948d 100644 --- a/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php +++ b/plugins/optimization-detective/storage/class-od-url-metrics-post-type.php @@ -154,6 +154,7 @@ static function ( $url_metric_data ) use ( $trigger_warning ) { } try { + // @phpstan-ignore-next-line -- Invalid data will be validated in the constructor. return new OD_URL_Metric( $url_metric_data ); } catch ( OD_Data_Validation_Exception $e ) { $trigger_warning( @@ -225,6 +226,9 @@ static function ( OD_URL_Metric $url_metric ): array { ), JSON_UNESCAPED_SLASHES // No need for escaped slashes since not printed to frontend. ); + if ( ! is_string( $post_data['post_content'] ) ) { + return new WP_Error( 'json_encode_error', json_last_error_msg() ); + } $has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ); if ( $has_kses ) { @@ -290,7 +294,7 @@ public static function delete_stale_posts(): void { ); foreach ( $query->posts as $post ) { - if ( self::SLUG === $post->post_type ) { // Sanity check. + if ( $post instanceof WP_Post && self::SLUG === $post->post_type ) { // Sanity check. wp_delete_post( $post->ID, true ); } } diff --git a/plugins/optimization-detective/storage/data.php b/plugins/optimization-detective/storage/data.php index 44d372702b..b94b7fc8cc 100644 --- a/plugins/optimization-detective/storage/data.php +++ b/plugins/optimization-detective/storage/data.php @@ -137,7 +137,7 @@ function od_get_current_url(): string { * @return string Slug. */ function od_get_url_metrics_slug( array $query_vars ): string { - return md5( wp_json_encode( $query_vars ) ); + return md5( (string) wp_json_encode( $query_vars ) ); } /** diff --git a/plugins/optimization-detective/storage/rest-api.php b/plugins/optimization-detective/storage/rest-api.php index 106d859e63..8dddf776c8 100644 --- a/plugins/optimization-detective/storage/rest-api.php +++ b/plugins/optimization-detective/storage/rest-api.php @@ -130,6 +130,7 @@ function od_handle_rest_request( WP_REST_Request $request ) { try { $properties = OD_URL_Metric::get_json_schema()['properties']; $url_metric = new OD_URL_Metric( + // @phpstan-ignore-next-line -- Array shape is validated by the constructor. array_merge( wp_array_slice_assoc( $request->get_params(), diff --git a/plugins/speculation-rules/class-plsr-url-pattern-prefixer.php b/plugins/speculation-rules/class-plsr-url-pattern-prefixer.php index be34cfca3c..50fb70a864 100644 --- a/plugins/speculation-rules/class-plsr-url-pattern-prefixer.php +++ b/plugins/speculation-rules/class-plsr-url-pattern-prefixer.php @@ -107,13 +107,13 @@ public function prefix_path_pattern( string $path_pattern, string $context = 'ho */ public static function get_default_contexts(): array { return array( - 'home' => self::escape_pattern_string( trailingslashit( wp_parse_url( home_url( '/' ), PHP_URL_PATH ) ) ), - 'site' => self::escape_pattern_string( trailingslashit( wp_parse_url( site_url( '/' ), PHP_URL_PATH ) ) ), - 'uploads' => self::escape_pattern_string( trailingslashit( wp_parse_url( wp_upload_dir( null, false )['baseurl'], PHP_URL_PATH ) ) ), - 'content' => self::escape_pattern_string( trailingslashit( wp_parse_url( content_url(), PHP_URL_PATH ) ) ), - 'plugins' => self::escape_pattern_string( trailingslashit( wp_parse_url( plugins_url(), PHP_URL_PATH ) ) ), - 'template' => self::escape_pattern_string( trailingslashit( wp_parse_url( get_stylesheet_directory_uri(), PHP_URL_PATH ) ) ), - 'stylesheet' => self::escape_pattern_string( trailingslashit( wp_parse_url( get_template_directory_uri(), PHP_URL_PATH ) ) ), + 'home' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( home_url( '/' ), PHP_URL_PATH ) ) ), + 'site' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( site_url( '/' ), PHP_URL_PATH ) ) ), + 'uploads' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( wp_upload_dir( null, false )['baseurl'], PHP_URL_PATH ) ) ), + 'content' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( content_url(), PHP_URL_PATH ) ) ), + 'plugins' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( plugins_url(), PHP_URL_PATH ) ) ), + 'template' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( get_stylesheet_directory_uri(), PHP_URL_PATH ) ) ), + 'stylesheet' => self::escape_pattern_string( trailingslashit( (string) wp_parse_url( get_template_directory_uri(), PHP_URL_PATH ) ) ), ); } diff --git a/plugins/speculation-rules/helper.php b/plugins/speculation-rules/helper.php index 758a72f6e6..ef0b8082fd 100644 --- a/plugins/speculation-rules/helper.php +++ b/plugins/speculation-rules/helper.php @@ -19,7 +19,7 @@ * * @since 1.0.0 * - * @return array Associative array of speculation rules by type. + * @return array>> Associative array of speculation rules by type. */ function plsr_get_speculation_rules(): array { $option = get_option( 'plsr_speculation_rules' ); @@ -34,7 +34,7 @@ function plsr_get_speculation_rules(): array { $option = array_merge( plsr_get_setting_default(), $option ); } - $mode = $option['mode']; + $mode = (string) $option['mode']; $eagerness = $option['eagerness']; $prefixer = new PLSR_URL_Pattern_Prefixer(); diff --git a/plugins/speculation-rules/hooks.php b/plugins/speculation-rules/hooks.php index d9f201690a..b5731232cc 100644 --- a/plugins/speculation-rules/hooks.php +++ b/plugins/speculation-rules/hooks.php @@ -27,8 +27,8 @@ function plsr_print_speculation_rules(): void { // This workaround is needed for WP 6.4. See . $needs_html5_workaround = ( ! current_theme_supports( 'html5', 'script' ) && - version_compare( strtok( get_bloginfo( 'version' ), '-' ), '6.4', '>=' ) && - version_compare( strtok( get_bloginfo( 'version' ), '-' ), '6.5', '<' ) + version_compare( (string) strtok( (string) get_bloginfo( 'version' ), '-' ), '6.4', '>=' ) && + version_compare( (string) strtok( (string) get_bloginfo( 'version' ), '-' ), '6.5', '<' ) ); if ( $needs_html5_workaround ) { $backup_wp_theme_features = $GLOBALS['_wp_theme_features']; @@ -36,7 +36,7 @@ function plsr_print_speculation_rules(): void { } wp_print_inline_script_tag( - wp_json_encode( $rules ), + (string) wp_json_encode( $rules ), array( 'type' => 'speculationrules' ) ); diff --git a/plugins/speculation-rules/settings.php b/plugins/speculation-rules/settings.php index 918b676c61..ae0c6ae818 100644 --- a/plugins/speculation-rules/settings.php +++ b/plugins/speculation-rules/settings.php @@ -206,8 +206,12 @@ function plsr_render_settings_field( array $args ): void { return; } - $value = $option[ $args['field'] ]; - $choices = call_user_func( "plsr_get_{$args['field']}_labels" ); + $value = $option[ $args['field'] ]; + $callback = "plsr_get_{$args['field']}_labels"; + if ( ! is_callable( $callback ) ) { + return; + } + $choices = call_user_func( $callback ); ?>
diff --git a/plugins/webp-uploads/helper.php b/plugins/webp-uploads/helper.php index 8bc47dfea0..ccb5d3460f 100644 --- a/plugins/webp-uploads/helper.php +++ b/plugins/webp-uploads/helper.php @@ -106,21 +106,22 @@ function webp_uploads_generate_additional_image_source( int $attachment_id, stri if ( is_wp_error( $image ) ) { return $image; } + if ( is_array( $image ) && array_key_exists( 'file', $image ) && is_string( $image['file'] ) ) { + // The filtered image provided all we need to short-circuit here. + if ( array_key_exists( 'filesize', $image ) && is_int( $image['filesize'] ) && $image['filesize'] > 0 ) { + return $image; + } - if ( - is_array( $image ) && - ! empty( $image['file'] ) && - ( - ! empty( $image['path'] ) || - array_key_exists( 'filesize', $image ) - ) - ) { - return array( - 'file' => $image['file'], - 'filesize' => array_key_exists( 'filesize', $image ) - ? $image['filesize'] - : wp_filesize( $image['path'] ), - ); + // Supply the filesize based on the filter-provided path. + if ( array_key_exists( 'path', $image ) && is_int( $image['path'] ) ) { + $filesize = wp_filesize( $image['path'] ); + if ( $filesize > 0 ) { + return array( + 'file' => $image['file'], + 'filesize' => $filesize, + ); + } + } } $allowed_mimes = array_flip( wp_get_mime_types() ); @@ -133,7 +134,7 @@ function webp_uploads_generate_additional_image_source( int $attachment_id, stri } $image_path = wp_get_original_image_path( $attachment_id ); - if ( ! file_exists( $image_path ) ) { + if ( ! $image_path || ! file_exists( $image_path ) ) { return new WP_Error( 'original_image_file_not_found', __( 'The original image file does not exists, subsizes are created out of the original image.', 'webp-uploads' ) ); } diff --git a/plugins/webp-uploads/hooks.php b/plugins/webp-uploads/hooks.php index b37ec51654..2266eff793 100644 --- a/plugins/webp-uploads/hooks.php +++ b/plugins/webp-uploads/hooks.php @@ -26,12 +26,22 @@ * @see wp_generate_attachment_metadata() * @see webp_uploads_get_upload_image_mime_transforms() * + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int + * } $metadata + * * @param array $metadata An array with the metadata from this attachment. * @param int $attachment_id The ID of the attachment where the hook was dispatched. + * * @return array{ * width: int, * height: int, - * file: non-falsy-string, + * file: string, * sizes: array }>, * image_meta: array, * filesize: int, @@ -47,13 +57,13 @@ function webp_uploads_create_sources_property( array $metadata, int $attachment_ // Not a supported mime type to create the sources property. $mime_type = get_post_mime_type( $attachment_id ); - if ( ! isset( $valid_mime_transforms[ $mime_type ] ) ) { + if ( ! is_string( $mime_type ) || ! isset( $valid_mime_transforms[ $mime_type ] ) ) { return $metadata; } $file = get_attached_file( $attachment_id, true ); // File does not exist. - if ( ! file_exists( $file ) ) { + if ( ! $file || ! file_exists( $file ) ) { return $metadata; } @@ -116,7 +126,9 @@ function webp_uploads_create_sources_property( array $metadata, int $attachment_ if ( ! in_array( $mime_type, $valid_mime_transforms[ $mime_type ], true ) && isset( $valid_mime_transforms[ $mime_type ][0] ) && - isset( $allowed_mimes[ $mime_type ] ) + isset( $allowed_mimes[ $mime_type ] ) && + array_key_exists( 'file', $metadata ) && + is_string( $metadata['file'] ) ) { $valid_mime_type = $valid_mime_transforms[ $mime_type ][0]; @@ -134,12 +146,17 @@ function webp_uploads_create_sources_property( array $metadata, int $attachment_ // If WordPress already modified the original itself, keep the original and discard WordPress's generated version. if ( ! empty( $metadata['original_image'] ) ) { - $uploadpath = wp_get_upload_dir(); - wp_delete_file_from_directory( get_attached_file( $attachment_id ), $uploadpath['basedir'] ); + $uploadpath = wp_get_upload_dir(); + $attached_file = get_attached_file( $attachment_id ); + if ( $attached_file ) { + wp_delete_file_from_directory( $attached_file, $uploadpath['basedir'] ); + } } // Replace the attached file with the custom MIME type version. - $metadata = _wp_image_meta_replace_original( $saved_data, $original_image, $metadata, $attachment_id ); + if ( $original_image ) { + $metadata = _wp_image_meta_replace_original( $saved_data, $original_image, $metadata, $attachment_id ); + } // Unset sources entry for the original MIME type, then save (to avoid inconsistent data // in case of an error after this logic). @@ -233,6 +250,15 @@ function webp_uploads_create_sources_property( array $metadata, int $attachment_ * * @see wp_get_missing_image_subsizes() * + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int + * } $image_meta + * * @param array|mixed $missing_sizes Associative array of arrays of image sub-sizes. * @param array $image_meta The metadata from the image. * @param int $attachment_id The ID of the attachment. @@ -716,7 +742,7 @@ function webp_uploads_wepb_fallback(): void { $javascript = ob_get_clean(); wp_print_inline_script_tag( - preg_replace( '/\s+/', '', $javascript ), + preg_replace( '/\s+/', '', (string) $javascript ), array( 'id' => 'webpUploadsFallbackWebpImages', 'data-rest-api' => esc_url_raw( trailingslashit( get_rest_url() ) ), diff --git a/plugins/webp-uploads/image-edit.php b/plugins/webp-uploads/image-edit.php index 6a38323d98..4b7ef4e4c6 100644 --- a/plugins/webp-uploads/image-edit.php +++ b/plugins/webp-uploads/image-edit.php @@ -42,7 +42,7 @@ * image_meta: array, * filesize: int, * original_image?: string, - * sources: array + * sources?: array * } Metadata with sources added. */ function webp_uploads_update_sources( array $metadata, array $valid_mime_transforms, array $main_images, array $subsized_images ): array { @@ -194,7 +194,7 @@ static function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_t continue; } - if ( ! $editor::supports_mime_type( $targeted_mime ) ) { + if ( $editor instanceof WP_Image_Editor && ! $editor::supports_mime_type( $targeted_mime ) ) { continue; } @@ -228,7 +228,7 @@ static function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_t } $subsized_images[ $targeted_mime ] = array( 'thumbnail' => $result ); - } else { + } elseif ( $editor instanceof WP_Image_Editor ) { $destination = trailingslashit( $original_directory ) . "{$filename}.{$extension}"; remove_filter( 'image_editor_output_format', 'webp_uploads_filter_image_editor_output_format', 10 ); @@ -263,6 +263,16 @@ static function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_t * * @see wp_update_attachment_metadata() * + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array }>, + * image_meta: array, + * filesize: int, + * original_image: string + * } $data + * * @param array $data The current metadata of the attachment. * @param int $attachment_id The ID of the current attachment. * @@ -305,8 +315,20 @@ function webp_uploads_update_attachment_metadata( array $data, int $attachment_i * * @since 1.0.0 * + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int, + * original_image: string, + * sources?: array + * } $data + * * @param int $attachment_id The ID representing the attachment. * @param array $data The current metadata of the attachment. + * * @return array{ * width: int, * height: int, @@ -437,6 +459,16 @@ function webp_uploads_get_next_full_size_key_from_backup( int $attachment_id ): * * @since 1.0.0 * + * @phpstan-param array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int, + * original_image: string + * } $data + * * @param int $attachment_id The ID of the attachment. * @param array $data The current metadata to be stored in the attachment. * @return array{ @@ -446,7 +478,7 @@ function webp_uploads_get_next_full_size_key_from_backup( int $attachment_id ): * sizes: array, * image_meta: array, * filesize: int, - * sources: array, + * sources?: array, * original_image: string * } The updated metadata of the attachment. */ diff --git a/plugins/webp-uploads/rest-api.php b/plugins/webp-uploads/rest-api.php index 947652f947..ab04bc732e 100644 --- a/plugins/webp-uploads/rest-api.php +++ b/plugins/webp-uploads/rest-api.php @@ -49,6 +49,6 @@ function webp_uploads_update_rest_attachment( WP_REST_Response $response, WP_Pos unset( $data['media_details']['sources'] ); } - return rest_ensure_response( $data ); + return new WP_REST_Response( $data ); } add_filter( 'rest_prepare_attachment', 'webp_uploads_update_rest_attachment', 10, 2 ); diff --git a/tests/includes/server-timing/perflab-server-timing-tests.php b/tests/includes/server-timing/perflab-server-timing-tests.php index 4c93f7e754..9c6df67514 100644 --- a/tests/includes/server-timing/perflab-server-timing-tests.php +++ b/tests/includes/server-timing/perflab-server-timing-tests.php @@ -44,7 +44,8 @@ public function test_register_metric_stores_metrics_and_runs_measure_callback(): $this->server_timing->register_metric( 'test-metric', array( - 'measure_callback' => static function () use ( &$called ): void { + 'measure_callback' => static function ( Perflab_Server_Timing_Metric $metric ) use ( &$called ): void { + unset( $metric ); $called = true; }, 'access_cap' => 'exist', @@ -61,7 +62,8 @@ public function test_register_metric_runs_measure_callback_based_on_access_cap() $this->server_timing->register_metric( 'test-metric', array( - 'measure_callback' => static function () use ( &$called ): void { + 'measure_callback' => static function ( Perflab_Server_Timing_Metric $metric ) use ( &$called ): void { + unset( $metric ); $called = true; }, 'access_cap' => $access_cap, @@ -75,7 +77,8 @@ public function test_register_metric_runs_measure_callback_based_on_access_cap() $this->server_timing->register_metric( 'test-metric-2', array( - 'measure_callback' => static function () use ( &$called ): void { + 'measure_callback' => static function ( Perflab_Server_Timing_Metric $metric ) use ( &$called ): void { + unset( $metric ); $called = true; }, 'access_cap' => $access_cap, @@ -141,7 +144,7 @@ public function test_register_metric_replaces_slashes(): void { $this->server_timing->register_metric( 'foo/bar/baz', array( - 'measure_callback' => static function ( $metric ): void { + 'measure_callback' => static function ( Perflab_Server_Timing_Metric $metric ): void { $metric->set_value( 123 ); }, 'access_cap' => 'exist', @@ -166,13 +169,13 @@ public function test_get_header( string $expected, array $metrics ): void { * @return array */ public function data_get_header(): array { - $measure_42 = static function ( $metric ): void { + $measure_42 = static function ( Perflab_Server_Timing_Metric $metric ): void { $metric->set_value( 42 ); }; - $measure_300 = static function ( $metric ): void { + $measure_300 = static function ( Perflab_Server_Timing_Metric $metric ): void { $metric->set_value( 300 ); }; - $measure_12point345 = static function ( $metric ): void { + $measure_12point345 = static function ( Perflab_Server_Timing_Metric $metric ): void { $metric->set_value( 12.345 ); }; diff --git a/tests/plugins/optimization-detective/class-od-url-metrics-group-collection-tests.php b/tests/plugins/optimization-detective/class-od-url-metrics-group-collection-tests.php index 8369c7b521..bdd9fea693 100644 --- a/tests/plugins/optimization-detective/class-od-url-metrics-group-collection-tests.php +++ b/tests/plugins/optimization-detective/class-od-url-metrics-group-collection-tests.php @@ -52,7 +52,7 @@ public function data_provider_test_construction(): array { 'breakpoints' => array( 'narrow' ), 'sample_size' => 3, 'freshness_ttl' => HOUR_IN_SECONDS, - 'exception' => PHP_MAJOR_VERSION >= 8 ? TypeError::class : InvalidArgumentException::class, + 'exception' => InvalidArgumentException::class, ), 'negative_sample_size_bad' => array( 'url_metrics' => array(), diff --git a/tests/plugins/optimization-detective/optimization-tests.php b/tests/plugins/optimization-detective/optimization-tests.php index 7c8eddfa83..659a33bae4 100644 --- a/tests/plugins/optimization-detective/optimization-tests.php +++ b/tests/plugins/optimization-detective/optimization-tests.php @@ -27,7 +27,7 @@ class OD_Optimization_Tests extends WP_UnitTestCase { public function set_up(): void { $this->original_request_uri = $_SERVER['REQUEST_URI']; $this->original_request_method = $_SERVER['REQUEST_METHOD']; - $this->default_mimetype = ini_get( 'default_mimetype' ); + $this->default_mimetype = (string) ini_get( 'default_mimetype' ); parent::set_up(); } diff --git a/tests/plugins/webp-uploads/helper-tests.php b/tests/plugins/webp-uploads/helper-tests.php index a30971c397..aa3aa488f2 100644 --- a/tests/plugins/webp-uploads/helper-tests.php +++ b/tests/plugins/webp-uploads/helper-tests.php @@ -277,8 +277,8 @@ public function it_should_create_an_image_with_filter_webp_uploads_pre_generate_ 'webp_uploads_pre_generate_additional_image_source', static function () { return array( - 'file' => 'image.webp', - 'path' => '/tmp/image.webp', + 'file' => 'image.webp', + 'filesize' => 1024, ); } );