: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Attempt to download a remote file attachment
* @param string $url URL of item to fetch
* @param array $post Attachment details
* @return array|WP_Error Local file location details on success, WP_Error otherwise
public function fetch_remote_file($url, $post)
// extract the file name and extension from the url
$file_name = basename($url);
// get placeholder file in the upload dir with a unique, sanitized filename
$upload = wp_upload_bits($file_name, null, '', $post['upload_date']);
return new \WP_Error('upload_dir_error', $upload['error']);
// fetch the remote url and write it to the placeholder file
$remote_response = wp_safe_remote_get($url, array(
'filename' => $upload['file'],
$headers = wp_remote_retrieve_headers($remote_response);
wp_delete_file($upload['file']);
return new \WP_Error('import_file_error', __('Remote server did not respond', 'popup-builder'));
$remote_response_code = wp_remote_retrieve_response_code($remote_response);
// make sure the fetch was successful
if ($remote_response_code != '200') {
wp_delete_file($upload['file']);
/* translators: remote response code, status header description */
return new \WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'popup-builder'), esc_html($remote_response_code), get_status_header_desc($remote_response_code)));
$filesize = filesize($upload['file']);
if (isset($headers['content-length']) && $filesize != $headers['content-length']) {
wp_delete_file($upload['file']);
return new \WP_Error('import_file_error', __('Remote file is incorrect size', 'popup-builder'));
wp_delete_file($upload['file']);
return new \WP_Error('import_file_error', __('Zero size file downloaded', 'popup-builder'));
$max_size = (int) $this->max_attachment_size();
if (!empty($max_size) && $filesize > $max_size) {
wp_delete_file($upload['file']);
/* translators: max size */
return new \WP_Error('import_file_error', sprintf(__('Remote file is too large, limit is %s', 'popup-builder'), size_format($max_size)));
// keep track of the old and new urls so we can substitute them later
$this->url_remap[$url] = $upload['url'];
$this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
// keep track of the destination if the remote url is redirected somewhere else
if (isset($headers['x-final-location']) && $headers['x-final-location'] != $url) {
$this->url_remap[$headers['x-final-location']] = $upload['url'];
* Attempt to associate posts and menu items with previously missing parents
* An imported post's parent may not have been imported when it was first created
* so try again. Similarly for child menu items and menu items which were missing
* the object (e.g. post) they represent in the menu
public function backfill_parents()
// find parents for post orphans
foreach ($this->post_orphans as $child_id => $parent_id) {
$local_child_id = $local_parent_id = false;
if (isset($this->processed_posts[$child_id]))
$local_child_id = $this->processed_posts[$child_id];
if (isset($this->processed_posts[$parent_id]))
$local_parent_id = $this->processed_posts[$parent_id];
if ($local_child_id && $local_parent_id) {
$wpdb->update($wpdb->posts, array('post_parent' => $local_parent_id), array('ID' => $local_child_id), '%d', '%d');
clean_post_cache($local_child_id);
// all other posts/terms are imported, retry menu items with missing associated object
$missing_menu_items = $this->missing_menu_items;
foreach ($missing_menu_items as $item)
$this->process_menu_item($item);
// find parents for menu item orphans
foreach ($this->menu_item_orphans as $child_id => $parent_id) {
$local_child_id = $local_parent_id = 0;
if (isset($this->processed_menu_items[$child_id])) {
$local_child_id = $this->processed_menu_items[$child_id];
if (isset($this->processed_menu_items[$parent_id])) {
$local_parent_id = $this->processed_menu_items[$parent_id];
if ($local_child_id && $local_parent_id) {
update_post_meta($local_child_id, '_menu_item_menu_item_parent', (int) $local_parent_id);
* Use stored mapping information to update old attachment URLs
public function backfill_attachment_urls()
// make sure we do the longest urls first, in case one is a substring of another
uksort($this->url_remap, array(&$this, 'cmpr_strlen'));
foreach ($this->url_remap as $from_url => $to_url) {
// remap urls in post_content
$wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url));
$result = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url));
* Update _thumbnail_id meta to new, imported attachment IDs
public function remap_featured_images()
// cycle through posts that have a featured image
foreach ($this->featured_images as $post_id => $value) {
if (isset($this->processed_posts[$value])) {
$new_id = $this->processed_posts[$value];
// only update if there's a difference
update_post_meta($post_id, '_thumbnail_id', $new_id);
* @param string $file Path to WXR file for parsing
* @return array Information gathered from the WXR file
public function parse($file)
$parser = new WXR_Parser();
return $parser->parse($file);
// Display import page title
echo '<div class="wrap">';
echo '<h2>' . esc_html( __('Import WordPress', 'popup-builder') ). '</h2>';
$updates = get_plugin_updates();
$basename = plugin_basename(__FILE__);
if (isset($updates[$basename])) {
$update = $updates[$basename];
echo '<div class="error"><p><strong>';
/* translators: new version */
printf(wp_kses_post(__('A new version of this importer is available. Please update to version %s to ensure compatibility with newer export files.', 'popup-builder')), esc_html( $update->update->new_version) );
echo '</strong></p></div>';
* Display introductory text and file upload form
echo '<div class="narrow">';
echo '<p>'. esc_html( __('Howdy!Upload your WordPress eXtended RSS (WXR) file and we’ll import the posts, pages, comments, custom fields, categories, and tags into this site.', 'popup-builder') ).'</p>';
echo '<p>'. esc_html( __('Choose a WXR (.xml) file to upload, then click Upload file and import.', 'popup-builder') ).'</p>';
wp_import_upload_form('admin.php?import=wordpress&step=1');
* Decide if the given meta key maps to information we will want to import
* @param string $key The meta key to check
* @return string|bool The key if we do want to import, false if not
public function is_valid_meta_key($key)
// skip attachment metadata since we'll regenerate it from scratch
// skip _edit_lock as not relevant for import
if (in_array($key, array('_wp_attached_file', '_wp_attachment_metadata', '_edit_lock')))
* Decide whether or not the importer is allowed to create users.
* Default is true, can be filtered via import_allow_create_users
* @return bool True if creating users is allowed
public function allow_create_users()
return apply_filters('import_allow_create_users', true);
* Decide whether or not the importer should attempt to download attachment files.
* Default is true, can be filtered via import_allow_fetch_attachments. The choice
* made at the import options screen must also be true, false here hides that checkbox.
* @return bool True if downloading attachments is allowed
public function allow_fetch_attachments()
return apply_filters('import_allow_fetch_attachments', true);
* Decide what the maximum file size for downloaded attachments is.
* Default is 0 (unlimited), can be filtered via import_attachment_size_limit
* @return int Maximum attachment file size to import
public function max_attachment_size()
return apply_filters('import_attachment_size_limit', 0);
* Added to http_request_timeout filter to force timeout at 60 seconds during import
public function bump_request_timeout($val)
// return the difference in length between two strings
public function cmpr_strlen($a, $b)
return strlen($b) - strlen($a);