diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-admin/includes/export.php --- a/wp/wp-admin/includes/export.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-admin/includes/export.php Fri Sep 05 18:40:08 2025 +0200 @@ -31,27 +31,27 @@ * @param array $args { * Optional. Arguments for generating the WXR export file for download. Default empty array. * - * @type string $content Type of content to export. If set, only the post content of this post type - * will be exported. Accepts 'all', 'post', 'page', 'attachment', or a defined - * custom post. If an invalid custom post type is supplied, every post type for - * which `can_export` is enabled will be exported instead. If a valid custom post - * type is supplied but `can_export` is disabled, then 'posts' will be exported - * instead. When 'all' is supplied, only post types with `can_export` enabled will - * be exported. Default 'all'. - * @type string $author Author to export content for. Only used when `$content` is 'post', 'page', or - * 'attachment'. Accepts false (all) or a specific author ID. Default false (all). - * @type string $category Category (slug) to export content for. Used only when `$content` is 'post'. If - * set, only post content assigned to `$category` will be exported. Accepts false - * or a specific category slug. Default is false (all categories). - * @type string $start_date Start date to export content from. Expected date format is 'Y-m-d'. Used only - * when `$content` is 'post', 'page' or 'attachment'. Default false (since the - * beginning of time). - * @type string $end_date End date to export content to. Expected date format is 'Y-m-d'. Used only when - * `$content` is 'post', 'page' or 'attachment'. Default false (latest publish date). - * @type string $status Post status to export posts for. Used only when `$content` is 'post' or 'page'. - * Accepts false (all statuses except 'auto-draft'), or a specific status, i.e. - * 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', or - * 'trash'. Default false (all statuses except 'auto-draft'). + * @type string $content Type of content to export. If set, only the post content of this post type + * will be exported. Accepts 'all', 'post', 'page', 'attachment', or a defined + * custom post. If an invalid custom post type is supplied, every post type for + * which `can_export` is enabled will be exported instead. If a valid custom post + * type is supplied but `can_export` is disabled, then 'posts' will be exported + * instead. When 'all' is supplied, only post types with `can_export` enabled will + * be exported. Default 'all'. + * @type string $author Author to export content for. Only used when `$content` is 'post', 'page', or + * 'attachment'. Accepts false (all) or a specific author ID. Default false (all). + * @type string $category Category (slug) to export content for. Used only when `$content` is 'post'. If + * set, only post content assigned to `$category` will be exported. Accepts false + * or a specific category slug. Default is false (all categories). + * @type string $start_date Start date to export content from. Expected date format is 'Y-m-d'. Used only + * when `$content` is 'post', 'page' or 'attachment'. Default false (since the + * beginning of time). + * @type string $end_date End date to export content to. Expected date format is 'Y-m-d'. Used only when + * `$content` is 'post', 'page' or 'attachment'. Default false (latest publish date). + * @type string $status Post status to export posts for. Used only when `$content` is 'post' or 'page'. + * Accepts false (all statuses except 'auto-draft'), or a specific status, i.e. + * 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', or + * 'trash'. Default false (all statuses except 'auto-draft'). * } */ function export_wp( $args = array() ) { @@ -144,6 +144,52 @@ // Grab a snapshot of post IDs, just in case it changes during the export. $post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} $join WHERE $where" ); + // Get IDs for the attachments of each post, unless all content is already being exported. + if ( ! in_array( $args['content'], array( 'all', 'attachment' ), true ) ) { + // Array to hold all additional IDs (attachments and thumbnails). + $additional_ids = array(); + + // Create a copy of the post IDs array to avoid modifying the original array. + $processing_ids = $post_ids; + + while ( $next_posts = array_splice( $processing_ids, 0, 20 ) ) { + $posts_in = array_map( 'absint', $next_posts ); + $placeholders = array_fill( 0, count( $posts_in ), '%d' ); + + // Create a string for the placeholders. + $in_placeholder = implode( ',', $placeholders ); + + // Prepare the SQL statement for attachment ids. + $attachment_ids = $wpdb->get_col( + $wpdb->prepare( + " + SELECT ID + FROM $wpdb->posts + WHERE post_parent IN ($in_placeholder) AND post_type = 'attachment' + ", + $posts_in + ) + ); + + $thumbnails_ids = $wpdb->get_col( + $wpdb->prepare( + " + SELECT meta_value + FROM $wpdb->postmeta + WHERE $wpdb->postmeta.post_id IN ($in_placeholder) + AND $wpdb->postmeta.meta_key = '_thumbnail_id' + ", + $posts_in + ) + ); + + $additional_ids = array_merge( $additional_ids, $attachment_ids, $thumbnails_ids ); + } + + // Merge the additional IDs back with the original post IDs after processing all posts + $post_ids = array_unique( array_merge( $post_ids, $additional_ids ) ); + } + /* * Get the requested terms ready, empty unless posts filtered by category * or all content. @@ -189,7 +235,7 @@ } /** - * Wrap given string in XML CDATA tag. + * Wraps given string in XML CDATA tag. * * @since 2.1.0 * @@ -207,7 +253,7 @@ } /** - * Return the URL of the site + * Returns the URL of the site. * * @since 2.5.0 * @@ -218,17 +264,17 @@ // Multisite: the base URL. return network_home_url(); } else { - // WordPress (single site): the blog URL. + // WordPress (single site): the site URL. return get_bloginfo_rss( 'url' ); } } /** - * Output a cat_name XML tag from a given category object + * Outputs a cat_name XML tag from a given category object. * * @since 2.1.0 * - * @param WP_Term $category Category Object + * @param WP_Term $category Category Object. */ function wxr_cat_name( $category ) { if ( empty( $category->name ) ) { @@ -239,11 +285,11 @@ } /** - * Output a category_description XML tag from a given category object + * Outputs a category_description XML tag from a given category object. * * @since 2.1.0 * - * @param WP_Term $category Category Object + * @param WP_Term $category Category Object. */ function wxr_category_description( $category ) { if ( empty( $category->description ) ) { @@ -254,11 +300,11 @@ } /** - * Output a tag_name XML tag from a given tag object + * Outputs a tag_name XML tag from a given tag object. * * @since 2.3.0 * - * @param WP_Term $tag Tag Object + * @param WP_Term $tag Tag Object. */ function wxr_tag_name( $tag ) { if ( empty( $tag->name ) ) { @@ -269,11 +315,11 @@ } /** - * Output a tag_description XML tag from a given tag object + * Outputs a tag_description XML tag from a given tag object. * * @since 2.3.0 * - * @param WP_Term $tag Tag Object + * @param WP_Term $tag Tag Object. */ function wxr_tag_description( $tag ) { if ( empty( $tag->description ) ) { @@ -284,11 +330,11 @@ } /** - * Output a term_name XML tag from a given term object + * Outputs a term_name XML tag from a given term object. * * @since 2.9.0 * - * @param WP_Term $term Term Object + * @param WP_Term $term Term Object. */ function wxr_term_name( $term ) { if ( empty( $term->name ) ) { @@ -299,11 +345,11 @@ } /** - * Output a term_description XML tag from a given term object + * Outputs a term_description XML tag from a given term object. * * @since 2.9.0 * - * @param WP_Term $term Term Object + * @param WP_Term $term Term Object. */ function wxr_term_description( $term ) { if ( empty( $term->description ) ) { @@ -314,10 +360,12 @@ } /** - * Output term meta XML tags for a given term object. + * Outputs term meta XML tags for a given term object. * * @since 4.6.0 * + * @global wpdb $wpdb WordPress database abstraction object. + * * @param WP_Term $term Term object. */ function wxr_term_meta( $term ) { @@ -345,7 +393,7 @@ } /** - * Output list of authors with posts + * Outputs list of authors with posts. * * @since 3.1.0 * @@ -353,7 +401,7 @@ * * @param int[] $post_ids Optional. Array of post IDs to filter the query by. */ - function wxr_authors_list( array $post_ids = null ) { + function wxr_authors_list( ?array $post_ids = null ) { global $wpdb; if ( ! empty( $post_ids ) ) { @@ -384,7 +432,7 @@ } /** - * Output all navigation menu terms + * Outputs all navigation menu terms. * * @since 3.1.0 */ @@ -405,7 +453,7 @@ } /** - * Output list of taxonomy terms, in XML tag format, associated with a post + * Outputs list of taxonomy terms, in XML tag format, associated with a post. * * @since 2.3.0 */ @@ -424,8 +472,12 @@ } /** - * @param bool $return_me - * @param string $meta_key + * Determines whether to selectively skip post meta used for WXR exports. + * + * @since 3.3.0 + * + * @param bool $return_me Whether to skip the current post meta. Default false. + * @param string $meta_key Meta key. * @return bool */ function wxr_filter_postmeta( $return_me, $meta_key ) { @@ -515,7 +567,8 @@ comment_ID; ?> comment_author ); ?> comment_author_email ); ?> - comment_author_url ); ?> + comment_author_url ); ?> comment_author_IP ); ?> comment_date ); ?> comment_date_gmt ); ?>