File: //usr/local/wp/vendor/wp-cli/export-command/src/Export_Command.php
<?php
use WP_CLI\Utils;
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- Changing breaks Phar compat.
define( 'WP_CLI_EXPORT_COMMAND_NO_SPLIT', '-1' );
/**
* Exports WordPress content to a WXR file.
*
* ## EXAMPLES
*
* # Export posts published by the user between given start and end date
* $ wp export --dir=/tmp/ --user=admin --post_type=post --start_date=2011-01-01 --end_date=2011-12-31
* Starting export process...
* Writing to file /tmp/staging.wordpress.2016-05-24.000.xml
* Success: All done with export.
*
* @package wp-cli
*/
class Export_Command extends WP_CLI_Command {
/**
* Initialize the array of arguments that will be eventually be passed to export_wp.
*
* @var array
*/
public $export_args = [];
private $stdout;
private $max_file_size;
private $include_once;
private $wxr_path;
/**
* Exports WordPress content to a WXR file.
*
* Generates one or more WXR files containing authors, terms, posts,
* comments, and attachments. WXR files do not include site configuration
* (options) or the attachment files themselves.
*
* ## OPTIONS
*
* [--dir=<dirname>]
* : Full path to directory where WXR export files should be stored. Defaults
* to current working directory.
*
* [--stdout]
* : Output the whole XML using standard output (incompatible with --dir=)
*
* [--skip_comments]
* : Don't include comments in the WXR export file.
*
* [--max_file_size=<MB>]
* : A single export file should have this many megabytes. -1 for unlimited.
* ---
* default: 15
* ---
*
* [--filename_format=<format>]
* : Use a custom format for export filenames. Defaults to '{site}.wordpress.{date}.{n}.xml'.
*
* [--include_once=<before_posts>]
* : Include specified export section only in the first export file. Valid options
* are categories, tags, nav_menu_items, custom_taxonomies_terms. Separate multiple
* sections with a comma. Defaults to none.
*
* [--allow_orphan_terms]
* : Export orphaned terms with `parent=0`, instead of throwing an exception.
*
* ## FILTERS
*
* [--start_date=<date>]
* : Export only posts published after this date, in format YYYY-MM-DD.
*
* [--end_date=<date>]
* : Export only posts published before this date, in format YYYY-MM-DD.
*
* [--post_type=<post-type>]
* : Export only posts with this post_type. Separate multiple post types with a
* comma.
* ---
* default: any
* ---
*
* [--post_type__not_in=<post-type>]
* : Export all post types except those identified. Separate multiple post types
* with a comma. Defaults to none.
*
* [--post__in=<pid>]
* : Export all posts specified as a comma-separated or space-separated list of IDs.
* Post's attachments won't be exported unless --with_attachments is specified.
*
* [--with_attachments]
* : Force including attachments in case --post__in has been specified.
*
* [--start_id=<pid>]
* : Export only posts with IDs greater than or equal to this post ID.
*
* [--max_num_posts=<num>]
* : Export no more than <num> posts (excluding attachments).
*
* [--author=<author>]
* : Export only posts by this author. Can be either user login or user ID.
*
* [--category=<name|id>]
* : Export only posts in this category.
*
* [--post_status=<status>]
* : Export only posts with this status.
*
* ## EXAMPLES
*
* # Export posts published by the user between given start and end date
* $ wp export --dir=/tmp/ --user=admin --post_type=post --start_date=2011-01-01 --end_date=2011-12-31
* Starting export process...
* Writing to file /tmp/staging.wordpress.2016-05-24.000.xml
* Success: All done with export.
*
* # Export posts by IDs
* $ wp export --dir=/tmp/ --post__in=123,124,125
* Starting export process...
* Writing to file /tmp/staging.wordpress.2016-05-24.000.xml
* Success: All done with export.
*
* # Export a random subset of content
* $ wp export --post__in="$(wp post list --post_type=post --orderby=rand --posts_per_page=8 --format=ids)"
* Starting export process...
* Writing to file /var/www/example.com/public_html/staging.wordpress.2016-05-24.000.xml
* Success: All done with export.
*/
public function __invoke( $_, $assoc_args ) {
$defaults = [
'dir' => null,
'stdout' => false,
'start_date' => null,
'end_date' => null,
'post_type' => null,
'post_type__not_in' => null,
'max_num_posts' => null,
'author' => null,
'category' => null,
'post_status' => null,
'post__in' => null,
'with_attachments' => true, // or FALSE if user requested some post__in
'start_id' => null,
'skip_comments' => null,
'max_file_size' => 15,
'filename_format' => '{site}.wordpress.{date}.{n}.xml',
'include_once' => null,
'allow_orphan_terms' => null,
];
if ( ! empty( $assoc_args['stdout'] ) && ( ! empty( $assoc_args['dir'] ) || ! empty( $assoc_args['filename_format'] ) ) ) {
WP_CLI::error( '--stdout and --dir cannot be used together.' );
}
if ( ! empty( $assoc_args['post__in'] ) && empty( $assoc_args['with_attachments'] ) ) {
$defaults['with_attachments'] = false;
}
$assoc_args = wp_parse_args( $assoc_args, $defaults );
$this->validate_args( $assoc_args );
$this->export_args['with_attachments'] = Utils\get_flag_value(
$assoc_args,
'with_attachments',
$defaults['with_attachments']
);
if ( ! function_exists( 'wp_export' ) ) {
self::load_export_api();
}
if ( ! $this->stdout ) {
WP_CLI::log( 'Starting export process...' );
}
add_action(
'wp_export_new_file',
static function ( $file_path ) {
WP_CLI::log( sprintf( 'Writing to file %s', $file_path ) );
Utils\wp_clear_object_cache();
}
);
try {
if ( $this->stdout ) {
wp_export(
[
'filters' => $this->export_args,
'writer' => 'WP_Export_File_Writer',
'writer_args' => 'php://output',
]
);
} else {
wp_export(
[
'filters' => $this->export_args,
'writer' => 'WP_Export_Split_Files_Writer',
'writer_args' => [
'max_file_size' => $this->max_file_size,
'destination_directory' => $this->wxr_path,
'filename_template' => self::get_filename_template( $assoc_args['filename_format'] ),
'include_once' => $this->include_once,
],
]
);
}
} catch ( Exception $e ) {
WP_CLI::error( $e->getMessage() );
}
if ( ! $this->stdout ) {
WP_CLI::success( 'All done with export.' );
}
}
private static function get_filename_template( $filename_format ) {
$sitename = sanitize_key( get_bloginfo( 'name' ) );
if ( empty( $sitename ) ) {
$sitename = 'site';
}
return str_replace( [ '{site}', '{date}', '{n}' ], [ $sitename, date( 'Y-m-d' ), '%03d' ], $filename_format ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
}
public static function load_export_api() {
require dirname( __DIR__ ) . '/functions.php';
}
private function validate_args( $args ) {
$has_errors = false;
foreach ( $args as $key => $value ) {
if ( is_callable( [ $this, 'check_' . $key ] ) ) {
$result = call_user_func( [ $this, 'check_' . $key ], $value );
if ( false === $result ) {
$has_errors = true;
}
}
}
if ( $args['stdout'] ) {
$this->wxr_path = null;
$this->stdout = true;
}
if ( $has_errors ) {
WP_CLI::halt( 1 );
}
}
private function check_dir( $path ) {
if ( empty( $path ) ) {
$path = getcwd();
} elseif ( ! is_dir( $path ) ) {
WP_CLI::error( sprintf( "The directory '%s' does not exist.", $path ) );
} elseif ( ! is_writable( $path ) ) {
WP_CLI::error( sprintf( "The directory '%s' is not writable.", $path ) );
}
$this->wxr_path = trailingslashit( $path );
return true;
}
private function check_start_date( $date ) {
if ( null === $date ) {
return true;
}
$time = strtotime( $date );
if ( ! empty( $date ) && ! $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
return true;
}
private function check_end_date( $date ) {
if ( null === $date ) {
return true;
}
$time = strtotime( $date );
if ( ! empty( $date ) && ! $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
return true;
}
private function check_post_type( $post_type ) {
if ( null === $post_type || 'any' === $post_type ) {
return true;
}
$post_type = array_unique( array_filter( explode( ',', $post_type ) ) );
$post_types = get_post_types();
foreach ( $post_type as $type ) {
if ( ! in_array( $type, $post_types, true ) ) {
WP_CLI::warning(
sprintf(
'The post type %s does not exist. Choose "any" or any of these existing post types instead: %s',
$type,
implode( ', ', $post_types )
)
);
return false;
}
}
$this->export_args['post_type'] = $post_type;
return true;
}
private function check_post_type__not_in( $post_type ) {
if ( null === $post_type ) {
return true;
}
$post_type = array_unique( array_filter( explode( ',', $post_type ) ) );
$post_types = get_post_types();
foreach ( $post_type as $type ) {
if ( ! in_array( $type, $post_types, true ) ) {
WP_CLI::warning(
sprintf(
'The post type %s does not exist. Use any of these existing post types instead: %s',
$type,
implode( ', ', $post_types )
)
);
return false;
}
}
$this->export_args['post_type'] = array_diff( $post_types, $post_type );
return true;
}
private function check_post__in( $post__in ) {
if ( null === $post__in ) {
return true;
}
$separator = false !== stripos( $post__in, ' ' ) ? ' ' : ',';
$post__in = array_filter( array_unique( array_map( 'intval', explode( $separator, $post__in ) ) ) );
if ( empty( $post__in ) ) {
WP_CLI::warning( 'post__in should be comma-separated or space-separated post IDs.' );
return false;
}
// New exporter uses a different argument.
$this->export_args['post_ids'] = $post__in;
return true;
}
private function check_start_id( $start_id ) {
if ( null === $start_id ) {
return true;
}
$start_id = (int) $start_id;
// Post IDs must be greater than 0.
if ( 0 >= $start_id ) {
WP_CLI::warning( "Invalid start ID: {$start_id}" );
return false;
}
$this->export_args['start_id'] = $start_id;
return true;
}
private function check_author( $author ) {
if ( null === $author ) {
return true;
}
// 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 ) ) {
WP_CLI::warning( 'Could not find any authors in this blog.' );
return false;
}
$hit = false;
foreach ( $authors as $user ) {
if ( $hit ) {
break;
}
if ( (int) $author === $user->ID || $author === $user->user_login ) {
$hit = $user->ID;
}
}
if ( false === $hit ) {
$authors_nice = [];
foreach ( $authors as $_author ) {
$authors_nice[] = sprintf( '%s (%s)', $_author->user_login, $_author->display_name );
}
WP_CLI::warning( sprintf( 'Could not find a matching author for %s. The following authors exist: %s', $author, implode( ', ', $authors_nice ) ) );
return false;
}
$this->export_args['author'] = $hit;
return true;
}
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.' );
return false;
}
$this->export_args['max_num_posts'] = (int) $num;
return true;
}
private function check_category( $category ) {
if ( null === $category ) {
return true;
}
if ( is_numeric( $category ) ) {
$category = (int) $category;
}
$term = category_exists( $category );
if ( empty( $term ) || is_wp_error( $term ) ) {
WP_CLI::warning( sprintf( 'Could not find a category matching %s.', $category ) );
return false;
}
$this->export_args['category'] = $category;
return true;
}
private function check_post_status( $status ) {
if ( null === $status ) {
return true;
}
$stati = get_post_stati();
if ( empty( $stati ) || is_wp_error( $stati ) ) {
WP_CLI::warning( 'Could not find any post stati.' );
return false;
}
if ( ! isset( $stati[ $status ] ) ) {
WP_CLI::warning( sprintf( 'Could not find a post_status matching %s. Here is a list of available stati: %s', $status, implode( ', ', array_keys( $stati ) ) ) );
return false;
}
$this->export_args['status'] = $status;
return true;
}
private function check_skip_comments( $skip ) {
if ( null === $skip ) {
return true;
}
if ( 0 !== (int) $skip && 1 !== (int) $skip ) {
WP_CLI::warning( 'skip_comments needs to be 0 (no) or 1 (yes).' );
return false;
}
$this->export_args['skip_comments'] = $skip;
return true;
}
private function check_max_file_size( $size ) {
if ( ! is_numeric( $size ) ) {
WP_CLI::warning( 'max_file_size should be numeric.' );
return false;
}
$this->max_file_size = $size;
return true;
}
private function check_include_once( $once ) {
if ( null === $once ) {
return true;
}
$separator = false !== stripos( $once, ' ' ) ? ' ' : ',';
$once = array_filter( array_unique( array_map( 'strtolower', explode( $separator, $once ) ) ) );
$once = array_intersect( $once, array( 'categories', 'tags', 'nav_menu_terms', 'custom_taxonomies_terms' ) );
if ( empty( $once ) ) {
WP_CLI::warning( 'include_once should be comma-separated values for optional before_posts sections.' );
return false;
}
$this->include_once = $once;
return true;
}
private function check_allow_orphan_terms( $allow_orphan_terms ) {
if ( null === $allow_orphan_terms ) {
return true;
}
if ( 0 !== (int) $allow_orphan_terms && 1 !== (int) $allow_orphan_terms ) {
WP_CLI::warning( 'allow_orphan_terms needs to be 0 (no) or 1 (yes).' );
return false;
}
$this->export_args['allow_orphan_terms'] = $allow_orphan_terms;
return true;
}
}