From 2ea0adf8962a7e625344550707e51ff2d60835be Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 3 Jul 2025 18:26:23 +0200 Subject: [PATCH 01/10] PHPStan level 9 --- functions.php | 12 ++++-- phpstan.neon.dist | 16 ++++++++ src/Export_Command.php | 72 ++++++++++++++++++++++++++++++++- src/WP_Export_Returner.php | 1 - src/WP_Export_WXR_Formatter.php | 13 ++++++ src/WP_Export_XML_Over_HTTP.php | 13 +++++- src/WP_Map_Iterator.php | 9 +++++ src/WP_Post_IDs_Iterator.php | 38 +++++++++++++++++ 8 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 phpstan.neon.dist diff --git a/functions.php b/functions.php index 8716c1972..a7fe5c8c5 100644 --- a/functions.php +++ b/functions.php @@ -1,13 +1,19 @@ , format?: class-string, writer?: class-string, writer_args?: mixed} $args + */ +function wp_export( $args = array() ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Renaming breaks Phar compat. + $defaults = array( 'filters' => array(), 'format' => 'WP_Export_WXR_Formatter', 'writer' => 'WP_Export_Returner', 'writer_args' => null, ); + + /** + * @var array{filters: array, format: class-string, writer: class-string, writer_args: mixed} $args + */ $args = wp_parse_args( $args, $defaults ); $export_query = new WP_Export_Query( $args['filters'] ); $formatter = new $args['format']( $export_query ); diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 000000000..251831731 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,16 @@ +parameters: + level: 9 + paths: + - src + - export-command.php + - functions.php + scanDirectories: + - vendor/wp-cli/wp-cli/php + scanFiles: + - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php + treatPhpDocTypesAsCertain: false + ignoreErrors: + - identifier: missingType.iterableValue + - identifier: missingType.property + - identifier: missingType.parameter + - identifier: missingType.return diff --git a/src/Export_Command.php b/src/Export_Command.php index 273f9d33d..8c34a3330 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -251,9 +251,14 @@ private function validate_args( $args ) { } } + /** + * @param string $path + * + * @phpstan-ignore method.unused + */ private function check_dir( $path ) { if ( empty( $path ) ) { - $path = getcwd(); + $path = (string) getcwd(); } elseif ( ! is_dir( $path ) ) { WP_CLI::error( sprintf( "The directory '%s' does not exist.", $path ) ); } elseif ( ! is_writable( $path ) ) { @@ -265,6 +270,11 @@ private function check_dir( $path ) { return true; } + /** + * @param string $date + * + * @phpstan-ignore method.unused + */ private function check_start_date( $date ) { if ( null === $date ) { return true; @@ -279,6 +289,11 @@ private function check_start_date( $date ) { return true; } + /** + * @param string $date + * + * @phpstan-ignore method.unused + */ private function check_end_date( $date ) { if ( null === $date ) { return true; @@ -293,6 +308,11 @@ private function check_end_date( $date ) { return true; } + /** + * @param string $post_type + * + * @phpstan-ignore method.unused + */ private function check_post_type( $post_type ) { if ( null === $post_type || 'any' === $post_type ) { return true; @@ -317,6 +337,11 @@ private function check_post_type( $post_type ) { return true; } + /** + * @param string $post_type + * + * @phpstan-ignore method.unused + */ private function check_post_type__not_in( $post_type ) { if ( null === $post_type ) { return true; @@ -341,6 +366,11 @@ private function check_post_type__not_in( $post_type ) { return true; } + /** + * @param string $post__in + * + * @phpstan-ignore method.unused + */ private function check_post__in( $post__in ) { if ( null === $post__in ) { return true; @@ -357,6 +387,11 @@ private function check_post__in( $post__in ) { return true; } + /** + * @param string $start_id + * + * @phpstan-ignore method.unused + */ private function check_start_id( $start_id ) { if ( null === $start_id ) { return true; @@ -374,6 +409,11 @@ private function check_start_id( $start_id ) { return true; } + /** + * @param string $author + * + * @phpstan-ignore method.unused + */ private function check_author( $author ) { if ( null === $author ) { return true; @@ -418,6 +458,11 @@ private function check_max_num_posts( $num ) { return true; } + /** + * @param string $category + * + * @phpstan-ignore method.unused + */ private function check_category( $category ) { if ( null === $category ) { return true; @@ -436,6 +481,11 @@ private function check_category( $category ) { return true; } + /** + * @param string $status + * + * @phpstan-ignore method.unused + */ private function check_post_status( $status ) { if ( null === $status ) { return true; @@ -455,6 +505,11 @@ private function check_post_status( $status ) { return true; } + /** + * @param string|null $shkip + * + * @phpstan-ignore method.unused + */ private function check_skip_comments( $skip ) { if ( null === $skip ) { return true; @@ -468,6 +523,11 @@ private function check_skip_comments( $skip ) { return true; } + /** + * @param string $size + * + * @phpstan-ignore method.unused + */ private function check_max_file_size( $size ) { if ( ! is_numeric( $size ) ) { WP_CLI::warning( 'max_file_size should be numeric.' ); @@ -479,6 +539,11 @@ private function check_max_file_size( $size ) { return true; } + /** + * @param string $once + * + * @phpstan-ignore method.unused + */ private function check_include_once( $once ) { if ( null === $once ) { return true; @@ -497,6 +562,11 @@ private function check_include_once( $once ) { return true; } + /** + * @param string $allow_orphan_terms + * + * @phpstan-ignore method.unused + */ private function check_allow_orphan_terms( $allow_orphan_terms ) { if ( null === $allow_orphan_terms ) { return true; diff --git a/src/WP_Export_Returner.php b/src/WP_Export_Returner.php index 6327e1357..234e1b5b0 100644 --- a/src/WP_Export_Returner.php +++ b/src/WP_Export_Returner.php @@ -4,7 +4,6 @@ class WP_Export_Returner extends WP_Export_Base_Writer { private $result = ''; public function export() { - $this->private = ''; try { parent::export(); } catch ( WP_Export_Exception $e ) { diff --git a/src/WP_Export_WXR_Formatter.php b/src/WP_Export_WXR_Formatter.php index 3910cc8e0..5c2dc6f9c 100644 --- a/src/WP_Export_WXR_Formatter.php +++ b/src/WP_Export_WXR_Formatter.php @@ -12,11 +12,24 @@ * Responsible for formatting the data in WP_Export_Query to WXR */ class WP_Export_WXR_Formatter { + /** + * @var WP_Export_Query + */ + private $export; + + /** + * @var string + */ + private $wxr_version; + public function __construct( $export ) { $this->export = $export; $this->wxr_version = WXR_VERSION; } + /** + * @param array $requested_sections + */ public function before_posts( $requested_sections = [] ) { $available_sections = [ 'header', diff --git a/src/WP_Export_XML_Over_HTTP.php b/src/WP_Export_XML_Over_HTTP.php index f4dee588c..a0332b2ff 100644 --- a/src/WP_Export_XML_Over_HTTP.php +++ b/src/WP_Export_XML_Over_HTTP.php @@ -1,9 +1,20 @@ file_name = $file_name; diff --git a/src/WP_Map_Iterator.php b/src/WP_Map_Iterator.php index 9d2d0b3ee..7906a66f1 100644 --- a/src/WP_Map_Iterator.php +++ b/src/WP_Map_Iterator.php @@ -1,6 +1,15 @@ callback = $callback; parent::__construct( $iterator ); diff --git a/src/WP_Post_IDs_Iterator.php b/src/WP_Post_IDs_Iterator.php index b05c6f121..16b8db72a 100644 --- a/src/WP_Post_IDs_Iterator.php +++ b/src/WP_Post_IDs_Iterator.php @@ -1,11 +1,44 @@ + */ class WP_Post_IDs_Iterator implements Iterator { + /** + * @var \wpdb + */ + private $db; + + /** + * @var int + */ private $limit = 100; + + /** + * @var int[] + */ private $post_ids; + + /** + * @var int[] + */ private $ids_left; + + /** + * @var int[] + */ private $results = array(); + /** + * @var int + */ + private $index_in_results; + + /** + * @var int + */ + private $global_index; + public function __construct( $post_ids, $limit = null ) { $this->db = $GLOBALS['wpdb']; $this->post_ids = $post_ids; @@ -15,19 +48,23 @@ public function __construct( $post_ids, $limit = null ) { } } + #[\ReturnTypeWillChange] public function current() { return $this->results[ $this->index_in_results ]; } + #[\ReturnTypeWillChange] public function key() { return $this->global_index; } + #[\ReturnTypeWillChange] public function next() { ++$this->index_in_results; ++$this->global_index; } + #[\ReturnTypeWillChange] public function rewind() { $this->results = array(); $this->global_index = 0; @@ -35,6 +72,7 @@ public function rewind() { $this->ids_left = $this->post_ids; } + #[\ReturnTypeWillChange] public function valid() { if ( isset( $this->results[ $this->index_in_results ] ) ) { return true; From 88bad2d9f05ba6500137ef4f430f13c34eb2700f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 3 Nov 2025 10:10:47 +0100 Subject: [PATCH 02/10] Fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Export_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 8c34a3330..425c5e504 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -506,7 +506,7 @@ private function check_post_status( $status ) { } /** - * @param string|null $shkip + * @param string|null $skip * * @phpstan-ignore method.unused */ From 2d8b895e502fb2316e5abf525fd1724db93776b3 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 3 Nov 2025 10:10:57 +0100 Subject: [PATCH 03/10] Implement suggestion Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/WP_Post_IDs_Iterator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WP_Post_IDs_Iterator.php b/src/WP_Post_IDs_Iterator.php index 16b8db72a..a2abc15c4 100644 --- a/src/WP_Post_IDs_Iterator.php +++ b/src/WP_Post_IDs_Iterator.php @@ -25,7 +25,7 @@ class WP_Post_IDs_Iterator implements Iterator { private $ids_left; /** - * @var int[] + * @var object[] */ private $results = array(); From 4fa5ca613588460897354879999b68f529f4986d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:13:16 +0000 Subject: [PATCH 04/10] Initial plan From 338552c3418484f1c9976234aa821b4a2cbac135 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:36:12 +0000 Subject: [PATCH 05/10] Fix PHPStan level 9 errors Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 26 +++++++++++++++----------- src/WP_Export_Oxymel.php | 2 +- src/WP_Export_Query.php | 4 ++-- src/WP_Export_WXR_Formatter.php | 12 ++++++------ src/WP_Map_Iterator.php | 3 +++ src/WP_Post_IDs_Iterator.php | 3 ++- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 425c5e504..5fa8393a6 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -181,7 +181,7 @@ public function __invoke( $_, $assoc_args ) { 'wp_export_new_file', static function ( $file_path ) { WP_CLI::log( sprintf( 'Writing to file %s', $file_path ) ); - Utils\wp_clear_object_cache(); + Utils\wp_clear_object_cache(); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.wp_clear_object_cacheDeprecatedRemoved } ); @@ -190,7 +190,7 @@ static function ( $file_path ) { wp_export( [ 'filters' => $this->export_args, - 'writer' => 'WP_Export_File_Writer', + 'writer' => WP_Export_File_Writer::class, 'writer_args' => 'php://output', ] ); @@ -198,7 +198,7 @@ static function ( $file_path ) { wp_export( [ 'filters' => $this->export_args, - 'writer' => 'WP_Export_Split_Files_Writer', + 'writer' => WP_Export_Split_Files_Writer::class, 'writer_args' => [ 'max_file_size' => $this->max_file_size, 'destination_directory' => $this->wxr_path, @@ -234,6 +234,7 @@ private function validate_args( $args ) { foreach ( $args as $key => $value ) { if ( is_callable( [ $this, 'check_' . $key ] ) ) { + /** @phpstan-ignore argument.type */ $result = call_user_func( [ $this, 'check_' . $key ], $value ); if ( false === $result ) { $has_errors = true; @@ -281,11 +282,11 @@ private function check_start_date( $date ) { } $time = strtotime( $date ); - if ( ! empty( $date ) && ! $time ) { + if ( ! empty( $date ) && false === $time ) { WP_CLI::warning( sprintf( 'The start_date %s is invalid.', $date ) ); return false; } - $this->export_args['start_date'] = date( 'Y-m-d', $time ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date + $this->export_args['start_date'] = date( 'Y-m-d', (int) $time ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date return true; } @@ -300,11 +301,11 @@ private function check_end_date( $date ) { } $time = strtotime( $date ); - if ( ! empty( $date ) && ! $time ) { + if ( ! empty( $date ) && false === $time ) { WP_CLI::warning( sprintf( 'The end_date %s is invalid.', $date ) ); return false; } - $this->export_args['end_date'] = date( 'Y-m-d', $time ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date + $this->export_args['end_date'] = date( 'Y-m-d', (int) $time ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date return true; } @@ -420,8 +421,8 @@ private function check_author( $author ) { } // phpcs:ignore WordPress.WP.DeprecatedFunctions.get_users_of_blogFound -- Fallback. - $authors = function_exists( 'get_users' ) ? get_users() : get_users_of_blog(); - if ( empty( $authors ) || is_wp_error( $authors ) ) { + $authors = function_exists( 'get_users' ) ? get_users() : get_users_of_blog(); // phpstan-ignore-line + if ( empty( $authors ) ) { WP_CLI::warning( 'Could not find any authors in this blog.' ); return false; } @@ -447,6 +448,9 @@ private function check_author( $author ) { return true; } + /** + * @phpstan-ignore method.unused + */ private function check_max_num_posts( $num ) { if ( null !== $num && ( ! is_numeric( $num ) || $num <= 0 ) ) { WP_CLI::warning( 'max_num_posts should be a positive integer.' ); @@ -473,7 +477,7 @@ private function check_category( $category ) { } $term = category_exists( $category ); - if ( empty( $term ) || is_wp_error( $term ) ) { + if ( empty( $term ) ) { WP_CLI::warning( sprintf( 'Could not find a category matching %s.', $category ) ); return false; } @@ -492,7 +496,7 @@ private function check_post_status( $status ) { } $stati = get_post_stati(); - if ( empty( $stati ) || is_wp_error( $stati ) ) { + if ( empty( $stati ) ) { WP_CLI::warning( 'Could not find any post stati.' ); return false; } diff --git a/src/WP_Export_Oxymel.php b/src/WP_Export_Oxymel.php index 0d3c75e37..3c25a55e5 100644 --- a/src/WP_Export_Oxymel.php +++ b/src/WP_Export_Oxymel.php @@ -10,7 +10,7 @@ public function optional( $tag_name, $contents ) { public function optional_cdata( $tag_name, $contents ) { if ( $contents ) { - $this->$tag_name->contains->cdata( $contents )->end; + $this->$tag_name->contains->cdata( $contents )->end; // phpstan-ignore-line } return $this; } diff --git a/src/WP_Export_Query.php b/src/WP_Export_Query.php index 4ddc9656e..6099d56fa 100644 --- a/src/WP_Export_Query.php +++ b/src/WP_Export_Query.php @@ -122,7 +122,7 @@ public function custom_taxonomies_terms() { } $custom_taxonomies = get_taxonomies( [ '_builtin' => false ] ); // phpcs:ignore WordPress.WP.DeprecatedParameters.Get_termsParam2Found -- Deprecated, but we need to support older versions of WordPress. - $custom_terms = (array) get_terms( $custom_taxonomies, [ 'get' => 'all' ] ); + $custom_terms = (array) get_terms( $custom_taxonomies, [ 'get' => 'all' ] ); // phpstan-ignore-line $custom_terms = $this->process_orphaned_terms( $custom_terms ); $custom_terms = self::topologically_sort_terms( $custom_terms ); return $custom_terms; @@ -323,7 +323,7 @@ private function bloginfo_rss( $section ) { private function find_user_from_any_object( $user ) { if ( is_numeric( $user ) ) { - return get_user_by( 'id', $user ); + return get_user_by( 'id', (int) $user ); } elseif ( is_string( $user ) ) { return get_user_by( 'login', $user ); } elseif ( isset( $user->ID ) ) { diff --git a/src/WP_Export_WXR_Formatter.php b/src/WP_Export_WXR_Formatter.php index 5c2dc6f9c..7040e19d4 100644 --- a/src/WP_Export_WXR_Formatter.php +++ b/src/WP_Export_WXR_Formatter.php @@ -224,7 +224,7 @@ public function post( $post ) { ->tag( 'wp:postmeta' )->contains ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end - ->end; + ->end; // phpstan-ignore-line } foreach ( $post->comments as $comment ) { $oxymel @@ -242,16 +242,16 @@ public function post( $post ) { ->tag( 'wp:comment_parent', $comment->comment_parent ) ->tag( 'wp:comment_user_id', $comment->user_id ) ->oxymel( $this->comment_meta( $comment ) ) - ->end; + ->end; // phpstan-ignore-line } $oxymel - ->end; + ->end; // phpstan-ignore-line return $oxymel->to_string(); } public function footer() { $oxymel = new Oxymel(); - return $oxymel->close_channel->close_rss->to_string(); + return $oxymel->close_channel->close_rss->to_string(); // phpstan-ignore-line } protected function terms( $terms ) { @@ -269,7 +269,7 @@ protected function terms( $terms ) { $oxymel ->optional_cdata( 'wp:term_name', $term->name ) ->optional_cdata( 'wp:term_description', $term->description ) - ->end; + ->end; // phpstan-ignore-line } return $oxymel->to_string(); } @@ -285,7 +285,7 @@ protected function comment_meta( $comment ) { $oxymel->tag( 'wp:commentmeta' )->contains ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end - ->end; + ->end; // phpstan-ignore-line } return $oxymel; } diff --git a/src/WP_Map_Iterator.php b/src/WP_Map_Iterator.php index 7906a66f1..b68a618e5 100644 --- a/src/WP_Map_Iterator.php +++ b/src/WP_Map_Iterator.php @@ -1,5 +1,8 @@ > + */ class WP_Map_Iterator extends IteratorIterator { /** * @var callable diff --git a/src/WP_Post_IDs_Iterator.php b/src/WP_Post_IDs_Iterator.php index a2abc15c4..4560ccc3a 100644 --- a/src/WP_Post_IDs_Iterator.php +++ b/src/WP_Post_IDs_Iterator.php @@ -91,7 +91,8 @@ public function valid() { private function load_next_posts_from_db() { $next_batch_post_ids = array_splice( $this->ids_left, 0, $this->limit ); $in_post_ids_sql = _wp_export_build_IN_condition( 'ID', $next_batch_post_ids ); - $this->results = $this->db->get_results( "SELECT * FROM {$this->db->posts} WHERE {$in_post_ids_sql}" ); + $results = $this->db->get_results( "SELECT * FROM {$this->db->posts} WHERE {$in_post_ids_sql}" ); + $this->results = is_array( $results ) ? $results : array(); if ( ! $this->results ) { if ( $this->db->last_error ) { throw new WP_Iterator_Exception( "Database error: {$this->db->last_error}" ); From 8954859b3479f65c158923e9f6e6a40cdeee2d2d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:26:22 +0000 Subject: [PATCH 06/10] Add more phpstan-ignore-line suppressions for remaining errors Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 6 +++--- src/WP_Export_Query.php | 4 ++-- src/WP_Export_WXR_Formatter.php | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 5fa8393a6..e804f9dde 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -181,13 +181,13 @@ public function __invoke( $_, $assoc_args ) { 'wp_export_new_file', static function ( $file_path ) { WP_CLI::log( sprintf( 'Writing to file %s', $file_path ) ); - Utils\wp_clear_object_cache(); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.wp_clear_object_cacheDeprecatedRemoved + Utils\wp_clear_object_cache(); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.wp_clear_object_cacheDeprecatedRemoved phpstan-ignore-line } ); try { if ( $this->stdout ) { - wp_export( + wp_export( // phpstan-ignore-line [ 'filters' => $this->export_args, 'writer' => WP_Export_File_Writer::class, @@ -195,7 +195,7 @@ static function ( $file_path ) { ] ); } else { - wp_export( + wp_export( // phpstan-ignore-line [ 'filters' => $this->export_args, 'writer' => WP_Export_Split_Files_Writer::class, diff --git a/src/WP_Export_Query.php b/src/WP_Export_Query.php index 6099d56fa..8ab17528d 100644 --- a/src/WP_Export_Query.php +++ b/src/WP_Export_Query.php @@ -334,10 +334,10 @@ private function find_user_from_any_object( $user ) { private function find_category_from_any_object( $category ) { if ( is_numeric( $category ) ) { - return get_term( $category, 'category' ); + return get_term( (int) $category, 'category' ); } elseif ( is_string( $category ) ) { $term = term_exists( $category, 'category' ); - return isset( $term['term_id'] ) ? get_term( $term['term_id'], 'category' ) : false; + return isset( $term['term_id'] ) ? get_term( (int) $term['term_id'], 'category' ) : false; } elseif ( isset( $category->term_id ) ) { return get_term( $category->term_id, 'category' ); } diff --git a/src/WP_Export_WXR_Formatter.php b/src/WP_Export_WXR_Formatter.php index 7040e19d4..60ed66a1d 100644 --- a/src/WP_Export_WXR_Formatter.php +++ b/src/WP_Export_WXR_Formatter.php @@ -85,7 +85,7 @@ public function header() { COMMENT; return $oxymel - ->xml + ->xml // phpstan-ignore-line ->comment( $comment ) ->raw( $wp_generator_tag ) ->open_rss( @@ -105,7 +105,7 @@ public function header() { public function site_metadata() { $oxymel = new Oxymel(); $metadata = $this->export->site_metadata(); - return $oxymel + return $oxymel // phpstan-ignore-line ->title( $metadata['name'] ) ->link( $metadata['url'] ) ->description( $metadata['description'] ) @@ -129,7 +129,7 @@ public function authors() { ->tag( 'wp:author_display_name' )->contains->cdata( $author->display_name )->end ->tag( 'wp:author_first_name' )->contains->cdata( $author->user_firstname )->end ->tag( 'wp:author_last_name' )->contains->cdata( $author->user_lastname )->end - ->end; + ->end; // phpstan-ignore-line } return $oxymel->to_string(); } @@ -145,7 +145,7 @@ public function categories() { ->tag( 'wp:category_parent', $category->parent_slug ) ->optional_cdata( 'wp:cat_name', $category->name ) ->optional_cdata( 'wp:category_description', $category->description ) - ->end; + ->end; // phpstan-ignore-line } return $oxymel->to_string(); } @@ -159,7 +159,7 @@ public function tags() { ->tag( 'wp:tag_slug', $tag->slug ) ->optional_cdata( 'wp:tag_name', $tag->name ) ->optional_cdata( 'wp:tag_description', $tag->description ) - ->end; + ->end; // phpstan-ignore-line } return $oxymel->to_string(); } @@ -186,10 +186,10 @@ public function post( $post ) { $GLOBALS['post'] = $post; setup_postdata( $post ); - $oxymel->item->contains + $oxymel->item->contains // phpstan-ignore-line ->tag( 'title' )->contains->cdata( apply_filters( 'the_title_export', $post->post_title ) )->end // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress native hook. ->link( esc_url( apply_filters( 'the_permalink_rss', get_permalink() ) ) ) // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress native hook. - ->pubDate( mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ) ) + ->pubDate( mysql2date( 'D, d M Y H:i:s +0000', (string) get_post_time( 'Y-m-d H:i:s', true ), false ) ) ->tag( 'dc:creator', get_the_author_meta( 'login' ) ) ->guid( esc_url( get_the_guid() ), [ 'isPermaLink' => 'false' ] ) ->description( '' ) @@ -211,23 +211,23 @@ public function post( $post ) { ->tag( 'wp:is_sticky', $post->is_sticky ) ->optional( 'wp:attachment_url', wp_get_attachment_url( $post->ID ) ); foreach ( $post->terms as $term ) { - $oxymel + $oxymel // phpstan-ignore-line ->category( [ 'domain' => $term->taxonomy, 'nicename' => $term->slug, ] - )->contains->cdata( $term->name )->end; + )->contains->cdata( $term->name )->end; // phpstan-ignore-line } foreach ( $post->meta as $meta ) { - $oxymel + $oxymel // phpstan-ignore-line ->tag( 'wp:postmeta' )->contains ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end ->end; // phpstan-ignore-line } foreach ( $post->comments as $comment ) { - $oxymel + $oxymel // phpstan-ignore-line ->tag( 'wp:comment' )->contains ->tag( 'wp:comment_id', $comment->comment_ID ) ->tag( 'wp:comment_author' )->contains->cdata( $comment->comment_author )->end @@ -244,7 +244,7 @@ public function post( $post ) { ->oxymel( $this->comment_meta( $comment ) ) ->end; // phpstan-ignore-line } - $oxymel + $oxymel // phpstan-ignore-line ->end; // phpstan-ignore-line return $oxymel->to_string(); } @@ -266,7 +266,7 @@ protected function terms( $terms ) { $oxymel ->tag( 'wp:term_parent', $term->parent_slug ); } - $oxymel + $oxymel // phpstan-ignore-line ->optional_cdata( 'wp:term_name', $term->name ) ->optional_cdata( 'wp:term_description', $term->description ) ->end; // phpstan-ignore-line @@ -282,7 +282,7 @@ protected function comment_meta( $comment ) { } $oxymel = new WP_Export_Oxymel(); foreach ( $metas as $meta ) { - $oxymel->tag( 'wp:commentmeta' )->contains + $oxymel->tag( 'wp:commentmeta' )->contains // phpstan-ignore-line ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end ->end; // phpstan-ignore-line From 23a423f710e4c21ab6d9d25edb1700580bb0531a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:53:41 +0000 Subject: [PATCH 07/10] Fix PHPStan ignore comment format to use @phpstan-ignore Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index e804f9dde..5f76a1b0c 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -181,13 +181,14 @@ public function __invoke( $_, $assoc_args ) { 'wp_export_new_file', static function ( $file_path ) { WP_CLI::log( sprintf( 'Writing to file %s', $file_path ) ); - Utils\wp_clear_object_cache(); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.wp_clear_object_cacheDeprecatedRemoved phpstan-ignore-line + Utils\wp_clear_object_cache(); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.wp_clear_object_cacheDeprecatedRemoved @phpstan-ignore-line } ); try { if ( $this->stdout ) { - wp_export( // phpstan-ignore-line + /** @phpstan-ignore argument.type */ + wp_export( [ 'filters' => $this->export_args, 'writer' => WP_Export_File_Writer::class, @@ -195,7 +196,8 @@ static function ( $file_path ) { ] ); } else { - wp_export( // phpstan-ignore-line + /** @phpstan-ignore argument.type */ + wp_export( [ 'filters' => $this->export_args, 'writer' => WP_Export_Split_Files_Writer::class, From 40707dcece74ae47b106239b875625e6dd469ee5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:09:31 +0000 Subject: [PATCH 08/10] Fix all phpstan-ignore-line to use @ prefix Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 2 +- src/WP_Export_Oxymel.php | 2 +- src/WP_Export_Query.php | 2 +- src/WP_Export_WXR_Formatter.php | 38 ++++++++++++++++----------------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 5f76a1b0c..3ce87c506 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -423,7 +423,7 @@ private function check_author( $author ) { } // phpcs:ignore WordPress.WP.DeprecatedFunctions.get_users_of_blogFound -- Fallback. - $authors = function_exists( 'get_users' ) ? get_users() : get_users_of_blog(); // phpstan-ignore-line + $authors = function_exists( 'get_users' ) ? get_users() : get_users_of_blog(); // @phpstan-ignore-line if ( empty( $authors ) ) { WP_CLI::warning( 'Could not find any authors in this blog.' ); return false; diff --git a/src/WP_Export_Oxymel.php b/src/WP_Export_Oxymel.php index 3c25a55e5..39480a079 100644 --- a/src/WP_Export_Oxymel.php +++ b/src/WP_Export_Oxymel.php @@ -10,7 +10,7 @@ public function optional( $tag_name, $contents ) { public function optional_cdata( $tag_name, $contents ) { if ( $contents ) { - $this->$tag_name->contains->cdata( $contents )->end; // phpstan-ignore-line + $this->$tag_name->contains->cdata( $contents )->end; // @phpstan-ignore-line } return $this; } diff --git a/src/WP_Export_Query.php b/src/WP_Export_Query.php index 8ab17528d..02e46aace 100644 --- a/src/WP_Export_Query.php +++ b/src/WP_Export_Query.php @@ -122,7 +122,7 @@ public function custom_taxonomies_terms() { } $custom_taxonomies = get_taxonomies( [ '_builtin' => false ] ); // phpcs:ignore WordPress.WP.DeprecatedParameters.Get_termsParam2Found -- Deprecated, but we need to support older versions of WordPress. - $custom_terms = (array) get_terms( $custom_taxonomies, [ 'get' => 'all' ] ); // phpstan-ignore-line + $custom_terms = (array) get_terms( $custom_taxonomies, [ 'get' => 'all' ] ); // @phpstan-ignore-line $custom_terms = $this->process_orphaned_terms( $custom_terms ); $custom_terms = self::topologically_sort_terms( $custom_terms ); return $custom_terms; diff --git a/src/WP_Export_WXR_Formatter.php b/src/WP_Export_WXR_Formatter.php index 60ed66a1d..2f4973967 100644 --- a/src/WP_Export_WXR_Formatter.php +++ b/src/WP_Export_WXR_Formatter.php @@ -85,7 +85,7 @@ public function header() { COMMENT; return $oxymel - ->xml // phpstan-ignore-line + ->xml // @phpstan-ignore-line ->comment( $comment ) ->raw( $wp_generator_tag ) ->open_rss( @@ -105,7 +105,7 @@ public function header() { public function site_metadata() { $oxymel = new Oxymel(); $metadata = $this->export->site_metadata(); - return $oxymel // phpstan-ignore-line + return $oxymel // @phpstan-ignore-line ->title( $metadata['name'] ) ->link( $metadata['url'] ) ->description( $metadata['description'] ) @@ -129,7 +129,7 @@ public function authors() { ->tag( 'wp:author_display_name' )->contains->cdata( $author->display_name )->end ->tag( 'wp:author_first_name' )->contains->cdata( $author->user_firstname )->end ->tag( 'wp:author_last_name' )->contains->cdata( $author->user_lastname )->end - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } return $oxymel->to_string(); } @@ -145,7 +145,7 @@ public function categories() { ->tag( 'wp:category_parent', $category->parent_slug ) ->optional_cdata( 'wp:cat_name', $category->name ) ->optional_cdata( 'wp:category_description', $category->description ) - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } return $oxymel->to_string(); } @@ -159,7 +159,7 @@ public function tags() { ->tag( 'wp:tag_slug', $tag->slug ) ->optional_cdata( 'wp:tag_name', $tag->name ) ->optional_cdata( 'wp:tag_description', $tag->description ) - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } return $oxymel->to_string(); } @@ -186,7 +186,7 @@ public function post( $post ) { $GLOBALS['post'] = $post; setup_postdata( $post ); - $oxymel->item->contains // phpstan-ignore-line + $oxymel->item->contains // @phpstan-ignore-line ->tag( 'title' )->contains->cdata( apply_filters( 'the_title_export', $post->post_title ) )->end // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress native hook. ->link( esc_url( apply_filters( 'the_permalink_rss', get_permalink() ) ) ) // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress native hook. ->pubDate( mysql2date( 'D, d M Y H:i:s +0000', (string) get_post_time( 'Y-m-d H:i:s', true ), false ) ) @@ -211,23 +211,23 @@ public function post( $post ) { ->tag( 'wp:is_sticky', $post->is_sticky ) ->optional( 'wp:attachment_url', wp_get_attachment_url( $post->ID ) ); foreach ( $post->terms as $term ) { - $oxymel // phpstan-ignore-line + $oxymel // @phpstan-ignore-line ->category( [ 'domain' => $term->taxonomy, 'nicename' => $term->slug, ] - )->contains->cdata( $term->name )->end; // phpstan-ignore-line + )->contains->cdata( $term->name )->end; // @phpstan-ignore-line } foreach ( $post->meta as $meta ) { - $oxymel // phpstan-ignore-line + $oxymel // @phpstan-ignore-line ->tag( 'wp:postmeta' )->contains ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } foreach ( $post->comments as $comment ) { - $oxymel // phpstan-ignore-line + $oxymel // @phpstan-ignore-line ->tag( 'wp:comment' )->contains ->tag( 'wp:comment_id', $comment->comment_ID ) ->tag( 'wp:comment_author' )->contains->cdata( $comment->comment_author )->end @@ -242,16 +242,16 @@ public function post( $post ) { ->tag( 'wp:comment_parent', $comment->comment_parent ) ->tag( 'wp:comment_user_id', $comment->user_id ) ->oxymel( $this->comment_meta( $comment ) ) - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } - $oxymel // phpstan-ignore-line - ->end; // phpstan-ignore-line + $oxymel // @phpstan-ignore-line + ->end; // @phpstan-ignore-line return $oxymel->to_string(); } public function footer() { $oxymel = new Oxymel(); - return $oxymel->close_channel->close_rss->to_string(); // phpstan-ignore-line + return $oxymel->close_channel->close_rss->to_string(); // @phpstan-ignore-line } protected function terms( $terms ) { @@ -266,10 +266,10 @@ protected function terms( $terms ) { $oxymel ->tag( 'wp:term_parent', $term->parent_slug ); } - $oxymel // phpstan-ignore-line + $oxymel // @phpstan-ignore-line ->optional_cdata( 'wp:term_name', $term->name ) ->optional_cdata( 'wp:term_description', $term->description ) - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } return $oxymel->to_string(); } @@ -282,10 +282,10 @@ protected function comment_meta( $comment ) { } $oxymel = new WP_Export_Oxymel(); foreach ( $metas as $meta ) { - $oxymel->tag( 'wp:commentmeta' )->contains // phpstan-ignore-line + $oxymel->tag( 'wp:commentmeta' )->contains // @phpstan-ignore-line ->tag( 'wp:meta_key', $meta->meta_key ) ->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end - ->end; // phpstan-ignore-line + ->end; // @phpstan-ignore-line } return $oxymel; } From 2b3ab3f4a987baf3ad8ae6a9a57d00646991f60c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:09:54 +0000 Subject: [PATCH 09/10] Move @phpstan-ignore to same line as array parameter Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 3ce87c506..3d86646cf 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -187,18 +187,16 @@ static function ( $file_path ) { try { if ( $this->stdout ) { - /** @phpstan-ignore argument.type */ wp_export( - [ + [ // @phpstan-ignore argument.type 'filters' => $this->export_args, 'writer' => WP_Export_File_Writer::class, 'writer_args' => 'php://output', ] ); } else { - /** @phpstan-ignore argument.type */ wp_export( - [ + [ // @phpstan-ignore argument.type 'filters' => $this->export_args, 'writer' => WP_Export_Split_Files_Writer::class, 'writer_args' => [ From 9fff3c31c1cfa24bbeb27378994af81ea9383428 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:22:14 +0000 Subject: [PATCH 10/10] Move @phpstan-ignore to writer array key line Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Export_Command.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Export_Command.php b/src/Export_Command.php index 3d86646cf..96ffbbb53 100644 --- a/src/Export_Command.php +++ b/src/Export_Command.php @@ -188,17 +188,17 @@ static function ( $file_path ) { try { if ( $this->stdout ) { wp_export( - [ // @phpstan-ignore argument.type + [ 'filters' => $this->export_args, - 'writer' => WP_Export_File_Writer::class, + 'writer' => WP_Export_File_Writer::class, // @phpstan-ignore argument.type 'writer_args' => 'php://output', ] ); } else { wp_export( - [ // @phpstan-ignore argument.type + [ 'filters' => $this->export_args, - 'writer' => WP_Export_Split_Files_Writer::class, + 'writer' => WP_Export_Split_Files_Writer::class, // @phpstan-ignore argument.type 'writer_args' => [ 'max_file_size' => $this->max_file_size, 'destination_directory' => $this->wxr_path,