info['ID'] = 'WPEXP'; $this->info['name'] = __( 'XML export', 'backwpup' ); $this->info['description'] = __( 'WordPress XML export', 'backwpup' ); $this->info['URI'] = __( 'https://backwpup.com', 'backwpup' ); $this->info['author'] = 'WP Media'; $this->info['authorURI'] = 'https://wp-media.me'; $this->info['version'] = BackWPup::get_plugin_data( 'Version' ); } /** * Whether the job type creates a file. * * @return bool */ public function creates_file() { return true; } /** * Returns default options for the job type. * * @return array */ public function option_defaults() { return [ 'wpexportcontent' => 'all', 'wpexportfilecompression' => '', 'wpexportfile' => sanitize_text_field( get_bloginfo( 'name' ) ) . '.wordpress.%Y-%m-%d', ]; } /** * Renders the job type edit tab. * * @param int|array $jobid Job ID or list of job IDs. */ public function edit_tab( $jobid ) { ?>



false, 'can_export' => true, ], 'objects' ) as $post_type ) { ?>
.xml
' . esc_html__( 'none', 'backwpup' ) . '
'; if ( function_exists( 'gzopen' ) ) { echo '
'; } else { echo '
'; } ?>
steps_data[ $job_object->step_working ]['SAVE_STEP_TRY'] !== $job_object->steps_data[ $job_object->step_working ]['STEP_TRY'] ) { $job_object->log( sprintf( /* translators: %d: attempt number. */ __( '%d. Trying to create a WordPress export to XML file …', 'backwpup' ), $job_object->steps_data[ $job_object->step_working ]['STEP_TRY'] ) ); $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] = BackWPup::get_plugin_data( 'TEMP' ) . $job_object->generate_filename( $job_object->job['wpexportfile'], 'xml', true ); $job_object->steps_data[ $job_object->step_working ]['substep'] = 'header'; $job_object->steps_data[ $job_object->step_working ]['post_ids'] = []; $job_object->substeps_todo = 10; $job_object->substeps_done = 0; } add_filter( 'backwpup_wxr_export_skip_postmeta', [ $this, 'wxr_filter_postmeta' ], 10, 2 ); if ( 'header' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { $post_status = 'auto-draft'; $post_ids = []; $cache_group = 'backwpup_wpexport'; if ( 'all' !== $job_object->job['wpexportcontent'] && post_type_exists( $job_object->job['wpexportcontent'] ) ) { $ptype = get_post_type_object( $job_object->job['wpexportcontent'] ); if ( ! $ptype->can_export ) { /* translators: %s: post type slug. */ $job_object->log( sprintf( __( 'WP Export: Post type ā€œ%sā€ does not allow export.', 'backwpup' ), $job_object->job['wpexportcontent'] ), E_USER_ERROR ); return false; } $post_ids_key = 'post_ids_' . $job_object->job['wpexportcontent'] . '_' . $post_status; $post_ids = wp_cache_get( $post_ids_key, $cache_group ); if ( false === $post_ids ) { $post_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw export selection. $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_type = %s AND {$wpdb->posts}.post_status != %s", $job_object->job['wpexportcontent'], $post_status ) ); wp_cache_set( $post_ids_key, $post_ids, $cache_group, MINUTE_IN_SECONDS ); } } else { $post_types = array_values( get_post_types( [ 'can_export' => true ] ) ); $placeholders = implode( ',', array_fill( 0, count( $post_types ), '%s' ) ); $post_ids_key = 'post_ids_' . md5( implode( ',', $post_types ) . '|' . $post_status ); $post_ids = wp_cache_get( $post_ids_key, $cache_group ); if ( false === $post_ids ) { $post_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw export selection. $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Dynamic IN clause placeholders. "SELECT ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_type IN ({$placeholders}) AND {$wpdb->posts}.post_status != %s", array_merge( $post_types, [ $post_status ] ) ) ); wp_cache_set( $post_ids_key, $post_ids, $cache_group, MINUTE_IN_SECONDS ); } $job_object->job['wpexportcontent'] = 'all'; } // Grab a snapshot of post IDs, just in case it changes during the export. $job_object->steps_data[ $job_object->step_working ]['post_ids'] = $post_ids; $job_object->substeps_todo = $job_object->substeps_todo + count( $job_object->steps_data[ $job_object->step_working ]['post_ids'] ); $header = '\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n"; $header .= "\n\n"; $header .= '\n"; $header .= "\n"; $header .= "\n"; $header .= "\t" . get_bloginfo_rss( 'name' ) . "\n"; $header .= "\t" . get_bloginfo_rss( 'url' ) . "\n"; $header .= "\t" . get_bloginfo_rss( 'description' ) . "\n"; $header .= "\t" . gmdate( 'D, d M Y H:i:s +0000', time() ) . "\n"; $header .= "\t" . get_bloginfo_rss( 'language' ) . "\n"; $header .= "\t" . $wxr_version . "\n"; $header .= "\t" . $this->wxr_site_url() . "\n"; $header .= "\t" . get_bloginfo_rss( 'url' ) . "\n"; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $header, FILE_APPEND ); if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } unset( $header ); $job_object->steps_data[ $job_object->step_working ]['substep'] = 'authors'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'authors' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $this->wxr_authors_list(), FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'cats'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'cats' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( 'all' === $job_object->job['wpexportcontent'] ) { $cats = []; $categories = (array) get_categories( [ 'get' => 'all' ] ); // Put categories in order with no child going before its parent. while ( ! empty( $categories ) ) { $cat = array_shift( $categories ); if ( 0 === (int) $cat->parent || isset( $cats[ $cat->parent ] ) ) { $cats[ $cat->term_id ] = $cat; } else { $categories[] = $cat; } } $cats_xml = ''; foreach ( $cats as $c ) { $parent_slug = $c->parent ? $cats[ $c->parent ]->slug : ''; $cats_xml .= "\t" . $c->term_id . '' . $c->slug . '' . $parent_slug . '' . $this->wxr_cat_name( $c ) . $this->wxr_category_description( $c ) . "\n"; } $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $cats_xml, FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } unset( $cats_xml ); } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'tags'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'tags' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( 'all' === $job_object->job['wpexportcontent'] ) { $tags = (array) get_tags( [ 'get' => 'all' ] ); $tags_xml = ''; foreach ( $tags as $t ) { $tags_xml .= "\t" . $t->term_id . '' . $t->slug . '' . $this->wxr_tag_name( $t ) . $this->wxr_tag_description( $t ) . "\n"; } $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $tags_xml, FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } unset( $tags_xml ); } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'terms'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'terms' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( 'all' === $job_object->job['wpexportcontent'] ) { $terms = []; $custom_taxonomies = get_taxonomies( [ '_builtin' => false ] ); $custom_terms = (array) get_terms( [ 'taxonomy' => $custom_taxonomies, 'hide_empty' => false, ] ); // Put terms in order with no child going before its parent. while ( ! empty( $custom_terms ) ) { $t = array_shift( $custom_terms ); if ( 0 === (int) $t->parent || isset( $terms[ $t->parent ] ) ) { $terms[ $t->term_id ] = $t; } else { $custom_terms[] = $t; } } $terms_xml = ''; foreach ( $terms as $t ) { $parent_slug = $t->parent ? $terms[ $t->parent ]->slug : ''; $terms_xml .= "\t" . $t->term_id . '' . $t->taxonomy . '' . $t->slug . '' . $parent_slug . '' . $this->wxr_term_name( $t ) . $this->wxr_term_description( $t ) . "\n"; } $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $terms_xml, FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } unset( $terms_xml ); } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'menus'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'menus' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { $menu_xml = ''; if ( 'all' === $job_object->job['wpexportcontent'] ) { $menu_xml .= $this->wxr_nav_menu_terms(); } $menu_xml .= "\thttp://wordpress.org/?v=" . get_bloginfo_rss( 'version' ) . "\n"; $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $menu_xml, FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } unset( $menu_xml ); $job_object->steps_data[ $job_object->step_working ]['substep'] = 'posts'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'posts' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( ! empty( $job_object->steps_data[ $job_object->step_working ]['post_ids'] ) ) { $cache_group = 'backwpup_wpexport'; $wp_query->in_the_loop = true; // Fake being in the loop. // Fetch 20 posts at a time rather than loading the entire table into memory. while ( ! empty( $job_object->steps_data[ $job_object->step_working ]['post_ids'] ) ) { $next_posts = array_splice( $job_object->steps_data[ $job_object->step_working ]['post_ids'], 0, 20 ); $next_posts = array_map( 'intval', $next_posts ); $placeholders = implode( ',', array_fill( 0, count( $next_posts ), '%d' ) ); $posts_key = 'post_chunk_' . md5( implode( ',', $next_posts ) ); $posts = wp_cache_get( $posts_key, $cache_group ); if ( false === $posts ) { $posts = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw export selection. $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- Dynamic IN clause placeholders. "SELECT * FROM {$wpdb->posts} WHERE ID IN ({$placeholders})", $next_posts ) ); wp_cache_set( $posts_key, $posts, $cache_group, MINUTE_IN_SECONDS ); } $wxr_post = ''; // Begin loop. /* @var WP_Post $post_item */ foreach ( $posts as $post_item ) { setup_postdata( $post_item ); $is_sticky = is_sticky( $post_item->ID ) ? 1 : 0; $wxr_post .= "\t\n"; $wxr_post .= "\t\t" . wpm_apply_filters_typed( 'string', 'the_title_rss', $post_item->post_title ) . "\n"; $wxr_post .= "\t\t" . esc_url( wpm_apply_filters_typed( 'string', 'the_permalink_rss', get_permalink( $post_item ) ) ) . "\n"; $wxr_post .= "\t\t" . mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true, $post_item ), false ) . "\n"; $wxr_post .= "\t\t" . $this->wxr_cdata( get_the_author_meta( 'login', $post_item->post_author ) ) . "\n"; $wxr_post .= "\t\t" . esc_url( get_the_guid( $post_item->ID ) ) . "\n"; $wxr_post .= "\t\t\n"; $wxr_post .= "\t\t" . $this->wxr_cdata( wpm_apply_filters_typed( 'string', 'the_content_export', $post_item->post_content ) ) . "\n"; $wxr_post .= "\t\t" . $this->wxr_cdata( wpm_apply_filters_typed( 'string', 'the_excerpt_export', $post_item->post_excerpt ) ) . "\n"; $wxr_post .= "\t\t" . $post_item->ID . "\n"; $wxr_post .= "\t\t" . $post_item->post_date . "\n"; $wxr_post .= "\t\t" . $post_item->post_date_gmt . "\n"; $wxr_post .= "\t\t" . $post_item->comment_status . "\n"; $wxr_post .= "\t\t" . $post_item->ping_status . "\n"; $wxr_post .= "\t\t" . $post_item->post_name . "\n"; $wxr_post .= "\t\t" . $post_item->post_status . "\n"; $wxr_post .= "\t\t" . $post_item->post_parent . "\n"; $wxr_post .= "\t\t" . $post_item->menu_order . "\n"; $wxr_post .= "\t\t" . $post_item->post_type . "\n"; $wxr_post .= "\t\t" . $post_item->post_password . "\n"; $wxr_post .= "\t\t" . $is_sticky . "\n"; if ( 'attachment' === $post_item->post_type ) { $wxr_post .= "\t\t" . wp_get_attachment_url( $post_item->ID ) . "\n"; } $wxr_post .= $this->wxr_post_taxonomy(); $postmeta_key = 'postmeta_' . $post_item->ID; $postmeta = wp_cache_get( $postmeta_key, $cache_group ); if ( false === $postmeta ) { $postmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE post_id = %d", $post_item->ID ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw postmeta export. wp_cache_set( $postmeta_key, $postmeta, $cache_group, MINUTE_IN_SECONDS ); } foreach ( $postmeta as $meta ) { if ( wpm_apply_filters_typed( 'boolean', 'backwpup_wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) ) { continue; } $wxr_post .= "\t\t\n\t\t\t" . $meta->meta_key . "\n\t\t\t" . $this->wxr_cdata( $meta->meta_value ) . "\n\t\t\n"; } $comments_key = 'comments_' . $post_item->ID; $comments = wp_cache_get( $comments_key, $cache_group ); if ( false === $comments ) { $comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->comments} WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post_item->ID ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw comment export. wp_cache_set( $comments_key, $comments, $cache_group, MINUTE_IN_SECONDS ); } foreach ( $comments as $c ) { $wxr_post .= "\t\t\n"; $wxr_post .= "\t\t\t" . $c->comment_ID . "\n"; $wxr_post .= "\t\t\t" . $this->wxr_cdata( $c->comment_author ) . "\n"; $wxr_post .= "\t\t\t" . $c->comment_author_email . "\n"; $wxr_post .= "\t\t\t" . esc_url_raw( $c->comment_author_url ) . "\n"; $wxr_post .= "\t\t\t" . $c->comment_author_IP . "\n"; $wxr_post .= "\t\t\t" . $c->comment_date . "\n"; $wxr_post .= "\t\t\t" . $c->comment_date_gmt . "\n"; $wxr_post .= "\t\t\t" . $this->wxr_cdata( $c->comment_content ) . "\n"; $wxr_post .= "\t\t\t" . $c->comment_approved . "\n"; $wxr_post .= "\t\t\t" . $c->comment_type . "\n"; $wxr_post .= "\t\t\t" . $c->comment_parent . "\n"; $wxr_post .= "\t\t\t" . $c->user_id . "\n"; $commentmeta_key = 'commentmeta_' . $c->comment_ID; $c_meta = wp_cache_get( $commentmeta_key, $cache_group ); if ( false === $c_meta ) { $c_meta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->commentmeta} WHERE comment_id = %d", $c->comment_ID ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw commentmeta export. wp_cache_set( $commentmeta_key, $c_meta, $cache_group, MINUTE_IN_SECONDS ); } foreach ( $c_meta as $meta ) { $wxr_post .= "\t\t\t\n\t\t\t\t" . $meta->meta_key . "\n\t\t\t\t" . $this->wxr_cdata( $meta->meta_value ) . "\n\t\t\t\n"; } $wxr_post .= "\t\t\n"; } $wxr_post .= "\t\n"; ++$job_object->substeps_done; } wp_reset_postdata(); $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $wxr_post, FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } $job_object->do_restart_time(); } } $written = file_put_contents( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], "\n", FILE_APPEND ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents if ( false === $written ) { $job_object->log( __( 'WP Export file could not written.', 'backwpup' ), E_USER_ERROR ); return false; } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'check'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } remove_filter( 'backwpup_wxr_export_skip_postmeta', [ $this, 'wxr_filter_postmeta' ], 10 ); if ( 'check' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( class_exists( \DOMDocument::class ) ) { $job_object->log( __( 'Check WP Export file …', 'backwpup' ) ); $job_object->need_free_memory( filesize( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ) * 2 ); try { $validator = new WxrValidator( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ); $validator->validateWxr(); $job_object->log( __( 'WP Export file is a valid WXR file.', 'backwpup' ) ); } catch ( InvalidXmlException $e ) { $errors = $e->getErrors(); foreach ( $errors as $error ) { switch ( $error->level ) { case LIBXML_ERR_WARNING: $job_object->log( E_USER_WARNING, sprintf( // translators: 1: XML error code. 2: XML error message. __( 'XML WARNING (%1$s): %2$s', 'backwpup' ), $error->code, trim( $error->message ) ), $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $error->line ); break; case LIBXML_ERR_ERROR: $job_object->log( E_USER_WARNING, sprintf( // translators: 1: XML error code. 2: XML error message. __( 'XML RECOVERABLE (%1$s): %2$s', 'backwpup' ), $error->code, trim( $error->message ) ), $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $error->line ); break; case LIBXML_ERR_FATAL: $job_object->log( E_USER_WARNING, sprintf( // translators: 1: XML error code. 2: XML error message. __( 'XML ERROR (%1$s): %2$s', 'backwpup' ), $error->code, trim( $error->message ) ), $job_object->steps_data[ $job_object->step_working ]['wpexportfile'], $error->line ); break; } } } catch ( InvalidWxrFileException $e ) { $job_object->log( $e->getMessage(), E_USER_ERROR ); } } else { $job_object->log( __( 'WP Export file can not be checked, because no XML extension is loaded, to ensure the file verification.', 'backwpup' ) ); } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'compress'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } // Compress file. if ( 'compress' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { if ( ! empty( $job_object->job['wpexportfilecompression'] ) ) { $job_object->log( __( 'Compressing file …', 'backwpup' ) ); try { $compress = new BackWPup_Create_Archive( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] . $job_object->job['wpexportfilecompression'] ); if ( $compress->add_file( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ) ) { unset( $compress ); wp_delete_file( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ); $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] .= $job_object->job['wpexportfilecompression']; $job_object->log( __( 'Compressing done.', 'backwpup' ) ); } } catch ( Exception $e ) { $job_object->log( $e->getMessage(), E_USER_ERROR, $e->getFile(), $e->getLine() ); return false; } } $job_object->steps_data[ $job_object->step_working ]['substep'] = 'addfile'; ++$job_object->substeps_done; $job_object->update_working_data(); $job_object->do_restart_time(); } if ( 'addfile' === $job_object->steps_data[ $job_object->step_working ]['substep'] ) { // Add XML file to backup files. if ( is_readable( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ) ) { $job_object->additional_files_to_backup[] = $job_object->steps_data[ $job_object->step_working ]['wpexportfile']; $filesize = filesize( $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ); /* translators: 1: XML export filename, 2: XML export file size. */ $job_object->log( sprintf( __( 'Added XML export "%1$s" with %2$s to backup file list.', 'backwpup' ), basename( (string) $job_object->steps_data[ $job_object->step_working ]['wpexportfile'] ), size_format( $filesize, 2 ) ) ); } ++$job_object->substeps_done; $job_object->update_working_data(); } return true; } /** * Wrap given string in XML CDATA tag. * * @since WordPress 2.1.0 * * @param string $str String to wrap in XML CDATA tag. * * @return string */ private function wxr_cdata( $str ) { $str = (string) $str; // Use wp_is_valid_utf8() if available (WP 6.9+), otherwise fall back to seems_utf8(). if ( function_exists( 'wp_is_valid_utf8' ) ) { $is_valid_utf8 = wp_is_valid_utf8( $str ); } else { $is_valid_utf8 = seems_utf8( $str ); // phpcs:ignore WordPress.WP.DeprecatedFunctions.seems_utf8Found } if ( ! $is_valid_utf8 ) { $str = utf8_encode( $str ); } // Not allowed UTF-8 chars in XML. $str = preg_replace( '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', '', $str ); // $str = ent2ncr( esc_html( $str ) ); return '', ']]]]>', $str ) . ']]>'; } /** * Return the URL of the site. * * @since WordPress 2.5.0 * * @return string Site URL. */ private function wxr_site_url() { // MS: the base URL. if ( is_multisite() ) { return network_home_url(); } // WP: the blog URL. return get_bloginfo_rss( 'url' ); } /** * Output a cat_name XML tag from a given category object. * * @since WordPress 2.1.0 * * @param object $category Category object. * * @return string */ private function wxr_cat_name( $category ) { if ( empty( $category->name ) ) { return ''; } return '' . $this->wxr_cdata( $category->name ) . ''; } /** * Output a category_description XML tag from a given category object. * * @since WordPress 2.1.0 * * @param object $category Category object. * * @return string */ private function wxr_category_description( $category ) { if ( empty( $category->description ) ) { return ''; } return '' . $this->wxr_cdata( $category->description ) . ''; } /** * Output a tag_name XML tag from a given tag object. * * @since WordPress 2.3.0 * * @param object $tag Tag object. * * @return string */ private function wxr_tag_name( $tag ) { if ( empty( $tag->name ) ) { return ''; } return '' . $this->wxr_cdata( $tag->name ) . ''; } /** * Output a tag_description XML tag from a given tag object. * * @since WordPress 2.3.0 * * @param object $tag Tag object. * * @return string */ private function wxr_tag_description( $tag ) { if ( empty( $tag->description ) ) { return ''; } return '' . $this->wxr_cdata( $tag->description ) . ''; } /** * Output a term_name XML tag from a given term object. * * @since WordPress 2.9.0 * * @param object $term Term object. * * @return string */ private function wxr_term_name( $term ) { if ( empty( $term->name ) ) { return ''; } return '' . $this->wxr_cdata( $term->name ) . ''; } /** * Output a term_description XML tag from a given term object. * * @since WordPress 2.9.0 * * @param object $term Term object. * * @return string */ private function wxr_term_description( $term ) { if ( empty( $term->description ) ) { return ''; } return '' . $this->wxr_cdata( $term->description ) . ''; } /** * Output list of authors with posts. * * @since WordPress 3.1.0 * * @return string */ private function wxr_authors_list() { global $wpdb; $authors = []; $cache_group = 'backwpup_wpexport'; $authors_key = 'authors_' . DB_NAME; $results = wp_cache_get( $authors_key, $cache_group ); if ( false === $results ) { $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- No WP API for raw author export. $wpdb->prepare( "SELECT DISTINCT post_author FROM {$wpdb->posts} WHERE post_status != %s", 'auto-draft' ) ); wp_cache_set( $authors_key, $results, $cache_group, MINUTE_IN_SECONDS ); } foreach ( (array) $results as $result ) { $authors[] = get_userdata( $result->post_author ); } $authors = array_filter( $authors ); $wxr_authors = ''; foreach ( $authors as $author ) { $wxr_authors .= "\t"; $wxr_authors .= '' . $author->ID . ''; $wxr_authors .= '' . $author->user_login . ''; $wxr_authors .= '' . $author->user_email . ''; $wxr_authors .= '' . $this->wxr_cdata( $author->display_name ) . ''; $wxr_authors .= '' . $this->wxr_cdata( $author->user_firstname ) . ''; $wxr_authors .= '' . $this->wxr_cdata( $author->user_lastname ) . ''; $wxr_authors .= "\n"; } return $wxr_authors; } /** * Ouput all navigation menu terms. * * @since WordPress 3.1.0 */ private function wxr_nav_menu_terms() { $nav_menus = wp_get_nav_menus(); if ( empty( $nav_menus ) || ! is_array( $nav_menus ) ) { return ''; } $wxr_nav_meuns = ''; foreach ( $nav_menus as $menu ) { $wxr_nav_meuns .= "\t{$menu->term_id}nav_menu{$menu->slug}"; $wxr_nav_meuns .= $this->wxr_term_name( $menu ); $wxr_nav_meuns .= "\n"; } return $wxr_nav_meuns; } /** * Output list of taxonomy terms, in XML tag format, associated with a post. * * @since WordPress 2.3.0 */ private function wxr_post_taxonomy() { $post = get_post(); if ( ! $post instanceof WP_Post ) { return ''; } $taxonomies = get_object_taxonomies( $post->post_type ); if ( empty( $taxonomies ) ) { return ''; } $terms = wp_get_object_terms( $post->ID, $taxonomies ); $wxr_post_tags = ''; foreach ( (array) $terms as $term ) { $wxr_post_tags .= "\t\ttaxonomy}\" nicename=\"{$term->slug}\">" . $this->wxr_cdata( $term->name ) . "\n"; } return $wxr_post_tags; } /** * Filter postmeta keys that should be skipped during WXR export. * * @param bool $return_me Whether to skip the meta key. * @param string $meta_key Meta key name. * * @return bool */ public function wxr_filter_postmeta( $return_me, $meta_key ) { if ( '_edit_lock' === $meta_key ) { $return_me = true; } return $return_me; } }