_config = Dispatcher::config(); } /** * Purge attachment * * Upload _wp_attached_file, _wp_attachment_metadata, _wp_attachment_backup_sizes * * @param integer $attachment_id * @param array $results * @return boolean */ function purge_attachment( $attachment_id, &$results ) { $common = Dispatcher::component( 'Cdn_Core' ); $files = $common->get_attachment_files( $attachment_id ); return $common->purge( $files, $results ); } /** * Updates file date in the queue * * @param integer $queue_id * @param string $last_error * @return integer */ function queue_update( $queue_id, $last_error ) { global $wpdb; $sql = sprintf( 'UPDATE %s SET last_error = "%s", date = NOW() WHERE id = %d', $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE, esc_sql( $last_error ), $queue_id ); return $wpdb->query( $sql ); } /** * Removes from queue * * @param integer $queue_id * @return integer */ function queue_delete( $queue_id ) { global $wpdb; $sql = sprintf( 'DELETE FROM %s WHERE id = %d', $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE, $queue_id ); return $wpdb->query( $sql ); } /** * Empties queue * * @param integer $command * @return integer */ function queue_empty( $command ) { global $wpdb; $sql = sprintf( 'DELETE FROM %s WHERE command = %d', $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE, $command ); return $wpdb->query( $sql ); } /** * Returns queue * * @param integer $limit * @return array */ function queue_get( $limit = null ) { global $wpdb; $sql = sprintf( 'SELECT * FROM %s%s ORDER BY date', $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE ); if ( $limit ) { $sql .= sprintf( ' LIMIT %d', $limit ); } $results = $wpdb->get_results( $sql ); $queue = array(); if ( $results ) { foreach ( (array) $results as $result ) { $queue[$result->command][] = $result; } } return $queue; } /** * Process queue * * @param integer $limit * @return integer */ function queue_process( $limit ) { $items = 0; $commands = $this->queue_get( $limit ); $force_rewrite = $this->_config->get_boolean( 'cdn.force.rewrite' ); if ( count( $commands ) ) { $common = Dispatcher::component( 'Cdn_Core' ); $cdn = $common->get_cdn(); foreach ( $commands as $command => $queue ) { $files = array(); $results = array(); $map = array(); foreach ( $queue as $result ) { $files[] = $common->build_file_descriptor( $result->local_path, $result->remote_path ); $map[$result->local_path] = $result->id; $items++; } switch ( $command ) { case W3TC_CDN_COMMAND_UPLOAD: foreach ( $files as $file ) { $local_file_name = $file['local_path']; $remote_file_name = $file['remote_path']; if ( !file_exists( $local_file_name ) ) { Dispatcher::create_file_for_cdn( $local_file_name ); } } $cdn->upload( $files, $results, $force_rewrite ); foreach ( $results as $result ) { if ( $result['result'] == W3TC_CDN_RESULT_OK ) { Dispatcher::on_cdn_file_upload( $result['local_path'] ); } } break; case W3TC_CDN_COMMAND_DELETE: $cdn->delete( $files, $results ); break; case W3TC_CDN_COMMAND_PURGE: $cdn->purge( $files, $results ); break; } foreach ( $results as $result ) { if ( $result['result'] == W3TC_CDN_RESULT_OK ) { $this->queue_delete( $map[$result['local_path']] ); } else { $this->queue_update( $map[$result['local_path']], $result['error'] ); } } } } return $items; } /** * Export library to CDN * * @param integer $limit * @param integer $offset * @param integer $count * @param integer $total * @param array $results * @return void */ function export_library( $limit, $offset, &$count, &$total, &$results, $timeout_time = 0 ) { global $wpdb; $count = 0; $total = 0; $upload_info = Util_Http::upload_info(); if ( $upload_info ) { $sql = sprintf( 'SELECT pm.meta_value AS file, pm2.meta_value AS metadata FROM %sposts AS p LEFT JOIN %spostmeta AS pm ON p.ID = pm.post_ID AND pm.meta_key = "_wp_attached_file" LEFT JOIN %spostmeta AS pm2 ON p.ID = pm2.post_ID AND pm2.meta_key = "_wp_attachment_metadata" WHERE p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_value IS NOT NULL) GROUP BY p.ID ORDER BY p.ID', $wpdb->prefix, $wpdb->prefix, $wpdb->prefix ); if ( $limit ) { $sql .= sprintf( ' LIMIT %d', $limit ); if ( $offset ) { $sql .= sprintf( ' OFFSET %d', $offset ); } } $posts = $wpdb->get_results( $sql ); if ( $posts ) { $count = count( $posts ); $total = $this->get_attachments_count(); $files = array(); $common = Dispatcher::component( 'Cdn_Core' ); foreach ( $posts as $post ) { $post_files = array(); if ( $post->file ) { $file = $common->normalize_attachment_file( $post->file ); $local_file = $upload_info['basedir'] . '/' . $file; $remote_file = ltrim( $upload_info['baseurlpath'] . $file, '/' ); $post_files[] = $common->build_file_descriptor( $local_file, $remote_file ); } if ( $post->metadata ) { $metadata = @unserialize( $post->metadata ); $post_files = array_merge( $post_files, $common->get_metadata_files( $metadata ) ); } $post_files = apply_filters( 'w3tc_cdn_add_attachment', $post_files ); $files = array_merge( $files, $post_files ); } $common = Dispatcher::component( 'Cdn_Core' ); $common->upload( $files, false, $results, $timeout_time ); } } } /** * Imports library * * @param integer $limit * @param integer $offset * @param integer $count * @param integer $total * @param array $results * @return boolean */ function import_library( $limit, $offset, &$count, &$total, &$results ) { global $wpdb; $count = 0; $total = 0; $results = array(); $upload_info = Util_Http::upload_info(); $uploads_use_yearmonth_folders = get_option( 'uploads_use_yearmonth_folders' ); $document_root = Util_Environment::document_root(); @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_import' ) ); if ( $upload_info ) { /** * Search for posts with links or images */ $sql = sprintf( 'SELECT ID, post_content, post_date FROM %sposts WHERE post_status = "publish" AND (post_type = "post" OR post_type = "page") AND (post_content LIKE "%%src=%%" OR post_content LIKE "%%href=%%") ', $wpdb->prefix ); if ( $limit ) { $sql .= sprintf( ' LIMIT %d', $limit ); if ( $offset ) { $sql .= sprintf( ' OFFSET %d', $offset ); } } $posts = $wpdb->get_results( $sql ); if ( $posts ) { $count = count( $posts ); $total = $this->get_import_posts_count(); $regexp = '~(' . $this->get_regexp_by_mask( $this->_config->get_string( 'cdn.import.files' ) ) . ')$~'; $config_state = Dispatcher::config_state(); $import_external = $config_state->get_boolean( 'cdn.import.external' ); foreach ( $posts as $post ) { $matches = null; $replaced = array(); $attachments = array(); $post_content = $post->post_content; /** * Search for all link and image sources */ if ( preg_match_all( '~(href|src)=[\'"]?([^\'"<>\s]+)[\'"]?~', $post_content, $matches, PREG_SET_ORDER ) ) { foreach ( $matches as $match ) { list( $search, $attribute, $origin ) = $match; /** * Check if $search is already replaced */ if ( isset( $replaced[$search] ) ) { continue; } $error = ''; $result = false; $src = Util_Environment::normalize_file_minify( $origin ); $dst = ''; /** * Check if file exists in the library */ if ( stristr( $origin, $upload_info['baseurl'] ) === false ) { /** * Check file extension */ $check_src = $src; if ( Util_Environment::is_url( $check_src ) ) { $qpos = strpos( $check_src, '?' ); if ( $qpos !== false ) { $check_src = substr( $check_src, 0, $qpos ); } } if ( preg_match( $regexp, $check_src ) ) { /** * Check for already uploaded attachment */ if ( isset( $attachments[$src] ) ) { list( $dst, $dst_url ) = $attachments[$src]; $result = true; } else { if ( $uploads_use_yearmonth_folders ) { $upload_subdir = date( 'Y/m', strtotime( $post->post_date ) ); $upload_dir = sprintf( '%s/%s', $upload_info['basedir'], $upload_subdir ); $upload_url = sprintf( '%s/%s', $upload_info['baseurl'], $upload_subdir ); } else { $upload_subdir = ''; $upload_dir = $upload_info['basedir']; $upload_url = $upload_info['baseurl']; } $src_filename = pathinfo( $src, PATHINFO_FILENAME ); $src_extension = pathinfo( $src, PATHINFO_EXTENSION ); /** * Get available filename */ for ( $i = 0; ; $i++ ) { $dst = sprintf( '%s/%s%s%s', $upload_dir, $src_filename, ( $i ? $i : '' ), ( $src_extension ? '.' . $src_extension : '' ) ); if ( !file_exists( $dst ) ) { break; } } $dst_basename = basename( $dst ); $dst_url = sprintf( '%s/%s', $upload_url, $dst_basename ); $dst_path = ltrim( str_replace( $document_root, '', Util_Environment::normalize_path( $dst ) ), '/' ); if ( $upload_subdir ) { Util_File::mkdir( $upload_subdir, 0777, $upload_info['basedir'] ); } $download_result = false; /** * Check if file is remote URL */ if ( Util_Environment::is_url( $src ) ) { /** * Download file */ if ( $import_external ) { $download_result = Util_Http::download( $src, $dst ); if ( !$download_result ) { $error = 'Unable to download file'; } } else { $error = 'External file import is disabled'; } } else { /** * Otherwise copy file from local path */ $src_path = $document_root . '/' . urldecode( $src ); if ( file_exists( $src_path ) ) { $download_result = @copy( $src_path, $dst ); if ( !$download_result ) { $error = 'Unable to copy file'; } } else { $error = 'Source file doesn\'t exists'; } } /** * Check if download or copy was successful */ if ( $download_result ) { $title = $dst_basename; $guid = ltrim( $upload_info['baseurlpath'] . $title, ',' ); $mime_type = Util_Mime::get_mime_type( $dst ); $GLOBALS['wp_rewrite'] = new \WP_Rewrite(); /** * Insert attachment */ $id = wp_insert_attachment( array( 'post_mime_type' => $mime_type, 'guid' => $guid, 'post_title' => $title, 'post_content' => '', 'post_parent' => $post->ID ), $dst ); if ( !is_wp_error( $id ) ) { /** * Generate attachment metadata and upload to CDN */ require_once ABSPATH . 'wp-admin/includes/image.php'; wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $dst ) ); $attachments[$src] = array( $dst, $dst_url ); $result = true; } else { $error = 'Unable to insert attachment'; } } } /** * If attachment was successfully created then replace links */ if ( $result ) { $replace = sprintf( '%s="%s"', $attribute, $dst_url ); // replace $search with $replace $post_content = str_replace( $search, $replace, $post_content ); $replaced[$search] = $replace; $error = 'OK'; } } else { $error = 'File type rejected'; } } else { $error = 'File already exists in the media library'; } /** * Add new entry to the log file */ $results[] = array( 'src' => $src, 'dst' => $dst_path, 'result' => $result, 'error' => $error ); } } /** * If post content was chenged then update DB */ if ( $post_content != $post->post_content ) { wp_update_post( array( 'ID' => $post->ID, 'post_content' => $post_content ) ); } } } } } /** * Rename domain * * @param array $names * @param integer $limit * @param integer $offset * @param integer $count * @param integer $total * @param integer $results * @return void */ function rename_domain( $names, $limit, $offset, &$count, &$total, &$results ) { global $wpdb; @set_time_limit( $this->_config->get_integer( 'timelimit.domain_rename' ) ); $count = 0; $total = 0; $results = array(); $upload_info = Util_Http::upload_info(); foreach ( $names as $index => $name ) { $names[$index] = str_ireplace( 'www.', '', $name ); } if ( $upload_info ) { $sql = sprintf( 'SELECT ID, post_content, post_date FROM %sposts WHERE post_status = "publish" AND (post_type = "post" OR post_type = "page") AND (post_content LIKE "%%src=%%" OR post_content LIKE "%%href=%%") ', $wpdb->prefix ); if ( $limit ) { $sql .= sprintf( ' LIMIT %d', $limit ); if ( $offset ) { $sql .= sprintf( ' OFFSET %d', $offset ); } } $posts = $wpdb->get_results( $sql ); if ( $posts ) { $count = count( $posts ); $total = $this->get_rename_posts_count(); $names_quoted = array_map( array( '\W3TC\Util_Environment', 'preg_quote' ), $names ); foreach ( $posts as $post ) { $matches = null; $post_content = $post->post_content; $regexp = '~(href|src)=[\'"]?(https?://(www\.)?(' . implode( '|', $names_quoted ) . ')' . Util_Environment::preg_quote( $upload_info['baseurlpath'] ) . '([^\'"<>\s]+))[\'"]~'; if ( preg_match_all( $regexp, $post_content, $matches, PREG_SET_ORDER ) ) { foreach ( $matches as $match ) { $old_url = $match[2]; $new_url = sprintf( '%s/%s', $upload_info['baseurl'], $match[5] ); $post_content = str_replace( $old_url, $new_url, $post_content ); $results[] = array( 'old' => $old_url, 'new' => $new_url, 'result' => true, 'error' => 'OK' ); } } if ( $post_content != $post->post_content ) { wp_update_post( array( 'ID' => $post->ID, 'post_content' => $post_content ) ); } } } } } /** * Returns attachments count * * @return integer */ function get_attachments_count() { global $wpdb; $sql = sprintf( 'SELECT COUNT(DISTINCT p.ID) FROM %sposts AS p LEFT JOIN %spostmeta AS pm ON p.ID = pm.post_ID AND pm.meta_key = "_wp_attached_file" LEFT JOIN %spostmeta AS pm2 ON p.ID = pm2.post_ID AND pm2.meta_key = "_wp_attachment_metadata" WHERE p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_value IS NOT NULL)', $wpdb->prefix, $wpdb->prefix, $wpdb->prefix ); return $wpdb->get_var( $sql ); } /** * Returns import posts count * * @return integer */ function get_import_posts_count() { global $wpdb; $sql = sprintf( 'SELECT COUNT(*) FROM %sposts WHERE post_status = "publish" AND (post_type = "post" OR post_type = "page") AND (post_content LIKE "%%src=%%" OR post_content LIKE "%%href=%%") ', $wpdb->prefix ); return $wpdb->get_var( $sql ); } /** * Returns rename posts count * * @return integer */ function get_rename_posts_count() { return $this->get_import_posts_count(); } /** * Returns regexp by mask * * @param string $mask * @return string */ function get_regexp_by_mask( $mask ) { $mask = trim( $mask ); $mask = Util_Environment::preg_quote( $mask ); $mask = str_replace( array( '\*', '\?', ';' ), array( '@ASTERISK@', '@QUESTION@', '|' ), $mask ); $regexp = str_replace( array( '@ASTERISK@', '@QUESTION@' ), array( '[^\\?\\*:\\|"<>]*', '[^\\?\\*:\\|"<>]' ), $mask ); return $regexp; } /** * media_row_actions filter * * @param array $actions * @param object $post * @return array */ function media_row_actions( $actions, $post ) { $actions = array_merge( $actions, array( 'cdn_purge' => sprintf( '' . __( 'Purge from CDN', 'w3-total-cache' ) . '', wp_nonce_url( sprintf( 'admin.php?page=w3tc_dashboard&w3tc_cdn_purge_attachment&attachment_id=%d', $post->ID ), 'w3tc' ) ) ) ); return $actions; } function is_running() { /** * CDN */ $running = true; /** * Check CDN settings */ $cdn_engine = $this->_config->get_string( 'cdn.engine' ); switch ( true ) { case ( $cdn_engine == 'ftp' && !count( $this->_config->get_array( 'cdn.ftp.domain' ) ) ): $running = false; break; case ( $cdn_engine == 's3' && ( $this->_config->get_string( 'cdn.s3.key' ) == '' || $this->_config->get_string( 'cdn.s3.secret' ) == '' || $this->_config->get_string( 'cdn.s3.bucket' ) == '' ) ): $running = false; break; case ( $cdn_engine == 'cf' && ( $this->_config->get_string( 'cdn.cf.key' ) == '' || $this->_config->get_string( 'cdn.cf.secret' ) == '' || $this->_config->get_string( 'cdn.cf.bucket' ) == '' || ( $this->_config->get_string( 'cdn.cf.id' ) == '' && !count( $this->_config->get_array( 'cdn.cf.cname' ) ) ) ) ): $running = false; break; case ( $cdn_engine == 'cf2' && ( $this->_config->get_string( 'cdn.cf2.key' ) == '' || $this->_config->get_string( 'cdn.cf2.secret' ) == '' || ( $this->_config->get_string( 'cdn.cf2.id' ) == '' && !count( $this->_config->get_array( 'cdn.cf2.cname' ) ) ) ) ): $running = false; break; case ( $cdn_engine == 'rscf' && ( $this->_config->get_string( 'cdn.rscf.user' ) == '' || $this->_config->get_string( 'cdn.rscf.key' ) == '' || $this->_config->get_string( 'cdn.rscf.container' ) == '' || !count( $this->_config->get_array( 'cdn.rscf.cname' ) ) ) ): $running = false; break; case ( $cdn_engine == 'azure' && ( $this->_config->get_string( 'cdn.azure.user' ) == '' || $this->_config->get_string( 'cdn.azure.key' ) == '' || $this->_config->get_string( 'cdn.azure.container' ) == '' ) ): $running = false; break; case ( $cdn_engine == 'mirror' && !count( $this->_config->get_array( 'cdn.mirror.domain' ) ) ): $running = false; break; case ( $cdn_engine == 'cotendo' && !count( $this->_config->get_array( 'cdn.cotendo.domain' ) ) ): $running = false; break; case ( $cdn_engine == 'edgecast' && !count( $this->_config->get_array( 'cdn.edgecast.domain' ) ) ): $running = false; break; case ( $cdn_engine == 'att' && !count( $this->_config->get_array( 'cdn.att.domain' ) ) ): $running = false; break; case ( $cdn_engine == 'akamai' && !count( $this->_config->get_array( 'cdn.akamai.domain' ) ) ): $running = false; break; } return $running; } }