| Current Path : /home/k/r/o/krobertfnz/www/wp-content/plugins/vamtam-importers/ |
| Current File : /home/k/r/o/krobertfnz/www/wp-content/plugins/vamtam-importers/vamtam-import-attachments.php |
<?php
class Vamtam_Import_Attachments extends WP_Background_Process {
/**
* @var string
*/
protected $action = 'vamtam_import_attachments';
private $base_url = '';
private function log( $message ) {
error_log( $message );
}
public function get_queue_length() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$data_in = 'option_value';
if ( is_multisite() ) {
$table = $wpdb->sitemeta;
$column = 'meta_key';
$data_in = 'meta_value';
}
$key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
$batches = $wpdb->get_results( $wpdb->prepare( "
SELECT *
FROM {$table}
WHERE {$column} LIKE %s
", $key ) );
$count = 0;
foreach ( $batches as $batch ) {
if ( isset( $batch->$data_in ) ) {
$data = maybe_unserialize( $batch->$data_in );
if ( is_countable( $data ) ) {
$count += count( $data );
}
}
}
return $count;
}
/**
* Generate thumbnails for each imported image
* @return false
*/
protected function task( $task ) {
// import, generate thumbnails, replace URLs
if ( is_array( $task ) && isset( $task['step'] ) ) {
$data = $task['data'];
if ( $task['step'] === 1 ) {
$this->base_url = $data['base_url'];
$imported = $this->process_attachment( $data['attachment'][0], $data['attachment'][1] );
if ( is_wp_error( $imported ) ) {
$message = 'VAMTAM -- importing attachment failed:' . $data['attachment'][1] . " \n ";
$message .='error: ' . $imported->get_error_message();
$this->log( $message );
return false;
}
$message = 'VAMTAM -- imported attachment:' . $data['attachment'][1] . " \n ";
$this->log( $message );
$old_remap = get_option( 'vamtam_import_attachments_url_remap', [] );
update_option( 'vamtam_import_attachments_url_remap', array_merge( $old_remap, $imported['url_remap'] ) );
return [
'step' => 2,
'data' => $imported,
];
} elseif ( $task['step'] === 2 ) {
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
include ABSPATH . 'wp-admin/includes/image.php';
}
$new_metadata = wp_generate_attachment_metadata( $data['post_id'], get_attached_file( $data['post_id'] ) );
$message = 'VAMTAM -- updating attachment ' . $data['post_id'] . get_attached_file( $data['post_id'] ) . " \n ";
$message .='result: ' . (int)wp_update_attachment_metadata( $data['post_id'], $new_metadata );
$this->log( $message );
return false;
}
}
return false;
}
protected function complete() {
parent::complete();
require 'vamtam-import-search-replace.php';
$map = get_option( 'vamtam_last_import_map' );
$this->remap_featured_images( $map['featured_images'], $map['posts'] );
$this->backfill_attachment_urls( get_option( 'vamtam_import_attachments_url_remap', [] ) );
}
/**
* @override
* Maybe process queue
*
* Checks whether data exists within the queue and that
* the process is not already running.
*/
public function maybe_handle() {
// Don't lock up other requests while processing
session_write_close();
$is_vamtam_importer = $this->action === 'vamtam_import_attachments';
if ( $this->is_process_running() && ! $is_vamtam_importer ) {
// Background process already running.
wp_die();
}
if ( $this->is_queue_empty() ) {
// No data to process.
wp_die();
}
check_ajax_referer( $this->identifier, 'nonce' );
$this->handle();
wp_die();
}
/**
* Update _thumbnail_id meta to new, imported attachment IDs
*/
protected function remap_featured_images( $featured_images, $processed_posts ) {
// cycle through posts that have a featured image
foreach ( $featured_images as $post_id => $value ) {
if ( isset( $processed_posts[$value] ) ) {
$new_id = $processed_posts[$value];
// only update if there's a difference
if ( $new_id != $value ) {
update_post_meta( $post_id, '_thumbnail_id', $new_id );
}
}
}
}
/**
* Use stored mapping information to update old attachment URLs
*
* With Beaver support - see https://stackoverflow.com/a/3277781/635882
*/
protected function backfill_attachment_urls( $url_remap ) {
global $wpdb;
// make sure we do the longest urls first, in case one is a substring of another
uksort( $url_remap, function( $a, $b ) {
return strlen( $b ) - strlen( $a );
} );
foreach ( $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) );
// Beaver Builder support - replace serialized data in the postmeta and options tables
$search = 's:' . strlen( $from_url) . ':"' . $from_url . '"';
$replace = 's:' . strlen( $to_url ) . ':"' . $to_url . '"';
$result = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s)", $search, $replace ) );
$result = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->options} SET option_value = REPLACE(option_value, %s, %s)", $search, $replace ) );
$meta_to_repace = $wpdb->get_results( $wpdb->prepare( "SELECT meta_id, meta_value FROM {$wpdb->postmeta} WHERE meta_value LIKE '%%%s%%'", $from_url ) );
foreach ( $meta_to_repace as $meta ) {
$meta->meta_value = Vamtam_Import_Search_Replace::recursive_unserialize_replace( $from_url, $to_url, $meta->meta_value );
if ( ! is_string( $meta->meta_value ) ) {
$meta->meta_value = serialize( $meta->meta_value );
}
$wpdb->update(
$wpdb->postmeta,
array(
'meta_value' => $meta->meta_value,
),
array( 'meta_id' => $meta->meta_id ),
array(
'%s',
),
array( '%d' )
);
}
}
}
/**
* If fetching attachments is enabled then attempt to create a new attachment
*
* @param array $post Attachment post details from WXR
* @param string $url URL to fetch attachment from
* @return int|WP_Error Post ID on success, WP_Error otherwise
*/
protected function process_attachment( $post, $url ) {
if ( ! apply_filters( 'import_allow_fetch_attachments', true ) ) {
return new WP_Error( 'attachment_processing_error',
__( 'Fetching attachments is not enabled', 'wordpress-importer' ) );
}
$post_exists = post_exists( $post['post_title'], '', $post['post_date'] );
/**
* Filter ID of the existing post corresponding to post currently importing.
*
* Return 0 to force the post to be imported. Filter the ID to be something else
* to override which existing post is mapped to the imported post.
*
* @see post_exists()
* @since 0.6.2
*
* @param int $post_exists Post ID, or 0 if post did not exist.
* @param array $post The post array to be inserted.
*/
$post_exists = apply_filters( 'wp_import_existing_post', $post_exists, $post );
// if the URL is absolute, but does not contain address, then upload it assuming base_site_url
if ( preg_match( '|^/[\w\W]+$|', $url ) ) {
$url = rtrim( $this->base_url, '/' ) . $url;
}
$fetched = $this->fetch_remote_file( $url, $post );
if ( is_wp_error( $fetched ) ) {
return $fetched;
}
extract( $fetched );
if ( $info = wp_check_filetype( $upload['file'] ) ) {
$post['post_mime_type'] = $info['type'];
} else {
return new WP_Error( 'attachment_processing_error', __('Invalid file type', 'wordpress-importer') );
}
$post['guid'] = $upload['url'];
// as per wp-admin/includes/upload.php
$post_id = wp_insert_attachment( $post, $upload['file'] );
add_filter( 'intermediate_image_sizes_advanced', '__return_false' );
wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );
remove_filter( 'intermediate_image_sizes_advanced', '__return_false' );
$result = [
'post_id' => $post_id,
'url_remap' => $url_remap,
];
// remap resized image URLs, works by stripping the extension and remapping the URL stub.
if ( preg_match( '!^image/!', $info['type'] ) ) {
$parts = pathinfo( $url );
$name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2
$parts_new = pathinfo( $upload['url'] );
$name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
$result['url_remap'][ $parts['dirname'] . '/' . $name ] = $parts_new['dirname'] . '/' . $name_new;
}
$map = get_option( 'vamtam_last_import_map' );
$map['posts'][ $post['import_id'] ] = $post_id;
update_option( 'vamtam_last_import_map', $map );
Vamtam_Importers::process_post_additional_data( $post, $post_id, $post_exists, $map['authors'] );
return $result;
}
/**
* 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
*/
protected 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, 0, '', $post['upload_date'] );
if ( $upload['error'] ) {
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(
'timeout' => 300,
'stream' => true,
'filename' => $upload['file'],
) );
$headers = wp_remote_retrieve_headers( $remote_response );
// request failed
if ( ! $headers ) {
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', __('Remote server did not respond', 'wordpress-importer') );
}
$remote_response_code = wp_remote_retrieve_response_code( $remote_response );
// make sure the fetch was successful
if ( $remote_response_code != '200' ) {
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', sprintf( __('Remote server returned error response %1$d %2$s', 'wordpress-importer'), 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'] ) {
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', __('Remote file is incorrect size', 'wordpress-importer') );
}
if ( 0 == $filesize ) {
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', __('Zero size file downloaded', 'wordpress-importer') );
}
$max_size = (int) apply_filters( 'import_attachment_size_limit', 0 );
if ( ! empty( $max_size ) && $filesize > $max_size ) {
@unlink( $upload['file'] );
return new WP_Error( 'import_file_error', sprintf(__('Remote file is too large, limit is %s', 'wordpress-importer'), size_format($max_size) ) );
}
// keep track of the old and new urls so we can substitute them later
$result = [
'upload' => $upload,
'url_remap' => [
$url => $upload['url'],
$post['guid'] => $upload['url'],
]
];
// keep track of the destination if the remote url is redirected somewhere else
if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url ) {
$result['url_remap'][ $headers['x-final-location'] ] = $upload['url'];
}
return $result;
}
}