Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@wpmudev-sls
Last active October 28, 2019 08:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wpmudev-sls/79fe3dd890bdde0c15911d96487a03be to your computer and use it in GitHub Desktop.
Save wpmudev-sls/79fe3dd890bdde0c15911d96487a03be to your computer and use it in GitHub Desktop.
[Snapshot] Sync backup files, reject large files
<?php
/**
* Plugin Name: [Snapshot] Sync backup files, reject large files
* Description: [Snapshot] Sync backup files, reject large files. Define SNAPSHOT_FILESET_LARGE_FILE_SIZE (in bytes) to limit max file size for backup, default is 15MB (15 * 1024 * 1024 bytes). Define SNAPSHOT_FILESET_STANDARD_FILE_SIZE (in bytes) to limit file size for sync uploads file, default is 1MB (1024 * 1024 bytes). We will generate a backup file have a name like this snapshot-sync***.zip, please keep on it for sync files - tested to 3.2.1.2 - 1125290498119891
* Version: 2.3
* Author: Thobk @ WPMUDEV
* Author URI: https://premium.wpmudev.org
* License: GPLv2 or later
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Short Description:
*
* This MU will create a standard backup file (snapshot-sync***.zip) to sync the files, and then while trying to create the backup file we will only backup the rest of files.
* + Default this MU will auto sync the uploads folders for standard file size (<= 1MB), define SNAPSHOT_FILESET_STANDARD_FILE_SIZE in bytes to change it.
* + And default we will reject all files have size more than 15MB, define SNAPSHOT_FILESET_LARGE_FILE_SIZE in bytes to change it,
* Ex: define('SNAPSHOT_FILESET_LARGE_FILE_SIZE', 20 * 1024 * 1024);
* + This MU will auto create an copy standard backup file to use later for perfomance (move is faster than copy), define SNAPSHOT_DISABLED_COPY_SYNC_FILE to disable it.
*
* ***** WARNING: This MU will modify Snapshot_Helper_Utility class so this can be conflict with the new update of Snapshot. So we suggest install this as a new plugin so you can see the update if have any update on this MU plugin. *****
*
*
* ---- Database ----
* + Default this MU will automatic daily sync db, you can define SNAPSHOT_RECURRENCE_SYNC_TABLES to change the frequence (daily, snapshot-weekly, snapshot-monthly, snapshot-yearly, default: daily)
* + Define SNAPSHOT_DISABLE_SYNC_DB to toggle disable auto sync database.
* + Define SNAPSHOT_TABLES_CHUNK_SIZE to set number tables auto sync in one section (one process), default is 5.
* + Define SNAPSHOT_MYSQLDUMP_MODE to set the MysqlDump mode (PHP | MYSQLDUMP), default will try to use MYSQLDUMP first, this is faster.
*
* ---- WP Core folders (wp-admin, wp-includes) ----
* + Define SNAPSHOT_DISABLE_SYNC_CORE to toggle disable auto sync wp-core folders => the core folders will auto update if have an upgrade version --- Note this MU will don't update if you manual download and upload the core folders.
*
* ---- Plugins/Themes ----
* After the standard backup file created, you can go to plugins/themes manager page to manual sync/reject plugins/themes. We suggest you try this each install new plugins.
* + We suggest to manual reject all plugins/themes that you don't need, it's good for performance. Also sync all the plugins/themes that you need.
* + As WP Cores folders, all plugins/themes synced will auto update if have any update on the version or remove from the standard backup file if the plugins/themes don't exist. And we suggest leave `sync` on list custom plugins/themes because these will not update if manual update them.
* + Default this MU disable option to manual sync for the active theme, define SNAPSHOT_ENABLE_SYNC_ACTIVE_THEME to enabled it.
*
*
* ---- Manual Sync Folders ----
* + Define SNAPSHOT_MANUAL_SYNC_FOLDERS as the serialize array folders to set automatic sync for these folders, ex:
* define('SNAPSHOT_MANUAL_SYNC_FOLDERS', serialize([
* 'wp-content/languages'
* ]));
* + Define SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE as the year to auto sync all the year's upload folders less than this, ex:
* define('SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE', date('Y') - 1);//now is 2019, this MU will auto sync all year upload folders before 2018 (2017, 2016, ...)
* + Define SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE as the year to auto reject all year's upload folders before this, ex:
* define('SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE', date('Y') - 4);
* + Default `manual sync folders` will auto monthly update if have new change, define SNAPSHOT_RECURRENCE_SYNC_FOLDERS to change it (snapshot-weekly, snapshot-monthly, snapshot-yearly).
* + Default this MU will not delete the old synced folder/files that defined from (SNAPSHOT_MANUAL_SYNC_FOLDERS or SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE) from the standard backup file if you have a change/new year, so you can toggle enable this by define SNAPSHOT_MANUAL_FORCE_REJECT (true|false)
*/
// re-order plugins make sure this MU load before snapshot plugin
add_filter( 'pre_update_site_option_active_sitewide_plugins', 'wpmudev_snapshot_make_sure_load_this_plugin_before_snapshot' );
add_filter( 'pre_update_option_active_plugins', 'wpmudev_snapshot_make_sure_load_this_plugin_before_snapshot' );
function wpmudev_snapshot_make_sure_load_this_plugin_before_snapshot( $active_plugins ){
$plugin_name = plugin_basename( __FILE__ );
if( $active_plugins ){
if( ( $plugin_pos = array_search( $plugin_name, $active_plugins ) ) !== false && $plugin_pos > 0 ){
unset( $active_plugins[ $plugin_pos ] );
array_unshift( $active_plugins, $plugin_name );
}
}
return $active_plugins;
}
// deactivate plugin
register_deactivation_hook( __FILE__, function(){
// remove crons
$crons = [
'snapshot_mu_backup_cron_prepare_sync_file',
'snapshot_mu_backup_cron_sync_file',
'snapshot_mu_backup_cron_sync_fail',
'snapshot_mu_backup_cron_sync_database',
'wpmudev-snapshot-controller-full-cron-start_sync',
'wpmudev_snapshot_clean_temp_zip_file',
'snapshot_mu_backup_cron_sync_folders'
];
foreach( $crons as $cron ){
wp_unschedule_hook( $cron );
}
});
add_action( 'plugins_loaded', 'wpmudev_snapshot_backup_reject_large_file_func', 100 );
function wpmudev_snapshot_backup_reject_large_file_func(){
if( ! is_main_site() ) return;
if( defined('SNAPSHOT_VERSION') && class_exists('WPMUDEVSnapshot') ){
class WPMUDEV_Snapshot_Reject_Large_File{
private static $_instance;
private static $_zip;
private $version = '2.3';
private $backup_session_folder;
private $transient_large_files;
private $backup_folder;
private $options_file;
private $backup_sync_folder;
private $max_file_size;
// private $can_call_func = false;
private $configs = [];
private $backup_sync_folder_name = 'snapshot-sync';
private $backup_cron_hook = 'snapshot_mu_backup_cron_sync_file';
private $database_cron_hook = 'snapshot_mu_backup_cron_sync_database';
private $manual_sync_folder_cron_hook = 'snapshot_mu_backup_cron_sync_folders';
private $manual_sync_activated_plugins_cron_hook = 'snapshot_mu_backup_cron_sync_activated_plugins';
private $core_cron_hook = 'snapshot_mu_backup_cron_sync_core';
private $fail_files_cron_hook = 'snapshot_mu_backup_cron_sync_fail';
private $prepare_backup_cron_hook = 'snapshot_mu_backup_cron_prepare_sync_file';
private $sync_cron_hook = 'wpmudev-snapshot-controller-full-cron-start_sync';
private $clean_cron_hook = 'wpmudev_snapshot_clean_temp_zip_file';
private $backup_sync_file;
private $backup_sync_file_copy;
private $options = [];
private $locking;
private $blog_upload_path;
private $log_fp;
private $regular_cron_item_key;
private $snapshot_backup_keys = ['regular' => 1, 'managed' => 1, 'regular_cron' => 1];
private $maybe_compress_options = [
'sync_files',
'manual_sync_themes',
'manual_sync_plugins',
'manual_sync_fail'
];
private $disable_sync;
private $file_options;
private static $ignore_dirs = array( '.', '..', '.svn', '.git', '.DS_Store' );
public function __construct(){
// set max file sizeof()
$this->set_max_file_size( 15 * 1024 * 1024 );
$this->transient_large_files = $this->get_transient( 'large_files_'. $this->max_file_size, array() );
// for regular backup
add_action( 'wp_ajax_snapshot_backup_ajax', array( $this, 'ajax_init_base_file_from_sync_file' ), 0);
add_action( 'wp_ajax_snapshot_restore_ajax', array( $this, 'ajax_init_restore' ), 0 );
add_filter( 'snapshot_limit_of_files_per_session', array( $this, 'set_chunk_size') );
add_action( 'admin_init', array( $this, 'maybe_create_event_backup_upload_folder' ) );
add_action( 'wp_ajax_snapshot_mu_backup_upload_folder', array( $this, 'create_event_backup_upload_folder' ) );
add_action( 'wp_ajax_nopriv_snapshot_mu_backup_upload_folder', array( $this, 'create_event_backup_upload_folder' ) );
add_action( $this->backup_cron_hook, array( $this, 'run_cron_backup_upload_folder') );
add_action( $this->fail_files_cron_hook, array( $this, 'run_cron_manual_sync_fail' ) );
add_action( $this->core_cron_hook, array( $this, 'run_cron_sync_core' ) );
if( ! $this->disable_copy_sync_file() ){
add_action( $this->prepare_backup_cron_hook, array( $this, 'prepare_cron_copy_version_backup_file' ) );
}
//for managed backup
add_action( 'wp_ajax_snapshot-full_backup-start', array( $this, 'locking_for_doing_managed_backup'), 0 );
add_action( 'snapshot-controller-full-cron-start_backup', array( $this, 'locking_for_doing_managed_backup'), 0 );
add_action( 'snapshot-controller-full-backup_start', array( $this, 'cron_init_full_backup' ) );
// add_action( 'snapshot-controller-full-backup_processing', array( $this, 'generate_tableset_session' ) );
add_action( 'snapshot-controller-full-cron-backup_start', array( $this, 'cron_init_full_backup' ) );
// add_action( 'snapshot-controller-full-cron-backup_processing', array( $this, 'generate_tableset_session' ) );
// finish backup
add_action( 'snapshot-controller-full-backup_finished', array( $this, 'prepare_finish_process' ) );
add_action( 'snapshot-controller-full-error', array( $this, 'prepare_finish_process' ) );
add_action( 'snapshot-controller-full-ajax_error_stop', array( $this, 'prepare_finish_process' ) );
add_action( 'snapshot-controller-full-cron-backup_finished', array( $this, 'prepare_finish_process' ) );
add_action( 'snapshot-controller-full-cron-error', array( $this, 'prepare_finish_process' ) );
add_action( 'wp_ajax_snapshot-full_backup-abort-processing', array( $this, 'prepare_finish_process' ), 9 );
// database
if( $this->enable_sync_database() ){
add_action( 'snapshot-controller-full-backup_processing', array( $this, 'generate_tableset_session' ) );
add_action( 'snapshot-controller-full-cron-backup_processing', array( $this, 'generate_tableset_session' ) );
add_action( $this->database_cron_hook, array( $this, 'run_cron_sync_database' ) );
add_filter( 'snapshot_queue_tableset_full', array( $this, 'use_utility_get_tables_func_insteadof'));
add_filter( 'snapshot_pre_get_database_tables', array( $this, 'multiple_site_list_tables') );
add_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
add_filter( 'snapshot_queue_fileset_reject_oversized', array( $this, 'will_reject_large_file'), 10, 3 );
// filter manifest
add_filter( 'wpmudev_snapshot_manifest_data', array( $this, 'update_manifest_file' ) );
}
add_action( $this->sync_cron_hook, array( $this, 'maybe_sync_new_files' ) );
add_action( 'init', array( $this, 'after_snapshot_init_proc' ), 11 );
if( $this->can_manage_items() ){
// media button
add_filter( 'media_row_actions', array( $this, 'add_media_action_sync_button' ), 10, 2);
// add_action( 'post_action_wpmudev_snapshot_manual_sync_media', array( $this, 'manual_sync_file_add' ) );
// add_action( 'post_action_wpmudev_snapshot_manual_unsync_media', array( $this, 'manual_unsync_file' ) );
add_action( 'attachment_submitbox_misc_actions', array( $this, 'add_media_single_action_sync_button') );
// add_action('admin_action_wpmudev_snapshot_manual_sync_theme', array( $this, 'manual_sync_theme_add'));
// add_action('admin_action_wpmudev_snapshot_manual_unsync_theme', array( $this, 'manual_unsync_theme'));
add_action( 'wp_ajax_wpmudev_snapshot_manual_media_sync', array( $this, 'manual_sync_file_add' ) );
add_action( 'wp_ajax_wpmudev_snapshot_manual_media_unsync', array( $this, 'manual_unsync_file' ) );
add_action( 'wp_ajax_wpmudev_snapshot_manual_media_reject', array( $this, 'manual_reject_file' ) );
add_action( 'wp_ajax_wpmudev_snapshot_manual_media_unreject', array( $this, 'manual_unreject_file' ) );
add_action('wp_ajax_wpmudev_snapshot_manual_theme_sync', array( $this, 'manual_sync_theme_add'));
add_action('wp_ajax_wpmudev_snapshot_manual_theme_unsync', array( $this, 'manual_unsync_theme'));
add_action( 'wp_ajax_wpmudev_snapshot_manual_theme_reject', array( $this, 'manual_reject_theme' ) );
add_action( 'wp_ajax_wpmudev_snapshot_manual_theme_unreject', array( $this, 'manual_unreject_directory' ) );
// plugin
if( is_multisite() ){
add_filter( 'network_admin_plugin_action_links', array( $this, 'add_plugin_sync_action'), 10, 3 );
add_filter( 'theme_action_links', array( $this, 'network_add_theme_sync_action'), 10, 2 );
}else{
add_filter( 'plugin_action_links', array( $this, 'add_plugin_sync_action'), 10, 3 );
// add theme action
add_action( 'admin_footer-themes.php', array( $this, 'add_theme_action_sync'));
}
add_action('wp_ajax_wpmudev_snapshot_manual_plugin_sync', array( $this, 'manual_sync_plugin'));
add_action('wp_ajax_wpmudev_snapshot_manual_plugin_unsync', array( $this, 'manual_unsync_plugin'));
add_action( 'wp_ajax_wpmudev_snapshot_manual_plugin_reject', array( $this, 'manual_reject_plugin' ) );
add_action( 'wp_ajax_wpmudev_snapshot_manual_plugin_unreject', array( $this, 'manual_unreject_directory' ) );
}
// sync plugin/theme on upgrade
add_action( 'upgrader_process_complete', array( $this, 'sync_upgrade_item'), 10, 2 );
// admin hook for notice
add_action( 'snapshot_page_snapshot_pro_snapshots', array( $this, 'snapshot_admin_notice' ) );
add_action( 'snapshot_page_snapshot_pro_managed_backups', array( $this, 'snapshot_admin_notice' ) );
// core
add_filter( 'update_option_wpmudev_snapshot_backup_manual_sync_core', array( $this, 'update_synced_core'), 10, 2 );
add_filter( 'update_site_option_wpmudev_snapshot_backup_manual_sync_core', array( $this, 'update_synced_core'), 10, 2 );
// filter exclude files, dirs
// if( ! $this->disabled_sync() ){
// filter options
$snapshot = $this->snapshot();
$snapshot_option = $snapshot->get_setting('options_key');
add_filter( 'option_'. $snapshot_option, array( $this, 'overwrite_exclude_files_option') );
add_filter( 'pre_update_option_'. $snapshot_option, array( $this, 'release_exclude_files_option') );
// regular cron
add_action( $snapshot->get_setting('backup_cron_hook'), array( $this, 'init_regular_cron' ), 0 );
add_action( $snapshot->get_setting('backup_cron_hook'), array( $this, 'finish_regular_cron' ), 11 );
// filter scandir
add_filter( 'snapshot_scandir', array( $this, 'scandir_filter' ), 10, 2 );
// }
add_filter( 'snapshot_scandir_file', array( $this, 'reject_large_file') );
add_action( 'admin_print_footer_scripts', array( $this, 'admin_footer_script') );
add_action( 'admin_enqueue_scripts', array( $this, 'custom_scripts' ), 11 );
// handle fata error
register_shutdown_function(array( $this, 'hander_error_shutdown') );
// trigger cron when use server cron
add_action( 'init', array( $this, 'run_immediate_cron' ) );
// clean schedule
add_action( $this->clean_cron_hook, array( $this, 'clean_temp_zip_file') );
// manual sync folders
if( $this->enable_sync_folders() ){
add_action( $this->manual_sync_folder_cron_hook, array( $this, 'run_cron_manual_sync_folders' ) );
}
// manual sync activated plugins
if( $this->enable_sync_activated_plugins() ){
add_action( $this->manual_sync_activated_plugins_cron_hook, array( $this, 'run_cron_manual_sync_activated_plugins' ) );
}
// cron complete
add_action( 'snapshot_mu_cron_complete_sync', array( $this, 'complete_sync_cron' ) );
// add yearly
add_filter( 'cron_schedules', array( $this, 'add_cron_schedules' ), 99 );
// maybe upgrade
add_action( 'admin_init', array( $this, 'maybe_upgrade' ), 0 );
}
public function __destruct(){
// save large files
if( isset( $this->options['update_large_files'] ) ){
$this->set_transient( 'large_files_'. $this->max_file_size, $this->transient_large_files );
}
}
public static function instance(){
if( is_null( self::$_instance ) ){
self::$_instance = new self();
}
return self::$_instance;
}
public function snapshot(){
return WPMUDEVSnapshot::instance();
}
public function disabled_wp_cron(){
return defined('DISABLE_WP_CRON') && DISABLE_WP_CRON;
}
public function maybe_trigger_immediate_cron(){
if( $this->disabled_wp_cron() ){
$this->set_transient( 'immediate_cron', 1 );
}
}
public function disable_immediate_cron(){
if( $this->disabled_wp_cron() ){
$this->delete_transient( 'immediate_cron' );
}
}
public function add_cron_schedules( $cron_schedules ){
$cron_schedules['snapshot-yearly'] = array(
'interval' => YEAR_IN_SECONDS, // 2,592,000
'display' => __( 'Yearly', 'snapshot' ),
);
return $cron_schedules;
}
public function run_immediate_cron(){
if( $this->disabled_wp_cron() && $this->get_transient( 'immediate_cron' ) ){
spawn_cron();
}
}
public function can_manage_items(){
if ( is_multisite() ) {
if ( ! is_super_admin() ) {
return;
}
} else {
if ( ! current_user_can( 'manage_snapshots_items' ) ) {
return;
}
}
return true;
}
public function get_file_option( $name, $default = array() ){
if( false !== $this->get_file_options() && isset( $this->file_options[ $name ] ) ){
return (array) $this->file_options[ $name ];
}
return $default;
}
public function get_file_options(){
if( is_null( $this->file_options ) ){
$this->load_config();
// $cache = wp_cache_get( 'snapshot_sync_file_options', 'snapshot-sync' );
// if( false === $cache ){
if( @file_exists( $this->options_file ) ){
if( Snapshot_Helper_Utility::connect_fs() ){
global $wp_filesystem;
$this->file_options = (array) json_decode( gzuncompress( $wp_filesystem->get_contents( $this->options_file ) ) );
}else{
$this->log('Cannot initialize filesystem');
$this->file_options = false;
}
}else{
$this->file_options = array();
}
// wp_cache_set( 'snapshot_sync_file_options', $this->file_options, 'snapshot-sync' );
// }
}
return $this->file_options;
}
public function save_file_option( $name, $option ){
if( false !== $this->get_file_options() ){
$this->file_options[ $name ] = $option;
global $wp_filesystem;
$wp_filesystem->put_contents( $this->options_file, gzcompress( json_encode( $this->file_options ) ) );
$this->save_option('have_change_options', 1, true);
// wp_cache_set( 'snapshot_sync_file_options', $this->file_options, 'snapshot-sync' );
}
}
public function get_option( $name, $default = array() ){
if( defined('SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE') && SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE && in_array( $name, $this->maybe_compress_options ) ){
return $this->get_file_option( $name );
}
if ( is_multisite() ) {
$option = get_site_option( "wpmudev_snapshot_backup_{$name}", $default );
} else {
$option = get_option( "wpmudev_snapshot_backup_{$name}", $default );
}
return $option;
}
public function save_option( $name, $option, $autoload = false ){
if( defined('SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE') && SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE && in_array( $name, $this->maybe_compress_options ) ){
return $this->save_file_option( $name, $option );
}
if ( is_multisite() ) {
$status = update_site_option( "wpmudev_snapshot_backup_{$name}", $option, $autoload );
} else {
$status = update_option( "wpmudev_snapshot_backup_{$name}", $option, $autoload );
}
return $status;
}
public function delete_option( $name ){
if ( is_multisite() ) {
$status = delete_site_option( "wpmudev_snapshot_backup_{$name}" );
} else {
$status = delete_option( "wpmudev_snapshot_backup_{$name}" );
}
return $status;
}
public function get_transient( $name, $default = false ){
if ( is_multisite() ) {
$option = get_site_transient( "wpmudev_snapshot_transient_{$name}" );
} else {
$option = get_transient( "wpmudev_snapshot_transient_{$name}" );
}
if( false === $option && false !== $default ){
$option = $default;
}
return $option;
}
public function set_transient( $name, $value, $expiration = 3600){
if ( is_multisite() ) {
$status = set_site_transient( "wpmudev_snapshot_transient_{$name}", $value, $expiration );
} else {
$status = set_transient( "wpmudev_snapshot_transient_{$name}", $value, $expiration );
}
return $status;
}
public function delete_transient( $name ){
if ( is_multisite() ) {
$status = delete_site_transient( "wpmudev_snapshot_transient_{$name}" );
} else {
$status = delete_transient( "wpmudev_snapshot_transient_{$name}" );
}
return $status;
}
public function load_config( $force=false ){
if( empty( $this->configs ) || $force ){
$this->configs = $this->get_option('config');
if( isset( $this->configs['backup_session_folder'] ) ){
$this->backup_session_folder = $this->configs['backup_session_folder'];
if( isset( $this->configs['backup_folder'] ) ){
$this->backup_folder = $this->configs['backup_folder'];
}else{
$this->backup_session_folder = false;
}
}
if( empty( $this->backup_session_folder ) ){
$this->get_backup_session_folder();
$this->configs['backup_session_folder'] = $this->backup_session_folder;
$this->configs['backup_folder'] = $this->backup_folder;
// update config
$this->save_config();
}
if( $this->enabled_save_sync_options_in_file() && isset( $this->configs['snapshot_item'] ) && $this->configs['snapshot_item'] ){
$this->options_file = trailingslashit( $this->backup_folder ) . $this->backup_sync_folder_name .'-options-'. $this->configs['snapshot_item'] .'.txt';
}
}
return true;
}
public function save_config(){
if( $this->configs && is_array( $this->configs ) ){
$this->save_option('config', $this->configs, true);
}
}
public function update_sync_files( $files ){
if( $files = $this->check_new_files( $files, $this->get_option('sync_files') ) ){
$this->save_option( 'sync_files', $files );
}
}
public function is_regular_backup(){
return 'regular' === $this->is_lock_for_doing_cron();
}
public function maybe_upgrade(){
if( ! defined('SNAPSHOT_MU_UPGRADING') ){
define('SNAPSHOT_MU_UPGRADING', 1);
$version = $this->get_option( 'version', '1.2' );
if( version_compare( $version, $this->version, '<' ) ){
if( version_compare( $version, '2.0', '<') ){
$this->upgrade_2_0();
$version = '2.0';
// $this->save_option('version', $version);
}
if( version_compare( $version, '2.2', '<') ){
$this->upgrade_2_2();
$version = '2.2';
// $this->save_option('version', $version);
}
$this->save_option('version', $this->version);
}
}
}
public function upgrade_2_0(){
$manual_sync_fail = $this->get_option('manual_sync_fail');
if( $manual_sync_fail ){
foreach( $manual_sync_fail as $item => $options ){
if( isset( $options['action'] ) ){
unset( $manual_sync_fail[ $item ] );
$action = $options['action'];
unset( $options['action'] );
$manual_sync_fail[ $item ][ $action ] = $options;
}
}
$this->save_option('manual_sync_fail', $manual_sync_fail);
}
}
public function upgrade_2_2(){
if( $this->get_option( 'manual_sync_folders' ) ){
$this->save_option('sync-folders-complete', 1);
}
if( $this->get_option( 'manual_sync_plugins' ) ){
$this->save_option('sync-plugins-complete', 1);
}
if( $this->get_option( 'manual_sync_tables' ) ){
$this->save_option('sync-db-complete', 1);
}
}
public function log( $message ){
if( $this->is_regular_backup() ){
if( is_null( $this->log_fp ) && isset( $_REQUEST['snapshot-item'], $_REQUEST['snapshot-data-item'] ) ){
$snapshot = $this->snapshot();
$backup_folder = $snapshot->get_setting('backupLogFolderFull');
$item_key = intval( $_REQUEST['snapshot-item'] );
$data_item_key = intval( $_REQUEST['snapshot-data-item'] );
$log_file = $backup_folder . "/" . $item_key . "_" . $data_item_key . ".log";
$this->log_fp = fopen( $log_file, 'a' );
}
if ( $this->log_fp ) {
fwrite( $this->log_fp, Snapshot_Helper_Utility::show_date_time( time(), 'Y-m-d H:i:s' ) . ": " . $message . "\r\n" );
fflush( $this->log_fp );
}else{
Snapshot_Helper_Log::warn( 'Regular - '. $message );
}
}else{
Snapshot_Helper_Log::warn( $message );
}
}
function hander_error_shutdown()
{
$a=error_get_last();
if($a !== null){
if( isset( $a['type'] ) ){
switch ($a['type']) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
Snapshot_Helper_Log::error(sprintf("Error code %s: %s!", $a['type'], $a['message'] ) );
$this->prepare_finish_process();
# code...
break;
default:
# code...
break;
}
}
}
}
// public function get_transient_large_files(){
// return $this->get_transient( 'large_files_'. $this->max_file_size, array() );
// }
public function get_current_url(){
return set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
}
public function notice_to_reset_backup_process(){
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-error-backup-sync';
$message = sprintf(__("If you have any error while trying to create the backup file, you can click <a href='%s'>here</a> to reset the process.", "snapshot"), add_query_arg('snapshot-force-cache',1, $this->get_current_url() ) );
printf( '<div data-dismissible="%1$s" class="%2$s"><p>%3$s</p></div>', $dismis_key, esc_attr( $class ), wp_kses( $message, array(
'strong' => array(),
'a'=> array(
'href'=>array(),
'onclick' => array()
),
'span' => array(
'id'=>array()
)
)
) );
}
public function snapshot_admin_notice(){
if( wp_doing_ajax() ) return;
if( isset( $_GET['snapshot-action'] ) && ( 'backup' === $_GET['snapshot-action'] || 'restore' === $_GET['snapshot-action'] ) ){
return;
}
// maybe call check sync cron
if( $this->get_sync_backup_file() && ! $this->get_sync_backup_copy_file() && $this->is_lock_for_doing_cron() === 'regular' ){
if( isset( $_GET['page'] ) && 'snapshot_pro_snapshots' === $_GET['page'] && ( ! isset( $_GET['snapshot-action'] ) || $_GET['snapshot-action'] !== 'backup') ){
// $this->prepare_finish_process();
$this->notice_to_reset_backup_process();
}else{
if( $this->disable_copy_sync_file() ){
// maybe have a abort the backup process, trigger finish backup action
if( time() - @filemtime( $this->snapshot()->get_setting('backupLogFolderFull') ) > 300){
// $this->prepare_finish_process();
$this->notice_to_reset_backup_process();
}
}else{
$cron_copy_file = wp_next_scheduled( $this->prepare_backup_cron_hook );
if( ! $cron_copy_file ){
// maybe have a abort the backup process, trigger finish backup action
// $this->prepare_finish_process();
$this->notice_to_reset_backup_process();
}
}
}
}
$this->load_config();
// add_action( 'admin_footer', array( $this, 'admin_disable_snapshot_button'), 100 );
if( ! $this->get_sync_backup_file() ){
if( ! empty( $this->configs['snapshot_item_processing'] ) ){
$timestamp = wp_next_scheduled( $this->backup_cron_hook, array( intval( $this->configs['snapshot_item']) ) );
if( $timestamp ){
$error = '';
if( ! empty( $this->configs['snapshot_item_error'] ) ){
$error = ' "'. $this->configs['snapshot_item_error'] .'"';
if( false !== strripos($error, 'connection timeout')){
if( ! isset( $this->configs['snapshot_current_standard_size'] ) ){
$this->configs['snapshot_current_standard_size'] = $this->get_standard_size();
$this->save_config();
$error .= sprintf( __('Your current standard size is %s, please try to reduce this by define SNAPSHOT_FILESET_STANDARD_FILE_SIZE in bytes in your wp-config.php file and check again.', 'snapshot' ), $this->configs['snapshot_current_standard_size'] );
}else{
if( $this->configs['snapshot_current_standard_size'] > $this->get_standard_size() ){
$message = __('Retrying to create the sync upload file', 'snapshot');
}
}
}else{
$error .= __(". If you can't manage it, welcome to WPMUDEV support ♥ !", "snapshot");
}
}else{
// $rest_time_new_cron = ( $timestamp - time() ) / 3600;
// if( $rest_time_new_cron && $rest_time_new_cron > 0.5 ){
// $error .= __(". If you can't manage it, welcome to WPMUDEV support ♥ !", "snapshot");
// }else{
$error = false;
// }
}
if( ! isset( $message ) && false !== $error ){
$message = sprintf(__('Have error while trying to create a sync backup file %s','snapshot'), $error);
}
}
if( ! isset( $message ) ){
$message = __('We are trying to create a sync backup file, please try a cup while waiting!', 'snapshot');
add_action( 'admin_footer', array( $this, 'admin_disable_snapshot_button'), 100 );
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync';
}
}else{
if( $this->get_sync_backup_copy_file() ){
$waiting_cron_prepare = wp_next_scheduled( $this->prepare_backup_cron_hook );
if( $waiting_cron_prepare && ($waiting_cron_prepare - time()) < 120 ){
if( ! $this->is_copying_file() && ( $waiting_cron_prepare - time() > 0 ) ){
$message = sprintf(__('Have a new change on sync backup file, wait a time for preparing a new copy version. It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','prepare-copyfile', $this->get_current_url() ) );
echo $this->script_coundown( $waiting_cron_prepare );
}else{
$message = __('Have a new change on sync backup file, we are preparing a copy version for performance.', 'snapshot');
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-new-copy';
}else{
$message = __('Great, go ahead and create your backup now!', 'snapshot');
$class = 'notice notice-success is-dismissible';
$dismis_key = 'wpmudev-snapshot-success-backup-sync';
}
}else{
if( $this->enable_sync_folders() &&
( $this->is_lock_for_doing_cron() === 'sync-folders'
|| ( $folder_in_progress = $this->get_transient( 'sync-folders-args' ) )
|| ! $this->get_option( 'sync-folders-complete' )
|| $this->get_transient( 'force-manual-sync-folders' )
)
){
$next_scheduled_sync_folders = wp_next_scheduled( $this->manual_sync_folder_cron_hook );
$folder_in_progress = isset( $folder_in_progress ) ? $folder_in_progress : $this->get_transient( 'sync-folders-args' );
if( $folder_in_progress ){
$folder_in_progress = array_splice($folder_in_progress, 0, 2 );
$folder_in_progress = ' ('. join( ', ', $folder_in_progress ) .',...)';
}
$message = sprintf(__('We are trying to sync the manual folders files%s. ', 'snapshot'), $folder_in_progress );
// $this->get_transient( 'sync-folders-args' ) || ! $this->is_lock_for_doing_cron() === 'sync-core' ||
if( $next_scheduled_sync_folders
&& ! $this->is_call_directly_sync_folders()
&& ( $delay = $next_scheduled_sync_folders - time() ) > 10
&& $delay < 90
){
$message = sprintf(__('We are trying to sync the manual folders files. It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','sync-folders', $this->get_current_url() ) );
echo $this->script_coundown( $next_scheduled_sync_folders );
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-folders';
}elseif(
$this->enable_sync_database() &&
( $this->is_lock_for_doing_cron() === 'sync-db'
|| ( $sync_db_args = $this->get_transient( 'sync-db-args' ) )
|| ! $this->get_option( 'sync-db-complete' )
)
){
$next_scheduled_sync_db = wp_next_scheduled( $this->database_cron_hook );
$sync_db_args = isset( $sync_db_args ) ? $sync_db_args : $this->get_transient( 'sync-db-args' );
if(
$next_scheduled_sync_db
&& ( $delay = $next_scheduled_sync_db - time() ) > 10
&& $delay < 90
&& ! $this->is_call_directly_sync_db()
){
$message = sprintf( __('The sync backup uploads file created, now we are trying to sync the database. It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','sync-db', $this->get_current_url() ) );
echo $this->script_coundown( $next_scheduled_sync_db );
}else{
$tables_in_progress = '';
if( $sync_db_args ){
$tables_in_progress = array_splice($sync_db_args, 0, 3 );
if( $tables_in_progress ){
$tables_in_progress = ' (Tables: '. join(', ', $tables_in_progress ) .',...)';
}
}
$message = sprintf(__('We are trying to sync the database%s. ', 'snapshot'), $tables_in_progress );
unset( $tables_in_progress );
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-db';
}elseif(
$this->enable_sync_core() &&
(
( $core_in_progress = $this->get_transient( 'sync-core-args' ) )
|| ! $this->is_synced_core()
)
){
// add_action( 'admin_footer', array( $this, 'admin_disable_snapshot_button'), 100 );
$next_scheduled_sync_core = wp_next_scheduled( $this->core_cron_hook);
$core_in_progress = isset( $core_in_progress ) ? $core_in_progress : $this->get_transient( 'sync-core-args' );
if( $core_in_progress ){
$core_in_progress = ' ('. $core_in_progress .')';
}
$message = sprintf(__('We are trying to sync the core files%s. ', 'snapshot'), $core_in_progress );
// $this->get_transient( 'sync-core-args' ) || ! $this->is_lock_for_doing_cron() === 'sync-core' ||
if( $next_scheduled_sync_core && ! $this->is_call_directly_sync_core() ){
$delay = $next_scheduled_sync_core - time();
if( $delay > 10 && $delay < 90 ){
$message = sprintf(__('We are trying to sync the core files. It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','sync-core', $this->get_current_url() ) );
echo $this->script_coundown( $next_scheduled_sync_core );
}
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-core';
}elseif(
$this->enable_sync_activated_plugins() &&
(
( $plugins_in_progress = $this->get_transient( 'sync-plugins-args' ) )
|| empty( $this->get_option( 'sync-plugins-complete' ) )
)
){
// add_action( 'admin_footer', array( $this, 'admin_disable_snapshot_button'), 100 );
$next_scheduled_sync_plugins = wp_next_scheduled( $this->manual_sync_activated_plugins_cron_hook);
$plugins_in_progress = isset( $plugins_in_progress ) ? $plugins_in_progress : $this->get_transient( 'sync-plugins-args' );
if( $plugins_in_progress ){
// $plugins_in_progress = array_splice($plugins_in_progress, 0, 2 );
$plugins_in_progress_str = '(';
$i = 0;
foreach( $plugins_in_progress as $plugin ){
if( $i > 0 ){
$plugins_in_progress_str .= ', ';
}
$plugins_in_progress_str .= dirname( $plugin );
if( $i >= 1 ){
break;
}
$i++;
}
$plugins_in_progress_str .=')';
$plugins_in_progress = $plugins_in_progress_str;
unset( $plugins_in_progress_str );
}
$message = sprintf(__('We are trying to sync the plugins %s... ', 'snapshot'), $plugins_in_progress );
// $this->get_transient( 'sync-plugins-args' ) || ! $this->is_lock_for_doing_cron() === 'sync-core' ||
if( $next_scheduled_sync_plugins && ! $this->is_call_directly_sync_activated_plugins() ){
$delay = $next_scheduled_sync_plugins - time();
if( $delay > 10 && $delay < 90 ){
$message = sprintf(__('We are trying to sync the activated plugins files. It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','sync-plugins', $this->get_current_url() ) );
echo $this->script_coundown( $next_scheduled_sync_plugins );
}
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-plugin';
}else{
if( ! $this->disable_copy_sync_file() ){
$message = __('The sync backup file created, now we are preparing a copy version for performance. ', 'snapshot');
$waiting_cron_prepare = wp_next_scheduled( $this->prepare_backup_cron_hook );
if( ! $this->is_copying_file() && ( $waiting_cron_prepare - time() > 10 ) ){
$message .= sprintf(__('It will start in <span id="wpmudev-snapshot-countdown"></span> or click <a onclick="wpmudevSnapshotStopCountDown()" href="%s">here</a> to trigger it now!', 'snapshot'), add_query_arg('snapshot-run','prepare-copyfile', $this->get_current_url() ) );
echo $this->script_coundown( $waiting_cron_prepare );
}
$class = 'notice notice-warning is-dismissible';
$dismis_key = 'wpmudev-snapshot-warning-backup-sync-copy';
}else{
$message = __('Great, go ahead and create your backup now!', 'snapshot');
$class = 'notice notice-success is-dismissible';
$dismis_key = 'wpmudev-snapshot-success-backup-sync';
}
}
}
$manual_sync_fail = $this->get_option('manual_sync_fail');
if( ! empty( $manual_sync_fail ) && ! $this->is_busy_for_doing('resync-fail-items')
&& ( ! isset( $dismis_key ) || ( $dismis_key === 'wpmudev-snapshot-warning-backup-sync-copy' || strpos( $dismis_key, 'wpmudev-snapshot-warning-backup-sync-' ) !== false ) )
){
add_action( 'admin_footer', array( $this, 'admin_disable_snapshot_button'), 100 );
if( 'resync-fail-items' === $this->locking || ( isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'resync-fail-items' ) ){
$message_fails = __('We are trying to resync the files, which are sync failed before.', 'snapshot');
}else{
$next_fail_sync = isset( $next_fail_sync ) ? $next_fail_sync : wp_next_scheduled( $this->fail_files_cron_hook );
if( $next_fail_sync ){
$message_fails = sprintf( __('We have some files are not successfull to sync from the sync backup file. It mean if you try to create the backup now, maybe the backup file will not working corectly. We will try to run again at %s or click <a href="%s">here</a> to trigger it now!', 'snapshot'), date( 'd/m/Y h:i:s', $next_fail_sync ), add_query_arg('snapshot-run','resync-fail-items', $this->get_current_url() ) );
}else{
$this->get_next_manual_sync_queue();
}
}
if( isset( $message_fails ) ){
if( isset( $dismis_key ) && $dismis_key === 'wpmudev-snapshot-success-backup-sync' ){
unset( $dismis_key );
}
$class_fail = 'notice notice-warning is-dismissible';
$dismis_key_fail = 'wpmudev-snapshot-warning-backup-sync-fail';
printf( '<div data-dismissible="%1$s" class="%2$s"><p>%3$s</p></div>', $dismis_key_fail, esc_attr( $class_fail ), wp_kses( $message_fails, array(
'strong' => array(),
'a'=> array(
'href'=>array(),
'onclick' => array()
),
'span' => array(
'id'=>array()
)
)
) );
}
}
}
if( isset( $dismis_key ) ){
printf( '<div data-dismissible="%1$s" class="%2$s"><p>%3$s</p></div>', $dismis_key, esc_attr( $class ), wp_kses( $message, array(
'strong' => array(),
'a'=> array(
'href'=>array(),
'onclick' => array()
),
'span' => array(
'id'=>array()
)
)
) );
if( $this->disabled_wp_cron() && strpos( $dismis_key, 'wpmudev-snapshot-warning') !== false ){
spawn_cron();
}
}
}
public function script_coundown( $time ){
$time += 1;
return '<script> var _snapshot_distance='. $time .';
var _snapshot_countdown = setInterval(function() {
var _now = new Date().getTime() / 1000;
var distance = _snapshot_distance - _now;
// Time calculations for minutes and seconds
var minutes = Math.floor((distance % (60 * 60)) / 60);
var seconds = Math.floor((distance % 60));
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(_snapshot_countdown);
location.reload();
}else{
document.getElementById("wpmudev-snapshot-countdown").innerHTML = minutes + "m " + seconds + "s ";
}
}, 1000);
function wpmudevSnapshotStopCountDown(){
clearInterval(_snapshot_countdown);
}
</script>';
}
public function is_busy_on_sync(){
$server_busy_on = $this->is_lock_for_doing_cron();
if( isset( $this->snapshot_backup_keys[ $server_busy_on ] ) ){
$server_busy_on = false;
}
return $server_busy_on;
}
public function custom_scripts(){
$custom_var_message_response = '';
if( $server_busy_on = $this->is_busy_on_sync() ){
switch ( $server_busy_on ) {
case 'prepare-copyfile':
$custom_var_message_response = __('Sorry, we are preparing a copy sync backup file for performance!', 'snapshot');
break;
case 'sync-db':
$custom_var_message_response = __('Sorry, we are trying to sync the Database!', 'snapshot');
break;
case 'sync-core':
$custom_var_message_response = __('Sorry, we are trying to sync the core files (wp-admin & wp-includes)!', 'snapshot');
break;
case 'resync-fail-items':
$custom_var_message_response = __('Sorry, we are trying to resync the files, which are sync failed before!', 'snapshot');
break;
case 'create-sync-backup':
$custom_var_message_response = __('Sorry, we are trying to create a sync backup file!', 'snapshot');
break;
default:
# code...
break;
}
if( ! empty( $custom_var_message_response ) ){
$custom_var_message_response = 'snapshot_messages.snapshot_failed = "'. $custom_var_message_response .'";';
wp_add_inline_script( 'snapshot-pro-admin', $custom_var_message_response );
}
}
}
public function is_copying_file(){
return ( isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'prepare-copyfile' ) || $this->is_lock_for_doing_cron() === 'prepare-copyfile';
}
public function admin_footer_script(){
global $pagenow;
$is_themes_page = $pagenow === 'themes.php';
$locked = $this->is_lock_for_doing_cron();
if( $locked ){
$locked = str_replace('-', ' ', $locked);
}
echo '<style>
.snapshot-hide{
display:none!important;
}
.snapshot-manual-sync.unsync,.snapshot-manual-sync.unreject{
color: #a00 !important;
}
.snapshot-manual-sync:after{
display: inline-block;
font: normal 20px/1 dashicons;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.snapshot-manual-sync.updating:after{
color: #f56e28;
content: "\f463";
animation: rotation 2s infinite linear;
}
.snapshot-manual-sync.updated:after{
color: #79ba49;
content: "\f147";
}
</style>
<script>
(function($){
$(function(){
var _ajax_url = "'. admin_url( 'admin-ajax.php' ) .'",
_locked = "'. $locked .'",
_nonce = "'. wp_create_nonce( 'wpmudev-manual-sync' ) .'",
_label = {
"unsync" : "'. ( $is_themes_page ? esc_js(__("Sync","snapshot") ) : esc_js(__("Snapshot Sync","snapshot") ) ) .'",
"sync": "'. ( $is_themes_page ? esc_js(__("Unsync","snapshot") ) : esc_js(__("Snapshot Unsync","snapshot") ) ) .'",
"reject": "'. ( $is_themes_page ? esc_js(__("Unreject","snapshot") ) : esc_js(__("Snapshot Unreject","snapshot") ) ) .'",
"unreject": "'. ( $is_themes_page ? esc_js(__("Reject","snapshot") ) : esc_js(__("Snapshot Reject","snapshot") ) ) .'",
},
_class = {
"sync" : "unsync",
"unsync" : "sync",
"reject" : "unreject",
"unreject" : "reject"
};
var _list_items = [], _previous_id = 0, _data_obj, _interval_items;
$(document.body).on("click", ".snapshot-manual-sync", function(e){
e.preventDefault();
var _this = $(this),
_group = _this.data("group"),
_id = _this.data("id"),
_sync_action = _this.data("action");
_sync_action = (_sync_action) ? _sync_action : "sync";
console.log(_sync_action);
if( _locked && _sync_action.indexOf("reject") === -1 ){
alert("Your server is busy on "+ _locked +", please try again later!");
return false;
}
if( ( _group ) && ( _id ) ){
_this.removeClass("updated").addClass("updating");
var _data = {
"action" : "wpmudev_snapshot_manual_" + _group + "_"+ _sync_action,
"id" : _id,
"nonce" : _nonce
};
_list_items.push({
data: _data,
element: _this,
action: _sync_action,
group: _group
});
_interval_items = setInterval( function(){
if( 0 === _previous_id ){
_previous_id = 1;
if( _list_items.length ){
_data_obj = _list_items.shift();
_previous_id = _data_obj.id;
_ajax_action( _data_obj.data, _data_obj.group, _data_obj.action, _data_obj.element );
}else{
clearInterval( _interval_items );
_previous_id = 0;
}
}
}, 1000);
}
});
function _ajax_action( _data, _group, _sync_action, _element ){
$.post({
"url" : _ajax_url,
"data" : _data
}).done(function(data){
_element.removeClass("updating");
if( data.success ){
_element.removeClass(_sync_action)
.addClass(_class[_sync_action] +" updated")
.text( _label[_sync_action ] )
.removeAttr("title")
.data("action", _class[_sync_action]);
if( _sync_action.indexOf("reject") > -1 ){
if( _group === "theme" ){
_element.siblings(".sync").toggleClass("snapshot-hide");
}else{
_element.parent().siblings(".snapshot_manual_sync").toggleClass("snapshot-hide");
}
}else{
if( _group === "theme" ){
_element.siblings(".reject").toggleClass("snapshot-hide");
}else{
_element.parent().siblings(".snapshot_manual_reject").toggleClass("snapshot-hide");
}
}
} else if ( data.data ){
alert( data.data );
}
_previous_id = 0;
}).fail( function( data, textStatus, jqXHR ){
if( jqXHR.responseText ){
alert("Error: "+ jqXHR.responseText);
window.location.reload();
return;
}else{
alert("Have error, please try again later!");
}
_element.removeClass("updating");
_previous_id = 0;
});
}
})
})(window.jQuery)
</script>';
}
public function admin_disable_snapshot_button(){
echo '<style>
.wpmud #wpbody #container.snapshot-three .wpmud-box-title a.button.button-blue, .wpmud #wpbody #container.snapshot-three .wpmud-box-title a.button.button-blue:hover{
border: 1px solid #b4b8b9 !important;
background: #b4b8b9 !important;
color: #fff !important;
cursor: default;
}
</style>';
echo '<script>
jQuery("#container.snapshot-three").find(".button-blue").attr({
"href": "javascript:void(0);",
"title": "'. esc_js(__("Sorry, I'm busy now, please try a cup and go back ♥", "snapshot") ) .'"
});
</script>';
}
public function get_attachment_edit_link_by_path( $file ){
$file = str_replace($this->get_root('uploads'), '', $file);
global $wpdb;
$attachment_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_type='attachment' AND guid LIKE '%{$file}' LIMIT 1;");
if( $attachment_id ){
return get_edit_post_link( $attachment_id );
}
return false;
}
public function is_zip_file($file){
return preg_match('!\.(zip|rar|gz|bz2)$!i', $file);
}
public function disabled_sync(){
if( is_null( $this->disable_sync ) ){
$this->disable_sync = $this->get_transient( 'disable_sync' );
}
return $this->disable_sync;
}
public function enable_sync_filter(){
$this->disable_sync = false;
return $this->delete_transient( 'disable_sync' );
}
public function complete_sync_cron( $doing_cron ){
// delete transsient args
$this->unlock_for_finish_cron();
if( $doing_cron !== 'create-sync-backup'){
$this->delete_transient( "{$doing_cron}-args" );
$this->save_option("{$doing_cron}-complete", 1);
}else{
$this->check_status_sync_backup();
}
switch ($doing_cron) {
case 'create-sync-backup':
if( $this->enable_sync_folders() ){
$this->create_schedule_sync_folders();
break;
}
$doing_cron = 'sync-folders';
case 'sync-folders':
// maybe sync database
if( $this->enable_sync_database() && ! $this->get_option( 'sync-db-complete' ) ){
$this->create_schedule_sync_database();
break;
}
$doing_cron = 'sync-db';
case 'sync-db':
if( $this->enable_sync_core() && ! $this->is_synced_core() ){
$this->create_schedule_sync_core();
break;
}
$doing_cron = 'sync-core';
case 'sync-core':
if( $this->enable_sync_activated_plugins() && $this->get_option( 'sync-plugins-complete' ) ){
$this->create_schedule_sync_activated_plugins();
break;
}
default:
// it's time prepare copy backup file
if( ! $this->get_sync_backup_copy_file() ){
$this->create_cron_prepare_copy_backup_file();
}
break;
}
}
public function clean_tempzip( $base, $zip_regex, $only_parent = false ){
$result = scandir($base);
$data = !empty($result) ? array_diff( $result, self::$ignore_dirs ) : array();
$now = current_time('timestamp');
foreach ( $data as $key => $value ) :
if ( ! $only_parent && is_dir( $base . '/' . $value ) ) :
$this->clean_tempzip( $base . '/' . $value, $zip_regex );
elseif ( is_file( $base . '/' . $value ) ) :
$file = false;
if( 'snapshot-backup.zip' === $value ){
$file = $base . '/' . $value;
}elseif( preg_match( $zip_regex, $value ) ){
$file = $base . '/' . $value;
}
if( $file && ( $now - @filemtime( $file ) > DAY_IN_SECONDS ) ){
// clean the file
@unlink( $file );
}
endif;
endforeach;
}
public function clean_temp_zip_file(){
// load config
$this->load_config();
$is_pclzip = false;
if( ! isset( $this->snapshot()->config_data['config']['zipLibrary'] ) ){
$this->snapshot()->load_config();
}
if( $this->snapshot()->config_data['config']['zipLibrary'] === 'PclZip' ){
$is_pclzip = true;
}
if( $is_pclzip ){
$zip_regex = '/pclzip-[\w]+(?:(?:\.zip)?\.tmp$|\.gz)/';
}else{
$zip_regex = '/\.zip\.(?:[\w]{6})$/';
}
$this->clean_tempzip( $this->backup_folder, $zip_regex );
if( $is_pclzip ){
$this->clean_tempzip( $this->get_home_path(), $zip_regex, 'only-root' );
}
}
public function will_reject_large_file( $could_reject, $file, $filesize ){
// if( ! defined('SNAPSHOT_DISABLE_LOG_EDIT_LARGE_FILE_LINK' ) && $edit_link = $this->get_attachment_edit_link_by_path( $file ) ){
// $this->log("Edit file link: {$edit_link}", "snapshot");
// }
// only reject plugin/theme file if it is zip archive type
if( ( strpos( $file, WP_PLUGIN_DIR) === 0 || 0 == strpos( $file, $this->get_root('themes')) ) && ! $this->is_zip_file($file) ){
$could_reject = false;
if( $filesize > 0 && defined('WP_DEBUG') && WP_DEBUG ){
$this->log("Large file: {$file} ({$filesize})", "snapshot");
}
}else{
$could_reject = true;
}
return $could_reject;
}
public function init_backup_file( $backup_file ){
if( ! $this->backup_sync_file ) return;
$status = false;
// $this->set_transient( 'init-backup', 1 );
if( $copy_file = $this->get_sync_backup_copy_file() ){
if( @rename( $copy_file, $backup_file ) ){
$status = true;
}
}elseif( @copy( $this->backup_sync_file, $backup_file ) ){
$status = true;
}
return $status;
}
public function prepare_finish_process(){
if( $this->is_lock_for_doing_cron() ){
switch ($this->locking) {
case 'regular':
case 'regular_cron':
case 'managed':
$this->delete_transient( 'init_backup_from_sync_file' );
break;
case 'sync-db':
delete_transient( 'sync-db-args' );
break;
case 'sync-core':
delete_transient( 'sync-core-args' );
break;
case 'restore':
if( empty( $this->get_sync_backup_file() ) ){
// keep holding on restore processing => don't excute backup process
$this->set_transient( 'lock-doing-cron', 'restore', 180 );
}
break;
default:
# code...
break;
}
$this->enable_sync_filter();
$this->unlock_for_finish_cron();
}
}
public function do_not_use_sync_backup(){
$this->set_transient('disable_sync', 1);
$this->disable_sync = 1;
$this->reset_exclude_files_option();
}
// Regular cron
public function init_regular_cron( $item_key ){
$snapshot = $this->snapshot();
$stop = $snapshot->maybe_should_it_stop();
if( $stop || empty( $snapshot->config_data['items'][ $item_key ] ) ){
return;
}
$this->lock_for_doing_cron('regular_cron');
if( 'all' !== $snapshot->config_data['items'][ $item_key ]['files-option'] || ! $this->get_sync_backup_file() ){
$this->do_not_use_sync_backup();
return;
}else{
$this->enable_sync_filter();
}
$this->regular_cron_item_key = $item_key;
add_filter( 'snapshot_scandir', array( $this, 'init_backup_file_for_regular_cron') );
}
public function finish_regular_cron( $item_key ){
$this->prepare_finish_process();
}
public function init_backup_file_for_regular_cron( $files ){
if( $this->regular_cron_item_key ){
remove_filter( 'snapshot_scandir', array( $this, 'init_backup_file_for_regular_cron') );
$backupFolderFull = trailingslashit( $this->snapshot()->get_setting('backupBackupFolderFull') ) . $this->regular_cron_item_key;
// $this->options['backupFolderFull'] = $backupFolderFull;
$backup_file = $backupFolderFull . '/snapshot-backup.zip';
// reset
$this->regular_cron_item_key = null;
if( ! @file_exists( $backup_file ) ){
$status = $this->init_backup_file( $backup_file );
if( ! $status ){
// go back default snapshot func
$this->do_not_use_sync_backup();
}
}
}
return $files;
}
// managed cron
public function locking_for_doing_managed_backup(){
$this->lock_for_doing_cron('managed');
// no return
}
public function cron_init_full_backup($backup)
{
$status = false;
if( $this->get_sync_backup_file() ){
// make sure enable sync filter
$this->enable_sync_filter();
// try sync new files
// if( ! wp_next_scheduled( $this->sync_cron_hook ) ){
// $this->maybe_sync_new_files();
// }
// lock copy hook while running cron
$this->lock_for_doing_cron('managed');
$status = $this->init_backup_file( $backup->get_archive_path('full') );
if( $status ){
Snapshot_Helper_Log::warn( sprintf("Backup Config: Max file size is %s", size_format( $this->max_file_size) ) );
// log files manual reject
$this->log_list_files_manual_reject();
}
}
if( ! $status ){
// go back default snapshot func
$this->do_not_use_sync_backup();
}
}
public function generate_tableset_session( $backup ){
if( ! $this->disabled_sync() ){
if( $backup->is_done() ){
$session = $backup::get_session('full');
if( isset( $session->data['queues'] ) ){
remove_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
$tableset = Snapshot_Model_Queue_Tableset::all('full');
$tableset->set_done();
$backup->add_queue( $tableset );
// $backup->save();
add_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
}
}else{
$this->lock_for_doing_cron('managed');
}
}
}
public function use_utility_get_tables_func_insteadof( $include_other ){
return false;
}
public function get_backup_sync_folder(){
if( is_null( $this->backup_sync_folder ) ){
$this->backup_sync_folder = trailingslashit( $this->backup_folder ) . 'sync/';
if( ! @file_exists( $this->backup_sync_folder ) ){
if( wp_mkdir_p( $this->backup_sync_folder ) ){
Snapshot_Helper_Utility::secure_folder( $this->backup_sync_folder);
}else{
wp_die(__("Can't create backup sync folder!","snapshot"));
}
}
}
return $this->backup_sync_folder;
}
public function zip_action( $files, $action='add', $root = 'uploads' ){
if( ! $this->get_sync_backup_file() ) return $files;
if( empty( $this->snapshot()->config_data['config']['zipLibrary'] ) ){
$this->snapshot()->load_config();
}
// $this->set_root( $root );
$files = (array) $files;
if ( "PclZip" === $this->snapshot()->config_data['config']['zipLibrary'] ) {
if ( ! class_exists('PclZip') ){
require_once(ABSPATH . '/wp-admin/includes/class-pclzip.php');
}
if( is_null( self::$_zip ) ){
self::$_zip = new PclZip( $this->backup_sync_file );
}
if( empty( self::$_zip ) ) return $files;
try {
$files = $this->pcl_zip_action( $files, $action, $root );
} catch (Exception $e){
$this->prepare_finish_process();
Snapshot_Helper_Log::error( sprintf( __("Error (%s) on PclZip: %s", "snapshot"), $this->locking, $e->getMessage() ) );
}
}else if( "ZipArchive" === $this->snapshot()->config_data['config']['zipLibrary'] ){
if( is_null( self::$_zip ) ){
self::$_zip = new ZipArchive();
}
$zip_status = self::$_zip->open( $this->backup_sync_file );
if( $zip_status !== true ){
Snapshot_Helper_Log::error( sprintf( __("Can't open zip file %s. Error code: %s", "snapshot"), $this->backup_sync_file, $zip_status ) );
return $files;
}
try {
$files = $this->zip_archive_action( $files, $action, $root );
} catch (Exception $e){
$this->prepare_finish_process();
Snapshot_Helper_Log::error( sprintf( __("Error (%s) on ZipArchive: %s", "snapshot"), $this->locking, $e->getMessage() ) );
}
if( self::$_zip ){
self::$_zip->close();
}
}
return $files;
}
public function pcl_zip_action( $files, $action='add', $root ){
$list_files = array_keys( $files );
if( $root === 'database' ){
$home_path = $this->get_root( $root );
$backup_root = '/';
}else{
$home_path = apply_filters( 'snapshot_home_path', $this->get_home_path() );
$backup_root = 'www/';
}
switch ($action) {
case 'add':
$root = $this->get_root( $root );
foreach( $list_files as $key => $file ){
$list_files[ $key ] = $root . $file;
}
$zip_add_rest = self::$_zip->add(
$list_files,
PCLZIP_OPT_REMOVE_PATH, $home_path,
PCLZIP_OPT_ADD_PATH, $backup_root,
PCLZIP_OPT_TEMP_FILE_THRESHOLD, 10,
PCLZIP_OPT_ADD_TEMP_FILE_ON
);
if ( ! $zip_add_rest ) {
return $files;
}
break;
case 'delete':
foreach( $list_files as $key => $file ){
$list_files[ $key ] = $backup_root . $this->get_zip_path( $root ) . $file;
}
$zip_del_rest = self::$_zip->delete( PCLZIP_OPT_BY_NAME, $list_files );
if ( ! $zip_del_rest ) {
return $files;
}
break;
default:
# code...
break;
}
return false;
}
public function zip_archive_action($files, $action = 'add', $root = 'uploads'){
$limit = $this->get_chunk_size();
$count = 0;
$backup_root = $root === 'database' ? '/' : 'www/';
$zip_path = $backup_root . $this->get_zip_path( $root );
$root_path = $this->get_root( $root );
foreach ($files as $file => $filetime) {
$count++;
$zip_file_path = $zip_path . $file;
$zip_file_path = wp_normalize_path($zip_file_path);
if( $action === 'add' ){
$file_path = $root_path . $file;
$file_path = wp_normalize_path($file_path);
if (!file_exists($file_path)) continue;
if( self::$_zip->addFile($file_path, $zip_file_path) ){
unset( $files[ $file ] );
}
// if( $count > 5){
// return $files;
// }
}elseif( $action === 'delete' ){
if( self::$_zip->deleteName( $zip_file_path ) ){
unset( $files[ $file ] );
}
// if( $count > 5){
// return $files;
// }
}
/*
Apparently, there is a limit to the number of files that can be added at once.
So we are setting a limit of 200 files per add session.
Then we close the archive and re-open.
*/
if ($count >= $limit) {
self::$_zip->close();
self::$_zip->open($this->backup_sync_file);
$count = 0;
}
}
return $files;
}
public function check_new_files( $new_files, $old_files, $is_upload = true ){
if( empty( $old_files ) ) return $new_files;
if( ! $this->get_sync_backup_file() ) return false;
$old_files = (array) $old_files;
$new_sync_files = array_diff_key( $new_files, $old_files );
if( $is_upload ){
$manual_sync_files = $this->get_manual_sync_files();
$delete_files = array_diff_key( $old_files, $new_files, $manual_sync_files );
}else{
$delete_files = array_diff_key( $old_files, $new_files );
}
$exist_new = ! empty( $new_sync_files );
foreach( $new_files as $file => $filetime ){
if( $exist_new && isset( $new_sync_files[$file] ) ){
continue;
}
if( $filetime > $old_files[ $file ] ){
$new_sync_files[ $file ] = $filetime;
}
}
$changed = false;
if( $delete_files ){
$delete_files = $this->zip_action( $delete_files, 'delete');
if( ! empty( $delete_files ) ){
$new_files = array_merge( $delete_files, $new_files );
}
$changed = true;
}
if( ! empty( $new_sync_files ) ){
$new_sync_files = $this->zip_action( $new_sync_files );
if( ! empty( $new_sync_files ) ){
$new_files = array_diff_key( $new_files, $new_sync_files );
}
$changed = true;
}
if( $changed ){
if( $this->get_sync_backup_copy_file() ){
@unlink( $this->backup_sync_file_copy );
}
return $new_files;
}
return false;
}
public function get_manual_sync_files( $force = false )
{
$manual_sync_files = (array) $this->get_option('manual_sync_files');
if( $force && ! empty( $manual_sync_files ) ){
$delete_files = [];
foreach( $manual_sync_files as $file => $id ){
if( @file_exists( $this->get_root('uploads') . $file ) ){
$delete_files[ $file ] = $id;
unset( $manual_sync_files[ $file ] );
}
}
if( ! empty( $delete_files ) ){
$delete_files = $this->zip_action( $delete_files, 'delete' );
if( ! empty( $delete_files ) && is_array( $delete_files ) ){
// add list files can't delete back
$manual_sync_files = array_merge( $manual_sync_files, $delete_files );
}
$this->save_option('manual_sync_files', $manual_sync_files);
}
}
return apply_filters( 'wpmudev_snapshot_manual_sync_files', $manual_sync_files );
}
public function get_manual_sync_themes( $force=false, $active_theme = false, $all_themes = false )
{
$manual_sync_themes = (array) $this->get_option('manual_sync_themes');
if( ! empty( $manual_sync_themes ) ){
$all_themes = $all_themes ?: wp_get_themes();
if( ! is_array( $active_theme ) ){
$active_theme = $this->get_active_themes();
}
$delete_themes = [];
foreach( $manual_sync_themes as $theme_id => $v ){
if( ! isset( $all_themes[ $theme_id ] ) || in_array( $theme_id, $active_theme) ){
$delete_themes[] = $theme_id;
unset( $manual_sync_themes[ $theme_id ] );
}
}
if( $force && ! empty( $delete_themes ) ){
$delete_themes = $this->manual_unsync_items( $delete_themes, 'themes' );
$this->save_option( 'manual_sync_themes', $manual_sync_themes );
}
}
return apply_filters( 'wpmudev_snapshot_manual_sync_themes', $manual_sync_themes );
}
public function release_exclude_files_option( $options ){
if( $this->is_snapshot_setting_screen() ){
return $options;
}
if( isset( $this->options['filesIgnore'] ) && isset( $options['config']['filesIgnore'] ) ){
$options['config']['filesIgnore'] = $this->options['filesIgnore'];
}
if( isset( $this->options['filesManagedIgnore'] ) && isset( $options['config']['filesManagedIgnore'] ) ){
$options['config']['filesManagedIgnore'] = $this->options['filesManagedIgnore'];
}
return $options;
}
public function is_snapshot_setting_screen(){
if( is_admin() && isset( $_POST['filesIgnore'] ) || isset( $_POST['managed-backup-files-ignore'] ) || isset( $_GET['snapshot-action'] ) || ( isset( $_GET['page'] ) && in_array($_GET['page'], array('snapshot_pro_settings', 'snapshot_pro_managed_backups')) ) ){
return true;
}
return false;
}
public function detect_dirs_ignore($pattern, $key, &$option_ignore, $section='media'){
$pos_path = strpos( $pattern, $option_ignore[$section]['folder']);
$origin_pattern = $pattern;
if( false !== $pos_path ){
if( $pos_path ){
if( @is_dir( $pattern ) ){
$option_ignore['dir'][untrailingslashit( realpath( $pattern ) )] = 1;
unset( $option_ignore['all'][ $key ] );
}else{
$pos_path = ( $option_ignore[$section]['folder'] === $option_ignore[$section]['path'] ) ? $pos_path : strpos( $pattern, $option_ignore[$section]['path'] );
if( false !== $pos_path ){
$pattern = $option_ignore[$section]['root'] . substr( $pattern, $pos_path + strlen( $option_ignore[$section]['path'] ) );
if( @is_dir( $pattern ) ){
$option_ignore['dir'][ untrailingslashit( realpath( $pattern ) ) ] = 1;
unset( $option_ignore['all'][ $key ] );
}else{
$option_ignore['all'][ $key ] = $pattern;
}
}else{
// keep it - don't look like wp core folder
$option_ignore['not_filtered'][ $origin_pattern ] = 1;
}
}
}else{
$pattern = $option_ignore[$section]['root'] . substr( $pattern, strlen( $option_ignore[$section]['folder'] ) );
if( @is_dir( $pattern ) ){
$option_ignore['dir'][ untrailingslashit( realpath( $pattern ) ) ] = 1;
unset( $option_ignore['all'][ $key ] );
}else{
$option_ignore['all'][ $key ] = $pattern;
}
}
}else{
$option_ignore['not_filtered'][ $origin_pattern ] = 1;
}
return $option_ignore;
}
public function get_core_folder_info( $section ='uploads' ){
$folder = [];
$folder['root'] = $this->get_root( $section );
$folder['path'] = $this->get_zip_path( $section );
if( strpos( $folder['root'], WP_CONTENT_DIR) !== false ){
$folder['folder'] = trailingslashit( ltrim( str_replace( WP_CONTENT_DIR, '', $folder['root'] ), '/') );
}else{
$folder['folder'] = $folder['path'];
}
return $folder;
}
public function retrieve_dirs_ignore($pattern_excludes){
if( ! empty( $pattern_excludes ) ){
$pattern_excludes = (array) $pattern_excludes;
$option_ignore['all'] = $pattern_excludes;
$option_ignore['dir'] = [];
$option_ignore['not_filtered'] = [];
$option_ignore['media'] = $this->get_core_folder_info('uploads');
$option_ignore['themes'] = $this->get_core_folder_info('themes');
$option_ignore['plugins'] = $this->get_core_folder_info('plugins');
// home path
$home_path = $this->get_home_path();
// wp-content
$option_ignore['wp-content'] = array(
'path' => 'wp-content',
'root' => WP_CONTENT_DIR,
'folder' => 'wp-content'
);
// core
$option_ignore['wp-admin'] = array(
'path' => 'wp-admin',
'root' => $home_path .'wp-admin',
'folder' => 'wp-admin'
);
$option_ignore[WPINC] = array(
'path' => WPINC,
'root' => $home_path . WPINC,
'folder' => WPINC
);
$root = dirname( $home_path );
if( $root !== '.' ){
$public_html_folder = trailingslashit( ltrim(str_replace( $root, '', $home_path ), '/' ) );
$option_ignore['root'] = array(
'path' => $public_html_folder,
'root' => $home_path,
'folder' => $public_html_folder
);
}
foreach( $pattern_excludes as $key => $pattern ){
// check belong to uploads
$pattern = trim( $pattern );
if( empty( $pattern ) ){
unset( $option_ignore['all'][ $key ] );
continue;
}
if( is_file( $pattern ) ) continue;
if( @is_dir( $pattern ) ){
$option_ignore['dir'][ untrailingslashit( realpath( $pattern ) ) ] = 1;
unset( $option_ignore['all'][ $key ] );
continue;
}
// check uploads
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'media');
// check themes
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'themes');
// check plugins
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'plugins');
// check wp-content
if( isset( $option_ignore['not_filtered'][ $pattern ] ) ){
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'wp-content');
}
// check wp-admin
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'wp-admin');
// check wp-includes
$this->detect_dirs_ignore($pattern, $key, $option_ignore, WPINC);
// check root path
if( isset( $option_ignore['root'] ) && isset( $option_ignore['not_filtered'][ $pattern ] ) ){
$this->detect_dirs_ignore($pattern, $key, $option_ignore, 'root');
}
}
}
return [$option_ignore['all'], $option_ignore['dir']];
}
public function get_snapshot_upload_folder( $backup_folder ){
if( is_null( $this->backup_folder ) ){
$configs = $this->get_option('config');
if( isset( $configs['backup_folder'] ) ){
$this->backup_folder = trim( $configs['backup_folder'] );
}else{
$backup_folder = str_replace( '\\', '/', $backup_folder );
// Are we dealing with Abolute or relative path?
if ( '/' === ( substr( $backup_folder, 0, 1 ) )
|| ':/' === ( substr( $backup_folder, 1, 2 ) )
) {
$this->backup_folder = trailingslashit( $backup_folder );
} else {
// If relative then we store the files into the /uploads/ folder tree.
$this->backup_folder = $this->get_root('uploads') . $backup_folder;
}
}
}
return $this->backup_folder;
}
public function overwrite_exclude_files_option( $options ){
if( $this->is_snapshot_setting_screen() ){
return $options;
}
if( ! isset( $this->options['filtered_options'] ) ){
$this->options['filesIgnore'] = array();
$this->options['filesManagedIgnore'] = array();
if( ! empty( $options['config']['filesIgnore'] ) ){
$options['config']['filesIgnore'] = (array) $options['config']['filesIgnore'];
$this->options['filesIgnore'] = $options['config']['filesIgnore'];
list( $options['config']['filesIgnore'], $options['config']['dirsIgnore'] ) = $this->retrieve_dirs_ignore( $options['config']['filesIgnore'] );
}else{
$options['config']['filesIgnore'] = array();
$options['config']['dirsIgnore'] = array();
}
if( ! isset( $options['config']['managedBackupExclusions'] ) || $options['config']['managedBackupExclusions'] === 'global' ){
$options['config']['filesManagedIgnore'] = $options['config']['filesIgnore'];
$options['config']['dirsManagedIgnore'] = $options['config']['dirsIgnore'];
}else{
if( ! empty( $options['config']['filesManagedIgnore'] ) ){
$options['config']['filesManagedIgnore'] = (array) $options['config']['filesManagedIgnore'];
$this->options['filesManagedIgnore'] = $options['config']['filesManagedIgnore'];
list( $options['config']['filesManagedIgnore'], $options['config']['dirsManagedIgnore'] ) = $this->retrieve_dirs_ignore( $options['config']['filesManagedIgnore'] );
}else{
$options['config']['filesManagedIgnore'] = array();
$options['config']['dirsManagedIgnore'] = array();
}
}
// exclude snapshot upload directory
$options['backupFolder'] = empty( $options['backupFolder'] ) ? 'snapshots' : $options['backupFolder'];
$snapshot_upload = $this->get_snapshot_upload_folder( $options['backupFolder'] );
$options['config']['dirsIgnore'][ $snapshot_upload ] = 1;
$options['config']['dirsManagedIgnore'][ $snapshot_upload ] = 1;
// save original options
$this->options['filtered_origin_options'] = $options;
$home_path = $this->get_home_path();
// disabled sync filter
if( ! $this->disabled_sync() ){
// manual reject upload folders
$manual_reject_upload_folders = $this->get_reject_upload_folders();
if( $manual_reject_upload_folders ){
foreach( $manual_reject_upload_folders as $dir ){
$dir = $home_path . $dir;
$options['config']['dirsIgnore'][$dir] = 1;
$options['config']['dirsManagedIgnore'][$dir] = 1;
}
}
// manual sync folders
$manual_sync_folders = $this->get_sync_folders();
if( $manual_sync_folders ){
foreach( $manual_sync_folders as $dir ){
$dir = $home_path . $dir;
$options['config']['dirsIgnore'][$dir] = 1;
$options['config']['dirsManagedIgnore'][$dir] = 1;
}
}
// save original options
$this->options['filtered_uploads_options'] = $options;
}
// reject dirs/files
$manual_reject_files = $this->get_manual_reject_files();
$manual_reject_dirs = $this->get_manual_reject_dirs();
if( ! empty( $manual_reject_dirs ) ){
// $home_path = $this->get_home_path();
foreach( $manual_reject_dirs as $dir ){
$dir = $home_path . $dir;
$options['config']['dirsIgnore'][$dir] = 1;
$options['config']['dirsManagedIgnore'][$dir] = 1;
}
}
if( ! empty( $manual_reject_files ) ){
$exclude_files = array();
foreach( $manual_reject_files as $media_id => $files ){
$files = array_map(function($file){
return $this->get_root('uploads') . $file;
}, $files);
$exclude_files = array_merge( $exclude_files, $files );
}
$options['config']['filesIgnore'] = array_unique( array_merge( $this->options['filesIgnore'], $exclude_files ) );
$options['config']['filesManagedIgnore'] = array_unique( array_merge( $this->options['filesManagedIgnore'], $exclude_files ) );
}
if( ! isset( $this->options['exclude_files'] ) ){
$exclude_files = (array) $this->get_option('sync_files');
$manual_sync_files = $this->get_manual_sync_files();
$manual_sync_themes = $this->get_manual_sync_themes();
$manual_sync_plugins = $this->get_manual_sync_plugins();
$exclude_files = array_merge( $exclude_files, $manual_sync_files );
if( ! empty( $exclude_files ) ){
$exclude_files = array_keys( $exclude_files );
$exclude_files = array_map(function($file){
return $this->get_root('uploads') . $file;
}, $exclude_files);
}
if( ! empty( $manual_sync_themes ) ){
$root_themes = $this->get_root('themes');
foreach( $manual_sync_themes as $theme_id => $v ){
$theme_dir = $root_themes . $theme_id;;
$options['config']['dirsIgnore'][$theme_dir] = 1;
$options['config']['dirsManagedIgnore'][$theme_dir] = 1;
}
}
if( ! empty( $manual_sync_plugins ) ){
$root_plugins = $this->get_root('plugins');
foreach( $manual_sync_plugins as $plugin_file => $v ){
$plugin_dir = $root_plugins . dirname( $plugin_file );
$options['config']['dirsIgnore'][$plugin_dir] = 1;
$options['config']['dirsManagedIgnore'][$plugin_dir] = 1;
}
}
if( $this->enable_sync_core() ){
$synced_core = $this->get_option('synced_core');
if( $synced_core ){
$root_core = $this->get_root();
foreach( $synced_core as $core_dir ){
$core_dir = $root_core . $core_dir;
$options['config']['dirsIgnore'][$core_dir] = 1;
$options['config']['dirsManagedIgnore'][$core_dir] = 1;
}
}
}
$this->options['exclude_files'] = $exclude_files;
// exclude large files
if( $this->transient_large_files ){
$this->options['exclude_files'] = array_merge( $this->options['exclude_files'], $this->transient_large_files );
}
}
if( ! empty( $this->options['exclude_files'] ) ){
$options['config']['filesIgnore'] = array_unique( array_merge( $this->options['filesIgnore'], $this->options['exclude_files'] ) );
$options['config']['filesManagedIgnore'] = array_unique( array_merge( $this->options['filesManagedIgnore'], $this->options['exclude_files'] ) );
}
$this->options['filtered_options'] = $options;
}else{
$options = $this->options['filtered_options'];
}
return $options;
}
public function scandir_filter( $result, $base ){
if( $lock_key = $this->is_lock_for_doing_cron() ){
$exclude_key = false;
if( $lock_key == 'managed' ){
$exclude_key = 'dirsManagedIgnore';
}elseif( in_array( $lock_key, ['regular', 'regular_cron', 'create-sync-backup'] ) ){
$exclude_key = 'dirsIgnore';
}
if( isset( $this->options['snapshot-mu-scanning'] ) ){
if( $exclude_key ){
if( isset( $this->options['filtered_uploads_options']['config'] ) ){
$filtered_options = $this->options['filtered_uploads_options']['config'];
}elseif( isset( $this->options['filtered_origin_options']['config'] ) ){
$filtered_options = $this->options['filtered_origin_options']['config'];
}
if( isset( $filtered_options ) && ! empty( $filtered_options[ $exclude_key ] ) && isset( $filtered_options[ $exclude_key ][ $base ] ) ){
$result = array();
}
}
}else{
if( $exclude_key && ! empty( $this->snapshot()->config_data['config'][ $exclude_key ] ) && isset( $this->snapshot()->config_data['config'][ $exclude_key ][ $base ] ) ){
$result = array();
}
}
}
return $result;
}
public function reject_large_file( $file ){
if( ! isset( $this->transient_large_files[ $file ] ) ){
$filesize = @filesize( $file );
if( $filesize > $this->max_file_size ){
$filesize = size_format( $filesize );
$this->log("Reject {$file} ({$filesize}) because of the size constraint.", "snapshot");
$this->transient_large_files[ $file ] = 1;
$file = false;//reject this file;
}
}else{
$file = false;
}
return $file;
}
// rest original
public function reset_exclude_files_option($exclude_files = array()){
if( isset( $this->options['filtered_options'] ) ){
$this->options['_filtered_options'] = $this->options['filtered_options'];
$this->options['_exclude_files'] = $this->options['exclude_files'];
unset( $this->options['filtered_options'] );
}
$this->options['exclude_files'] = $exclude_files;
$this->snapshot()->load_config();
}
// reset to filtered
public function back_to_filtered_exclude_files_option(){
if( isset( $this->options['_filtered_options'] ) ){
$this->options['filtered_options'] = $this->options['_filtered_options'];
$this->options['exclude_files'] = $this->options['_exclude_files'];
}
$this->snapshot()->load_config();
}
public function get_backup_session_folder(){
$snapshot = $this->snapshot();
if( ! $snapshot->get_setting('backupSessionFolderFull') ){
$snapshot->load_config();
$snapshot->set_backup_folder();
$snapshot->set_log_folders();
}
$this->backup_session_folder = $snapshot->get_setting('backupSessionFolderFull');
$this->backup_folder = $snapshot->get_setting('backupBaseFolderFull');
return $this->backup_session_folder;
}
public function clear_old_backup_sync_data( $data, $keep_item_data_key ){
$snapshot = $this->snapshot();
$snapshot_item_key = (int) $this->configs['snapshot_item'];
if( ! empty( $data ) ){
foreach ( $data as $item_data_key => $item_data ) {
if ( isset( $item_data['filename'] ) && $item_data_key !== $keep_item_data_key ) {
$backupFile = trailingslashit( $this->backup_folder ) . $item_data['filename'];
if ( @is_writable( $backupFile ) ) {
$copy_file = $this->get_backup_file_copy_name();
if( @is_writable( $copy_file ) ){
@unlink( $copy_file );
}
@unlink( $backupFile );
}
}
if ( isset( $item_data['timestamp'] ) ) {
$backupLogFileFull = trailingslashit( $snapshot->get_setting('backupLogFolderFull') ) . $snapshot_item_key . "_" . $item_data['timestamp'] . ".log";
if ( @is_writable( $backupLogFileFull ) ) {
@unlink( $backupLogFileFull );
}
}
}
}
$backupLogFileFull = trailingslashit( $snapshot->get_setting('backupLogFolderFull') ) . $snapshot_item_key . "_backup.log";
if ( @is_writable( $backupLogFileFull ) ) {
@unlink( $backupLogFileFull );
}
$backupLogFileFull = trailingslashit( $snapshot->get_setting('backupLogFolderFull') ) . $snapshot_item_key . "_restore.log";
if ( @is_writable( $backupLogFileFull ) ) {
@unlink( $backupLogFileFull );
}
$backupLockFileFull = trailingslashit( $snapshot->get_setting('backupLockFolderFull') ) . $snapshot_item_key . ".lock";
if ( @is_writable( $backupLockFileFull ) ) {
@unlink( $backupLockFileFull );
}
$backupFolderFull = trailingslashit( $snapshot->get_setting('backupBackupFolderFull') ) . $snapshot_item_key;
if ( @is_dir( $backupFolderFull ) ) {
@rmdir( $backupFolderFull );
}
// $this->unschedule_backup_sync_event( $snapshot_item_key );
wp_unschedule_hook( $this->backup_cron_hook );
// remove item from snapshot config
unset( $snapshot->config_data['items'][ $snapshot_item_key ] );
$snapshot->save_config();
}
public function unschedule_backup_sync_event( $snapshot_item_key ){
$timestamp = wp_next_scheduled( $this->backup_cron_hook, array( $snapshot_item_key ) );
if( $timestamp ){
wp_unschedule_event( $timestamp, $this->backup_cron_hook, array( $snapshot_item_key ) );
}
}
public function is_call_directly_sync_db(){
return isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'sync-db';
}
public function is_call_directly_sync_folders(){
return isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'sync-folders';
}
public function get_recurrency_sync_database(){
$recurrence = defined('SNAPSHOT_RECURRENCE_SYNC_TABLES') ? SNAPSHOT_RECURRENCE_SYNC_TABLES : false;
if( $recurrence ){
$schedules = wp_get_schedules();
if( ! isset( $schedules[ $recurrence ] ) ){
$recurrence = 'daily';
}
}else{
$recurrence = 'daily';
}
return $recurrence;
}
public function is_call_directly_sync_activated_plugins(){
return isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'sync-plugins';
}
public function get_interval_sync_database(){
static $interval;
if( is_null( $interval ) ){
$interval = defined('SNAPSHOT_RECURRENCE_SYNC_TABLES') ? SNAPSHOT_RECURRENCE_SYNC_TABLES : false;
if( $interval ){
$schedules = wp_get_schedules();
if( ! isset( $schedules[ $interval ] ) ){
$interval = DAY_IN_SECONDS;
}else{
$interval = $schedules[ $interval ]['interval'];
}
}else{
$interval = DAY_IN_SECONDS;
}
}
return $interval;
}
public function create_cron_daily_sync_db(){
$early = 1.5 * 60 * 60;
$schedule_time = $this->get_full_cron_schedule_time();
$now = Snapshot_Model_Time::get()->get_utc_time();
$next_event = strtotime(date("Y-m-d 00:00:00", $now), $now) + $schedule_time;
$recurrence = $this->get_recurrency_sync_database();
if( $now > $next_event && 'daily' === $recurrence ) {
// Local time of next event is in the past, move to future.
$next_event += DAY_IN_SECONDS;
}elseif( 'daily' !== $recurrence ){
$early = DAY_IN_SECONDS;
}
wp_schedule_event( $next_event - $early, $recurrence, $this->database_cron_hook );
}
public function create_cron_weekly_clean_temp_file(){
$next_clean_temp_zip = wp_next_scheduled( $this->clean_cron_hook );
if( ! $next_clean_temp_zip ){
$schedule_time = $this->get_full_cron_schedule_time();
$now = Snapshot_Model_Time::get()->get_utc_time();
$next_event = strtotime(date("Y-m-d 00:00:00", $now), $now) + $schedule_time + 2 * DAY_IN_SECONDS;
wp_schedule_event( $next_event, 'snapshot-weekly', $this->clean_cron_hook );
}
}
public function maybe_clear_cache_snapshot_settings( $item_key ){
$snapshot = $this->snapshot();
$configs = $snapshot->load_config();
$clear_cache = empty( $configs['items'] );
if( ! $clear_cache ){
if( ! isset( $configs['items'][ $item_key ] ) ){
$clear_cache = true;
}
}
if( $clear_cache ){
$option = $snapshot->get_setting('options_key');
if( is_multisite() ){
$network_id = get_current_network_id();
$cache_key = "$network_id:$option";
wp_cache_delete( $cache_key, 'site-options' );
}else{
$alloptions = wp_load_alloptions();
if ( isset( $alloptions[ $option ] ) ) {
unset( $alloptions[ $option ] );
wp_cache_set( 'alloptions', $alloptions, 'options' );
}else{
wp_cache_delete( $option, 'options' );
}
}
}
}
public function force_cache(){
$this->prepare_finish_process();
// delete Snapshot Ajax OPTIONS_FLAG
class_exists('Snapshot_Controller_Full_Ajax') && delete_site_option( Snapshot_Controller_Full_Ajax::OPTIONS_FLAG );
$this->delete_transient( 'sync-folders-args' );
$this->delete_transient( 'sync-upload-folders' );
$this->delete_transient( 'sync-db-args' );
$this->delete_transient( 'sync-core-args' );
$this->load_config();
$save = false;
if( isset( $this->configs['snapshot_item'] ) && 0 === $this->configs['snapshot_item']){
unset( $this->configs['snapshot_item'] );
$save = true;
}
if( isset( $_GET['snapshot-clear-item'] ) ){
if( isset( $this->configs['snapshot_item'] ) ){
if( @file_exists( $this->options_file ) ){
@unlink( $this->options_file );
}
unset( $this->configs['snapshot_item'] );
$save = true;
}
if( isset( $this->configs['snapshot_item_processing'] ) ){
unset( $this->configs['snapshot_item_processing'] );
$save = true;
}
}
if( $save ){
$this->save_config();
}
}
public function snapshot_events(){
if( isset( $_GET['snapshot-run'] ) ){
// cron fail file
if( $_GET['snapshot-run'] === 'resync-fail-items' && ! $this->is_lock_for_doing_cron() ){
do_action( $this->fail_files_cron_hook );
}
// elseif( $_GET['snapshot-run'] === 'sync-core' && ! $this->get_transient( 'try-sync-core' ) ){
// do_action( $this->core_cron_hook );
// }
}
// cron manual sync folders
$waiting_for_sync_folders = false;
if( $this->enable_sync_folders() ){
if( ! $this->get_transient( 'sync-folders-args' ) || $this->is_lock_for_doing_cron() === 'sync-folders' ){
$force_sync_folders = $this->maybe_force_sync_folders();
$next_sync_event = wp_next_scheduled( $this->manual_sync_folder_cron_hook );
if( $force_sync_folders || empty( $this->get_option( 'sync-folders-complete' ) ) ){
$waiting_for_sync_folders = true;
if( $force_sync_folders ){
$this->maybe_remove_copy_file();
}
if( $this->is_call_directly_sync_folders() ){
if( $next_sync_event ){
wp_unschedule_event( $next_sync_event, $this->manual_sync_folder_cron_hook );
}
do_action( $this->manual_sync_folder_cron_hook );
}else{
if( $next_sync_event && ( $next_sync_event - time() > 120 ) ){
wp_unschedule_event( $next_sync_event, $this->manual_sync_folder_cron_hook );
wp_schedule_single_event( time() + 60, $this->manual_sync_folder_cron_hook );
$this->locking = 'sync-folders';
$this->maybe_trigger_immediate_cron();
}elseif( ! $next_sync_event ){
wp_schedule_single_event( time() + 60, $this->manual_sync_folder_cron_hook );
$this->locking = 'sync-folders';
$this->maybe_trigger_immediate_cron();
}
}
}elseif( ! $next_sync_event ){
$this->create_cron_monthly_sync_folders();
}
}else{
$waiting_for_sync_folders = true;
}
}else{
if( $next_scheduled_sync_folders = wp_next_scheduled( $this->manual_sync_folder_cron_hook ) ){
wp_unschedule_event( $next_scheduled_sync_folders, $this->manual_sync_folder_cron_hook );
}
}
// cron sync db
if( isset( $this->configs['build_mode'] ) && $this->configs['build_mode'] !== $this->get_build_mode() ){
$this->delete_option( 'manual_sync_tables' );
// update build mode
$this->configs['build_mode'] = $this->get_build_mode();
$this->save_config();
}
$waiting_for_sync_db = $waiting_for_sync_folders;
if( ! $waiting_for_sync_folders && $this->enable_sync_database() ){
if( ! $this->get_transient( 'sync-db-args' ) || $this->is_lock_for_doing_cron() === 'sync-db' ){
$next_sync_event = wp_next_scheduled( $this->database_cron_hook );
if( empty( $this->get_option( 'sync-db-complete' ) ) ){
$waiting_for_sync_db = true;
if( $this->is_call_directly_sync_db() ){
if( $next_sync_event ){
wp_unschedule_event( $next_sync_event, $this->database_cron_hook );
}
do_action( $this->database_cron_hook );
}else{
// $this->create_cron_daily_sync_db();
if( $next_sync_event && ( $next_sync_event - time() > 120 ) ){
wp_unschedule_event( $next_sync_event, $this->database_cron_hook );
wp_schedule_single_event( time() + 60, $this->database_cron_hook );
$this->locking = 'sync-db';
$this->maybe_trigger_immediate_cron();
}elseif( ! $next_sync_event ){
wp_schedule_single_event( time() + 60, $this->database_cron_hook );
$this->locking = 'sync-db';
$this->maybe_trigger_immediate_cron();
}
}
}elseif( ! $next_sync_event ){
$this->create_cron_daily_sync_db();
}
}else{
$waiting_for_sync_db = true;
}
}else{
if( $next_scheduled_sync_db = wp_next_scheduled( $this->database_cron_hook ) ){
wp_unschedule_event( $next_scheduled_sync_db, $this->database_cron_hook );
}
}
// cron sync core
$waiting_for_sync_core = $waiting_for_sync_db;
if( $this->enable_sync_core() ){
if( $waiting_for_sync_db ){
$next_sync_event = wp_next_scheduled( $this->core_cron_hook );
if( $next_sync_event ){
wp_unschedule_event( $next_sync_event, $this->core_cron_hook );
}
}elseif( ! $this->get_transient( 'sync-core-args' ) ){
if( ! $this->is_synced_core() ){
if( $this->is_call_directly_sync_core() ){
do_action( $this->core_cron_hook );
}
// $this->create_cron_daily_sync_db();
$next_sync_event = wp_next_scheduled( $this->core_cron_hook );
if( ! $next_sync_event ){
wp_schedule_single_event( time() + 60, $this->core_cron_hook );
$this->locking = 'sync-core';
$this->maybe_trigger_immediate_cron();
}elseif( $next_sync_event && ( $next_sync_event - time() > 120 ) ){
wp_unschedule_event( $next_sync_event, $this->core_cron_hook );
wp_schedule_single_event( time() + 60, $this->core_cron_hook );
$this->locking = 'sync-core';
$this->maybe_trigger_immediate_cron();
}
}
}
}elseif( $synced_core = $this->get_option('synced_core') ){
// unsync the core files
$this->manual_unsync_items( $synced_core, 'core' );
}
// cron sync activated plugins
if( $this->enable_sync_activated_plugins() ){
if( $waiting_for_sync_core ){
$next_sync_event = wp_next_scheduled( $this->manual_sync_activated_plugins_cron_hook );
if( $next_sync_event ){
wp_unschedule_event( $next_sync_event, $this->manual_sync_activated_plugins_cron_hook );
}
}elseif( ! $this->get_transient( 'sync-plugins-args' ) ){
if( ! $this->get_option( 'sync-plugins-complete' ) ){
if( $this->is_call_directly_sync_core() ){
do_action( $this->manual_sync_activated_plugins_cron_hook );
}
// $this->create_cron_daily_sync_db();
$next_sync_event = wp_next_scheduled( $this->manual_sync_activated_plugins_cron_hook );
if( ! $next_sync_event ){
wp_schedule_single_event( time() + 60, $this->manual_sync_activated_plugins_cron_hook );
$this->locking = 'sync-plugin';
$this->maybe_trigger_immediate_cron();
}elseif( $next_sync_event && ( $next_sync_event - time() > 120 ) ){
wp_unschedule_event( $next_sync_event, $this->manual_sync_activated_plugins_cron_hook );
wp_schedule_single_event( time() + 60, $this->manual_sync_activated_plugins_cron_hook );
$this->locking = 'sync-plugin';
$this->maybe_trigger_immediate_cron();
}
}
}
}
// cron copy file
if( ( ! $this->disable_copy_sync_file() && ! $this->get_sync_backup_copy_file() ) ){
if( isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'prepare-copyfile' ){
$this->remove_cron_prepare_copy_backup_file();
do_action( $this->prepare_backup_cron_hook );
}elseif( ! $this->locking && ! $this->is_lock_for_doing_cron() ){
$this->create_cron_prepare_copy_backup_file();
}
}
// create cron for clean temp zip file
$this->create_cron_weekly_clean_temp_file();
}
public function maybe_create_event_backup_upload_folder(){
// load config
if( wp_doing_ajax() ) return;
static $checked;
if( $checked ) return;
$checked = true;
if( isset( $_GET['snapshot-force-cache'] ) ){
$this->force_cache();
}
if( $this->is_lock_for_doing_cron() ){
if( $this->locking === 'sync-core' && ! $this->enable_sync_core() ){
$this->unlock_for_finish_cron();
}elseif( $this->locking === 'prepare-copyfile' && $this->disable_copy_sync_file() ){
$this->unlock_for_finish_cron();
}else{
return;
}
}
$this->load_config();
if( $this->get_sync_backup_file() ){
return $this->snapshot_events();
}
if( ! isset( $this->configs['snapshot_item'] ) ){
$response = wp_remote_post( admin_url( 'admin-ajax.php' ), array(
'timeout' => 3,
'body' => array(
'action' => 'snapshot_mu_backup_upload_folder',
// '_nonce' => wp_create_nonce( '_backup_upload_folder_' )
),
/** This filter is documented in wp-includes/class-wp-http-streams.php */
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
) );
if( is_wp_error( $response ) ){
if( strpos( $response->get_error_message(), 'Operation timed out') ){
$response = wp_remote_post( admin_url( 'admin-ajax.php' ), array(
'timeout' => 10,
/** This filter is documented in wp-includes/class-wp-http-streams.php */
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
'body' => array(
'action' => 'snapshot_mu_backup_upload_folder',
// '_nonce' => wp_create_nonce( '_backup_upload_folder_' )
)
) );
}else{
Snapshot_Helper_Log::warn( $response->get_error_message(), "snapshot");
}
}
$body = wp_remote_retrieve_body( $response );
$item_key = 0;
if( $body ){
$body = json_decode( $body );
if( is_object( $body ) && ! empty( $body->data ) ){
$item_key = (int) $body->data;
$this->configs['snapshot_item'] = $item_key;
if( wp_using_ext_object_cache() ){
$this->maybe_clear_cache_snapshot_settings( $item_key );
}
// run cron backup
$this->cron_backup_upload_folder( $item_key, 0 );
}
}
if( ! $item_key ){
// stop
$this->configs['snapshot_item'] = $item_key;
Snapshot_Helper_Log::warn("MU Plugin can't create snapshot item", "snapshot");
}
// SAVE CONFIG
$this->save_config();
}else{
$snapshot = $this->snapshot();
$snapshot->load_config();
if( ! isset( $snapshot->config_data['items'][ $this->configs['snapshot_item'] ] ) ){
// unschedule
$this->unschedule_backup_sync_event( intval( $this->configs['snapshot_item'] ) );
if( @file_exists( $this->options_file ) ){
@unlink( $this->options_file );
}
unset( $this->configs['snapshot_item'] );
if( isset( $this->configs['snapshot_item_processing'] ) ){
unset( $this->configs['snapshot_item_processing'] );
}
if( isset( $this->configs['snapshot_file_name'] ) ){
// maybe unset copy file
$copy_file = $this->get_backup_file_copy_name( $this->configs['snapshot_file_name'] );
if( @file_exists( $copy_file ) ){
@unlink( $copy_file );
}
unset( $this->configs['snapshot_file_name'] );
}
$this->save_config();
// try create new backup file
// $this->maybe_create_event_backup_upload_folder();
}else{
if( ! empty( $this->configs['snapshot_item_processing'] ) ){
if( isset( $snapshot->config_data['items'][$this->configs['snapshot_item']]['data'] ) ){
$this->check_status_sync_backup();
}else{
// maybe try call cron again
$item_key = (int) $this->configs['snapshot_item'];
$timestamp = wp_next_scheduled( $this->backup_cron_hook, array( $item_key ) );
if( ! $timestamp ){
wp_schedule_single_event( time() + 2 * 3600, $this->backup_cron_hook, array( $item_key ) );
}
}
}else{
if( isset( $this->configs['snapshot_item'] ) ){
// run cron backup
$item_key = intval( $this->configs['snapshot_item'] );
$this->cron_backup_upload_folder( $item_key );
}
}
}
}
}
public function check_status_sync_backup(){
$this->load_config();
$data = $this->snapshot()->config_data['items'][$this->configs['snapshot_item']]['data'];
// krsort( $data ); already sorted
$error = false;
foreach( $data as $time => $item ){
if( ! empty( $item['filename'] ) && $this->get_sync_backup_file( $item['filename'] ) ){
$this->configs['snapshot_file_name'] = $item['filename'];
$this->configs['build_mode'] = $this->get_build_mode();
$error = false;
break;
}elseif( isset( $item['errorStatus'] ) && ( true === $item['errorStatus'] ) ){
$error = $item['errorText'];
}
}
if( empty( $error ) && $data ){
$this->clear_old_backup_sync_data( $data, $time );
unset( $this->configs['snapshot_item_processing'] );
if( isset( $this->configs['snapshot_item_error'] ) ){
unset( $this->configs['snapshot_item_error'] );
}
}else{
$this->configs['snapshot_item_error'] = $error;
}
$this->save_config();
}
public function get_sync_backup_file( $file_name=false ){
if( empty( $this->backup_sync_file ) ){
$this->load_config();
if( ! $file_name && isset( $this->configs['snapshot_file_name']) ){
$file_name = $this->configs['snapshot_file_name'];
}
// elseif( 'restore' === $this->is_lock_for_doing_cron() ){
// $files = scandir($this->backup_folder);
// foreach( $files as $file ){
// if( strpos( $file, $this->backup_sync_folder_name ) !== false && $this->is_zip_file( $file ) && substr( $file, -10 ) !== 'copy.zip' ){
// $file_name = $file;
// break;
// }
// }
// }
// }
if( $file_name ){
$file_path = trailingslashit( $this->backup_folder ) . $file_name;
if( @file_exists( $file_path ) && @is_writable( $file_path ) ){
$this->backup_sync_file = $file_path;
if( empty( $this->configs['snapshot_file_name'] ) ){
// $this->delete_transient( 'checked-exist-old-sync-file' );
$this->configs['snapshot_file_name'] = $file_name;
$this->save_config();
}
}else{
// maybe wrong backup folder
$this->get_backup_session_folder();
if( $this->configs['backup_folder'] !== $this->backup_folder ){
$this->configs['backup_session_folder'] = $this->backup_session_folder;
$this->configs['backup_folder'] = $this->backup_folder;
// update config
$this->save_config();
return $this->get_sync_backup_file( $file_name );
}
}
}
}
return $this->backup_sync_file;
}
public function get_backup_file_copy_name( $file_name = false ){
if( ! $this->backup_sync_file_copy ){
if( $file_name ){
$this->load_config();
$this->backup_sync_file_copy = trailingslashit( $this->backup_folder ) . $file_name .'.copy.zip';
}elseif( $this->backup_sync_file ){
$this->backup_sync_file_copy = $this->backup_sync_file .'.copy.zip';
}
}
return $this->backup_sync_file_copy;
}
public function get_sync_backup_copy_file(){
if( $this->disable_copy_sync_file() || 'prepare-copyfile' === $this->is_lock_for_doing_cron() ) return;
if( $this->get_sync_backup_file() ){
$this->backup_sync_file_copy = $this->get_backup_file_copy_name();
if( @file_exists( $this->backup_sync_file_copy ) ){
return $this->backup_sync_file_copy;
}
}else{
$this->backup_sync_file_copy = null;
}
return false;
}
public function maybe_remove_copy_file(){
// remove schedule if exist
$this->remove_cron_prepare_copy_backup_file();
if( $this->get_backup_file_copy_name() && ! isset( $this->snapshot_backup_keys[ $this->is_lock_for_doing_cron() ] ) ){
if( @file_exists( $this->backup_sync_file_copy ) ){
return @unlink( $this->backup_sync_file_copy );
}
}
return false;
}
public function cron_backup_upload_folder( $item_key, $delay = 60 ){
$this->unschedule_backup_sync_event( $item_key );
wp_schedule_single_event( time() + $delay, $this->backup_cron_hook, array( $item_key ) );
$this->load_config();
$this->configs['snapshot_item_processing'] = 1;
$this->save_config();
$this->maybe_trigger_immediate_cron();
}
public function get_included_media_files(){
$snapshot = $this->snapshot();
$snapshot->load_config();
$files = $snapshot->snapshot_gather_item_files($this->get_backup_sync_args());
if( ! empty( $files['included']['media'] ) ){
return $files['included']['media'];
}
return false;
}
public function get_home_path(){
static $home_path;
if( is_null( $home_path ) ){
$home_path = get_home_path();
}
return $home_path;
}
public function get_root( $root='core' ){
switch ($root) {
case 'uploads':
if( ! isset( $this->options['root'][ $root ] ) ){
$this->options['root'][ $root ] = $this->get_home_path() . $this->get_zip_path( $root );
}
break;
case 'plugins':
if( ! isset( $this->options['root'][ $root ] ) ){
$this->options['root'][ $root ] = trailingslashit( WP_PLUGIN_DIR );
}
break;
case 'themes':
if( ! isset( $this->options['root'][ $root ] ) ){
$this->options['root'][ $root ] = trailingslashit( WP_CONTENT_DIR ) . 'themes/';
}
break;
case 'database':
if( ! isset( $this->options['root'][ $root ] ) ){
$this->options['root'][ $root ] = trailingslashit( $this->backup_folder );
}
break;
default:
$this->options['root'][ $root ] = $this->get_home_path();
break;
}
return $this->options['root'][ $root ];
}
public function get_zip_path( $root = 'core' ){
switch ($root) {
case 'uploads':
if( ! isset( $this->options['path'][ $root ] ) ){
$this->options['path'][ $root ] = trailingslashit( Snapshot_Helper_Utility::get_blog_upload_path( 0, 'basedir' ) );
}
break;
case 'plugins':
if( ! isset( $this->options['path'][ $root ] ) ){
$this->options['path'][ $root ] = str_replace( $this->get_home_path(), '', $this->get_root( $root ) );
}
break;
case 'themes':
if( ! isset( $this->options['path'][ $root ] ) ){
$this->options['path'][ $root ] = str_replace( $this->get_home_path(), '', $this->get_root( $root ) );
}
break;
default:
$this->options['path'][ $root ] = '';
break;
}
return $this->options['path'][ $root ];
}
public function enabled_save_sync_options_in_file(){
static $enabled;
if( is_null( $enabled ) ){
$enabled = defined("SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE") && SNAPSHOT_SAVE_SYNC_OPTIONS_IN_FILE;
}
return $enabled;
}
public function add_sync_option_file(){
// sync snapshot sync option
if( $this->enabled_save_sync_options_in_file() && $this->get_option( 'have_change_options' ) ){
$this->load_config();
if( @file_exists( $this->options_file ) ){
$upload_path = $this->get_root('uploads');
$sync_options_file = array(
str_replace($upload_path, '', $this->options_file) => 1
);
$this->zip_action( $sync_options_file );
$backup_file = $this->backup_sync_file;
if( $this->get_sync_backup_copy_file() ){
// update for copy file
$this->backup_sync_file = $this->backup_sync_file_copy;
self::$_zip = null;
$new_sync_files = $this->zip_action( $sync_options_file );
}
// reset backup file
$this->backup_sync_file = $backup_file;
}
$this->delete_option( 'have_change_options' );
}
}
public function maybe_sync_new_files(){
$exclude_files = $this->get_transient( 'sync_new_files' );
if( false === $exclude_files ){
$upload_path = $this->get_root('uploads');
$exclude_files = [];
// $this->remove_cron_prepare_copy_backup_file();
if ( is_dir( $upload_path ) ) {
// $snapshot_option = $this->snapshot()->get_setting('options_key');
$files = $this->scandir_files_for_backup('uploads','', $this->get_standard_size());
// $no_file_exclude = 0;
// $max_file_size = $this->get_max_file_size();
// $standard_file_size = $this->get_standard_size();
// if( $max_file_size && $max_file_size < $standard_file_size ){
// $standard_file_size = $max_file_size;
// }
// $sync = [];
// foreach( $files as $k => $file ){
// if( @filesize( $file ) > $standard_file_size ){
// unset( $files[ $k ] );
// $exclude_files[] = $file;
// continue;
// }
// $file_path = str_replace($upload_path, '', $file);
// $sync[$file_path] = @filemtime( $file );
// }
if( ! empty( $files['included'] ) && $this->get_sync_backup_file() ){
// remove copy file
$this->maybe_remove_copy_file();
// add sync option file
if( $this->enabled_save_sync_options_in_file() && $this->get_option( 'have_change_options' ) ){
$files['included'][ str_replace($upload_path, '', $this->options_file) ] = 1;
$this->delete_option( 'have_change_options' );
}
$this->update_sync_files( $files['included'] );
}
if( ! empty( $files['excluded_large'] ) ){
$exclude_files = $files['excluded_large'];
}
}
$this->set_transient( 'sync_new_files', $exclude_files, DAY_IN_SECONDS );
}
// maybe add sync option file
$this->add_sync_option_file();
return $exclude_files;
}
public function run_cron_backup_upload_folder( $item_key ){
// reset old options
if( ! $this->get_sync_backup_file() ){
// if( ! defined('SNAPSHOT_DOING_SYNC_BACKUP') ){
// define('SNAPSHOT_DOING_SYNC_BACKUP', 1);
// }
$this->delete_option('manual_sync_files');
$this->delete_option( 'manual_sync_fail' );
// core
$this->delete_option( 'manual_sync_core' );
$this->delete_option( 'synced_core' );
$this->delete_transient( 'sync-core-args' );
$this->delete_option( 'sync-core-complete' );
// themes & plugins
$this->delete_option('manual_sync_themes');
$this->delete_option( 'manual_sync_plugins' );
$this->delete_option( 'sync-plugins-complete' );
// database
$this->delete_option( 'manual_sync_tables' );
$this->delete_transient( 'sync-db-args' );
$this->delete_option( 'sync-db-complete' );
// media
$this->delete_transient( 'sync_new_files' );
$this->delete_option('sync_files');
// folders
$this->delete_option( 'manual_sync_folders' );
$this->delete_transient( 'sync-folders-args' );
$this->delete_option( 'sync-folders-complete' );
$this->remove_cron_prepare_copy_backup_file();
$this->lock_for_doing_cron('create-sync-backup');
$exclude_files = $this->maybe_sync_new_files();
$this->reset_exclude_files_option( $exclude_files );
$this->snapshot()->snapshot_backup_cron_proc( $item_key );
// go back filtered exclude files
$this->back_to_filtered_exclude_files_option();
// manual sync upload
do_action( 'snapshot_mu_cron_complete_sync', 'create-sync-backup' );
}else{
if( isset( $this->configs['snapshot_item'] ) ){
$this->unschedule_backup_sync_event( $this->configs['snapshot_item'] );
}
}
}
public function enable_sync_folders(){
return $this->enable_manual_sync_uploads() || $this->enable_manual_sync_folders();
}
public function enable_manual_sync_uploads(){
return defined('SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE') && SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE;
}
public function enable_manual_sync_folders(){
return defined('SNAPSHOT_MANUAL_SYNC_FOLDERS') && SNAPSHOT_MANUAL_SYNC_FOLDERS;
}
public function enable_manual_reject_uploads(){
return defined('SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE') && SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
}
public function enable_force_reject(){
return defined('SNAPSHOT_MANUAL_FORCE_REJECT') && SNAPSHOT_MANUAL_FORCE_REJECT;
}
public function enable_sync_database(){
return ! ( defined('SNAPSHOT_DISABLE_SYNC_DB') && SNAPSHOT_DISABLE_SYNC_DB );
}
public function disable_copy_sync_file(){
return defined('SNAPSHOT_DISABLED_COPY_SYNC_FILE') ? SNAPSHOT_DISABLED_COPY_SYNC_FILE : false;
}
public function enable_sync_activated_plugins(){
return ! ( defined('SNAPSHOT_DISABLE_SYNC_ACTIVATED_PLUGINS') && SNAPSHOT_DISABLE_SYNC_ACTIVATED_PLUGINS );
}
public function prepare_cron_copy_version_backup_file(){
if( $this->disable_copy_sync_file() || $this->get_transient( 'sync-db-args' ) ) return;
$this->get_sync_backup_copy_file();
if( $this->backup_sync_file_copy ){
if( $this->is_lock_for_doing_cron() ){
return;
}
// remove any prepare hook
$this->remove_cron_prepare_copy_backup_file();
$this->lock_for_doing_cron('prepare-copyfile');
if( @copy( $this->backup_sync_file, $this->backup_sync_file_copy ) ){
$this->unlock_for_finish_cron();
return true;
}else{
$this->unlock_for_finish_cron();
$this->locking = false;
}
}
}
public function lock_for_doing_cron( $type ){
if( isset( $this->snapshot_backup_keys[ $this->is_lock_for_doing_cron() ] ) ){
$this->log( sprintf("Locking for doing '%s'", $this->locking) );
return;
}
$this->set_transient( 'lock-doing-cron', $type );
$this->locking = $type;
}
public function unlock_for_finish_cron(){
$this->delete_transient('lock-doing-cron');
$this->locking = false;
$this->disable_immediate_cron();
}
public function is_lock_for_doing_cron(){
if( is_null( $this->locking ) ){
$this->locking = $this->get_transient('lock-doing-cron');
}
return $this->locking;
}
// rename is faster than copy so we should prepare a copy version to rename while processing backup
public function create_cron_prepare_copy_backup_file($force=false, $time=0){
// check syncing db
if(
$this->disable_copy_sync_file() || //disable copy action
! $this->get_sync_backup_file() || //check sync backup file
$this->get_transient( 'sync-folders-args' ) || //syncing folders
$this->get_transient( 'sync-db-args' ) //syncing db
){
return;
}
$cron_copy_file = wp_next_scheduled( $this->prepare_backup_cron_hook );
if( $this->is_lock_for_doing_cron() ){
if( $cron_copy_file ){
wp_unschedule_event( $cron_copy_file, $this->prepare_backup_cron_hook );
}
if( $force ){
$time = $time ?: 3600;
wp_schedule_single_event( time() + $time, $this->prepare_backup_cron_hook );
}
}else{
if( $force ){
if( $cron_copy_file ){
wp_unschedule_event( $cron_copy_file, $this->prepare_backup_cron_hook );
}
$time = $time ?: 90;
wp_schedule_single_event( time() + $time, $this->prepare_backup_cron_hook );
}elseif( ! $this->get_sync_backup_copy_file() ){
if( $cron_copy_file ){
if( $cron_copy_file - time() > 90 ){
wp_unschedule_event( $cron_copy_file, $this->prepare_backup_cron_hook );
$time = $time ?: 90;
wp_schedule_single_event( time() + $time, $this->prepare_backup_cron_hook );
}
}else{
$time = $time ?: 90;
wp_schedule_single_event( time() + $time, $this->prepare_backup_cron_hook );
}
}
}
if( $time > 0 && $time < 3600 ){
$this->maybe_trigger_immediate_cron();
}
}
public function remove_cron_prepare_copy_backup_file(){
$cron_copy_file = wp_next_scheduled( $this->prepare_backup_cron_hook );
if( $cron_copy_file ){
wp_unschedule_event( $cron_copy_file, $this->prepare_backup_cron_hook );
}
}
public function create_event_backup_upload_folder(){
// load config
$this->load_config();
if( ! isset( $this->configs['snapshot_item'] ) ){
// create a snapshot item
$item_key = $this->snapshot()->snapshot_add_update_action_proc(array(
'snapshot-action' => 'add',
'snapshot-name' => $this->backup_sync_folder_name,
'snapshot-files-option' => 'selected',
'snapshot-files-sections' => array( 'media' ),
'snapshot-item' => current_time( 'timestamp' )
));
if( is_numeric( $item_key ) ){
wp_send_json_success( $item_key );
}
}
wp_send_json_error();
}
public function get_backup_sync_args(){
return array(
'files-option' => 'selected',
'blog-id' => 0,
'files-sections' => array( 'media' )
);
}
public function ajax_init_restore(){
if( isset( $_REQUEST['snapshot_action'] ) ){
if( $_REQUEST['snapshot_action'] === 'finish' ){
$this->prepare_finish_process();
global $wp_filesystem;
if( Snapshot_Helper_Utility::connect_fs() ) {
$options_file = dirname(__FILE__) .'/wpmudev-snapshot-options.json';
if( @file_exists( $options_file ) ){
$options = (array) json_decode( $wp_filesystem->get_contents( $options_file ) );
if( $options && isset( $options['config'] ) ){
$this->config = (array) $options['config'];
$this->save_config();
unset( $options->config );
foreach( $options as $key => $option ){
$this->save_option( $key, (array) $option );
}
}
// unlink
@unlink( $options_file );
}
} else {
return new WP_Error("filesystem_error", "Cannot initialize filesystem");
}
}elseif( 'init' === $_REQUEST['snapshot_action'] ){
global $wp_filesystem;
if( Snapshot_Helper_Utility::connect_fs() ) {
$options_file = dirname(__FILE__) .'/wpmudev-snapshot-options.json';
if( ! @file_exists( $options_file ) ){
$options = array();
$list_options_key = ['config', 'sync_files', 'manual_sync_files', 'manual_sync_themes', 'manual_sync_plugins', 'manual_reject_files', 'manual_reject_dirs'];
foreach( $list_options_key as $key ){
$option = $this->get_option( $key );
if( $option ){
$options[ $key ] = $option;
}
}
if( $options ){
$wp_filesystem->put_contents( $options_file, json_encode( $options ) , 0600 );
}
}
}
}elseif( $this->locking !== 'restore' ){
$this->lock_for_doing_cron('restore');
}
}
}
public function update_manifest_file( $manifest_array ){
if( ! $this->disabled_sync() ){
// $this->load_config();
// $item_key = end( $manifest_array[ 'data' ] );
remove_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
$tables_sections = Snapshot_Helper_Utility::get_database_tables();
add_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
$sync_tables = $this->get_option('manual_sync_tables');
if( $sync_tables && $tables_sections ){
if( ! isset( $manifest_array['tables-sections'] ) ){
$manifest_array['tables-sections'] = [];
}
$manifest_array['tables-sections'] = array_merge( $manifest_array['tables-sections'], $tables_sections );
$manifest_array['TABLES'] = array_merge( $manifest_array['TABLES'], $tables_sections );
$table_datas = [];
foreach( $sync_tables as $table ){
if( ! empty( $table['table_data'] ) ){
$table_datas = array_merge( $table_datas, $table['table_data'] );
}
}
if( ! empty( $table_datas ) ){
if( ! isset( $manifest_array['TABLES-DATA'] ) ){
$manifest_array['TABLES-DATA'] = [];
}
$manifest_array['TABLES-DATA'] = array_merge( $manifest_array['TABLES-DATA'], $table_datas );
// $manifest_array['table_data'] = isset( $manifest_array['table_data'] ) ? array_merge( $manifest_array['table_data'], $table_datas ) : ;
// $session->data = $data;
// $session->save_session();
// echo "_session<pre>"; print_r($table_datas); echo "</pre>";
}
}
}
return $manifest_array;
}
// ajax
public function ajax_init_base_file_from_sync_file(){
if( isset( $_REQUEST['security'] ) ){
check_ajax_referer( 'snapshot-ajax-nonce', 'security' );
}elseif( ! isset( $_POST['snapshot-proc-action'], $_POST['snapshot-item'] ) ){
wp_die(-1, 403);
}
if( $this->is_busy_on_sync() ){
echo wp_json_encode( [
'responseText' => __('Sorry, the server is busy now, try again later!','snapshot')
]);
die();
}
if( isset( $_POST['snapshot-proc-action'], $_POST['snapshot-item'] ) ){
if( ! $this->disabled_sync() && ! $this->get_transient( 'init_backup_from_sync_file' ) && in_array( $_POST['snapshot-proc-action'], array( 'table', 'file', 'finish' ) ) ){
$this->set_transient( 'init_backup_from_sync_file', 1 );
$item_key = intval( $_POST['snapshot-item'] );
$backupFolderFull = trailingslashit( $this->snapshot()->get_setting('backupBackupFolderFull') ) . $item_key;
// $this->options['backupFolderFull'] = $backupFolderFull;
$backup_file = $backupFolderFull . '/snapshot-backup.zip';
if( ! @file_exists( $backup_file ) ){
$status = false;
if( $this->get_sync_backup_file() ){
$status = $this->init_backup_file( $backup_file );
}
if( ! $status ){
// go back default snapshot func
$this->do_not_use_sync_backup();
}
// $item_key = $_POST['snapshot-item'];
$session = new Snapshot_Helper_Session( trailingslashit( $this->backup_session_folder ), $item_key, false );
$data = $session->data;
echo wp_json_encode( [
'errorStatus' => false,
'errorText' => "",
'table_data' => isset( $data['table_data'] ) ? $data['table_data'] : null,
'files_data' => isset( $data['files_data'] ) ? $data['files_data'] : null,
'responseText' => 'MU init backup file from sync file'
]);
die();
}
}
if( 'init' === $_POST['snapshot-proc-action'] ){
$item_key = intval( $_POST['snapshot-item'] );
$this->log( sprintf("Backup Config: Max file size is %s", size_format( $this->max_file_size) ) );
// log files manual reject
$this->log_list_files_manual_reject();
// lock for regular
$this->lock_for_doing_cron('regular');
$items = $this->snapshot()->config_data['items'];
if( isset( $items[ $item_key ] ) ){
// only support for full backup
if( 'all' !== $items[ $item_key ]['files-option'] ){
$this->do_not_use_sync_backup();
}else{
$this->enable_sync_filter();
$this->delete_transient( 'init_backup_from_sync_file' );
if( $this->get_sync_backup_file() ){
// try sync new files
$this->maybe_sync_new_files();
}
}
}else{
if( isset( $_POST['snapshot-files-option'], $_POST['snapshot-tables-option'] ) && 'all' === $_POST['snapshot-files-option'] && 'all' === $_POST['snapshot-files-option'] ){
$this->enable_sync_filter();
$this->delete_transient( 'init_backup_from_sync_file' );
if( $this->get_sync_backup_file() ){
// try sync new files
$this->maybe_sync_new_files();
}
}else{
$this->do_not_use_sync_backup();
}
}
}elseif( $_POST['snapshot-proc-action'] === 'finish' ){
$this->prepare_finish_process();
}
}
}
public function log_list_files_manual_reject(){
$manual_reject_files = $this->get_manual_reject_files();
if( ! empty( $manual_reject_files ) ){
$reject_files = [];
foreach( $manual_reject_files as $media_id => $files ){
$reject_files = array_merge( $reject_files, $files );
}
if( $reject_files ){
$this->log( sprintf("Manual reject some files (WP_UPLOAD_DIR): %s.", join(', ', $reject_files) ) );
}
}
}
public function set_max_file_size( $max_file_size ){
$this->max_file_size = $this->get_max_file_size( $max_file_size );
return $this->max_file_size;
}
public function get_max_file_size( $default = 0 ){//15 * 1024 * 1024
if (defined('SNAPSHOT_FILESET_LARGE_FILE_SIZE') && SNAPSHOT_FILESET_LARGE_FILE_SIZE) {
$max_size = intval(SNAPSHOT_FILESET_LARGE_FILE_SIZE);
if( $max_size ){
$default = $max_size;
}
}
return $default;
}
public function get_standard_size(){
static $standard_file_size;
if( is_null( $standard_file_size ) ){
$standard_file_size = 1024 * 1024;
if (defined('SNAPSHOT_FILESET_STANDARD_FILE_SIZE') && SNAPSHOT_FILESET_STANDARD_FILE_SIZE) {
$defined_size = intval(SNAPSHOT_FILESET_STANDARD_FILE_SIZE);
if( $defined_size ){
$standard_file_size = $defined_size;
}
}
$max_file_size = $this->get_max_file_size();
if( $max_file_size && $standard_file_size > $max_file_size ){
$standard_file_size = $max_file_size;
}
}
return $standard_file_size;
}
public function set_chunk_size($chunk_size)
{
if( defined('SNAPSHOT_FILESET_CHUNK_SIZE') && is_numeric(SNAPSHOT_FILESET_CHUNK_SIZE) ){
$size = intval(SNAPSHOT_FILESET_CHUNK_SIZE);
if($size){
$chunk_size = $size;
}
}
return $chunk_size;
}
public function get_chunk_size(){
return apply_filters( 'snapshot_limit_of_files_per_session', 250 );
}
//for managed backup
public function after_snapshot_init_proc(){
if( wp_doing_cron() ) return;
$snapshot = $this->snapshot();
if( ! empty( $snapshot->config_data['config']['full']['active'] ) ){
$next_scheduled = wp_next_scheduled('snapshot-controller-full-cron-start_backup');
$early = 60 * 60 / 2;
if( $next_scheduled > $early){
$sync_cron = wp_next_scheduled( $this->sync_cron_hook );
if( $sync_cron > $next_scheduled - $early ){
wp_unschedule_event( $sync_cron, $this->sync_cron_hook );
}elseif( ! $sync_cron ){
wp_schedule_single_event( $next_scheduled - $early - 60, $this->sync_cron_hook);
}
}
}
if( ! isset( $sync_cron ) && ! empty( $snapshot->config_data['items'] ) ){
$scheds = (array) wp_get_schedules();
$sync_cron = wp_next_scheduled( $this->sync_cron_hook );
if( empty( $sync_cron ) ){
$early = 60 * 60 / 2;
foreach ( $snapshot->config_data['items'] as $key_slug => $item ) {
if ( ( isset( $item['interval'] ) ) && ( '' !== $item['interval'] ) ) {
if ( isset( $scheds[ $item['interval'] ] ) ) {
$next_scheduled = wp_next_scheduled( $snapshot->get_setting('backup_cron_hook'), array( intval( $key_slug ) ) );
if( $next_scheduled ){
wp_schedule_single_event( $next_scheduled - $early - 60, $this->sync_cron_hook);
}
}
}
}
}
}
}
public function get_manual_reject_files( $force = false ){
$manual_reject_files = $this->get_option('manual_reject_files');
if( $force && $manual_reject_files ){
if( ! $this->get_transient( 'check_reject_exist' ) ){
$update = false;
foreach( $manual_reject_files as $media_id => $files ){
if( ! get_post( $media_id ) ){
unset( $manual_reject_files[ $media_id ] );
$update = true;
}
}
if( $update ){
$this->save_option( 'manual_reject_files', $manual_reject_files );
}
}
$this->set_transient( 'check_reject_exist', 1 );
}
return $manual_reject_files;
}
public function get_manual_reject_dirs( $force = false ){
$manual_reject_dirs = $this->get_option('manual_reject_dirs');
if( $force && $manual_reject_dirs ){
$update = false;
$home_path = $this->get_home_path();
foreach( $manual_reject_dirs as $file => $dir ){
if( ! @file_exists( $home_path . $dir ) ){
unset( $manual_reject_dirs[ $file ] );
$update = true;
}
}
if( $update ){
$this->save_option( 'manual_reject_dirs', $manual_reject_dirs );
}
}
return $manual_reject_dirs;
}
// media
public function add_media_action_sync_button( $actions, $post )
{
if( $this->get_sync_backup_file() ){
static $manual_sync_files, $manual_reject_files;
if( is_null( $manual_sync_files ) ){
$manual_sync_files = $this->get_option('manual_sync_files');
$sync_files = $this->get_option('sync_files');
$manual_sync_files = array_merge( $manual_sync_files, $sync_files );
$manual_reject_files = $this->get_manual_reject_files( true );
}
$attached_file = get_post_meta( $post->ID, '_wp_attached_file', true );
if( $attached_file ){
$attached_file = $this->get_attachment_relative_path( $attached_file );
$filesize = @filesize( $this->get_root('uploads') . $attached_file );
if( $filesize > $this->get_standard_size() ){
if( isset( $manual_sync_files[ $attached_file ] ) ){
$title = esc_attr( sprintf( __( 'Remove &#8220;%s&#8221; from the sync Backup file','snapshot' ), esc_html( $post->post_title ) ) );
$actions['snapshot_unsync'] = sprintf(
'<a href="#" data-id="%s" data-group="media" data-action="unsync" class="snapshot-manual-sync unsync aria-button-if-js" title="%s" >%s (%s)</a>',
$post->ID,
$title,
__( 'Snapshot Unsync', 'snapshot' ),
size_format( $filesize, 1 )
);
}else{
$title = esc_attr( sprintf( __( 'Put &#8220;%s&#8221; to the next Backup file','snapshot' ), esc_html( $post->post_title ) ) );
if( isset( $manual_reject_files[ $post->ID ] ) ){
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="media" data-action="unreject" class="unreject snapshot-manual-sync aria-button-if-js" >%s (%s)</a>',
$post->ID,
__( 'Snapshot Unreject', 'snapshot' ),
size_format( $filesize, 1 )
);
$actions['snapshot_manual_sync snapshot-hide'] = sprintf(
'<a href="#" data-id="%s" data-group="media" class="add snapshot-manual-sync aria-button-if-js" title="%s" >%s (%s)</a>',
$post->ID,
$title,
__( 'Snapshot Sync', 'snapshot' ),
size_format( $filesize, 1 )
);
}else{
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="media" data-action="reject" class="reject snapshot-manual-sync aria-button-if-js" >%s</a>',
$post->ID,
__( 'Snapshot Reject', 'snapshot' )
);
$actions['snapshot_manual_sync'] = sprintf(
'<a href="#" data-id="%s" data-group="media" class="add snapshot-manual-sync aria-button-if-js" title="%s" >%s (%s)</a>',
$post->ID,
$title,
__( 'Snapshot Sync', 'snapshot' ),
size_format( $filesize, 1 )
);
}
}
}
}
}
return $actions;
}
// media
public function manual_sync_file_add(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to sync!", "snapshot"));
}
if( $this->get_sync_backup_file() ){
$post_id = $_POST['id'];
$attached_file = get_post_meta( $post_id, '_wp_attached_file', true );
$relative_path = trailingslashit( _wp_get_attachment_relative_path( $attached_file ) );
if( 0 !== strpos( $attached_file, $relative_path ) ){
$attached_file = $relative_path . basename( $attached_file );
}
$attachment_metadata = get_post_meta( $post_id, '_wp_attachment_metadata', true );
$attachments = [];
$manual_sync_files = $this->get_option('manual_sync_files');
// $sync_files = $this->get_option('sync_files');
// $sync_files = array_merge( $manual_sync_files, $sync_files );
$standard_file_size = $this->get_standard_size();
$full_upload_path = $this->get_root('uploads');
// add to manual file, only for large file > standard size
if( ! isset( $manual_sync_files[ $attached_file ] ) && @filesize( $full_upload_path . $attached_file ) > $standard_file_size ){
$attachments[ $attached_file ] = $post_id;
}
if( $attachment_metadata && ! empty( $attachment_metadata['sizes'] ) ){
foreach( $attachment_metadata['sizes'] as $size ){
if( ! empty( $size['file'] ) ){
$file = $relative_path . $size['file'];
// add to manual file, only for large file > standard size
if( ! isset( $manual_sync_files[ $file ] ) && @filesize( $full_upload_path . $file ) > $standard_file_size ){
$attachments[ $file ] = $post_id;
}
}
}
}
if( ! empty( $attachments ) ){
$rest = $this->zip_action( $attachments );
if( ! empty( $rest ) && is_array( $rest ) ){
$attachments = array_diff_key( $attachments, $rest );
}
$manual_sync_files = array_merge( $manual_sync_files, $attachments );
$this->save_option('manual_sync_files', $manual_sync_files);
wp_send_json_success();
}
wp_send_json_error( __('Media file does not exist!','snapshot' ) );
}else{
wp_send_json_error( __('Sync backup file does not exist!','snapshot' ) );
}
// wp_safe_redirect( $this->get_current_url() );
// exit();
}
public function get_attachment_relative_path($attachment_path){
$upload_pos = strpos( $attachment_path, 'wp-content/uploads' );
if ( false !== $upload_pos ) {
// Get the directory name relative to the upload directory (back compat for pre-2.7 uploads)
$attachment_path = ltrim( substr( $attachment_path, $upload_pos + 18 ), '/' );
}
return $attachment_path;
}
public function add_media_single_action_sync_button( $post ){
if( $this->get_sync_backup_file() ){
$manual_sync_files = $this->get_option('manual_sync_files');
// $sync_files = $this->get_option('sync_files');
// $manual_sync_files = array_merge( $manual_sync_files, $sync_files );
$attached_file = get_post_meta( $post->ID, '_wp_attached_file', true );
if( $attached_file ){
$attached_file = $this->get_attachment_relative_path( $attached_file );
$filesize = @filesize( $this->get_root('uploads') . $attached_file );
$manual_reject_files = $this->get_manual_reject_files();
if( $filesize > $this->get_standard_size() ){
if( isset( $manual_sync_files[ $attached_file ] ) ){
$title = esc_attr( sprintf( __( 'Remove &#8220;%s&#8221; from the sync Backup file','snapshot' ), esc_html( $post->post_title ) ) );
printf(
'<div class="misc-pub-section misc-pub-dimensions"><a href="#" data-id="%s" data-group="media" data-action="unsync" class="snapshot-manual-sync unsync aria-button-if-js" title="%s">%s (%s)</a></div>',
$post->ID,
$title,
$title,
__( 'Snapshot Unsync', 'snapshot' ),
size_format( $filesize, 1 )
);
}else{
if( isset( $manual_reject_files[ $post->ID ] ) ){
printf(
'<div class="misc-pub-section misc-pub-dimensions"><a href="#" data-id="%s" data-group="media" data-action="unreject" class="unreject snapshot-manual-sync aria-button-if-js" >%s (%s)</a></div>',
$post->ID,
__( 'Snapshot Unreject', 'snapshot' ),
size_format( $filesize, 1 )
);
}else{
printf(
'<div class="misc-pub-section misc-pub-dimensions"><a href="#" data-id="%s" data-group="media" data-action="reject" class="reject snapshot-manual-sync aria-button-if-js" >%s</a></div>',
$post->ID,
__( 'Snapshot Reject', 'snapshot' )
);
$title = esc_attr( sprintf( __( 'Put &#8220;%s&#8221; to the next Backup file','snapshot' ), esc_html( $post->post_title ) ) );
printf(
'<div class="misc-pub-section misc-pub-dimensions"><a href="#" data-id="%s" data-group="media" class="add snapshot-manual-sync aria-button-if-js" title="%s" >%s (%s)</a></div>',
$post->ID,
$title,
$title,
__( 'Snapshot Sync', 'snapshot' ),
size_format( $filesize, 1 )
);
}
}
}
}
}
}
public function manual_unsync_file(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to unsync!", "snapshot"));
}
if( $this->is_lock_for_doing_cron() ){
wp_send_json_error( __('Your server is busy now, please try again later!','snapshot') );
}
$post_id = $_POST['id'];
$attached_file = get_post_meta( $post_id, '_wp_attached_file', true );
if( $attached_file && $this->get_sync_backup_file() ){
$attached_file = $this->get_attachment_relative_path( $attached_file );
$relative_path = dirname( $attached_file );
$attachment_metadata = get_post_meta( $post_id, '_wp_attachment_metadata', true );
$attachments = [];
$manual_sync_files = $this->get_option('manual_sync_files');
$full_upload_path = $this->get_root('uploads');
$standard_file_size = $this->get_standard_size();
// add to delete from manual files, only for large file > standard size
if( @filesize( $full_upload_path . $attached_file ) > $standard_file_size ){
$attachments[ $attached_file ] = $post_id;
}
if( $attachment_metadata && ! empty( $attachment_metadata['sizes'] ) ){
foreach( $attachment_metadata['sizes'] as $size ){
if( ! empty( $size['file'] ) ){
$file = $relative_path . $size['file'];
// add to delete from manual files, only for large file > standard size
if( @filesize( $full_upload_path . $file ) > $standard_file_size ){
$attachments[ $file ] = $post_id;
}
}
}
}
if( ! empty( $attachments ) ){
$rest = $this->zip_action( $attachments, 'delete' );
if( ! empty( $rest ) && is_array( $rest ) ){
$attachments = array_diff_key( $attachments, $rest );
}
$manual_sync_files = array_diff_key( $manual_sync_files, $attachments );
$this->save_option('manual_sync_files', $manual_sync_files);
wp_send_json_success();
}
}
// wp_safe_redirect( $this->get_current_url() );
// exit();
wp_send_json_error( __('Media file or sync backup file does not exist!','snapshot' ) );
}
public function manual_reject_file(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to reject!", "snapshot"));
}
$post_id = $_POST['id'];
$attached_file = get_post_meta( $post_id, '_wp_attached_file', true );
if( $attached_file ){
$attached_file = $this->get_attachment_relative_path( $attached_file );
$relative_path = dirname( $attached_file );
$attachment_metadata = get_post_meta( $post_id, '_wp_attachment_metadata', true );
$attachments = [];
$manual_reject_files = $this->get_manual_reject_files();
$full_upload_path = $this->get_root('uploads');
$standard_file_size = $this->get_standard_size();
// reject only for large file
if( @filesize( $full_upload_path . $attached_file ) > $standard_file_size ){
$attachments[] = $attached_file;
}
if( $attachment_metadata && ! empty( $attachment_metadata['sizes'] ) ){
foreach( $attachment_metadata['sizes'] as $size ){
if( ! empty( $size['file'] ) ){
$file = $relative_path . $size['file'];
// add to delete from manual files, only for large file > standard size
if( @filesize( $full_upload_path . $file ) > $standard_file_size ){
$attachments[] = $file;
}
}
}
}
if( ! empty( $attachments ) ){
$manual_reject_files[ $post_id ] = $attachments;
$this->save_option('manual_reject_files', $manual_reject_files);
wp_send_json_success();
}
}
// wp_safe_redirect( $this->get_current_url() );
// exit();
wp_send_json_error( __('Media file does not exist!','snapshot' ) );
}
public function manual_unreject_file(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to unreject!", "snapshot"));
}
$post_id = $_POST['id'];
$manual_reject_files = $this->get_manual_reject_files();
if( isset( $manual_reject_files[ $post_id ] ) ){
unset( $manual_reject_files[ $post_id ] );
$this->save_option('manual_reject_files', $manual_reject_files);
wp_send_json_success();
}
// wp_safe_redirect( $this->get_current_url() );
// exit();
wp_send_json_error( __('Media file does not exist!','snapshot' ) );
}
// theme
public function add_theme_action_sync(){
if( $this->get_sync_backup_file() ){
$list_themes = wp_get_themes();
if( $list_themes ){
$themes = [];
$active_theme = $this->get_active_themes();
$sync_themes = $this->get_manual_sync_themes( true, $active_theme, $list_themes );
$manual_reject_dirs = $this->get_manual_reject_dirs( true );
foreach( $list_themes as $id => $theme ){
if( ! in_array( $id, $active_theme ) ){
if( isset( $sync_themes[ $id ] ) ){
$label = __('Snapshot Unsync', 'snapshot');
$title = esc_attr( sprintf( __( 'Remove &#8220;%s&#8221; from the sync Backup file','snapshot' ), esc_html( $theme->get('Name') ) ) );
$themes[$id] = array('sync' => sprintf('<a data-action="unsync" class="snapshot-manual-sync unsync button" data-id="%s" data-group="theme" href="#" title="%s">%s</a>', $id, $title, $label) );
}else{
$label = __('Sync', 'snapshot');
$title = esc_attr( sprintf( __( 'Put &#8220;%s&#8221; to the next Backup file','snapshot' ), esc_html( $theme->get('Name') ) ) );
if( isset( $manual_reject_dirs[ $id ] ) ){
$themes[$id] = array(
'reject' => sprintf(
'<a href="#" data-id="%s" data-group="theme" data-action="unreject" class="button unreject snapshot-manual-sync aria-button-if-js" >%s</a>',
$id,
__( 'Snapshot Unreject', 'snapshot' )
),
'sync' => sprintf('<a class="snapshot-hide button snapshot-manual-sync sync" href="#" data-id="%s" data-group="theme" title="%s">%s</a>', $id, $title, $label),
);
}else{
$themes[$id] = array(
'sync' => sprintf('<a class="button snapshot-manual-sync sync" href="#" data-id="%s" data-group="theme" title="%s">%s</a>', $id, $title, $label),
'reject' => sprintf(
'<a href="#" data-id="%s" data-group="theme" data-action="reject" title="%s" class="button reject snapshot-manual-sync aria-button-if-js" >%s</a>',
$id,
esc_attr( sprintf( __( 'Reject &#8220;%s&#8221; from the next Backup file','snapshot' ), esc_html( $theme->get('Name') ) ) ),
__( 'Reject', 'snapshot' )
)
);
}
}
}
}
echo '<script>
var _all_themes = '. json_encode( $themes ) .';
jQuery(document).ready(function(){
var _themes = jQuery(".themes");
if( _themes.length ){
_themes.children().each(function(){
var _this = jQuery(this),
_id = _this.data("slug");
if( ! _id && _this.hasClass("theme-overlay") ){
_id = _this.next().data("slug");
}
if( _id && _id in _all_themes ){
if( "reject" in _all_themes[ _id ] ){
_this.find(".theme-actions").append( _all_themes[ _id ]["reject"] );
}
if( "sync" in _all_themes[ _id ] ){
_this.find(".theme-actions").append( _all_themes[ _id ]["sync"] );
}
}
});
}
});
</script>';
}
}
}
public function network_add_theme_sync_action( $actions, $theme_data ){
if( $this->get_sync_backup_file() ){
$synced_themes = $this->get_manual_sync_themes( true, array() );
$theme = $theme_data->stylesheet;
if( isset( $synced_themes[ $theme ] ) ){
$label = __('Snapshot Unsync', 'snapshot');
$title = esc_attr( sprintf( __( 'Remove &#8220;%s&#8221; from the sync Backup file','snapshot' ), esc_html( $theme_data['Name'] ) ) );
$actions['snapshot_manual_sync'] = sprintf('<a data-action="unsync" class="snapshot-manual-sync unsync" data-id="%s" data-group="theme" href="#" title="%s">%s</a>', $theme, $title, $label);
}else{
$manual_reject_dirs = $this->get_manual_reject_dirs( true );
$label = __('Snapshot sync', 'snapshot');
$title = esc_attr( sprintf( __( 'Put &#8220;%s&#8221; to the next Backup file','snapshot' ), esc_html( $theme_data['Name'] ) ) );
if( isset( $manual_reject_dirs[ $theme ] ) ){
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="theme" data-action="unreject" class="unreject snapshot-manual-sync aria-button-if-js" >%s</a>',
$theme,
__( 'Snapshot Unreject', 'snapshot' )
);
$actions['snapshot_manual_sync snapshot-hide'] = sprintf('<a class="snapshot-manual-sync sync" href="#" data-id="%s" data-group="theme" title="%s">%s</a>', $theme, $title, $label);
}else{
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="theme" data-action="reject" class="reject snapshot-manual-sync aria-button-if-js" >%s</a>',
$theme,
__( 'Snapshot Reject', 'snapshot' )
);
$actions['snapshot_manual_sync'] = sprintf('<a class="snapshot-manual-sync sync" href="#" data-id="%s" data-group="theme" title="%s">%s</a>', $theme, $title, $label);
}
}
}
return $actions;
}
public function scandir_files_for_backup( $root = 'uploads', $child='', $max_file_size = 0 ){
if( empty( $root ) ) return;
$_root = $this->get_root( $root );
$_path = $_root . $child;
if( empty( $_path ) || ! is_dir( $_path ) ) return;
$_path = untrailingslashit( $_path );
// Exclude files.
$item_ignore_files = array();
// $item_ignore_files[] = trailingslashit( $this->snapshot()->get_setting('backupBaseFolderFull') );
// $item_ignore_files[] = trailingslashit( $this->snapshot()->get_setting('SNAPSHOT_PLUGIN_BASE_DIR') );
$snapshot = $this->snapshot();
// Then we add any global excludes
$snapshot_option = $this->snapshot()->get_setting('options_key');
$disable_scandir_filter = $root === 'folders' || $this->disabled_sync();
if( ! $disable_scandir_filter ){
// remove_filter( 'option_'. $snapshot_option, array( $this, 'overwrite_exclude_files_option') );
$this->options['snapshot-mu-scanning'] = 1;
}
remove_filter( 'snapshot_scandir_file', array( $this, 'reject_large_file') );
$item_files = Snapshot_Helper_Utility::scandir( $_path );
if( is_multisite() ){
$snapshot_settings = get_site_option( $snapshot_option, array() );
}else{
$snapshot_settings = get_option( $snapshot_option, array() );
}
if ( ( isset( $this->options[ 'filtered_origin_options' ]['config']['filesIgnore'] ) ) && ( ! empty( $this->options[ 'filtered_origin_options' ]['config']['filesIgnore'] ) ) ) {
$item_ignore_files = array_merge( $item_ignore_files, (array) $this->options[ 'filtered_origin_options' ]['config']['filesIgnore'] );
}
if( ! $disable_scandir_filter ){
// add_filter( 'option_'. $snapshot_option, array( $this, 'overwrite_exclude_files_option') );
$this->options['snapshot-mu-scanning'] = null;
}
add_filter( 'snapshot_scandir_file', array( $this, 'reject_large_file') );
if( ! $max_file_size ){
$max_file_size = $this->max_file_size;
}
$item_section_files = array();
// Need to exclude the user ignore patterns as well as our Snapshot base folder. No backup of the backups
foreach ( $item_files as $item_files_key => $item_files_file ) {
// We spin through all the files. They will fall into one of three sections...
// If the file is not readable we ignore
if ( ! is_readable( $item_files_file ) ) {
if ( ! isset( $item_section_files['error'] ) ) {
$item_section_files['error'] = array();
}
$item_section_files['error'][] = $item_files_file;
} else {
$EXCLUDE_THIS_FILE = false;
foreach ( $item_ignore_files as $item_ignore_file ) {
// Make sure we don't have any blank entries.
$item_ignore_file = trim( $item_ignore_file );
if ( empty( $item_ignore_file ) ) {
continue;
}
//echo "item_set_files_file<pre>"; print_r($item_files_file); echo "</pre>";
//echo "item_ignore_file[". $item_ignore_file ."]<br />";
$stristr_ret = stristr( $item_files_file, $item_ignore_file );
if ( false !== $stristr_ret ) {
$EXCLUDE_THIS_FILE = true;
break;
}
}
if ( false === $EXCLUDE_THIS_FILE ) {
// If file is valid we keep it
if ( ! isset( $item_section_files['included'] ) ) {
$item_section_files['included'] = array();
}
$filesize = @filesize($item_files_file);
if( $filesize && $filesize < $max_file_size ){
$item_section_files['included'][ str_replace($_root, '', $item_files_file) ] = $root === 'uploads' ? @filemtime( $item_files_file ) : 1;
}else{
if ( ! isset( $item_section_files['excluded_large'] ) ) {
$item_section_files['excluded_large'] = array();
}
$reject = true;
// in plugins or themes only exclude zip file
if( ($root === 'plugins' || $root === 'themes') && ( ! $this->is_zip_file( $item_files_file ) ) ){
$reject = false;
if( $filesize > 0 && defined('WP_DEBUG') && WP_DEBUG ){
$this->log("Large file: {$item_files_file} ({$filesize})", "snapshot");
}
}
if( $reject ){
$item_section_files['excluded_large'][] = $item_files_file;
// $this->log("Reject {$item_files_file} ({$filesize}) because of the size constraint.", "snapshot");
}
}
} else {
if ( ! isset( $item_section_files['excluded'] ) ) {
$item_section_files['excluded'] = array();
}
$item_section_files['excluded'][] = $item_files_file;
}
}
}
if( isset( $item_section_files['included'] ) && defined('WP_DEBUG') && WP_DEBUG ){
$this->log(sprintf("Have %s files from %s.", count( $item_section_files['included'] ), $_path ) );
}
//echo "item_section_files<pre>"; print_r($item_section_files); echo "</pre>";
//die();
return $item_section_files;
}
public function get_active_themes(){
if( defined('SNAPSHOT_ENABLE_SYNC_ACTIVE_THEME') && SNAPSHOT_ENABLE_SYNC_ACTIVE_THEME ){
return [];
}
return [ get_stylesheet() ];
// $active_theme = wp_get_theme();
// if( $parent = $active_theme->parent() ){
// return [$active_theme->get_stylesheet(), $parent->get_stylesheet()];
// }
// return [$active_theme->get_stylesheet()];
}
public function manual_sync_theme_add(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to sync!", "snapshot"));
}
if( $this->is_lock_for_doing_cron() ){
wp_send_json_error( __('Your server is busy now, please try again later!','snapshot') );
}
if( $this->get_sync_backup_file() ){
if( $status = $this->manual_sync_items( array( $_POST['id'] ), 'themes' ) ){
if( true === $status ){
wp_send_json_success();
}else{
wp_send_json_error( sprintf( __('Have error while trying to sync theme %s, and also added it to queue to sync later. Please try again or wait the auto sycn at %s!','snapshot'), $_POST['id'], date( 'd/m/Y h:i:s', $status ) ) );
}
}
wp_send_json_error( __('The theme empty or does not exist, please try again later!','snapshot') );
}else{
wp_send_json_error( __('The sync backup file does not exist','snapshot') );
}
}
public function manual_unsync_theme(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to unsync!", "snapshot"));
}
if( $this->is_lock_for_doing_cron() ){
wp_send_json_error( __('Your server is busy now, please try again later!','snapshot') );
}
if( $status = $this->manual_unsync_items( array( $_POST['id'] ), 'themes', true ) ){
if( $status === true ){
wp_send_json_success();
}else{
wp_send_json_error( sprintf(__('We unsyned theme %s, but not success to remove all the files. We added it to queue and try to delete the rest files later', 'snapshot' ), $_POST['id'] ) );
}
}else{
wp_send_json_error( __('Have error while trying to unsync, please try again later!','snapshot') );
}
// wp_safe_redirect( admin_url('themes.php') );
// exit;
}
public function manual_reject_theme(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to reject!", "snapshot"));
}
$manual_reject_dirs = $this->get_manual_reject_dirs();
$manual_reject_dirs[ $_POST['id'] ] = $this->get_zip_path('themes') . $_POST['id'];
$this->save_option( 'manual_reject_dirs', $manual_reject_dirs );
wp_send_json_success();
}
public function manual_unreject_directory(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to reject!", "snapshot"));
}
$manual_reject_dirs = $this->get_manual_reject_dirs();
if( isset( $manual_reject_dirs[ $_POST['id'] ] ) ){
unset( $manual_reject_dirs[ $_POST['id'] ] );
$this->save_option( 'manual_reject_dirs', $manual_reject_dirs );
wp_send_json_success();
}
wp_send_json_error( __("Not found the item in the list rejected files", "snapshot" ) );
}
public function manual_sync_items( $items, $group = 'plugins' ){
if( ! $this->get_sync_backup_file() ) return;
if( empty( $items ) ) return;
$items = (array) $items;
// $this->remove_cron_prepare_copy_backup_file();
$method = "get_manual_sync_{$group}";
if( ! method_exists($this, $method) ){
$this->log("Method get_manual_sync_{$group} do not exist!");
return;
}
$synced_items = $this->$method();
$add_files = [];
$manual_sync_fail = $this->get_option( 'manual_sync_fail', array() );
foreach( $items as $item ){
if( isset( $manual_sync_fail[ $item ]['add'] ) ){
if( $this->enabled_save_sync_options_in_file() ){
$manual_sync_fail[ $item ]['add'] = (array) $manual_sync_fail[ $item ]['add'];
}
$files = ! empty( $manual_sync_fail[ $item ]['add']['rest_files'] ) ? $manual_sync_fail[ $item ]['add']['rest_files'] : $manual_sync_fail[ $item ]['add']['files'];
$add_files = array_merge( $add_files, $files );
}else{
$item_dir = $item;
if( 'plugins' === $group ){
$item_dir = dirname( $item );
}
$files = $this->scandir_files_for_backup( $group, $item_dir );
if( ! empty( $files['included'] ) ){
$add_files = array_merge( $add_files, $files['included'] );
// $synced_items[ $item ] = $files['included'];
$manual_sync_fail[ $item ]['add'] = array(
'files' => $files['included'],
'group' => $group
);
// maybe delete the exists file
if( isset( $manual_sync_fail[ $item ]['delete'] ) ){
$rest_files = ( ! empty( $manual_sync_fail[ $item ]['delete']['rest_files'] ) ) ? $manual_sync_fail[ $item ]['delete']['rest_files'] : $manual_sync_fail[ $item ]['delete']['files'];
$delete_files = array_diff( $rest_files, $files['included'] );
$rest_files = false;
if( $delete_files ){
$rest_files = $this->zip_action( $delete_files, 'delete', $group );
}
// unset delete folder
if( ! $rest_files ){
unset( $manual_sync_fail[ $item ]['delete'] );
}elseif( count( $rest_files ) < count( $delete_files ) ){
$manual_sync_fail[ $item ]['delete']['rest_files'] = $rest_files;
}
}
}
}
}
if( ! empty( $add_files ) ){
// remove copy file
$this->maybe_remove_copy_file();
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
$rest_files = $this->zip_action( $add_files, 'add', $group );
$update_fail = $update_sync = false;
if( empty( $rest_files) || $update_fail = ( is_array( $rest_files ) && count( $rest_files ) < count( $add_files ) ) ){
// $this->save_option("manual_sync_$group", $synced_items);
// $manual_sync_fail = $this->get_option('manual_sync_fail');
if( $update_fail ){
if( count( $items ) > 1 ){
foreach( $items as $item ){
$manual_sync_fail[ $item ]['add']['rest_files'] = array_intersect_key( (array)$manual_sync_fail[ $item ]['add']['files'], $rest_files );
if( $manual_sync_fail[ $item ]['add']['rest_files'] ){
// $manual_sync_fail[ $item ]['add'] = $manual_sync_fail[ $item ]['add'];
Snapshot_Helper_Log::warn( sprintf( "Sync the plugin %s is not successfull, added to queue.", $item ), "snapshot");
}else{
$update_sync = true;
$synced_items[ $item ] = $manual_sync_fail[ $item ]['add']['files'];
// unset( $manual_sync_fail[ $item ]['add'] );
unset( $manual_sync_fail[ $item ] );
}
}
}else{
$manual_sync_fail[ $item ]['add']['rest_files'] = $rest_files;
Snapshot_Helper_Log::warn( sprintf( "Sync the plugin %s is not successfull, added to queue", $items[0] ), "snapshot");
}
if( $update_sync ){
$this->save_option("manual_sync_$group", $synced_items);
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
return $this->get_next_manual_sync_queue();
}else{
// $max_files_ok = $this->get_max_files_ok( 'add' );
foreach( $items as $item ){
$update_sync = true;
$synced_items[ $item ] = $manual_sync_fail[ $item ]['add']['files'];
// $max_files_ok = max( $max_files_ok, count( $synced_items[ $item ] ) );
// unset( $manual_sync_fail[ $item ]['add'] );
unset( $manual_sync_fail[ $item ] );
}
if( $update_sync ){
$this->save_option("manual_sync_$group", $synced_items);
// $this->save_max_files_ok( $max_files_ok, 'add' );
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
$this->create_cron_prepare_copy_backup_file( true, 120 );
return true;
}
}
}
return false;
}
public function manual_unsync_items( $items, $group = 'plugins', $force_delete = false ){
if( ! $this->get_sync_backup_file() ) return;
if( empty( $items ) ) return;
// $this->remove_cron_prepare_copy_backup_file();
$items = (array) $items;
$method = "get_manual_sync_{$group}";
if( ! method_exists($this, $method) ){
$this->log("Method get_manual_sync_{$group} do not exist!");
return;
}
$synced_items = $this->$method();
$delete_files = [];
$manual_sync_fail = $this->get_option( 'manual_sync_fail', array() );
foreach( $items as $item ){
if( isset( $synced_items[ $item ] ) ){
if( isset( $manual_sync_fail[ $item ]['delete'] ) ){
if( $this->enabled_save_sync_options_in_file() ){
$manual_sync_fail[ $item ]['delete'] = (array) $manual_sync_fail[ $item ]['delete'];
}
$files = ! empty( $manual_sync_fail[ $item ]['delete']['rest_files'] ) ? $manual_sync_fail[ $item ]['delete']['rest_files'] : $manual_sync_fail[ $item ]['delete']['files'];
$delete_files = array_merge( $delete_files, $files );
}else{
// maybe unset add fail files
if( $force_delete && isset( $manual_sync_fail[ $item ]['add'] ) ){
unset( $manual_sync_fail[ $item ]['add'] );
}
$delete_files = array_merge( $delete_files, $synced_items[ $item ] );
$manual_sync_fail[ $item ]['delete'] = array(
'files' => $synced_items[ $item ],
'group' => $group
);
}
// unset( $synced_items[ $item ] );
}
}
if( ! empty( $delete_files ) ){
// remove copy file
$this->maybe_remove_copy_file();
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
$rest_files = $this->zip_action( $delete_files, 'delete', $group );
$update_sync = $update_fail = false;
if( $rest_files && count( $rest_files ) === count( $delete_files ) ){
// try delete one file
foreach( $rest_files as $file => $filetime ){
if( ! $this->zip_action(array( $file => $filetime ), 'delete', $group ) ){
// already deleted
$rest_files = array();
}else{
unset( $rest_files[ $file ] );
}
break;
}
}
if( empty( $rest_files) || $update_fail = ( is_array( $rest_files ) && count( $rest_files ) < count( $delete_files ) ) ){
// $this->save_option("manual_sync_$group", $synced_items);
// $manual_sync_fail = $this->get_option('manual_sync_fail');
if( $update_fail ){
if( count( $items ) > 1 ){
foreach( $items as $item ){
$manual_sync_fail[ $item ]['delete']['rest_files'] = array_intersect_key( (array)$manual_sync_fail[ $item ]['delete']['files'], $rest_files );
if( $manual_sync_fail[ $item ]['delete']['rest_files'] ){
// $manual_sync_fail[ $item ] = $manual_sync_fail[ $item ];
Snapshot_Helper_Log::warn( sprintf( "Unsync the plugin %s is not successfull, added to queue.", $item ), "snapshot");
}else{
//deleted successfull, unset from fail options
unset( $manual_sync_fail[ $item ]['delete'] );
if( empty( $manual_sync_fail[ $item ] ) ){
unset( $manual_sync_fail[ $item ] );
}
if( isset( $synced_items[ $item ] ) ){
unset( $synced_items[ $item ] );
$update_sync = true;
}
}
}
}else{
$manual_sync_fail[ $item ]['delete']['rest_files'] = $rest_files;
Snapshot_Helper_Log::warn( sprintf( "Unsync the plugin %s is not successfull, added to queue", $items[0] ), "snapshot");
}
if( $update_sync ){
$this->save_option("manual_sync_$group", $synced_items);
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
return $this->get_next_manual_sync_queue();
}else{
// $max_files_ok = $this->get_max_files_ok( 'delete' );
foreach( $items as $item ){
unset( $manual_sync_fail[ $item ]['delete'] );
// unset all
if( empty( $manual_sync_fail[ $item ] ) ){
unset( $manual_sync_fail[ $item ] );
}
if( isset( $synced_items[ $item ] ) ){
// $max_files_ok = max( $max_files_ok, count( $synced_items[ $item ] ) );
unset( $synced_items[ $item ] );
$update_sync = true;
}
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
if( $update_sync ){
$this->save_option("manual_sync_$group", $synced_items);
// $this->save_max_files_ok( $max_files_ok, 'delete' );
}
$this->create_cron_prepare_copy_backup_file( true, 120 );
return true;
}
}
}
return false;
}
// plugins
public function create_schedule_sync_activated_plugins( $time = 0){
$time = $time ?: time() + 60;
wp_schedule_single_event( $time, $this->manual_sync_activated_plugins_cron_hook );
$this->maybe_trigger_immediate_cron();
}
public function run_cron_manual_sync_activated_plugins(){
if( $this->is_busy_for_doing('sync-plugins') ) return;
if( $this->get_sync_backup_file() ){
$sync_plugins = $this->get_transient( 'sync-plugins-args' );
$synced_plugins = $this->get_manual_sync_plugins();
if( false === $sync_plugins && empty( $synced_plugins ) ){
if( is_multisite() ){
$sync_plugins = get_site_option( 'active_sitewide_plugins', array() );
global $wpdb;
$offset = 0;
$limit = 100;
while ( $limit && $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} LIMIT $offset, $limit", ARRAY_A ) ) {
if ( $blogs ) {
foreach ( $blogs as $blog ) {
switch_to_blog( $blog['blog_id'] );
$acitvated_plugins = (array) get_option( 'active_plugins', array() );
if( $acitvated_plugins ){
$sync_plugins = array_merge( $sync_plugins, $acitvated_plugins );
}
restore_current_blog();
}
if( count( $blogs ) < $limit ){
$limit = 0;
}
}
$offset += $limit;
}
$sync_plugins = array_unique( $sync_plugins );
}else{
$sync_plugins = (array) get_option( 'active_plugins', array() );
}
$manual_reject_dirs = $this->get_manual_reject_dirs();
$update_reject = 0;
foreach ( $sync_plugins as $k => $plugin ) {
unset( $sync_plugins[ $k ] );
if( isset( $manual_reject_dirs[ $plugin ] ) ) continue;
if ( ! validate_file( $plugin ) // $plugin must validate as file
&& '.php' == substr( $plugin, -4 ) // $plugin must end with '.php'
&& file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist
) {
$sync_plugins[ $k ] = $plugin;
}else{
$update_reject = 1;
$manual_reject_dirs[ $plugin ] = $this->get_zip_path('plugins') . dirname( $plugin );
}
}
if( $update_reject ){
$this->save_option( 'manual_reject_dirs', $manual_reject_dirs );
}
}
if( ! empty( $sync_plugins ) ){
$this->lock_for_doing_cron('sync-plugins');
$i = 0;
$chunk_size = $this->get_chunk_folders_size();
$plugins = [];
// $sync_plugins = array_diff( $sync_plugins, array_keys( $synced_plugins ) );
foreach( $sync_plugins as $k => $plugin ){
if( isset( $synced_plugins[ $plugin ] ) ){
unset( $sync_plugins[ $k ] );
continue;
}
$plugins[] = $plugin;
$i++;
if( $i === $chunk_size ){
break;
}
}
if( ! empty( $plugins ) ){
try{
// remove copy file
$this->maybe_remove_copy_file();
$this->manual_sync_items( $plugins );
}catch( Exception $e){
$this->prepare_finish_process();
Snapshot_Helper_Log::error( sprintf( __("Error on sync plugin: %s", "snapshot"), $e->getMessage() ) );
wp_schedule_single_event( time() + 120, $this->manual_sync_activated_plugins_cron_hook );
return;
}
}
if( ! empty( $sync_plugins ) ){
$this->set_transient( 'sync-plugins-args', $sync_plugins );
wp_schedule_single_event( time() + $this->get_delaytime_incron(), $this->manual_sync_activated_plugins_cron_hook );
$this->maybe_trigger_immediate_cron();
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-plugins' );
}
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-plugins' );
}
}
}
public function manual_sync_plugin(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to sync!", "snapshot"));
}
if( $this->is_lock_for_doing_cron() ){
wp_send_json_error( __('Your server is busy now, please try again later!','snapshot') );
}
if( $this->get_sync_backup_file() ){
if( $status = $this->manual_sync_items( array( $_POST['id'] ) ) ){
if( $status === true ){
wp_send_json_success();
}else{
wp_send_json_error( sprintf( __('Have error while trying to sync plugin %s, and also added it to queue to sync later. Please try again or wait the auto sycn at %s!','snapshot'), $_POST['id'], date( 'd/m/Y h:i:s', $status ) ) );
}
}
wp_send_json_error( __('Have error while trying to sync, please try again later!','snapshot') );
}else{
wp_send_json_error( __('The sync backup file does not exist','snapshot') );
}
}
public function get_next_manual_sync_queue(){
$next_event = wp_next_scheduled( $this->fail_files_cron_hook );
$now = Snapshot_Model_Time::get()->get_utc_time();
if( $next_event ){
if( $next_event - $now > 600 ){
return $next_event;
}
wp_unschedule_event( $next_event, $this->fail_files_cron_hook );
}
$early = 2.5 * 60 * 60;
$schedule_time = $this->get_full_cron_schedule_time();
$next_event = strtotime(date("Y-m-d 00:00:00", $now), $now) + $schedule_time;
if ($now > $next_event) {
// Local time of next event is in the past, move to future.
$next_event += DAY_IN_SECONDS;
}
wp_schedule_single_event( $next_event - $early, $this->fail_files_cron_hook );
return $next_event;
}
public function get_max_files_ok( $action="add", $check_constant_defined=true ){
if( $check_constant_defined ){
$max_files_ok = strtoupper( "SNAPSHOT_MAX_FILES_{$action}_OK" );
if( defined( $max_files_ok ) && $max_files_ok = constant( $max_files_ok ) ){
return (int) $max_files_ok;
}
}
$max_files_ok = $this->get_option('max_files_ok', array());
if( isset( $max_files_ok[ $action ] ) ){
return (int) $max_files_ok[ $action ];
}
return $this->get_chunk_size();
}
public function save_max_files_ok( $no_files_ok, $action="add" ){
if( $no_files_ok < 200 ) return;
$max_files_ok = $this->get_option('max_files_ok');
$max_files_ok[ $action ]= $no_files_ok;
$this->save_option('max_files_ok', $max_files_ok );
}
public function get_manual_sync_plugins( $force=false )
{
$manual_sync_plugins = (array) $this->get_option('manual_sync_plugins');
if( ! empty( $manual_sync_plugins ) ){
$delete_plugins = [];
$root_plugin = $this->get_root('plugins');
foreach( $manual_sync_plugins as $plugin_file => $v ){
if( ! @file_exists( $root_plugin . $plugin_file ) ){
if( $force ){
$delete_plugins[] = $plugin_file;
}
unset( $manual_sync_plugins[ $plugin_file ] );
}
}
if( $force && ! empty( $delete_plugins ) ){
$delete_plugins = $this->manual_unsync_items( $delete_plugins );
// if( ! empty( $delete_plugins ) && is_array( $delete_plugins ) ){
// // add list themes can't delete back
// $manual_sync_plugins = array_merge( $manual_sync_plugins, $delete_plugins );
// }
$this->save_option( 'manual_sync_plugins', $manual_sync_plugins );
}
}
return apply_filters( 'wpmudev_snapshot_manual_sync_plugins', $manual_sync_plugins );
}
public function manual_unsync_plugin(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to unsync!", "snapshot"));
}
if( $this->is_lock_for_doing_cron() ){
wp_send_json_error( __('Your server is busy now, please try again later!','snapshot') );
}
$status = $this->manual_unsync_items( array( $_POST['id'] ), 'plugins', true );
if( $status === true ){
wp_send_json_success();
}else{
wp_send_json_error( sprintf( __('We unsyned plugin %s, but not success to remove all the files. We added it to queue and try to delete the rest files later', 'snapshot' ), $_POST['id'] ) );
}
// wp_safe_redirect( admin_url('themes.php') );
// exit;
}
public function add_plugin_sync_action( $actions, $plugin_file, $plugin_data ){
// skip for snapshot plugin
if( $plugin_file === 'snapshot-backup-reject-large-file.php' ) return $actions;
if( $this->get_sync_backup_file() ){
$synced_plugins = $this->get_manual_sync_plugins( true );
if( isset( $synced_plugins[ $plugin_file ] ) ){
$label = __('Snapshot Unsync', 'snapshot');
$title = esc_attr( sprintf( __( 'Remove &#8220;%s&#8221; from the sync Backup file','snapshot' ), esc_html( $plugin_data['Name'] ) ) );
$actions['snapshot_manual_sync'] = sprintf('<a data-action="unsync" class="snapshot-manual-sync unsync" data-id="%s" data-group="plugin" href="#" title="%s">%s</a>', $plugin_file, $title, $label);
}else{
$manual_reject_dirs = $this->get_manual_reject_dirs( true );
$label = __('Snapshot sync', 'snapshot');
$title = esc_attr( sprintf( __( 'Put &#8220;%s&#8221; to the next Backup file','snapshot' ), esc_html( $plugin_data['Name'] ) ) );
if( isset( $manual_reject_dirs[ $plugin_file ] ) ){
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="plugin" data-action="unreject" class="unreject snapshot-manual-sync aria-button-if-js" >%s</a>',
$plugin_file,
__( 'Snapshot Unreject', 'snapshot' )
);
$actions['snapshot_manual_sync snapshot-hide'] = sprintf('<a class="snapshot-manual-sync sync" href="#" data-id="%s" data-group="plugin" title="%s">%s</a>', $plugin_file, $title, $label);
}else{
$actions['snapshot_manual_reject'] = sprintf(
'<a href="#" data-id="%s" data-group="plugin" data-action="reject" class="reject snapshot-manual-sync aria-button-if-js" >%s</a>',
$plugin_file,
__( 'Snapshot Reject', 'snapshot' )
);
$actions['snapshot_manual_sync'] = sprintf('<a class="snapshot-manual-sync sync" href="#" data-id="%s" data-group="plugin" title="%s">%s</a>', $plugin_file, $title, $label);
}
}
}
return $actions;
}
public function manual_reject_plugin(){
// check_admin_referer( 'snapshot_manual_sync-post_'. $post_id );
if( ! isset( $_POST['nonce'], $_POST['id'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpmudev-manual-sync' )){
wp_send_json_error(__("Missing data to reject!", "snapshot"));
}
$manual_reject_dirs = $this->get_manual_reject_dirs();
$manual_reject_dirs[ $_POST['id'] ] = $this->get_zip_path('plugins') . dirname( $_POST['id'] );
$this->save_option( 'manual_reject_dirs', $manual_reject_dirs );
wp_send_json_success();
}
// upgrader
public function sync_upgrade_item( $upgrader_object, $options ){
if ($options['action'] == 'update' ){
if( $this->get_sync_backup_file() ){
if( $options['type'] === 'plugin' ){
$synced_plugins = $this->get_manual_sync_plugins();
if( $synced_plugins ){
$manual_sync_fail = $this->get_option('manual_sync_fail');
$plugins = [];
$upgrade_plugins = isset( $options['plugin'] ) ? (array) $options['plugin'] : (isset( $options['plugins'] ) ? $options['plugins'] : array() );
if( $upgrade_plugins ){
$unsync_items = 0;
foreach( $upgrade_plugins as $plugin ){
if( isset( $synced_plugins[ $plugin ] ) ){
$plugins[] = $plugin;
$files = $this->scandir_files_for_backup( 'plugins', dirname( $plugin ) );
if( ! empty( $files['included'] ) ){
$manual_sync_fail[ $plugin ]['add'] = array(
'files' => $files['included'],
'group' => 'plugins'
);
$delete_files = array_diff( $synced_plugins[ $plugin ], $files['included'] );
if( $delete_files ){
$manual_sync_fail[ $plugin ]['delete'] = array(
'rest_files' => $delete_files,
'group' => 'plugins'
);
$unsync_items = 1;
}
}
}
}
if( ! empty( $plugins ) ){
$this->save_option('manual_sync_fail', $manual_sync_fail);
if( $unsync_items ){
$this->manual_unsync_items( $plugins );
}
$this->manual_sync_items( $plugins );
}
}
}
}elseif( $options['type'] === 'theme' ){
$synced_themes = $this->get_manual_sync_themes();
if( $synced_themes ){
$manual_sync_fail = $this->get_option('manual_sync_fail');
$themes = [];
$upgrade_themes = isset( $options['theme'] ) ? (array) $options['theme'] : (isset( $options['themes'] ) ? $options['themes'] : array() );
if( $upgrade_themes ){
foreach( $upgrade_themes as $theme ){
if( isset( $synced_themes[ $theme ] ) ){
$themes[] = $theme;
$files = $this->scandir_files_for_backup( 'plugins', $theme );
if( ! empty( $files['included'] ) ){
$manual_sync_fail[ $theme ]['add'] = array(
'files' => $files['included'],
'group' => 'themes'
);
$delete_files = array_diff( $synced_themes[ $theme ], $files['included'] );
if( $delete_files ){
$manual_sync_fail[ $theme ]['delete'] = array(
'rest_files' => $delete_files,
'group' => 'themes'
);
$unsync_items = 1;
}
}
}
}
if( ! empty( $themes ) ){
$this->save_option('manual_sync_fail', $manual_sync_fail);
if( $unsync_items ){
$this->manual_unsync_items( $themes, 'themes' );
}
$this->manual_sync_items( $themes, 'themes' );
}
}
}
}elseif( $options['type'] === 'core' ){
$manual_sync_fail = $this->get_option('manual_sync_fail');
$core_folders = ['wp-admin', WPINC];
$unsync_items = 0;
$synced_core = $this->get_manual_sync_core();
foreach( $core_folders as $folder ){
$files = $this->scandir_files_for_backup( 'core', $folder );
if( ! empty( $files['included'] ) ){
$manual_sync_fail[ $folder ]['add'] = array(
'files' => $files['included'],
'group' => 'core'
);
$delete_files = array_diff( $synced_core[ $folder ], $files['included'] );
if( $delete_files ){
$manual_sync_fail[ $theme ]['delete'] = array(
'rest_files' => $delete_files,
'group' => 'core'
);
$unsync_items = 1;
}
}
}
$this->save_option('manual_sync_fail', $manual_sync_fail);
if( $unsync_items ){
$this->manual_unsync_items( $core_folders, 'core' );
}
$this->manual_sync_items( $core_folders, 'core' );
}
}
}
}
public function is_busy_for_doing( $doing_type = false ){
if( isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] !== $doing_type ){
return true;
}
if(
! $this->is_lock_for_doing_cron()
|| $doing_type === $this->locking
){
return false;
}
return true;
}
// public function get_n
public function run_cron_manual_sync_fail(){
if( ! $this->get_sync_backup_file() || $this->is_busy_for_doing('resync-fail-items') ) return;
$manual_sync_fail = $this->get_option('manual_sync_fail');
$next_event = wp_next_scheduled( $this->fail_files_cron_hook );
if( $next_event ){
wp_unschedule_event( $next_event, $this->fail_files_cron_hook );
}
if( ! empty( $manual_sync_fail ) ){
// $this->set_transient( 'try-sync-fail-files', 1 );
$this->lock_for_doing_cron('resync-fail-items');
// maybe remove copy files
$this->maybe_remove_copy_file();
$manual_sync = [];
$max_files_ok = $this->get_chunk_size();
foreach( $manual_sync_fail as $item => $options ){
// only do one plugin/theme in one time
// try delete first
$action = isset( $options['delete'] ) ? 'delete' : 'add';
if( empty( $options[ $action ] ) ){
unset( $options[ $action ] );
if( 'delete' === $action ){
$action = 'add';
}
if( empty( $options[ $action ] ) ){
unset( $options[ $action ] );
}
}
if( empty( $options ) ){
unset( $manual_sync_fail[ $item ] );
continue;
}
if( ! isset( $options[ $action ]['rest_files'] ) || ! empty( $options[ $action ]['rest_files'] ) ){
if( ! isset( $options[ $action ]['rest_files'] ) ){
$options[ $action ]['rest_files'] = $options[ $action ]['files'];
}
// $max_files_ok = $this->get_max_files_ok( $action );
$process_files = array_splice( $options[ $action ]['rest_files'], 0, $max_files_ok );
$rest_files = $this->zip_action( $process_files, $action, $options[ $action ]['group'] );
$no_proess_files = count( $process_files );
if( $rest_files && count( $rest_files ) === $no_proess_files ){
// $this->set_root( $options[ $action ]['group'] );
$root = $this->get_root( $options[ $action ]['group'] );
$files_not_exist = false;
foreach( $rest_files as $file => $filetime ){
$file_path = $root . $file;
if( $action === 'add' && @file_exists( $file_path ) ){
break;
}elseif( $action === 'delete' && empty( $this->zip_action( array( $file_path => $filetime ), 'delete', $options[ $action ]['group']) ) ){
unset( $options[ $action ]['rest_files'][ $file ] );
$manual_sync_fail[ $item ][ $action ]['rest_files'] = $options[ $action ]['rest_files'];
$this->save_option('manual_sync_fail', $manual_sync_fail, true );
break;
}else{
$files_not_exist = true;
// maybe the item don't exist or deleted from zip
// $options[ $action ]['rest_files'] = array();
$rest_files = array();
break;
}
}
if( ! $files_not_exist ){
Snapshot_Helper_Log::warn( sprintf( __("Can't sync the list fail files of %s. Stop all now, try again later.", "snapshot"), $item ) );
// $this->delete_transient( 'try-sync-fail-files' );
$this->unlock_for_finish_cron();
return $this->get_next_manual_sync_queue();
}
}
$update = false;
if( empty( $rest_files ) ){
if( count( $options[ $action ]['rest_files'] ) === 0 ){
unset( $manual_sync_fail[ $item ][ $action ] );
if( empty( $manual_sync_fail[ $item ] ) ){
unset( $manual_sync_fail[ $item ] );
}
$update = true;
}else{
$manual_sync_fail[ $item ][ $action ]['rest_files'] = $options[ $action ]['rest_files'];
}
}elseif( count( $rest_files ) < $no_proess_files ){
$manual_sync_fail[ $item ][ $action ]['rest_files'] = array_merge( $options[ $action ]['rest_files'], $rest_files );
}
if( $update ){
if( ! isset( $manual_sync[ $options[ $action ]['group'] ] ) ){
$manual_sync[ $options[ $action ]['group'] ] = $this->get_option("manual_sync_{$options[ $action ]['group']}");
}
if( $action === 'add' ){
$manual_sync[ $options[ $action ]['group'] ][ $item ] = $options[ $action ]['files'];
}else{
// delete
if( isset( $manual_sync[ $options[ $action ]['group'] ][ $item ] ) ){
unset( $manual_sync[ $options[ $action ]['group'] ][ $item ] );
}
}
$this->save_option("manual_sync_{$options[ $action ]['group']}", $manual_sync[ $options[ $action ]['group'] ] );
}
break;
}else{
unset( $manual_sync_fail[ $item ][ $action ] );
if( empty( $manual_sync_fail[ $item ] ) ){
unset( $manual_sync_fail[ $item ] );
}
if( ! isset( $manual_sync[ $options[ $action ]['group'] ] ) ){
$manual_sync[ $options[ $action ]['group'] ] = $this->get_option("manual_sync_{$options[ $action ]['group']}");
}
if( $action === 'add' ){
$manual_sync[ $options[ $action ]['group'] ][ $item ] = $options[ $action ]['files'];
}else{
// delete
if( isset( $manual_sync[ $options[ $action ]['group'] ][ $item ] ) ){
unset( $manual_sync[ $options[ $action ]['group'] ][ $item ] );
}
}
$this->save_option("manual_sync_{$options[ $action ]['group']}", $manual_sync[ $options[ $action ]['group'] ] );
}
}
$this->save_option('manual_sync_fail', $manual_sync_fail, true );
if( count( $manual_sync_fail ) ){
wp_schedule_single_event( time() + $this->get_delaytime_incron(), $this->fail_files_cron_hook );
$this->maybe_trigger_immediate_cron();
}else{
$this->unlock_for_finish_cron();
$this->create_cron_prepare_copy_backup_file( true, 120 );
// $this->delete_transient( 'try-sync-fail-files' );
}
}else{
$this->unlock_for_finish_cron();
$this->create_cron_prepare_copy_backup_file( true, 120 );
// $this->delete_transient( 'try-sync-fail-files' );
}
}
// database here
public function multiple_site_list_tables($all_tables)
{
if( is_multisite() ){
$all_tables = wp_cache_get( 'wpmudev-snapshot-ms-tables', 'snapshot' );
if( ! $all_tables ){
$all_tables = Snapshot_Model_Queue_Tableset::get_all_database_tables_ms();
$all_tables = ['wp' => $all_tables['all']];
wp_cache_add( 'wpmudev-snapshot-ms-tables', $all_tables, 'snapshot', WEEK_IN_SECONDS );
}
}
return $all_tables;
}
public function filter_synced_tables( $all_tables ){
$synced_tables = $this->get_option('manual_sync_tables');
if( ! empty( $synced_tables ) && $this->is_lock_for_doing_cron() && isset( $this->snapshot_backup_keys[ $this->locking ] ) ){
$interval = $this->get_interval_sync_database();
$current_time = time();
foreach( $all_tables as $source => $tables ){
foreach( $tables as $key => $table ){
if( isset( $synced_tables[ $table ] ) && ( $current_time - $synced_tables[ $table ]['time'] ) < ( $interval + 600 ) ){
unset( $all_tables[ $source ][ $key ] );
}
}
}
}
return $all_tables;
}
public static function escapeshellarg_windows_support($string)
{
if (strncasecmp(PHP_OS, 'WIN', 3) == 0) {
if (strstr($string, '%') || strstr($string, '!')) {
$result = '"'.str_replace('"', '', $string).'"';
return $result;
}
}
return escapeshellarg($string);
}
/**
* Can shell_exec be called on this server
*
* @return bool Returns true if shell_exec can be called on server
*
*/
public static function has_shell_exec()
{
$cmds = array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded');
//Function disabled at server level
if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions'))))) return false;
//Suhosin: http://www.hardened-php.net/suhosin/
//Will cause PHP to silently fail
if (extension_loaded('suhosin')) {
$suhosin_ini = @ini_get("suhosin.executor.func.blacklist");
if (array_intersect($cmds, array_map('trim', explode(',', $suhosin_ini)))) return false;
}
// Can we issue a simple echo command?
if (!@shell_exec('echo snapshot')) return false;
return true;
}
/**
* Is the server running Windows operating system
*
* @return bool Returns true if operating system is Windows
*
*/
public static function is_windows()
{
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
return true;
}
return false;
}
/**
* Try to return the mysqldump path on Windows servers
*
* @return boolean|string
*/
public static function get_windows_mysqldump_real_path()
{
if (function_exists('php_ini_loaded_file')) {
$get_php_ini_path = php_ini_loaded_file();
if ( @file_exists($get_php_ini_path) ) {
$search = array(
dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump.exe',
dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump.exe',
dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump',
dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump',
);
foreach ($search as $mysqldump) {
if ( @file_exists($mysqldump) ) {
return str_replace("\\", "/", $mysqldump);
}
}
}
}
unset($search);
unset($get_php_ini_path);
return false;
}
/**
* Finds if its a valid executable or not
*
* @param type $exe A non zero length executable path to find if that is executable or not.
* @param type $expectedValue expected value for the result
* @return boolean
*/
public static function is_executable($cmd)
{
if (strlen($cmd) < 1) return false;
if ( @is_executable($cmd) ) {
return true;
}
$output = shell_exec($cmd);
if (!is_null($output)) {
return true;
}
$output = shell_exec($cmd.' -?');
if ( !is_null($output) ) {
return true;
}
return false;
}
/**
* Returns the mysqldump path if the server is enabled to execute it otherwise false
*
* @return boolean|string
*/
public static function get_mysqldump_path()
{
static $mysqldump_path;
if( is_null( $mysqldump_path ) ){
//Is shell_exec possible
if ( ! self::has_shell_exec() ) {
$mysqldump_path = false;
return $mysqldump_path;
}
$custom_mysqldump_path = apply_filters( 'wpmudev_snapshot_mysqldump_path', '' );
//Common Windows Paths
if ( self::is_windows() ) {
$paths = array(
$custom_mysqldump_path,
self::get_windows_mysqldump_real_path(),
'C:/xampp/mysql/bin/mysqldump.exe',
'C:/Program Files/xampp/mysql/bin/mysqldump',
'C:/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
'C:/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
'C:/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump'
);
//Common Linux Paths
} else {
$path1 = '';
$path2 = '';
$mysqldump = `which mysqldump`;
if (self::is_executable($mysqldump)) {
$path1 = (!empty($mysqldump)) ? $mysqldump : '';
}
$mysqldump = dirname(`which mysql`)."/mysqldump";
if (self::is_executable($mysqldump)) {
$path2 = (!empty($mysqldump)) ? $mysqldump : '';
}
$paths = array(
$custom_mysqldump_path,
$path1,
$path2,
'/usr/local/bin/mysqldump',
'/usr/local/mysql/bin/mysqldump',
'/usr/mysql/bin/mysqldump',
'/usr/bin/mysqldump',
'/opt/local/lib/mysql6/bin/mysqldump',
'/opt/local/lib/mysql5/bin/mysqldump'
);
}
//Try to find a path that works. With open_basedir enabled, the file_exists may not work on some systems
//So we fallback and try to use exec as a last resort
$exec_available = function_exists('exec');
foreach ($paths as $path) {
if (@file_exists($path)) {
if (self::is_executable($path)) {
$mysqldump_path = $path;
return $mysqldump_path;
}
} elseif ($exec_available) {
$out = array();
$rc = -1;
$cmd = $path.' --help';
@exec($cmd, $out, $rc);
if ($rc === 0) {
$mysqldump_path = $path;
return $mysqldump_path;
}
}
}
$mysqldump_path = false;
}
return $mysqldump_path;
}
public function mysqldump_table( $table, $exePath ){
global $wpdb;
$host = explode(':', DB_HOST);
$host = reset($host);
$port = strpos(DB_HOST, ':') ? end(explode(':', DB_HOST)) : '';
$name = DB_NAME;
//Build command
$cmd = escapeshellarg($exePath);
$cmd .= ' --no-create-db';
$cmd .= ' --single-transaction';
$cmd .= ' --hex-blob';
// $cmd .= ' --skip-add-drop-table';
$cmd .= ' --routines';
$cmd .= ' --quote-names';
$cmd .= ' --skip-comments';
$cmd .= ' --skip-set-charset';
$cmd .= ' --allow-keywords';
$cmd .= ' --skip-add-locks';
$cmd .= ' -u '.escapeshellarg(DB_USER);
$cmd .= (DB_PASSWORD) ?
' -p'. self::escapeshellarg_windows_support(DB_PASSWORD) : '';
$cmd .= ' -h '.escapeshellarg($host);
$cmd .= (!empty($port) && is_numeric($port) ) ?
' -P '.$port : '';
$cmd .= ' -r '.escapeshellarg( $this->get_table_dump_path( $table ) );
$cmd .= ' '.escapeshellarg(DB_NAME);
$cmd .= ' '.escapeshellarg( $table );
$cmd .= ' 2>&1';
$output = shell_exec($cmd);
// if( $output ){
// if (trim($output) === 'Warning: Using a password on the command line interface can be insecure.') {
// $output = '';
// }else{
// $output = str_ireplace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $output);
// global $wp_filesystem;
// if( Snapshot_Helper_Utility::connect_fs() ) {
// $wp_filesystem->put_contents( $this->get_table_dump_path( $table ), $output );
// } else {
// return new WP_Error("filesystem_error", "Cannot initialize filesystem");
// }
// }
// }
return $output;
}
public function get_chunk_tables_size(){
$chunk_size = 4;
if( defined('SNAPSHOT_TABLES_CHUNK_SIZE') && SNAPSHOT_TABLES_CHUNK_SIZE ){
$chunk_size = SNAPSHOT_TABLES_CHUNK_SIZE;
}
return $chunk_size;
}
public function get_chunk_folders_size(){
$chunk_size = 2;
if( defined('SNAPSHOT_FOLDERS_CHUNK_SIZE') && SNAPSHOT_FOLDERS_CHUNK_SIZE ){
$chunk_size = SNAPSHOT_FOLDERS_CHUNK_SIZE;
}
return $chunk_size;
}
public function get_build_mode(){
static $build_mode;
if( is_null( $build_mode ) ){
if( defined('SNAPSHOT_MYSQLDUMP_MODE') ){
$build_mode = strtoupper( trim( SNAPSHOT_MYSQLDUMP_MODE ) );
if( $build_mode === 'MYSQLDUMP' ){
if( ! self::get_mysqldump_path() ){
$build_mode = 'PHP';
}
}else{
$build_mode = 'PHP';
}
}else{
$build_mode = 'PHP';
if( self::get_mysqldump_path() ){
$build_mode = 'MYSQLDUMP';
}
}
}
return $build_mode;
}
public function get_table_dump_path( $table ){
static $backup_folder;
if( is_null( $backup_folder ) ){
$this->load_config();
$backup_folder = trailingslashit( $this->backup_folder );
}
$table = sanitize_text_field( $table );
return $backup_folder . $table .'.sql';
}
public function sync_table( $table, &$synced_tables ){
if( ! $this->get_transient( 'synced-table-'. $table ) ){
$table_path = $this->get_table_dump_path( $table );
if( @file_exists( $table_path ) ){
@unlink( $table_path );
}
$table_datas = $this->get_table_data( $table );
if( 'PHP' === $this->get_build_mode() ){
// $table_datas = $this->get_table_data( $table );
$table_datas = $this->php_dump( $table, $table_datas );
if( ! is_array( $table_datas ) ){
$error_text = $table_datas;
}
}else{
$table_datas = end( $table_datas );
$table_datas['row_start'] = 0;
$table_datas['segment_idx'] = 1;
$table_datas['segment_total'] = 1;
$table_datas['ftell_before'] = 0;
$this->mysqldump_table( $table, self::get_mysqldump_path() );
$fp = fopen( $table_path, 'r' ); // phpcs:ignore
if ( $fp ) {
fseek( $fp, 0, SEEK_END );
$table_datas['ftell_after'] = ftell( $fp );
fclose( $fp );
}
$table_datas = array( $table_datas );
}
if( @file_exists( $table_path ) ){
// add to zip
$md5_file = md5_file( $table_path );
if( empty( $synced_tables[$table]['md5'] ) || $synced_tables[$table]['md5'] !== $md5_file){
$synced_tables[ $table ] = array(
'time' => time(),
'table_data' => $table_datas,
'md5' => $md5_file
);
if( @filesize( $table_path ) > 10485760 ){//10485760 = 10*1024*1024 = 10M
if( ! $this->zip_action( array( basename( $table_path ) => 1 ), 'add', 'database' ) ){
if( $this->get_sync_backup_copy_file() ){
$backup_file = $this->backup_sync_file;
// update for copy file
$this->backup_sync_file = $this->backup_sync_file_copy;
self::$_zip = null;
$this->zip_action( array( basename( $table_path ) => 1 ), 'add', 'database' );
// reset backup file
$this->backup_sync_file = $backup_file;
}
// remove table
@unlink( $table_path );
}
}else{
$this->options['tables'][ $table ] = $table_path;
}
}else{
$synced_tables[ $table ]['time'] = time();
unlink( $table_path );
}
$this->set_transient( 'synced-table-'. $table, 1, $this->get_interval_sync_database() );
}else{
if( ! isset( $error_text ) ){
$error_text = __("MYSQLDUMP Error", "snapshot");
}
Snapshot_Helper_Log::warn( sprintf( __("Can't dump table %s. %s", "snapshot"), $table, $error_text ) );
}
}
}
public function get_all_tables(){
remove_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
$all_tables = Snapshot_Helper_Utility::get_database_tables();
add_filter( 'snapshot_get_database_tables', array( $this, 'filter_synced_tables'));
$_tables = [];
foreach( $all_tables as $source => $tables ){
if( $tables ){
foreach( $tables as $table ){
$_tables[] = $table;
}
}
}
return $_tables;
}
public function get_delaytime_incron(){
$delay_time = 10;
if( defined('SNAPSHOT_DELAY_IN_CRON') ){
$delay_time = intval( SNAPSHOT_DELAY_IN_CRON );
}
return $delay_time;
}
public function maybe_force_sync_folders(){
if( $this->is_lock_for_doing_cron() || $this->get_transient( 'force-manual-sync-folders' ) ) return;
$forced_config = false;
$save_config = false;
if( defined('SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE') ){
if( isset( $this->configs['sync_upload_before'] ) ){
if( $this->configs['sync_upload_before'] !== SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE ){
$forced_config = true;
$this->delete_transient( 'sync-upload-folders' );
$this->configs['sync_upload_before'] = SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE;
}
}elseif( SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE ){
$this->configs['sync_upload_before'] = SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE;
$save_config = true;
}
}
if( defined('SNAPSHOT_MANUAL_SYNC_FOLDERS') ){
if( ! $forced_config && isset( $this->configs['sync_folders'] ) ){
if( $this->configs['sync_folders'] !== SNAPSHOT_MANUAL_SYNC_FOLDERS ){
$this->delete_transient( 'sync-upload-folders' );
$this->configs['sync_folders'] = SNAPSHOT_MANUAL_SYNC_FOLDERS;
$forced_config = true;
}
}elseif( SNAPSHOT_MANUAL_SYNC_FOLDERS ){
$this->configs['sync_folders'] = SNAPSHOT_MANUAL_SYNC_FOLDERS;
$save_config = true;
}
}
if( defined('SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE') ){
if( ! $forced_config && isset( $this->configs['reject_upload_before'] ) ){
if( $this->configs['reject_upload_before'] !== SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE ){
$this->delete_transient( 'reject-upload-folders' );
$this->delete_transient( 'sync-upload-folders' );
$this->configs['reject_upload_before'] = SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
$forced_config = true;
}
}elseif( SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE ){
$this->configs['reject_upload_before'] = SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
$save_config = true;
}
}
if( $save_config || $forced_config ){
$this->save_config();
}
return $forced_config ? $this->set_transient( 'force-manual-sync-folders', 1 ) : 0;
}
public function dir_is_empty($dirname){
if ( !is_dir( $dirname ) ) return false;
foreach ( scandir( $dirname ) as $file ){
if ( !in_array( $file, array('.','..','.svn','.git') ) ) return false;
}
return true;
}
public function get_sync_folders(){
$manual_sync_folders = [];
if( defined('SNAPSHOT_MANUAL_SYNC_FOLDERS') && SNAPSHOT_MANUAL_SYNC_FOLDERS ){
$manual_sync_folders = (array) maybe_unserialize( SNAPSHOT_MANUAL_SYNC_FOLDERS );
}
if( $this->enable_manual_sync_uploads() ){
if( $sync_upload_folders = $this->get_sync_upload_folders() ){
$manual_sync_folders = array_merge( $manual_sync_folders, $sync_upload_folders );
}
}
if( $manual_sync_folders ){
$root = $this->get_root();
foreach( $manual_sync_folders as $key => $folder ){
unset( $manual_sync_folders[ $key ] );
$manual_sync_folders[ $root . $folder ] = $folder;
}
}
return $manual_sync_folders;
}
public function get_reject_upload_folders(){
if( $this->enable_manual_reject_uploads() ){
$reject_folders = $this->get_transient( 'reject-upload-folders', array() );
if( ! $reject_folders ){
$min_year = date('Y') - 50;
$reject_year = SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
if( is_multisite() ){
global $wpdb;
$offset = 0;
$limit = 100;
while ( $limit && $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} LIMIT $offset, $limit", ARRAY_A ) ) {
if ( $blogs ) {
foreach ( $blogs as $blog ) {
switch_to_blog( $blog['blog_id'] );
$wp_upload_dir = wp_upload_dir( null, false );
$base = $wp_upload_dir['basedir'];
$base_dir = substr( $base, strlen( $this->get_home_path() ) );
$result = scandir( $base );
$data = !empty($result) ? array_diff( $result, self::$ignore_dirs ) : array();
foreach ( $data as $key => $value ){
if( ! is_numeric( $value ) ){
if( strpos( $value, '.' ) === false ){
break;
}
continue;
}
if( $value < $reject_year && $value > $min_year && is_dir( $base . '/' . $value ) ){
$reject_folders[] = $base_dir . '/' . $value;
}
}
restore_current_blog();
}
if( count( $blogs ) < $limit ){
$limit = 0;
}
}
$offset += $limit;
}
}else{
$wp_upload_dir = wp_upload_dir( null, false );
$base = $wp_upload_dir['basedir'];
$base_dir = substr( $base, strlen( $this->get_home_path() ) );
$result = scandir( $base );
$data = !empty($result) ? array_diff( $result, self::$ignore_dirs ) : array();
foreach ( $data as $key => $value ){
if( ! is_numeric( $value ) ){
if( strpos( $value, '.' ) === false ){
break;
}
continue;
}
if( $value < $reject_year && $value > $min_year && is_dir( $base . '/' . $value ) ){
$reject_folders[] = $base_dir . '/' . $value;
}
}
}
$this->set_transient( 'reject-upload-folders', $reject_folders, YEAR_IN_SECONDS );
}
return $reject_folders;
}
return false;
}
public function get_force_reject_upload_folders(){
$reject_folders = [];
if( $this->enable_manual_reject_uploads() ){
$sync_folders = $this->get_sync_upload_folders();
$reject_year = SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
foreach( $sync_folders as $folder => $year ){
if( $year < $reject_year ){
$reject_folders[ $folder ] = 1;
}
}
}
return $reject_folders;
}
public function get_sync_upload_folders(){
if( $this->enable_manual_sync_uploads() ){
$sync_folders = $this->get_transient( 'sync-upload-folders', array() );
if( ! $sync_folders ){
$max_year = SNAPSHOT_MANUAL_SYNC_UPLOAD_BEFORE;
$reject_year = $min_year = date('Y') - 50;
if( $this->enable_manual_reject_uploads() ){
$reject_year = SNAPSHOT_MANUAL_REJECT_UPLOAD_BEFORE;
}
$reject_folders = [];
if( is_multisite() ){
global $wpdb;
$offset = 0;
$limit = 100;
while ( $limit && $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} LIMIT $offset, $limit", ARRAY_A ) ) {
if ( $blogs ) {
foreach ( $blogs as $blog ) {
switch_to_blog( $blog['blog_id'] );
$wp_upload_dir = wp_upload_dir( null, false );
$base = $wp_upload_dir['basedir'];
$base_dir = substr( $base, strlen( $this->get_home_path() ) );
$result = scandir( $base );
$data = !empty($result) ? array_diff( $result, self::$ignore_dirs ) : array();
foreach ( $data as $key => $value ){
if( ! is_numeric( $value ) && strpos( $value, '.' ) === false ){
break;
}
if( $value < $reject_year && $value > $min_year && is_dir( $base . '/' . $value ) ){
$reject_folders[] = $base_dir . '/' . $value;
continue;
}
if( $value >= $max_year || $value < $reject_year ){
continue;
}
if ( is_dir( $base . '/' . $value ) ){
$sync_folders[] = $base_dir . '/' . $value;
}
}
restore_current_blog();
}
if( count( $blogs ) < $limit ){
$limit = 0;
}
}
$offset += $limit;
}
}else{
$wp_upload_dir = wp_upload_dir( null, false );
$base = $wp_upload_dir['basedir'];
$base_dir = substr( $base, strlen( $this->get_home_path() ) );
$result = scandir( $base );
$data = !empty($result) ? array_diff( $result, self::$ignore_dirs ) : array();
foreach ( $data as $key => $value ){
if( ! is_numeric( $value ) ){
if( strpos( $value, '.' ) === false ){
break;
}
continue;
}
if( $value < $reject_year && $value > $min_year && is_dir( $base . '/' . $value ) ){
$reject_folders[] = $base_dir . '/' . $value;
continue;
}
if( $value >= $max_year || $value < $reject_year ){
continue;
}
if ( is_dir( $base . '/' . $value ) ){
$sync_folders[] = $base_dir . '/' . $value;
}
}
}
$this->set_transient( 'sync-upload-folders', $sync_folders, YEAR_IN_SECONDS );
$this->set_transient( 'reject-upload-folders', $reject_folders, YEAR_IN_SECONDS );
}
return $sync_folders;
}
return false;
}
public function get_manual_sync_folders( $force = false )
{
$manual_sync_folders = (array) $this->get_option('manual_sync_folders');
if( ! empty( $manual_sync_folders ) ){
$delete_folders = [];
$root = $this->get_root('folders');
if( $this->enable_force_reject() ){
$delete_folders = array_diff( array_keys( $manual_sync_folders ), $this->get_sync_folders() );
}
foreach( $manual_sync_folders as $folder => $files ){
if( ! @file_exists( $root . $folder ) ){
if( $force ){
$delete_folders[ $folder ] = $folder;
}
unset( $manual_sync_folders[ $folder ] );
}
}
if( $force && ! empty( $delete_folders ) ){
$delete_folders = $this->manual_unsync_items( $delete_folders, 'folders' );
$this->save_option( 'manual_sync_folders', $manual_sync_folders );
}
}
return apply_filters( 'wpmudev_snapshot_manual_sync_folders', $manual_sync_folders );
}
public function manual_sync_folders( $folders ){
if( ! $this->get_sync_backup_file() || empty( $folders ) ) return;
$folders = (array) $folders;
// $this->remove_cron_prepare_copy_backup_file();
$synced_folders = $this->get_manual_sync_folders();
$add_files = [];
$manual_sync_fail = $this->get_option( 'manual_sync_fail', array() );
// $this->delete_option( 'manual_sync_fail' );
foreach( $folders as $folder ){
if( isset( $manual_sync_fail[ $folder ]['add'] ) ){
if( $this->enabled_save_sync_options_in_file() ){
$manual_sync_fail[ $folder ]['add'] = (array) $manual_sync_fail[ $folder ]['add'];
}
$files = ! empty( $manual_sync_fail[ $folder ]['add']['rest_files'] ) ? $manual_sync_fail[ $folder ]['add']['rest_files'] : $manual_sync_fail[ $folder ]['add']['files'];
$add_files = array_merge( $add_files, $files );
}else{
$files = $this->scandir_files_for_backup( 'folders', $folder );
if( ! empty( $files['included'] ) ){
if( isset( $synced_folders[ $folder ] ) ){
$this->check_new_files( $files, $synced_folders[ $folder ], false );
continue;
}
$add_files = array_merge( $add_files, $files['included'] );
$manual_sync_fail[ $folder ]['add'] = array(
'files' => $files['included'],
'group' => 'folders'
);
// maybe delete the exists file
if( isset( $manual_sync_fail[ $folder ]['delete'] ) ){
$rest_files = ( ! empty( $manual_sync_fail[ 'folders' ]['delete']['rest_files'] ) ) ? $manual_sync_fail[ 'folders' ]['delete']['rest_files'] : $manual_sync_fail[ 'folders' ]['delete']['files'];
$delete_files = array_diff( $rest_files, $files['included'] );
$rest_files = false;
if( $delete_files ){
$rest_files = $this->zip_action( $delete_files, 'delete', 'folders' );
}
// unset delete folder
if( ! $rest_files ){
unset( $manual_sync_fail[ $folder ]['delete'] );
}elseif( count( $rest_files ) < count( $delete_files ) ){
$manual_sync_fail[ $folder ]['delete']['rest_files'] = $rest_files;
}
}
}else{
if( ! isset( $reject_folders ) ){
$reject_folders = $this->get_transient( 'reject-upload-folders', array() );
}
if( ! in_array( $folder, $reject_folders ) ){
$reject_folders[] = $folder;
}
}
}
}
// save empty dirs
if( isset( $reject_folders ) ){
$sync_folders_args = $this->get_transient( 'sync-folders-args' );
$this->set_transient( 'reject-upload-folders', $reject_folders );
if( $sync_folders_args ){
$sync_folders_args = array_diff( $sync_folders_args, $reject_folders );
$this->set_transient( 'sync-folders-args', $sync_folders_args );
}
}
if( ! empty( $add_files ) ){
// remove copy file
$this->maybe_remove_copy_file();
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
$rest_files = $this->zip_action( $add_files, 'add', 'folders' );
$update_fail = $update_sync = false;
if( empty( $rest_files) || $update_fail = ( is_array( $rest_files ) && count( $rest_files ) < count( $add_files ) ) ){
// $this->save_option('manual_sync_folders', $synced_folders);
// $manual_sync_fail = $this->get_option('manual_sync_fail');
if( $update_fail ){
if( count( $folders ) > 1 ){
foreach( $folders as $folder ){
$manual_sync_fail[ $folder ]['add']['rest_files'] = array_intersect_key( (array)$manual_sync_fail[ $folder ]['add']['files'], $rest_files );
if( $manual_sync_fail[ $folder ]['add']['rest_files'] ){
// $manual_sync_fail[ $folder ]['add'] = $manual_sync_fail[ $folder ]['add'];
Snapshot_Helper_Log::warn( sprintf( "Sync the plugin %s is not successfull, added to queue.", $folder ), "snapshot");
}else{
$update_sync = true;
$synced_folders[ $folder ] = $manual_sync_fail[ $folder ]['add']['files'];
// unset( $manual_sync_fail[ $folder ]['add'] );
unset( $manual_sync_fail[ $folder ] );
}
}
}else{
$manual_sync_fail[ $folder ]['add']['rest_files'] = $rest_files;
Snapshot_Helper_Log::warn( sprintf( "Sync the plugin %s is not successfull, added to queue", $folders[0] ), "snapshot");
}
if( $update_sync ){
$this->save_option('manual_sync_folders', $synced_folders);
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
return $this->get_next_manual_sync_queue();
}else{
// $max_files_ok = $this->get_max_files_ok( 'add' );
foreach( $folders as $folder ){
$update_sync = true;
if( isset( $manual_sync_fail[ $folder ]['add'] ) ){
$synced_folders[ $folder ] = $manual_sync_fail[ $folder ]['add']['files'];
// unset( $manual_sync_fail[ $folder ]['add'] );
unset( $manual_sync_fail[ $folder ] );
}
// if( isset( $synced_folders[ $folder ] ) ){
// // $max_files_ok = max( $max_files_ok, count( $synced_folders[ $folder ] ) );
// }
}
if( $update_sync ){
$this->save_option('manual_sync_folders', $synced_folders);
// $this->save_max_files_ok( $max_files_ok, 'add' );
}
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true);
$this->create_cron_prepare_copy_backup_file( true, 120 );
return isset( $reject_folders ) ? $reject_folders : true;
}
}
}
return isset( $reject_folders ) ? $reject_folders : false;
}
public function create_schedule_sync_folders( $time = 0){
$time = $time ?: time() + 60;
wp_schedule_single_event( $time, $this->manual_sync_folder_cron_hook );
$this->maybe_trigger_immediate_cron();
}
public function create_cron_monthly_sync_folders(){
$early = 2 * DAY_IN_SECONDS;
$schedule_time = $this->get_full_cron_schedule_time();
$now = Snapshot_Model_Time::get()->get_utc_time();
$next_event = strtotime(date("Y-m-d 00:00:00", $now), $now) + MONTH_IN_SECONDS + $schedule_time;
$recurrence = defined('SNAPSHOT_RECURRENCE_SYNC_FOLDERS') ? SNAPSHOT_RECURRENCE_SYNC_FOLDERS : 'snapshot-monthly';
wp_schedule_event( $next_event - $early, $recurrence, $this->manual_sync_folder_cron_hook );
}
public function run_cron_manual_sync_folders(){
if( $this->is_busy_for_doing('sync-folders') ) return;
if( $this->get_sync_backup_file() ){
$sync_folders = $this->get_transient( 'sync-folders-args' );
if( false === $sync_folders ){
$sync_folders = $this->get_sync_folders();
if( isset( $this->options['filtered_origin_options']['config']['dirsIgnore'] ) ){
$dirs_ignore = $this->options['filtered_origin_options']['config'];
$sync_folders = array_diff_key( $sync_folders, $dirs_ignore );
if( is_multisite() ){
$upload_sites = $this->get_root('uploads') .'sites';
if( isset( $dirs_ignore[ $upload_sites ] ) || isset( $dirs_ignore[ $upload_sites .'/'] ) ){
foreach( $sync_folders as $key => $folder ){
if( strpos( $folder, $upload_sites ) !== false ){
unset( $sync_folders[ $key ] );
}
}
}
}
}
$synced_folders = $this->get_manual_sync_folders( true );
$diff_folders = array_diff( array_keys( $synced_folders ), $sync_folders );
if( $diff_folders ){
$this->manual_unsync_items( $diff_folders, 'folders' );
}
$this->delete_transient( 'force-manual-sync-folders' );
}
$rejected_uploads = $this->get_reject_upload_folders();
if( $rejected_uploads ){
$sync_folders = array_diff( $sync_folders, $rejected_uploads);
}
if( ! empty( $sync_folders ) ){
$this->lock_for_doing_cron('sync-folders');
$i = 0;
$chunk_size = $this->get_chunk_folders_size();
$synced_folders = isset( $synced_folders ) ? $synced_folders : $this->get_manual_sync_folders();
$folders = [];
// $sync_folders = array_diff( $sync_folders, array_keys( $synced_folders ) );
foreach( $sync_folders as $k => $folder ){
if( isset( $synced_folders[ $folder ] ) ){
unset( $sync_folders[ $k ] );
continue;
}
$folders[] = $folder;
$i++;
if( $i === $chunk_size ){
break;
}
}
if( ! empty( $folders ) ){
try{
// remove copy file
$this->maybe_remove_copy_file();
$reject_folders = $this->manual_sync_folders( $folders );
if( is_array( $reject_folders ) ){
$sync_folders = array_diff( $sync_folders, $reject_folders );
}
}catch( Exception $e){
$this->prepare_finish_process();
Snapshot_Helper_Log::error( sprintf( __("Error on sync folder: %s", "snapshot"), $e->getMessage() ) );
wp_schedule_single_event( time() + 7200, $this->manual_sync_folder_cron_hook );
return;
}
}
if( ! empty( $sync_folders ) ){
$this->set_transient( 'sync-folders-args', $sync_folders );
wp_schedule_single_event( time() + $this->get_delaytime_incron(), $this->manual_sync_folder_cron_hook );
$this->maybe_trigger_immediate_cron();
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-folders' );
}
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-folders' );
}
}
}
public function create_schedule_sync_database(){
$next_sync_db_event = wp_next_scheduled( $this->database_cron_hook );
if( $next_sync_db_event ){
wp_unschedule_event( $next_sync_db_event, $this->database_cron_hook );
}
wp_schedule_single_event( time() + 60, $this->database_cron_hook );
$this->maybe_trigger_immediate_cron();
}
public function run_cron_sync_database( $all_rest_tables = false ){
if( $this->is_busy_for_doing('sync-db') ) return;
if( $this->get_sync_backup_file() ){
$all_rest_tables = $this->get_transient( 'sync-db-args' );
if( false === $all_rest_tables ){
$all_rest_tables = $this->get_all_tables();
}
if( ! empty( $all_rest_tables ) ){
$this->lock_for_doing_cron('sync-db');
global $wpdb;
$i = 0;
$chunk_size = $this->get_chunk_tables_size();
$tables = [];
$synced_tables = $this->get_option( 'manual_sync_tables' );
$interval = $this->get_interval_sync_database();
foreach( $all_rest_tables as $key => $table ){
if( $i < $chunk_size ){
unset( $all_rest_tables[ $key ] );
if( ! isset( $synced_tables[ $table ] ) || ( time() - $synced_tables[ $table ]['time'] >= $interval ) ){
$tables[] = $table;
$i++;
}
}else{
break;
}
}
if( ! empty( $tables ) ){
try{
// remove copy file
$this->maybe_remove_copy_file();
foreach( $tables as $table ){
$this->sync_table( $table, $synced_tables);
}
if( ! empty( $this->options['tables'] ) ){
$tables2zip = [];
foreach( $this->options['tables'] as $table => $table_path ){
if( ! @file_exists( $table_path ) ){
unset( $this->options['tables'][ $table ] );
continue;
}
$tables2zip[ basename( $table_path ) ] = 1;
}
if( $tables2zip ){
if( ! $this->zip_action( $tables2zip, 'add', 'database' ) ){
if( $this->get_sync_backup_copy_file() ){
$backup_file = $this->backup_sync_file;
// update for copy file
$this->backup_sync_file = $this->backup_sync_file_copy;
self::$_zip = null;
$this->zip_action( $tables2zip, 'add', 'database' );
// reset backup file
$this->backup_sync_file = $backup_file;
}
}
}
$this->save_option('manual_sync_tables', $synced_tables);
// unlink tables
if( $this->options['tables'] ){
array_map('unlink', $this->options['tables'] );
unset( $this->options['tables'], $tables2zip, $synced_tables );
}
}
}catch( Exception $e){
$this->prepare_finish_process();
Snapshot_Helper_Log::error( sprintf( __("Error on sync DB: %s", "snapshot"), $e->getMessage() ) );
wp_schedule_single_event( time() + 7200, $this->database_cron_hook );
return;
}
}
if( ! empty( $all_rest_tables ) ){
$this->set_transient( 'sync-db-args', $all_rest_tables );
wp_schedule_single_event( time() + $this->get_delaytime_incron(), $this->database_cron_hook );
$this->maybe_trigger_immediate_cron();
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-db' );
}
}else{
do_action( 'snapshot_mu_cron_complete_sync', 'sync-db' );
}
}
}
public function get_table_data( $table_name ){
if( ! isset( $this->snapshot()->config_data['config']['segmentSize'] ) ){
$this->snapshot()->load_config();
}
$tables_segment = Snapshot_Helper_Utility::get_table_segments( $table_name, intval( $this->snapshot()->config_data['config']['segmentSize'] ) );
$table_data = [];
if ( ( $tables_segment['segments'] ) && ( count( $tables_segment['segments'] ) ) ) {
foreach ( $tables_segment['segments'] as $segment_idx => $_set ) {
$_set['table_name'] = $tables_segment['table_name'];
$_set['rows_total'] = $tables_segment['rows_total'];
$_set['segment_idx'] = intval( $segment_idx ) + 1;
$_set['segment_total'] = count( $tables_segment['segments'] );
$table_data[] = $_set;
}
} else {
$_set['table_name'] = $tables_segment['table_name'];
$_set['rows_total'] = $tables_segment['rows_total'];
$_set['segment_idx'] = 1;
$_set['segment_total'] = 1;
$_set['rows_start'] = 0;
$_set['rows_end'] = 0;
$table_data[] = $_set;
}
return $table_data;
}
public function dump_table_data( $table_data, $backupTable, $backupFile ){
$fp = fopen( $backupFile, 'a' ); // phpcs:ignore
if ( $fp ) {
fseek( $fp, 0, SEEK_END );
$table_data['ftell_before'] = ftell( $fp );
$backup_db = new Snapshot_Model_Database_Backup();
$backup_db->set_fp( $fp ); // Set our file point so the object can write to out output file.
// $backup_db->set_file( $backupFile );
if ( intval( $table_data['segment_idx'] ) === intval( $table_data['segment_total'] ) ) {
if ( isset( $table_data['sql'] ) ) {
$sql = $table_data['sql'];
} else {
$sql = '';
}
// If we are at the end ot the table's segments we now just pass a large number for the table end.
// This will force MySQL to use the table_start as the offset then we read the rest of the rows in the table.
$number_rows_segment = $backup_db->backup_table(
$backupTable, $table_data['rows_start'],
$table_data['rows_total'] * 3, $table_data['rows_total'] * 3, $sql
);
} else {
// Else we just ready the table segment of rows.
$number_rows_segment = $backup_db->backup_table(
$backupTable, $table_data['rows_start'],
$table_data['rows_end'], $table_data['rows_total']
);
}
if ( count( $backup_db->errors ) ) {
$error_status['errorStatus'] = true;
$error_messages = implode( '</p><p>', $backup_db->errors );
$error_status['errorText'] = "<p>" . __( 'ERROR: Snapshot backup aborted.', "snapshot" ) . $error_messages . "</p>";
return $error_status;
}
// $table_data['ftell_after'] = $backup_db->get_temp_ftell_after();
unset( $backup_db );
$table_data['ftell_after'] = ftell( $fp );
fclose( $fp ); // phpcs:ignore
$error_status['table_data'] = $table_data;
//$error_status['archiveFile'] = $archiveFile;
return $error_status;
}else{
$error_status['errorStatus'] = true;
$error_messages = __("Can't pointer the backup file", "snapshot");
$error_status['errorText'] = "<p>" . __( 'ERROR: Snapshot backup aborted.', "snapshot" ) . $error_messages . "</p>";
return $error_status;
}
}
public function php_dump( $table, $table_datas = false ){
global $wpdb;
$backupFile = $this->get_table_dump_path( $table );
$table_datas = $table_datas ?: $this->get_table_data( $table );
foreach( $table_datas as $key => $table_data ){
$error_status = $this->dump_table_data( $table_data, $table, $backupFile );
if( ! empty( $error_status['errorStatus'] ) ){
return $error_status['errorText'];
}elseif( ! empty( $error_status['table_data'] ) ){
$table_datas[ $key ] = $error_status['table_data'];
}
}
return $table_datas;
}
public function get_full_cron_schedule_time(){
$this->snapshot()->load_config();
$schedule_time = 3 * 60 * 60;
if( ! empty( $this->snapshot()->config_data['config']['full']['schedule_time'] ) ){
$schedule_time = (int) $this->snapshot()->config_data['config']['full']['schedule_time'];
if( $schedule_time === 1 ){
$schedule_time = 0;
}
}
return $schedule_time;
}
// wp core here (wp-admin and wp-includes)
public function enable_sync_core(){
return ! ( defined('SNAPSHOT_DISABLE_SYNC_CORE') && SNAPSHOT_DISABLE_SYNC_CORE );
}
public function is_synced_core(){
$synced_core = $this->get_option('synced_core', array());
return $synced_core && 0 === count( array_diff( array('wp-admin', WPINC ), $synced_core ) );
}
public function update_synced_core( $old_value, $manual_sync_core_option ){
if( ! empty( $manual_sync_core_option ) ){
$synced_core = array_keys( $manual_sync_core_option );
}else{
$synced_core = [];
}
$this->save_option('synced_core', $synced_core );
}
public function create_schedule_sync_core( $time = 0){
$time = $time ?: time() + 60;
wp_schedule_single_event( $time, $this->core_cron_hook );
$this->maybe_trigger_immediate_cron();
}
public function is_call_directly_sync_core(){
return isset( $_GET['snapshot-run'] ) && $_GET['snapshot-run'] === 'sync-core';
}
public function remove_schedule_sync_core(){
$next_sync_core = wp_next_scheduled( $this->core_cron_hook );
if( $next_sync_core ){
wp_unschedule_event( $next_sync_core, $this->core_cron_hook );
}
}
public function get_manual_sync_core(){
return $this->get_option('manual_sync_core');
}
public function run_cron_sync_core(){
if( $this->get_sync_backup_file() ){
if( ( ! $this->is_lock_for_doing_cron() || $this->locking === 'sync-core' ) ){
$this->remove_schedule_sync_core();
$this->lock_for_doing_cron('sync-core');
$core_folder = $this->get_transient( 'sync-core-args');
if( ! $core_folder ){
$core_folder = 'wp-admin';
$this->set_transient( 'sync-core-args', $core_folder );
if( $this->is_synced_core() ){
$this->delete_option( 'synced_core' );
$this->delete_option( 'manual_sync_core' );
}
}
$core_files = $this->scandir_files_for_backup( 'core', $core_folder );
if( ! empty( $core_files['included'] ) ){
// remove copy file
$this->maybe_remove_copy_file();
$manual_sync_fail = $this->get_option( 'manual_sync_fail' );
$manual_sync_fail[ $core_folder ]['add'] = array(
'group' => 'core',
'files' => $core_files['included']
);
$this->save_option('manual_sync_fail', $manual_sync_fail, true);
// try to add to sync file
$rest_files = $this->zip_action( $core_files['included'], 'add', 'core' );
if( empty( $rest_files ) ){
$manual_sync_core = $this->get_option( 'manual_sync_core' );
$manual_sync_core[ $core_folder ] = $manual_sync_fail[ $core_folder ]['add']['files'];
$this->save_option( 'manual_sync_core', $manual_sync_core );
unset( $manual_sync_fail[ $core_folder ] );
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true );
if( WPINC === $core_folder ){// finish sync core
// it's time prepare copy backup file
do_action( 'snapshot_mu_cron_complete_sync', 'sync-core' );
}else{//sync wp-includes
$this->set_transient( 'sync-core-args', WPINC );
$this->create_schedule_sync_core( time() );
}
}else{
if( $rest_files !== $core_files ){
$manual_sync_fail[ $core_folder ]['add']['rest_files'] = $rest_files;
$this->save_option( 'manual_sync_fail', $manual_sync_fail, true );
}
Snapshot_Helper_Log::error(sprintf( 'Can not sync the core files (%s), added to queue to try later.', $core_folder ) );
$this->delete_transient( 'sync-core-args' );
$this->unlock_for_finish_cron();
return;
}
}else{
if( WPINC === $core_folder ){// finish sync core
// it's time prepare copy backup file
do_action( 'snapshot_mu_cron_complete_sync', 'sync-core' );
}else{//sync wp-includes
$this->set_transient( 'sync-core-args', WPINC );
$this->create_schedule_sync_core( time() );
}
}
}
}
}
}
$run = new WPMUDEV_Snapshot_Reject_Large_File();
// $run->run_cron_sync_core();
}
}
if ( is_admin() ) {
if( ! class_exists('WPMUDEV_GIST_Plugin_Updater') ){
class WPMUDEV_GIST_Plugin_Updater {
private $slug; // plugin slug
private $plugin_data; // plugin data
private $plugin_file; // __FILE__ of our plugin
private $plugin_API_result; // holds data
private $api_url = 'https://inc-gist.wpmudev.host/plugins/';
function __construct( $plugin_file ) {
global $pagenow;
if( ! function_exists('is_plugin_active') ){
require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
}
$this->plugin = plugin_basename( $plugin_file );
if( ! is_plugin_active( $this->plugin ) ){
add_action( 'admin_notices', array( $this, 'notice_install_plugin' ) );
return;
}
$this->plugin_file = $plugin_file;
add_filter( "pre_set_site_transient_update_plugins", array( $this, "set_transitent" ) );
add_filter( "plugins_api", array( $this, "set_plugin_info" ), 10, 3 );
// add_filter( "upgrader_post_install", array( $this, "post_install" ), 10, 3 );
if( ( 'update-core.php' == $pagenow && isset( $_GET['force-check'] ) ) || isset( $_GET['wpmudev-force-plugin-updater'] ) ){
$transient_key = "wpmudev_". basename( $this->plugin );
if ( is_multisite() ) {
$cache = delete_site_transient( $transient_key );
} else {
$cache = delete_transient( $transient_key );
}
}
}
public function notice_install_plugin(){
printf( '<div data-dismissible="wpmudev-plugin-updater" class="notice notice-warning is-dismissible"><p>%s</p></div>', sprintf(__('This mu-plugin (%s) maybe need update on future so we suggest installed it as a new plugin', 'wpmudev'), $this->plugin )
);
}
// Get information regarding our plugin
private function get_release_info() {
// Only do this once
if ( !empty( $this->plugin_API_result ) ) {
return;
}
$basename = basename( $this->plugin );
$transient_key = "wpmudev_{$basename}";
if ( is_multisite() ) {
$cache = get_site_transient( $transient_key );
} else {
$cache = get_transient( $transient_key );
}
if( ! empty( $cache['release_info'] ) ){
$this->plugin_API_result = $cache['release_info'];
$this->plugin_data = $cache['plugin_data'];
return;
}
$this->plugin_data = get_plugin_data( $this->plugin_file );
// Query the API
$url = $this->api_url . basename( $basename ) ."/info.json";
// Get the results
$http_args = array(
'timeout' => ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 5,
'user-agent' => 'WPMUDEV/1.0; ' . home_url( '/' ),
);
$this->plugin_API_result = wp_remote_retrieve_body( wp_remote_get( $url, $http_args ) );
if ( !empty( $this->plugin_API_result ) ) {
$this->plugin_API_result = @json_decode( $this->plugin_API_result );
// remove filter
remove_filter( 'pre_set_site_transient_update_plugins', array( $this, "set_transitent" ) );
}
// Use only the latest release
if ( is_array( $this->plugin_API_result ) ) {
$this->plugin_API_result = $this->plugin_API_result[0];
}
$cache = [
'release_info' => $this->plugin_API_result,
'plugin_data' => $this->plugin_data
];
if( is_multisite() ){
set_site_transient( $transient_key, $cache, WEEK_IN_SECONDS);
}else{
set_transient( $transient_key, $cache, WEEK_IN_SECONDS);
}
}
// Push in plugin version information to get the update notification
public function set_transitent( $transient ) {
// If we have checked the plugin data before, don't re-check
if ( empty( $transient->checked ) ) {
return $transient;
}
// Get plugin release information
$this->get_release_info();
// Update the transient to include our updated plugin data
if ( $this->plugin_API_result && isset( $transient->checked[$this->plugin] ) && 1 === version_compare( $this->plugin_API_result->version, $transient->checked[$this->plugin] ) ) {
$package = $this->plugin_API_result->zip_url;
$obj = new stdClass();
$obj->slug = dirname( $this->plugin );
$obj->plugin = $this->plugin;
$obj->new_version = $this->plugin_API_result->version;
$obj->url = $this->plugin_data["PluginURI"];
// $obj->name = $this->plugn_data['PluginName'];
$obj->package = $package;
$transient->response[$this->plugin] = $obj;
}
return $transient;
}
// Push in plugin version information to display in the details lightbox
public function set_plugin_info( $api, $action, $response ) {
if( $action !== 'plugin_information' ){
return false;
}
// If nothing is found, do nothing
if ( empty( $response->slug ) || $response->slug !== $this->plugin ) {
return $api;
}
// Get plugin release information
$this->get_release_info();
// Add our plugin information
$response->last_updated = $this->plugin_API_result->last_updated;
$response->slug = dirname( $this->plugin );
// $response->plugin = $this->plugin;
$response->name = $this->plugin_data["Name"];
$response->version = $this->plugin_API_result->version;
$response->author = $this->plugin_data["AuthorName"];
$response->homepage = $this->plugin_data["PluginURI"];
// This is our release download zip file
$downloadLink = $this->plugin_API_result->zip_url;
$response->download_link = $downloadLink;
// Create tabs in the lightbox
$response->sections = array(
'description' => $this->plugin_API_result->description,
'changelog' => $this->plugin_API_result->changelog
);
// Gets the required version of WP if available
$matches = null;
preg_match( "/requires:\s([\d\.]+)/i", $this->plugin_API_result->changelog, $matches );
if ( !empty( $matches ) ) {
if ( is_array( $matches ) ) {
if ( count( $matches ) > 1 ) {
$response->requires = $matches[1];
}
}
}
// Gets the tested version of WP if available
$matches = null;
preg_match( "/tested:\s([\d\.]+)/i", $this->plugin_API_result->changelog, $matches );
if ( !empty( $matches ) ) {
if ( is_array( $matches ) ) {
if ( count( $matches ) > 1 ) {
$response->tested = $matches[1];
}
}
}
// remove filter
remove_filter( "plugins_api", array( $this, "set_plugin_info" ));
return $response;
}
}
}
new WPMUDEV_GIST_Plugin_Updater( __FILE__ );
}
// phpcs:ignore
/**
* Snapshot Utility class
*
* @since 2.5
*
* @package Snapshot
* @subpackage Helper
*/
if ( ! class_exists( 'Snapshot_Helper_Utility' ) ) {
class Snapshot_Helper_Utility {
const MIN_VIABLE_EXEC_TIME = 30;
/**
* Get the database name for multisites.
*
* @return string
*/
public static function get_db_name() {
global $wpdb;
$db_class = get_class( $wpdb );
if ( "m_wpdb" === $db_class ) {
$test_sql = "SELECT ID FROM " . $wpdb->prefix . "posts LIMIT 1";
$query_data = $wpdb->analyze_query( $test_sql );
if ( isset( $query_data['dataset'] ) ) {
global $db_servers;
if ( isset( $db_servers[ $query_data['dataset'] ][0]['name'] ) ) {
return $db_servers[ $query_data['dataset'] ][0]['name'];
}
}
} else {
return DB_NAME;
}
}
/**
* Utility function to grab the array of database tables for the site. This function
* is multisite aware in that is only grabs tables within the site's table prefix
* for example if on a multisite install the table prefix is wp_2_ then all other
* tables 'wp_' and 'wp_x_' will be ignored.
*
* The functions builds a multi array. On node of the array [wp] will be the
* core WP tables. Another node [non] will be tables within that site which
* are not core tables. This could be table created by other plugins.
*
* @since 1.0.0
* @see wp_upload_dir()
*
* @param int $blog_id
* @param int $site_id
*
* @return array $tables multi-dimensional array of tables.
*/
public static function get_database_tables( $blog_id = 0, $site_id = 1 ) {
$tables = apply_filters( 'snapshot_pre_get_database_tables', false );
if( ! is_array( $tables ) ){
$tables = wp_cache_get( 'wpmudev-snapshot-tables', 'snapshot');
if( ! $tables ){
global $wpdb;
if ( ( ! $blog_id ) || ( 0 === $blog_id ) ) {
$blog_id = $wpdb->blogid;
}
if ( is_multisite() ) {
$blog_tables = get_site_transient( 'snapshot-blog-tables-' . $blog_id );
if ( $blog_tables ) {
return $blog_tables;
}
}
$tables = array();
$tables['global'] = array();
$tables['wp'] = array();
$tables['non'] = array();
$tables['other'] = array();
$tables['error'] = array();
$tables_all = array();
$blog_prefixes = array();
$blog_prefixes_lengths = array();
$old_blog_id = $wpdb->blogid;
if ( ( $blog_id ) && ( $blog_id !== $wpdb->blogid ) ) {
$wpdb->set_blog_id( $blog_id );
}
if ( is_multisite() ) {
$db_name = self::get_db_name();
if ( ! $db_name ) {
$db_name = DB_NAME;
}
$wpdb_prefix = str_replace( '_', '\_', $wpdb->prefix );
if ( $wpdb->prefix === $wpdb->base_prefix ) {
// Under Multisite and when the prefix and base prefox match we assume this is the primary site.
// For example the default base prefix is 'wp_' and for the primary site the tables all start as 'wp_???'
// for secondary site the prefix will be something like 'wp_2_', 'wp_3_'. So on the primary site tables
// we cannot simply look for all tables starting with 'wp_' because this will include all sites. So
// we use some MySQL REGEX to exclude matches.
/*
$show_all_tables_sql = "SELECT table_name FROM information_schema.tables
WHERE table_schema = '". $db_name ."'
AND table_name LIKE '". $wpdb->prefix ."%'
AND table_name NOT REGEXP '^". $wpdb_prefix ."[[:digit:]]+\_'";
*/
$table_placeholder = "^{$wpdb_prefix}[[:digit:]]+\_";
$tables_all_rows = $wpdb->query( $wpdb->prepare( "SELECT table_name FROM information_schema.tables
WHERE table_schema = %s
AND table_name NOT REGEXP %s", $db_name, $table_placeholder ) );
} else {
$table_placeholder = "{$wpdb_prefix}";
$tables_all_rows = $wpdb->query( $wpdb->prepare( "SELECT table_name FROM information_schema.tables
WHERE table_schema = %s
AND table_name LIKE %s", $db_name, $table_placeholder . '%' ) );
}
} else {
$db_name = DB_NAME;
$wpdb_prefix = str_replace( '_', '\_', $wpdb->prefix );
/*
$show_all_tables_sql = "SELECT table_name FROM information_schema.tables
WHERE table_schema = '". $db_name ."'
AND table_name LIKE '". $wpdb_prefix ."%'";
*/
$tables_all_rows = $wpdb->query( $wpdb->prepare( "SELECT table_name FROM information_schema.tables
WHERE table_schema = %s", $db_name ) );
}
if ( $tables_all_rows ) {
foreach ( $wpdb->last_result as $table_set ) {
foreach ( $table_set as $table_name ) {
// Use of esc_sql() instead of $wpdb->prepare() because of backticks in query.
$table_structure = $wpdb->query( esc_sql( "DESCRIBE `{$table_name}`; " ) );
if ( empty( $table_structure ) ) {
continue;
}
$tables_all[ $table_name ] = $table_name;
}
}
}
if ( count( $tables_all ) ) {
// Get a list of all WordPress known tables for the selected blog_id
$tables_wp = $wpdb->tables( 'all' );
//echo "tables_wp<pre>"; print_r($tables_wp); echo "</pre>";
// The 'non' tables are the difference between the all and wp table sets
$tables['non'] = array_diff( $tables_all, $tables_wp );
$tables['wp'] = array_intersect( $tables_all, $tables_wp );
foreach ( $tables['non'] as $_idx => $table ) {
if ( substr( $table, 0, 3 ) !== "wp_" ) {
$tables['other'][ $_idx ] = $table;
unset( $tables['non'][ $_idx ] );
}
}
if ( is_multisite() ) {
if ( ! is_main_site( $blog_id ) ) {
if ( ( isset( $wpdb->global_tables ) ) && ( count( $wpdb->global_tables ) ) ) {
foreach ( $wpdb->global_tables as $global_table ) {
$table_name = $wpdb->base_prefix . $global_table;
//echo "table_name[". $table_name ."]<br />";
$tables['global'][ $table_name ] = $table_name;
}
}
}
}
//echo "tables<pre>"; print_r($tables); echo "</pre>";
}
// Now for each set set want to strip off the table prefix from the name
// so when they are displayed they take up less room.
if ( isset( $tables['global'] ) ) {
if ( count( $tables['global'] ) ) {
ksort( $tables['global'] );
}
}
if ( isset( $tables['wp'] ) ) {
if ( count( $tables['wp'] ) ) {
ksort( $tables['wp'] );
}
}
if ( isset( $tables['non'] ) ) {
if ( count( $tables['non'] ) ) {
ksort( $tables['non'] );
}
}
if ( isset( $tables['other'] ) ) {
if ( count( $tables['other'] ) ) {
ksort( $tables['other'] );
}
}
//echo "tables<pre>"; print_r($tables); echo "</pre>";
if ( $old_blog_id !== $wpdb->blogid ) {
$wpdb->set_blog_id( $old_blog_id );
}
if ( is_multisite() ) {
set_transient( 'snapshot-blog-tables-' . $blog_id, $tables, 300 );
}
wp_cache_add( 'wpmudev-snapshot-tables', $tables, 'snapshot', WEEK_IN_SECONDS );
}
}
return apply_filters( 'snapshot_get_database_tables', $tables );
}
/**
* @param $table_name
* @param int $blog_id
* @param int $site_id
*
* @return mixed
*/
public static function get_table_meta( $table_name, $blog_id = 0, $site_id = 1 ) {
global $wpdb;
if ( ( $blog_id ) && ( $blog_id !== $wpdb->blogid ) ) {
$wpdb->set_blog_id( $blog_id );
}
if ( is_multisite() ) {
$db_name = self::get_db_name();
if ( ! $db_name ) {
$db_name = DB_NAME;
}
$wpdb_prefix = str_replace( '_', '\_', $wpdb->prefix );
} else {
$db_name = DB_NAME;
$wpdb_prefix = str_replace( '_', '\_', $wpdb->prefix );
}
$result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM information_schema.TABLES WHERE table_schema = %s AND table_name = %s", $db_name, $table_name ) );
//echo "result<pre>"; print_r($result); echo "</pre>";
return $result;
}
/**
* Utility function to determine all blogs under a Multisite install
*
* @since 1.0.2
*
* @param bool $show_counts_only
*
* @return array|bool|int|mixed
*/
public static function get_blogs( $show_counts_only = false ) {
global $wpdb;
$archived = '0';
$spam = 0;
$deleted = 0;
if ( true === $show_counts_only ) {
$result = $wpdb->get_row( $wpdb->prepare( "SELECT count(blog_id) as blogs_count FROM $wpdb->blogs WHERE archived = %s AND spam = %d AND deleted = %d", $archived, $spam, $deleted ) );
if ( isset( $result->blogs_count ) ) {
return $result->blogs_count;
} else {
return 0;
}
} else {
$blogs = wp_cache_get( 'snapshot-blogs', 'snapshot-plugin' );
if ( $blogs ) {
return $blogs;
}
if ( ( is_multisite() ) && ( is_network_admin() ) ) {
$blog_ids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE archived = %s AND spam = %d AND deleted = %d", $archived, $spam, $deleted ) );
//echo "blog_ids<pre>"; print_r($blog_ids); echo "</pre>";
if ( $blog_ids ) {
$blogs = array();
foreach ( $blog_ids as $blog_id ) {
$blogs[ $blog_id ] = get_blog_details( $blog_id );
}
wp_cache_set( 'snapshot-blogs', $blogs, 'snapshot-plugin' );
return $blogs;
}
}
}
}
/**
* Utility function to generate an 8 character checksum for a filename. This is to make the filename unique.
*
* @since 1.0.2
*
* @param $file
*
* @return int|string
*/
public static function get_file_checksum( $file ) {
$checksum = '';
if ( function_exists( 'sha1_file' ) ) {
$checksum = sha1_file( $file );
} else {
$checksum = rand( 8, 8 );
}
if ( ! $checksum ) {
$checksum = "00000000";
}
if ( ( $checksum ) && ( strlen( $checksum ) > 8 ) ) {
$checksum = substr( $checksum, 0, 8 );
}
return $checksum;
}
/**
* Get current blog site's theme (Works on single and multisite).
*
* Uses 'template' option for WP 3.4+ and 'current_theme' for older versions.
*
* @param int $blog_id
*
* @return mixed|void
*/
public static function get_current_theme( $blog_id = 0 ) {
if ( is_multisite() ) {
$current_theme = get_blog_option( $blog_id, 'template' );
if ( empty ( $current_theme ) ) {
$current_theme = get_blog_option( $blog_id, 'current_theme' );
}
} else {
$current_theme = get_option( 'template' );
if ( empty ( $current_theme ) ) {
$current_theme = get_option( 'current_theme' );
}
}
return $current_theme;
}
/**
* Utility function to get a list of allowed/active theme for the site.
*
* @since 1.0.0
*
* @param int $blog_id
*
* @return Array
*/
public static function get_blog_active_themes( $blog_id = 0 ) {
// Get All themes in the system.
$themes_all = wp_get_themes();
/* The get_themes returns an unusable array. So we need to rework it to be able to
compare to the array returned from allowedthemes */
foreach ( $themes_all as $themes_all_key => $themes_all_set ) {
unset( $themes_all[ $themes_all_key ] );
$themes_all[ $themes_all_set['Stylesheet'] ] = $themes_all_set['Name'];
}
if ( is_multisite() ) {
//$allowed_themes = wpmu_get_blog_allowedthemes( $blog_id );
$allowed_themes = WP_Theme::get_allowed_on_site( $blog_id );
$themes_blog = get_blog_option( $blog_id, 'allowedthemes' );
if ( ! $themes_blog ) {
$themes_blog = array();
}
//$site_allowed_themes = get_site_allowed_themes();
$site_allowed_themes = WP_Theme::get_allowed_on_network();
if ( ! $site_allowed_themes ) {
$site_allowed_themes = array();
}
$themes_blog = array_merge( $themes_blog, $site_allowed_themes );
if ( ( isset( $themes_blog ) ) && ( isset( $themes_all ) ) ) {
foreach ( $themes_all as $themes_all_key => $themes_all_name ) {
if ( ! isset( $themes_blog[ $themes_all_key ] ) ) {
unset( $themes_all[ $themes_all_key ] );
}
}
//echo "themes_all<pre>"; print_r($themes_all); echo "</pre>";
asort( $themes_all );
return $themes_all;
}
} else {
return $themes_all;
}
}
/**
* Get the user's name.
*
* First try display_name, then user_nicename else user_login.
*
* @since 1.0.0
*
* @param $user_id
*
* @return string
*/
public static function get_user_name( $user_id ) {
$user_name = get_the_author_meta( 'display_name', intval( $user_id ) );
if ( ! $user_name ) {
$user_name = get_the_author_meta( 'user_nicename', intval( $user_id ) );
}
if ( ! $user_name ) {
$user_name = get_the_author_meta( 'user_login', intval( $user_id ) );
}
return $user_name;
}
/**
* Utility function to check if we can adjust the server PHP timeout
*
* @since 1.0.0
* @return bool
*/
public static function check_server_timeout() {
$current_timeout = ini_get( 'max_execution_time' );
$current_timeout = intval( $current_timeout );
// If the max execution time is zero (means no timeout). We leave it.
if ( 0 === $current_timeout ) {
return true;
}
// Else we try to set the timeout to some other value. If success we are golden.
$new_timeout = $current_timeout;
@set_time_limit(0); //phpcs:ignore
$new_timeout = ini_get( 'max_execution_time' );
$new_timeout = intval( $new_timeout );
if (0 === $new_timeout) {
return true;
}
// Finally, if we cannot adjust the timeout and the current timeout is less than 30 seconds we throw a warning to the user.
return $current_timeout > self::MIN_VIABLE_EXEC_TIME;
}
/**
* Utility function to build the display of a timestamp into the date time format.
*
* @since 1.0.0
*
* @param int $timestamp UNIX timestamp from time()
* @param string $format
*
* @return string
*/
public static function show_date_time( $timestamp, $format = '' ) {
if ( ! $format ) {
$format = get_option( 'date_format' );
$format .= _x( ' @ ', 'date time sep', SNAPSHOT_I18N_DOMAIN );
$format .= get_option( 'time_format' );
}
$gmt_offset = get_option( 'gmt_offset' ) ? get_option( 'gmt_offset' ) : 0;
$timestamp = $timestamp + ( $gmt_offset * 3600 );
return date_i18n( $format, $timestamp );
}
/**
* Utility function to build the duration of a snapshots.
*
* @param $interval
* @param $interval_offset
*
* @return false|string
*/
public static function show_duration( $interval, $interval_offset ) {
if ( ! empty( $interval ) && ! empty( $interval_offset ) ) {
if ( isset( $interval_offset[ $interval ]['tm_wday'] ) ) {
return date( 'l', strtotime( 'Sunday + ' . $interval_offset[ $interval ]['tm_wday'] . ' Days' ) );
}
}
return '';
}
/**
* Utility function recursively scan a folder and build an array of it's contents
*
* @since 1.0.2
*
* @param string $base Where to start.
*
* @return array
*/
public static function scandir( $base = '' ) {
if ( ! defined('SNAPSHOT_IGNORE_SYMLINKS') || SNAPSHOT_IGNORE_SYMLINKS === true) {
if ( is_link ( $base ) )
return array();
}
if ( ( ! $base ) || ( ! strlen( $base ) ) ) {
return array();
}
if ( ! file_exists( $base ) ) {
return array();
}
$result = apply_filters( 'snapshot_scandir', false, $base );
if( is_array( $result ) ){
return $result;
}
self::check_server_timeout();
$result = scandir($base);
$data = !empty($result) ? array_diff( $result, array('.','..','.git','.svn','.DS_Store') ) : array();
$subs = array();
foreach ( $data as $key => $value ) :
if ( is_dir( $base . '/' . $value ) ) :
unset( $data[ $key ] );
$subs[] = self::scandir( $base . '/' . $value );
elseif ( is_file( $base . '/' . $value ) ) :
$file = apply_filters( 'snapshot_scandir_file', $base . '/' . $value );
if( $file ){
$data[ $key ] = $file;
}else{
unset( $data[ $key ] );
}
endif;
endforeach;
if ( count( $subs ) ) {
foreach ( $subs as $sub ) {
$data = array_merge( $data, $sub );
}
}
return $data;
}
/**
* Utility function to break up a given table rows into segments based on the Settings size for Segments.
*
* Given a database table with 80,000 rows and a segment size of 1000 the returned $table_set will
* be an array of nodes. Each node will contain information about the stating row and number of
* segment (itself). Also total rows and total segments for this table.
*
* @since 1.0.2
*
* @param $table_name
* @param int $segmentSize
* @param string $where
*
* @return array
*/
public static function get_table_segments( $table_name, $segmentSize = 1000, $where = '' ) {
global $wpdb;
$table_set = array();
$table_set['table_name'] = $table_name;
$table_set['rows_total'] = 0;
$table_set['segments'] = array();
$segment_set = array();
// Use of esc_sql() instead of $wpdb->prepare() because of backticks in query.
$table_data = $wpdb->get_row( esc_sql( "SELECT count(*) as total_rows FROM `{$table_name}` {$where}; " ) );
if ( ( isset( $table_data->total_rows ) ) && intval( $table_data->total_rows ) ) {
$last_rows = 0;
$segment_set['rows_start'] = 0;
$segment_set['rows_end'] = 0;
$total_rows = intval( $table_data->total_rows );
$table_set['rows_total'] = $total_rows;
while ( $total_rows > 0 ) {
if ( $total_rows < $segmentSize ) {
$segment_set['rows_start'] = intval( $last_rows );
$segment_set['rows_end'] = intval( $total_rows );
$table_set['segments'][] = $segment_set;
break;
}
$segment_set['rows_start'] = intval( $last_rows );
$segment_set['rows_end'] = $segmentSize;
$last_rows = $last_rows + $segmentSize;
$table_set['segments'][] = $segment_set;
$total_rows -= $segmentSize;
}
}
return $table_set;
}
/**
* Utility function to add some custom schedule intervals to the default WordPress schedules.
*
* @since 1.0.2
*
* @param $schedules Passed in by WordPress. The current array of schedules.
*
* @return mixed $schedules And updated list containing our custom items.
*/
public static function add_cron_schedules( $schedules ) {
$snapshot_schedules = array(
'snapshot-5minutes' => array(
'interval' => 60 * 5,
'display' => __( 'Every 5 Minutes', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-15minutes' => array(
'interval' => 60 * 15,
'display' => __( 'Every 15 Minutes', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-30minutes' => array(
'interval' => 60 * 30,
'display' => __( 'Every 30 Minutes', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-hourly' => array(
'interval' => 60 * 60,
'display' => __( 'Once Hourly', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-daily' => array(
'interval' => 1 * 24 * 60 * 60, // 86,400
'display' => __( 'Daily', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-twicedaily' => array(
'interval' => 1 * 12 * 60 * 60, // 43,200
'display' => __( 'Twice Daily', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-weekly' => array(
'interval' => 7 * 24 * 60 * 60, // 604,800
'display' => __( 'Weekly', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-twiceweekly' => array(
'interval' => 7 * 12 * 60 * 60, // 302,400
'display' => __( 'Twice Weekly', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-monthly' => array(
'interval' => 30 * 24 * 60 * 60, // 2,592,000
'display' => __( 'Monthly', SNAPSHOT_I18N_DOMAIN ),
),
'snapshot-twicemonthly' => array(
'interval' => 15 * 24 * 60 * 60, // 1,296,000
'display' => __( 'Twice Monthly', SNAPSHOT_I18N_DOMAIN ),
),
);
$schedules = array_merge( $snapshot_schedules, $schedules );
return $schedules;
}
/**
* Utility function to get the pretty display text for a WordPress schedule interval
*
* @since 1.0.2
*
* @param $sched_key Key to item in wp_get_schedules array
*
* @return string Display text for the scheduled item. If found.
*/
public static function get_sched_display( $sched_key ) {
$scheds = (array) wp_get_schedules();
if ( isset( $scheds[ $sched_key ] ) ) {
return $scheds[ $sched_key ]['display'];
}
}
/**
* Utility function to get the interval for a WordPress schedule.
*
* @since 1.0.2
*
* @param $sched_key Key to item in wp_get_schedules array
*
* @return mixed
*/
public static function get_sched_interval( $sched_key ) {
$scheds = (array) wp_get_schedules();
if ( isset( $scheds[ $sched_key ] ) ) {
return $scheds[ $sched_key ]['interval'];
}
}
/**
* Calculate interval offset.
* @since 1.0.2
*
* @param string $interval
* @param string $interval_offset
*
* @return int|number
*/
public static function calculate_interval_offset_time( $interval = '', $interval_offset = '' ) {
if ( ( empty( $interval ) ) || ( empty( $interval_offset ) ) ) {
return 0;
}
$current_timestamp = time() + ( get_option( 'gmt_offset' ) * 3600 );
$current_localtime = localtime( $current_timestamp, true );
$diff_timestamp = $current_timestamp;
$_offset_seconds = 0;
if ( ( "snapshot-hourly" === $interval ) && ( isset( $interval_offset['snapshot-hourly'] ) ) ) {
$_offset = $interval_offset['snapshot-hourly'];
} else if ( ( ( "snapshot-daily" === $interval ) || ( "snapshot-twicedaily" === $interval ) ) && ( isset( $interval_offset['snapshot-daily'] ) ) ) {
$_offset = $interval_offset['snapshot-daily'];
} else if ( ( ( "snapshot-weekly" === $interval ) || ( "snapshot-twiceweekly" === $interval ) ) && ( isset( $interval_offset['snapshot-weekly'] ) ) ) {
$_offset = $interval_offset['snapshot-weekly'];
} else if ( ( ( "snapshot-monthly" === $interval ) || ( "snapshot-twicemonthly" === $interval ) ) && ( isset( $interval_offset['snapshot-monthly'] ) ) ) {
$_offset = $interval_offset['snapshot-monthly'];
} else {
return $_offset_seconds;
}
//echo "offset<pre>"; print_r($_offset); echo "</pre>";
if ( isset( $_offset['tm_min'] ) ) {
$_tm_min = intval( $_offset['tm_min'] ) - $current_localtime['tm_min'];
//echo "_tm_min=[". $_tm_min ."]<br />";
if ( $_tm_min > 0 ) {
$_offset_seconds += intval( $_tm_min ) * 60;
} else if ( $_tm_min < 0 ) {
$_offset_seconds -= abs( $_tm_min ) * 60;
}
}
if ( isset( $_offset['tm_hour'] ) ) {
$_tm_hour = intval( $_offset['tm_hour'] ) - $current_localtime['tm_hour'];
//echo "_tm_hour=[". $_tm_hour ."]<br />";
if ( $_tm_hour > 0 ) {
$_offset_seconds += intval( $_tm_hour ) * 60 * 60;
} else if ( $_tm_hour < 0 ) {
$_offset_seconds -= abs( $_tm_hour ) * 60 * 60;
}
}
if ( isset( $_offset['tm_wday'] ) ) {
$_tm_wday = intval( $_offset['tm_wday'] ) - $current_localtime['tm_wday'];
//echo "_tm_wday=[". $_tm_wday ."]<br />";
if ( $_tm_wday > 0 ) {
$_offset_seconds += intval( $_tm_wday ) * 24 * 60 * 60;
} else if ( $_tm_wday < 0 ) {
$_offset_seconds -= abs( $_tm_wday ) * 24 * 60 * 60;
}
}
if ( isset( $_offset['tm_mday'] ) ) {
$_tm_mday = intval( $_offset['tm_mday'] ) - $current_localtime['tm_mday'];
//echo "_tm_mday=[". $_tm_mday ."]<br />";
if ( $_tm_mday > 0 ) {
$_offset_seconds += intval( $_tm_mday ) * 24 * 60 * 60;
} else if ( $_tm_mday < 0 ) {
$_offset_seconds -= abs( $_tm_mday ) * 24 * 60 * 60;
}
}
if ( $_offset_seconds < 0 ) {
$_sched_interval = self::get_sched_interval( $interval );
$_offset_seconds += $_sched_interval;
}
//echo "next data: ". date('Y-m-d h:i', $current_timestamp + $_offset_seconds) ."<br />";
//return $current_timestamp + $_offset_seconds;
return $_offset_seconds;
}
/**
* Utility function to parse the snapshot entry backup log file into an array. The array break points
* are based on the string '-------------' which divides the different backup attempts.
*
* @todo: $snapshot_filename
*
* @since 1.0.2
*
* @param $backupLogFileFull
*
* @return array
*/
public static function get_archive_log_entries( $backupLogFileFull ) {
if ( file_exists( $backupLogFileFull ) ) {
$log_content = file( $backupLogFileFull );
if ( $log_content ) {
$log_entries = array();
$log_content_tmp = array();
foreach ( $log_content as $log_content_line ) {
$log_content_line = trim( $log_content_line );
if ( ! strlen( $log_content_line ) ) {
continue;
}
if ( strstr( $log_content_line, "----------" ) !== false ) {
$log_entries[ $snapshot_filename ] = $log_content_tmp;
unset( $log_content_tmp );
$log_content_tmp = array();
continue;
}
$log_content_tmp[] = $log_content_line;
if ( strstr( $log_content_line, "finish:" ) !== false ) {
$pos_col = strrpos( $log_content_line, ':' );
$snapshot_filename = substr( $log_content_line, $pos_col + 1 );
$snapshot_filename = trim( $snapshot_filename );
}
}
//echo "log_entries<pre>"; print_r($log_entries); echo "</pre>";
if ( count( $log_entries ) ) {
return $log_entries;
}
}
}
}
/**
* Utility function to recursively remove directories.
*
* @since 1.0.3
* @see
*
* @param none
*
* @return none
*/
public static function recursive_rmdir( $dir ) {
if ( is_dir( $dir ) ) {
$objects = scandir( $dir );
foreach ( $objects as $object ) {
if ( "." !== $object && ".." !== $object ) {
if ( filetype( $dir . "/" . $object ) === "dir" ) {
self::recursive_rmdir( $dir . "/" . $object );
} else {
unlink( $dir . "/" . $object );
}
}
}
reset( $objects );
rmdir( $dir );
}
}
/**
* Utility function to remove remaining sql files.
*
* @since 3.2.0.2
*
* @param string $dir Directory from where the sql files are to be removed.
*
* @return none
*/
public static function remove_sql_files( $dir ) {
if ( is_dir( $dir ) ) {
$dir = trailingslashit( wp_normalize_path( $dir ) );
$sql_files = glob($dir . '*.sql');
foreach ( $sql_files as $sql_file) {
unlink( $sql_file );
}
}
}
/**
* Utility function to remove the snapshot manifest.
*
* @since 3.2.0.2
*
* @param string $dir Directory from where the manifest file is to be removed.
*
* @return none
*/
public static function remove_manifest( $dir ) {
if ( is_dir( $dir ) ) {
$dir = trailingslashit( wp_normalize_path( $dir ) );
$manifest_file = $dir . 'snapshot_manifest.txt';
if ( file_exists( $manifest_file ) ) {
unlink( $manifest_file );
}
}
}
/**
* Utility function to access the latest item's data set.
*
* @since 1.0.4
*
* @param $data_items
*
* @return mixed
*/
public static function latest_data_item( $data_items ) {
krsort( $data_items );
foreach ( $data_items as $data_key => $data_item ) {
return $data_item;
}
}
/**
* Utility function to access the latest backup ever.
*
* @since 1.0.4
*
* @param $data_items
*
* @return mixed
*/
public static function latest_backup( $items ) {
$last_files = array();
foreach ($items as $key => $backup) {
if( isset( $backup['data'] ) ){
$data_backup = self::latest_data_item( $backup['data'] );
if( isset( $data_backup["timestamp"] ) ) {
$last_files[$data_backup["timestamp"]] = $data_backup;
}
}
}
krsort( $last_files );
return reset( $last_files );
}
/**
* Utility function Add index.php and .htaccess files to archive folders
*
* @since 1.0.5
*
* @param string $folder Destination folder to apply security files to
*/
public static function secure_folder( $folder ) {
if ( ! file_exists( trailingslashit( $folder ) . "index.php" ) ) {
global $wp_filesystem;
if( self::connect_fs() ) {
$wp_filesystem->put_contents( trailingslashit( $folder ) . "index.php", "<?php // Silence is golden. ?>", FS_CHMOD_FILE );
} else {
return new WP_Error("filesystem_error", "Cannot initialize filesystem");
}
}
if ( ! file_exists( trailingslashit( $folder ) . ".htaccess" ) ) {
global $wp_filesystem;
if( self::connect_fs() ) {
$wp_filesystem->put_contents( trailingslashit( $folder ) . ".htaccess", "IndexIgnore *\r\nOptions -Indexes`\r\n", FS_CHMOD_FILE );
} else {
return new WP_Error("filesystem_error", "Cannot initialize filesystem");
}
}
if ( ! file_exists( trailingslashit( $folder ) . "CACHEDIR.TAG" ) ) {
global $wp_filesystem;
if( self::connect_fs() ) {
$wp_filesystem->put_contents( trailingslashit( $folder ) . "CACHEDIR.TAG", "", FS_CHMOD_FILE );
} else {
return new WP_Error("filesystem_error", "Cannot initialize filesystem");
}
}
}
/**
* Get the upload path of the blog.
*
* @param int $switched_blog_id
* @param string $key
*
* @return array|mixed
*/
public static function get_blog_upload_path( $switched_blog_id = 0, $key = 'basedir' ) {
global $blog_id;
$home_path = apply_filters( 'snapshot_home_path', get_home_path() );
//echo "switched_blog_id[". $switched_blog_id ."] key[". $key ."]<br />";
if ( is_multisite() ) {
$blog_id_org = $blog_id;
switch_to_blog( $switched_blog_id );
$uploads = wp_upload_dir();
if ( "basedir" === $key ) {
if ( isset( $uploads['basedir'] ) ) {
$upload_path = str_replace( '\\', '/', $uploads['basedir'] );
$upload_path = str_replace( $home_path, '', $upload_path );
}
} else if ( "baseurl" === $key ) {
if ( isset( $uploads['baseurl'] ) ) {
$upload_path = array();
$upload_path['raw'] = str_replace( '\\', '/', $uploads['baseurl'] );
if ( ( defined( 'UPLOADS' ) ) && ( UPLOADS !== '' ) ) {
$UPLOADS = str_replace( '/' . $blog_id_org . '/', '/' . $switched_blog_id . '/', untrailingslashit( UPLOADS ) );
$upload_path['rewrite'] = str_replace( $UPLOADS, 'files', $upload_path['raw'] );
$upload_path['rewrite'] = str_replace( get_option( 'siteurl' ) . '/', '', $upload_path['rewrite'] );
}
$upload_path['raw'] = str_replace( get_option( 'siteurl' ) . '/', '', $upload_path['raw'] );
}
}
restore_current_blog();
} else {
$uploads = wp_upload_dir();
if ( "basedir" === $key ) {
if ( isset( $uploads['basedir'] ) ) {
$upload_path = str_replace( '\\', '/', $uploads['basedir'] );
$upload_path = str_replace( $home_path, '', $upload_path );
}
} else if ( "baseurl" === $key ) {
if ( isset( $uploads['baseurl'] ) ) {
$upload_path = str_replace( get_site_url(), '', $uploads['baseurl'] );
}
}
}
if ( "basedir" === $key ) {
if ( ! $upload_path ) {
$upload_path = trailingslashit( WP_CONTENT_DIR ) . "uploads";
$upload_path = str_replace( '\\', '/', $upload_path );
$upload_path = str_replace( $home_path, '', $upload_path );
}
}
return $upload_path;
}
/**
* @param $item
*
* @return array
*/
public static function get_tables_sections_display( $item ) {
$tables_sections_out = array();
$tables_sections_out['click'] = '';
$tables_sections_out['hidden'] = '';
//echo "item<pre>"; print_r($item); echo "</pre>";
if ( isset( $item['tables-option'] ) ) {
$tables_sections_out['click'] .= __( 'Tables:', SNAPSHOT_I18N_DOMAIN ) . " (" . $item['tables-option'] . ")";
if ( isset( $item['tables-sections'] ) ) {
foreach ( $item['tables-sections'] as $section_key => $section_tables ) {
if ( "wp" === $section_key ) {
$section_label = __( 'core', SNAPSHOT_I18N_DOMAIN );
} else if ( "non" === $section_key ) {
$section_label = __( 'non-core', SNAPSHOT_I18N_DOMAIN );
} else if ( "other" === $section_key ) {
$section_label = __( 'other', SNAPSHOT_I18N_DOMAIN );
} else if ( "error" === $section_key ) {
$section_label = __( 'error', SNAPSHOT_I18N_DOMAIN );
} else if ( "global" === $section_key ) {
$section_label = __( 'global', SNAPSHOT_I18N_DOMAIN );
}
if ( count( $section_tables ) ) {
if ( strlen( $tables_sections_out['click'] ) ) {
$tables_sections_out['click'] .= ", ";
}
$tables_sections_out['click'] .= '<a class="snapshot-list-table-' . $section_key . '-show" href="#">' . sprintf( '%d %s',
count( $section_tables ), $section_label ) . '</a>';
$tables_sections_out['hidden'] .= '<p style="display: none" class="snapshot-list-table-' . $section_key . '-container">' .
implode( ', ', $section_tables ) . '</p>';
}
}
}
}
return $tables_sections_out;
}
/**
* @param $data_item
*
* @return array
*/
public static function get_files_sections_display( $data_item ) {
$files_sections_out = array();
$files_sections_out['click'] = '';
$files_sections_out['hidden'] = '';
if ( isset( $data_item['files-option'] ) ) {
$files_sections_out['click'] .= __( 'Files:', SNAPSHOT_I18N_DOMAIN ) . ' (';
$files_sections_out['click'] .= $data_item['files-option'] . ") ";
//if ((isset($data_item['files-count'])) && (intval($data_item['files-count']))) {
// $files_sections_out['click'] .= ' '. $data_item['files-count'] .' ';
//}
if ( isset( $data_item['files-sections'] ) ) {
$sections_str = '';
foreach ( $data_item['files-sections'] as $section ) {
if ( strlen( $sections_str ) ) {
$sections_str .= ", ";
}
$sections_str .= ucwords( $section );
}
$files_sections_out['click'] .= $sections_str;
}
}
return $files_sections_out;
}
/**
* Read a file and display its content chunk by chunk.
*
* @param $filename
* @param bool $retbytes
*
* @todo DO WE REALLY NEED TO ECHO THE BUFFER?
*
* @return bool|int
*/
public static function file_output_stream_chunked( $filename, $retbytes = true ) {
$CHUNK_SIZE = 1024 * 1024; // Size (in bytes) of tiles chunk
$buffer = '';
$cnt = 0;
$handle = fopen( $filename, 'rb' ); // phpcs:ignore
if ( false === $handle ) {
return false;
}
while ( ! feof( $handle ) ) {
$buffer = fread( $handle, $CHUNK_SIZE ); // phpcs:ignore
echo $buffer; // phpcs:ignore
flush();
if( ob_get_level() > 0 ){
ob_flush();
}
if ( $retbytes ) {
$cnt += strlen( $buffer );
}
}
$status = fclose( $handle ); // phpcs:ignore
if ( $retbytes && $status ) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
/**
* @param $someFolder
*/
public static function clean_folder( $someFolder ) {
$someFolder = trailingslashit( $someFolder );
// Cleanup any files from a previous restore attempt
$dh = opendir( $someFolder );
if ( $dh ) {
$file = readdir( $dh );
while ( false !== $file ) {
if ( ( '.' === $file ) || ( '..' === $file ) ) {
$file = readdir( $dh );
continue;
}
self::recursive_rmdir( $someFolder . $file );
$file = readdir( $dh );
}
closedir( $dh );
}
}
/**
* @param $manifest_array
* @param $manifestFile
*
* @return bool
*/
public static function create_archive_manifest( $manifest_array, $manifestFile ) {
if ( ! $manifest_array ) {
return false;
}
$manifest_array = apply_filters( 'wpmudev_snapshot_manifest_data', $manifest_array );
global $wp_filesystem;
if( self::connect_fs() ) {
foreach ( $manifest_array as $token => $token_data ) {
$wp_filesystem->put_contents($manifestFile, $wp_filesystem->get_contents( $manifestFile ) . $token . ":" . maybe_serialize( $token_data ) . "\r\n", FS_CHMOD_FILE);
}
return true;
}
}
/**
*
* @param $manifest_file
*
* @return array
*/
public static function consume_archive_manifest( $manifest_file ) {
$snapshot_manifest = array();
$manifest_array = file( $manifest_file );
$sessionRestoreFolder = trailingslashit( WPMUDEVSnapshot::instance()->get_setting( 'backupRestoreFolderFull' ) );
/* Return an empty array if the manifest is empty */
if ( ! $manifest_array ) {
return array();
}
/* Read the manifest file into an array, joining entries that are split across multiple lines */
$manifest = array();
$last_key = '';
foreach ( $manifest_array as $line ) {
$matches = array();
preg_match( '/^([\w\s-]+):(.+)$/', $line, $matches );
if ( $matches ) {
/* If the line matches the expected format, extract the values and add them to the array */
$label = trim( $matches[1] );
$data = $matches[2];
$manifest[ $label ] = $data;
$last_key = $label;
} elseif ( $last_key ) {
/* Otherwise, treat this line as part of the previous one */
$manifest[ $last_key ] .= "\n" . $line;
}
}
/* Parse the raw manifest data into its proper form */
foreach ( $manifest as $key => $value ) {
if ( "TABLES" === $key ) {
if ( is_serialized( $value ) ) {
$value = maybe_unserialize( $value );
} else {
$table_values = explode( ',', $value );
foreach ( $table_values as $idx => $table_name ) {
$table_values[ $idx ] = trim( $table_name );
}
$value = $table_values;
}
} else if ( ( "TABLES-DATA" === $key ) || ( "ITEM" === $key ) || ( "FILES-DATA" === $key ) || ( 'WP_UPLOAD_URLS' === $key ) ) {
if ( is_serialized( $value ) ) {
$value = maybe_unserialize( $value );
} else {
$value = trim( $value );
}
} else {
$value = trim( $value );
}
$snapshot_manifest[ $key ] = $value;
}
//echo "snapshot_manifest<pre>"; print_r($snapshot_manifest); echo "</pre>";
//die();
if ( ! isset( $snapshot_manifest['SNAPSHOT_VERSION'] ) ) {
if ( isset( $snapshot_manifest['VERSION'] ) ) {
$snapshot_manifest['SNAPSHOT_VERSION'] = $snapshot_manifest['VERSION'];
unset( $snapshot_manifest['VERSION'] );
}
}
if ( ! isset( $snapshot_manifest['WP_BLOG_ID'] ) ) {
if ( isset( $snapshot_manifest['BLOG-ID'] ) ) {
$snapshot_manifest['WP_BLOG_ID'] = $snapshot_manifest['BLOG-ID'];
unset( $snapshot_manifest['BLOG-ID'] );
}
}
if ( ! isset( $snapshot_manifest['WP_DB_NAME'] ) ) {
if ( isset( $snapshot_manifest['DB_NAME'] ) ) {
$snapshot_manifest['WP_DB_NAME'] = $snapshot_manifest['DB_NAME'];
unset( $snapshot_manifest['DB_NAME'] );
}
}
if ( ! isset( $snapshot_manifest['WP_DB_BASE_PREFIX'] ) ) {
if ( isset( $snapshot_manifest['BASE_PREFIX'] ) ) {
$snapshot_manifest['WP_DB_BASE_PREFIX'] = $snapshot_manifest['BASE_PREFIX'];
unset( $snapshot_manifest['BASE_PREFIX'] );
}
}
if ( ! isset( $snapshot_manifest['WP_DB_PREFIX'] ) ) {
if ( isset( $snapshot_manifest['PREFIX'] ) ) {
$snapshot_manifest['WP_DB_PREFIX'] = $snapshot_manifest['PREFIX'];
unset( $snapshot_manifest['PREFIX'] );
}
}
if ( ! isset( $snapshot_manifest['WP_DB_CHARSET_COLLATE'] ) ) {
if ( isset( $snapshot_manifest['CHARSET_COLLATE'] ) ) {
$snapshot_manifest['WP_DB_CHARSET_COLLATE'] = $snapshot_manifest['CHARSET_COLLATE'];
unset( $snapshot_manifest['CHARSET_COLLATE'] );
}
}
if ( ! isset( $snapshot_manifest['WP_UPLOAD_PATH'] ) ) {
if ( isset( $snapshot_manifest['UPLOAD_PATH'] ) ) {
$snapshot_manifest['WP_UPLOAD_PATH'] = $snapshot_manifest['UPLOAD_PATH'];
unset( $snapshot_manifest['UPLOAD_PATH'] );
}
}
if ( ! isset( $snapshot_manifest['WP_HOME'] ) ) {
if ( isset( $snapshot_manifest['HOME'] ) ) {
$snapshot_manifest['WP_HOME'] = $snapshot_manifest['HOME'];
unset( $snapshot_manifest['HOME'] );
}
}
if ( ! isset( $snapshot_manifest['WP_SITEURL'] ) ) {
if ( isset( $snapshot_manifest['SITEURL'] ) ) {
$snapshot_manifest['WP_SITEURL'] = $snapshot_manifest['SITEURL'];
unset( $snapshot_manifest['SITEURL'] );
}
}
if ( ! isset( $snapshot_manifest['WP_BLOG_NAME'] ) ) {
$snapshot_manifest['WP_BLOG_NAME'] = '';
}
if ( ! isset( $snapshot_manifest['WP_BLOG_DOMAIN'] ) ) {
if ( isset( $snapshot_manifest['WP_SITEURL'] ) ) {
$snapshot_manifest['WP_BLOG_DOMAIN'] = wp_parse_url( $snapshot_manifest['WP_SITEURL'], PHP_URL_HOST );
}
}
if ( ! isset( $snapshot_manifest['WP_BLOG_PATH'] ) ) {
if ( isset( $snapshot_manifest['WP_SITEURL'] ) ) {
$snapshot_manifest['WP_BLOG_PATH'] = wp_parse_url( $snapshot_manifest['WP_SITEURL'], PHP_URL_PATH );
}
}
//echo "snapshot_manifest<pre>"; print_r($snapshot_manifest); echo "</pre>";
return $snapshot_manifest;
}
/**
* @param string $archiveFilename
* @param string $restoreFolder
*
* @return bool|string
*/
public static function extract_archive_manifest( $archiveFilename = '', $restoreFolder = '' ) {
$manifest_file = 'snapshot_manifest.txt';
if ( ! file_exists( $archiveFilename ) ) {
return false;
}
if ( ! $restoreFolder ) {
$restoreFolder = WPMUDEVSnapshot::instance()->get_setting( 'backupRestoreFolderFull' );
}
// It is assumed the folder already exists!~~~
// Clear out the restore folder.
self::recursive_rmdir( $restoreFolder );
$ret = wp_mkdir_p( $restoreFolder );
//echo "zipLibrary[". WPMUDEVSnapshot::instance()->config_data['config']['zipLibrary'] ."]<br />";
//die();
if ( "PclZip" === WPMUDEVSnapshot::instance()->config_data['config']['zipLibrary'] ) {
if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) ) {
define( 'PCLZIP_TEMPORARY_DIR', $restoreFolder );
}
if ( ! class_exists( 'PclZip' ) ) {
require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
}
$zipArchive = new PclZip( $archiveFilename );
$exteact_files_list = $zipArchive->extract( PCLZIP_OPT_PATH, $restoreFolder, PCLZIP_OPT_BY_NAME, array( 'snapshot_manifest.txt' ) );
} else {
$normalizedArchiveFilename = wp_normalize_path( $archiveFilename );
if ( strpos( strtolower( trim( $normalizedArchiveFilename ) ), '../' ) !== false ) {
throw new Exception('path traversal is not allowed');
}
$zip = new ZipArchive();
$res = $zip->open( $normalizedArchiveFilename );
if ( true === $res ) {
$zip->extractTo( $restoreFolder, array( 'snapshot_manifest.txt' ) );
$zip->close();
}
}
$manifest_filename = trailingslashit( $restoreFolder ) . $manifest_file;
if ( file_exists( $manifest_filename ) ) {
return $manifest_filename;
} else {
return false;
}
}
/**
* @param $restoreFile
* @param $restoreFolder
*
* @return array
*/
public static function archives_import_proc( $restoreFile, $restoreFolder ) {
global $wpdb;
WPMUDEVSnapshot::instance()->load_config();
WPMUDEVSnapshot::instance()->set_backup_folder();
WPMUDEVSnapshot::instance()->set_log_folders();
$CONFIG_CHANGED = false;
// echo "restoreFile=[". $restoreFile ."]<br />";
// echo "restoreFolder=[". $restoreFolder ."]<br />";
// echo "before items<pre>"; print_r(WPMUDEVSnapshot::instance()->config_data['items']); echo "</pre>";
$error_status = array();
$error_status['errorStatus'] = false;
$error_status['errorText'] = "";
$error_status['responseText'] = "";
$snapshot_manifest = self::extract_archive_manifest( $restoreFile, $restoreFolder );
if ( file_exists( $snapshot_manifest ) ) {
//echo "snapshot_manifest[". $snapshot_manifest ."]<br />";
$CONFIG_CHANGED = false;
$manifest_data = self::consume_archive_manifest( $snapshot_manifest );
//echo "manifest_data<pre>"; print_r($manifest_data); echo "</pre>";
//die();
if ( empty( $manifest_data ) ) {
$error_status['errorStatus'] = true;
$error_status['errorText'] = __( "Manifest data not found in archive.", SNAPSHOT_I18N_DOMAIN );
return $error_status;
}
if ( ( ! isset( $manifest_data['ITEM'] ) ) || ( empty( $manifest_data['ITEM'] ) ) ) {
$error_status['errorStatus'] = true;
$error_status['errorText'] = __( "Manifest data does not contain ITEM section.", SNAPSHOT_I18N_DOMAIN );
return $error_status;
}
$item = $manifest_data['ITEM'];
if ( ( ! isset( $item['timestamp'] ) ) || ( empty( $item['timestamp'] ) ) ) {
$error_status['errorStatus'] = true;
$error_status['errorText'] = __( "Manifest ITEM does not contain 'timestamp' item.", SNAPSHOT_I18N_DOMAIN );
return $error_status;
}
//$siteurl = get_option('siteurl');
//echo "siteurl=[". $siteurl ."]<br />";
$RESTORE['LOCAL'] = array();
if ( is_multisite() ) {
$blog_details = get_blog_details( $manifest_data['WP_BLOG_ID'] );
//echo "blog_details<pre>"; print_r($blog_details); echo "</pre>";
if ( ( isset( $blog_details->domain ) ) && ( ! empty( $blog_details->domain ) ) ) {
$RESTORE['LOCAL']['WP_BLOG_DOMAIN'] = $blog_details->domain;
} else {
$RESTORE['LOCAL']['WP_BLOG_DOMAIN'] = '';
}
if ( ( isset( $blog_details->path ) ) && ( ! empty( $blog_details->path ) ) ) {
$RESTORE['LOCAL']['WP_BLOG_PATH'] = $blog_details->path;
} else {
$RESTORE['LOCAL']['WP_BLOG_PATH'] = '';
}
} else {
$siteurl = get_option( 'siteurl' );
$RESTORE['LOCAL']['WP_BLOG_DOMAIN'] = wp_parse_url( $siteurl, PHP_URL_HOST );
$RESTORE['LOCAL']['WP_BLOG_PATH'] = wp_parse_url( $siteurl, PHP_URL_PATH );
//$RESTORE['LOCAL']['WP_BLOG_ID'] = $blog_id;
}
$RESTORE['IMPORT'] = array();
if ( isset( $manifest_data['WP_BLOG_ID'] ) ) {
$RESTORE['IMPORT']['WP_BLOG_ID'] = $manifest_data['WP_BLOG_ID'];
} else {
$RESTORE['IMPORT']['WP_BLOG_ID'] = '';
}
if ( isset( $manifest_data['WP_BLOG_NAME'] ) ) {
$RESTORE['IMPORT']['WP_BLOG_NAME'] = $manifest_data['WP_BLOG_NAME'];
} else {
$RESTORE['IMPORT']['WP_BLOG_NAME'] = '';
}
if ( isset( $manifest_data['WP_DB_NAME'] ) ) {
$RESTORE['IMPORT']['WP_DB_NAME'] = $manifest_data['WP_DB_NAME'];
} else {
$RESTORE['IMPORT']['WP_DB_NAME'] = '';
}
if ( isset( $manifest_data['WP_DB_BASE_PREFIX'] ) ) {
$RESTORE['IMPORT']['WP_DB_BASE_PREFIX'] = $manifest_data['WP_DB_BASE_PREFIX'];
} else {
$RESTORE['IMPORT']['WP_DB_BASE_PREFIX'] = '';
}
if ( isset( $manifest_data['WP_DB_PREFIX'] ) ) {
$RESTORE['IMPORT']['WP_DB_PREFIX'] = $manifest_data['WP_DB_PREFIX'];
} else {
$RESTORE['IMPORT']['WP_DB_PREFIX'] = '';
}
if ( isset( $manifest_data['WP_DB_CHARSET_COLLATE'] ) ) {
$RESTORE['IMPORT']['WP_DB_CHARSET_COLLATE'] = $manifest_data['WP_DB_CHARSET_COLLATE'];
} else {
$RESTORE['IMPORT']['WP_DB_CHARSET_COLLATE'] = '';
}
if ( isset( $manifest_data['WP_HOME'] ) ) {
$RESTORE['IMPORT']['WP_HOME'] = $manifest_data['WP_HOME'];
}
if ( isset( $manifest_data['WP_SITEURL'] ) ) {
$RESTORE['IMPORT']['WP_SITEURL'] = $manifest_data['WP_SITEURL'];
} else {
$RESTORE['IMPORT']['WP_SITEURL'] = '';
}
if ( isset( $manifest_data['WP_UPLOAD_PATH'] ) ) {
$RESTORE['IMPORT']['WP_UPLOAD_PATH'] = $manifest_data['WP_UPLOAD_PATH'];
} else {
$RESTORE['IMPORT']['WP_UPLOAD_PATH'] = '';
}
if ( isset( $manifest_data['WP_UPLOAD_URLS'] ) ) {
$RESTORE['IMPORT']['WP_UPLOAD_URLS'] = $manifest_data['WP_UPLOAD_URLS'];
} else {
$RESTORE['IMPORT']['WP_UPLOAD_URLS'] = array();
}
if ( isset( $manifest_data['WP_BLOG_DOMAIN'] ) ) {
$RESTORE['IMPORT']['WP_BLOG_DOMAIN'] = $manifest_data['WP_BLOG_DOMAIN'];
} else if ( isset( $manifest_data['WP_SITEURL'] ) ) {
$RESTORE['LOCAL']['WP_BLOG_DOMAIN'] = wp_parse_url( $manifest_data['WP_SITEURL'], PHP_URL_HOST );
}
if ( isset( $manifest_data['WP_BLOG_PATH'] ) ) {
$RESTORE['IMPORT']['WP_BLOG_PATH'] = $manifest_data['WP_BLOG_PATH'];
} else if ( isset( $manifest_data['WP_SITEURL'] ) ) {
$RESTORE['IMPORT']['WP_BLOG_PATH'] = wp_parse_url( $manifest_data['WP_SITEURL'], PHP_URL_PATH );
}
//echo "RESTORE<pre>"; print_r($RESTORE); echo "</pre>";
//die();
if ( ( $RESTORE['IMPORT']['WP_BLOG_DOMAIN'] !== $RESTORE['LOCAL']['WP_BLOG_DOMAIN'] )
|| ( $RESTORE['IMPORT']['WP_BLOG_PATH'] !== $RESTORE['LOCAL']['WP_BLOG_PATH'] )
) {
$item['IMPORT'] = $RESTORE['IMPORT'];
// For Multisite we try and lookup the site based on the DOMAIN+PATH
if ( is_multisite() ) {
global $wpdb;
if ( is_subdomain_install() ) {
$sql_str = $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $RESTORE['IMPORT']['WP_BLOG_DOMAIN'] );
//$sql_str = $wpdb->prepare("SELECT blog_id FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $RESTORE['LOCAL']['WP_BLOG_DOMAIN']);
$blog = $wpdb->get_row( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $RESTORE['IMPORT']['WP_BLOG_DOMAIN'] ) );
} else {
$snapshot_blog_id_search_path = trailingslashit( $RESTORE['IMPORT']['WP_BLOG_PATH'] );
$snapshot_blog_id_search_domain = untrailingslashit( $RESTORE['IMPORT']['WP_BLOG_DOMAIN'] );
$sql_str = $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s AND path = %s LIMIT 1",
$snapshot_blog_id_search_domain, $snapshot_blog_id_search_path );
$blog = $wpdb->get_row( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s AND path = %s LIMIT 1",
$snapshot_blog_id_search_domain, $snapshot_blog_id_search_path ) );
}
if ( ( isset( $blog->blog_id ) ) && ( $blog->blog_id > 0 ) ) { // found
//echo "blog<pre>"; print_r($blog); echo "</pre>";
$item['blog-id'] = $blog->blog_id;
} else {
$item['blog-id'] = 0;
}
} else {
$item['blog-id'] = 0;
}
}
//echo "item<pre>"; print_r($item); echo "</pre>";
//die();
$item_key = $item['timestamp'];
if ( ( ! isset( $item['data'] ) ) || ( ! count( $item['data'] ) ) ) {
$error_status['errorStatus'] = true;
$error_status['errorText'] = __( "Manifest ITEM does not contain 'data' section.", SNAPSHOT_I18N_DOMAIN );
return $error_status;
}
$normalizedPath = strtolower( trim( $restoreFile ) );
if ( strpos( $normalizedPath, 'phar://' ) !== false ) {
throw new Exception('phar handler not allowed');
}
// Now we check the manifest item against the config data.
foreach ( $item['data'] as $data_item_key => $data_item ) {
if ( ( ! isset( $data_item['filename'] ) ) || ( empty( $data_item['filename'] ) ) ) {
$item['data'][ $data_item_key ]['filename'] = basename( $restoreFile );
}
if ( ( ! isset( $data_item['file_size'] ) ) || ( empty( $data_item['file_size'] ) ) ) {
$item['data'][ $data_item_key ]['file_size'] = filesize( $restoreFile );
}
}
if ( ! isset( WPMUDEVSnapshot::instance()->config_data['items'][ $item_key ] ) ) {
WPMUDEVSnapshot::instance()->config_data['items'][ $item_key ] = $item;
$CONFIG_CHANGED = true;
$error_status['errorStatus'] = false;
$error_status['responseText'] = __( "Archive imported successfully.", SNAPSHOT_I18N_DOMAIN );
} else {
foreach ( $item['data'] as $data_item_key => $data_item ) {
if ( ! isset( WPMUDEVSnapshot::instance()->config_data['items'][ $item_key ]['data'][ $data_item_key ] ) ) {
WPMUDEVSnapshot::instance()->config_data['items'][ $item_key ]['data'][ $data_item_key ] = $data_item;
$CONFIG_CHANGED = true;
$error_status['errorStatus'] = false;
$error_status['responseText'] = __( "Archive imported successfully.", SNAPSHOT_I18N_DOMAIN );
} else {
$error_status['errorStatus'] = false;
$error_status['responseText'] = __( "already present. not importing.", SNAPSHOT_I18N_DOMAIN );
}
}
}
if ( true === $CONFIG_CHANGED ) {
WPMUDEVSnapshot::instance()->save_config();
}
} else {
$error_status['errorStatus'] = true;
$error_status['errorText'] = __( "Manifest data not found in archive.", SNAPSHOT_I18N_DOMAIN );
}
return $error_status;
}
/**
* Convert bytes to human readable format.
*
* @since 2.0.3
*
* @param int $bytes Size in bytes to convert
* @param int $precision
*
* @return string
*/
public static function size_format( $bytes = 0, $precision = 2 ) {
return size_format($bytes, $precision);
/*
$kilobyte = 1000;
$megabyte = $kilobyte * 1000;
$gigabyte = $megabyte * 1000;
$terabyte = $gigabyte * 1000;
if ( ( $bytes >= 0 ) && ( $bytes < $kilobyte ) ) {
return $bytes . 'b';
} elseif ( ( $bytes >= $kilobyte ) && ( $bytes < $megabyte ) ) {
return round( $bytes / $kilobyte, $precision ) . 'kb';
} elseif ( ( $bytes >= $megabyte ) && ( $bytes < $gigabyte ) ) {
return round( $bytes / $megabyte, $precision ) . 'M';
} elseif ( ( $bytes >= $gigabyte ) && ( $bytes < $terabyte ) ) {
return round( $bytes / $gigabyte, $precision ) . 'G';
} elseif ( $bytes >= $terabyte ) {
return round( $bytes / $terabyte, $precision ) . 'T';
} else {
return $bytes . 'b';
}
*/
}
/**
* Returns human readable file size to bytes.
*
* @param $val
*
* @return int|string
*/
public static function size_unformat( $val ) {
$val = trim( $val );
$last = strtolower( $val[ strlen( $val ) - 1 ] );
// Explicitly typecast the value to a numeric one
$val = (float)$val;
switch ( $last ) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
// No break
case 'm':
$val *= 1024;
// No break
case 'k':
$val *= 1024;
// No break
case 'b':
$val = $val;
// No break
}
return $val;
}
/**
* @param string $item_key
*
* @return array|mixed|string|void
*/
public static function item_get_lock_info( $item_key = '' ) {
if ( ! $item_key ) {
return;
}
$lock_info = array();
$lock_info['locked'] = false;
$lock_info['file'] = trailingslashit( WPMUDEVSnapshot::instance()->get_setting( 'backupLockFolderFull' ) ) . $item_key . ".lock";
if ( file_exists( $lock_info['file'] ) ) {
// phpcs:ignore
$lock_fp = fopen( $lock_info['file'], 'r' );
if ( $lock_fp ) {
// Try to obtain exclusive lock to prevent multiple processes.
if ( ! flock( $lock_fp, LOCK_EX | LOCK_NB ) ) {
$lock_info['locked'] = true;
flock( $lock_fp, LOCK_UN );
}
$lock_info = fgets( $lock_fp, 4096 );
if ( $lock_info ) {
$lock_info = maybe_unserialize( $lock_info );
}
// phpcs:ignore
fclose( $lock_fp );
}
}
return $lock_info;
}
/**
* Wrapper for WP current_user_can.
*
* @todo Is this still needed?
*
* @param $cap
*
* @return bool
*/
public static function current_user_can( $cap ) {
if ( is_multisite() ) {
if ( is_network_admin() ) {
return true;
}
} else {
return current_user_can( $cap );
}
}
/**
* @param $data_item
*
* @return int
*/
public static function data_item_file_processed_count( $data_item ) {
if ( ! isset( $data_item['destination-status'] ) ) {
return 0;
}
$_count = 0;
foreach ( $data_item['destination-status'] as $_status ) {
if ( isset( $_status['syncFilesTotal'] ) ) {
$_count += intval( $_status['syncFilesTotal'] );
}
}
return intval( $_count );
}
/**
* Will be used to replace old home URL with new home URL if the URL is changed during restore.
*
* @todo Method name is too generic
*
* @param $value
* @param $old_site_url
* @param $new_site_url
*
* @return mixed|string
*/
public static function replace_value( $value, $old_site_url, $new_site_url ) {
if ( is_serialized( $value ) ) {
$unserialized = maybe_unserialize( $value );
$unserialized_new = self::replace_value( $unserialized, $old_site_url, $new_site_url ); // recurse!
return maybe_serialize( $unserialized_new );
} elseif ( is_array( $value ) ) {
foreach ( $value as $key => &$val ) {
$val = self::replace_value( $val, $old_site_url, $new_site_url ); // recurse!
}
return $value;
} elseif ( ( is_object( $value ) ) || ( gettype( $value ) === 'object' ) ) {
try {
$new_object = clone $value;
foreach ( $value as $key => $val ) {
$new_object->$key = self::replace_value( $val, $old_site_url, $new_site_url ); // recurse!
}
return $new_object;
} catch ( Exception $e ) {
assert(true);
}
} elseif ( is_string( $value ) ) {
return str_replace( $old_site_url, $new_site_url, $value ); // no more recursion
} else {
assert(true); //echo "type unknown [". $val ."]<br />";
}
return $value;
}
/**
*
* @todo Look for another way.
*
* @param $remote_url
* @param $local_file
*/
public static function remote_url_to_local_file( $remote_url, $local_file ) {
if ( ! file_exists( dirname( $local_file ) ) ) {
mkdir( dirname( $local_file ), 0777, true );
}
if ( file_exists( $local_file ) ) {
unlink( $local_file );
}
$remote_host = wp_parse_url( $remote_url, PHP_URL_HOST );
if ( strpos( $remote_host, 'dropbox.com' ) ) {
$remote_url = add_query_arg( 'dl', '1', $remote_url );
}
global $wp_filesystem;
if( self::connect_fs() ) {
$create_file = $wp_filesystem->put_contents( $local_file, '' );
if ( $create_file ){
$response = wp_remote_get( $remote_url, array(
'sslverify' => false
)
);
$wp_filesystem->put_contents( $local_file, $response['body'] );
return self::size_format( $response['headers']['content-length'] );
} else {
echo wp_kses_post( "Unable to open local file [" . $local_file . "] for writing. Check parent folder permissions and reload the page." );
die();
}
} else {
echo wp_kses_post( "Cannot initialize filesystem." );
die();
}
}
/**
* @param $status
*
* @return string
*/
public static function get_zip_archive_status_string( $status ) {
switch ( (int) $status ) {
case ZipArchive::ER_OK :
return 'N No error';
case ZipArchive::ER_MULTIDISK :
return 'N Multi-disk zip archives not supported';
case ZipArchive::ER_RENAME :
return 'S Renaming temporary file failed';
case ZipArchive::ER_CLOSE :
return 'S Closing zip archive failed';
case ZipArchive::ER_SEEK :
return 'S Seek error';
case ZipArchive::ER_READ :
return 'S Read error';
case ZipArchive::ER_WRITE :
return 'S Write error';
case ZipArchive::ER_CRC :
return 'N CRC error';
case ZipArchive::ER_ZIPCLOSED :
return 'N Containing zip archive was closed';
case ZipArchive::ER_NOENT :
return 'N No such file';
case ZipArchive::ER_EXISTS :
return 'N File already exists';
case ZipArchive::ER_OPEN :
return 'S Can\'t open file';
case ZipArchive::ER_TMPOPEN :
return 'S Failure to create temporary file';
case ZipArchive::ER_ZLIB :
return 'Z Zlib error';
case ZipArchive::ER_MEMORY :
return 'N Malloc failure';
case ZipArchive::ER_CHANGED :
return 'N Entry has been changed';
case ZipArchive::ER_COMPNOTSUPP :
return 'N Compression method not supported';
case ZipArchive::ER_EOF :
return 'N Premature EOF';
case ZipArchive::ER_INVAL :
return 'N Invalid argument';
case ZipArchive::ER_NOZIP :
return 'N Not a zip archive';
case ZipArchive::ER_INTERNAL :
return 'N Internal error';
case ZipArchive::ER_INCONS :
return 'N Zip archive inconsistent';
case ZipArchive::ER_REMOVE :
return 'S Can\'t remove file';
case ZipArchive::ER_DELETED :
return 'N Entry has been deleted';
default:
return sprintf( 'Unknown status %s', $status );
}
}
/**
* Is this Snapshot Pro?
*
* @since 2.5
*
* @return bool
*/
public static function is_pro() {
return true;
}
/**
* Check system requirements
*
* @since 3.1
*
* @param $requirements
*
* @return Array
*/
public static function check_system_requirements($requirements = array()) {
$current_timeout = (int)ini_get( 'max_execution_time' );
$defaults = array(
'PhpVersion' => array(
'test' => version_compare(PHP_VERSION, '5.2') >= 0,
'value' => PHP_VERSION
),
'MaxExecTime' => array(
'test' => 0 >= $current_timeout || $current_timeout >= 150,
'value' => (int)ini_get('max_execution_time'),
'warning' => true
),
'Mysqli' => array(
'test' => (bool)function_exists('mysqli_connect'),
),
'Zip' => array(
'test' => defined('SNAPSHOT_FORCE_ZIP_LIBRARY') && 'pclzip' === SNAPSHOT_FORCE_ZIP_LIBRARY
? true
: class_exists('ZipArchive')
)
);
$requirements = wp_parse_args( $requirements, $defaults );
$all_good = true;
$warning = false;
foreach ($requirements as $check) {
if (!empty($check['test'])) continue;
if (!empty($check['warning']) && ($check['warning'])){
$warning = true;
continue;
}
$all_good = false;
break;
}
$results = array(
'checks' => $requirements,
'warning' => $warning,
'all_good' => $all_good
);
return $results;
}
/**
* Connect to the filesystem
*
* @param $url
* @param $method
* @param $context
* @param $fields
*
* @return bool
*/
public static function connect_fs( $url = '', $method = '', $context = '', $fields = null ) {
global $wp_filesystem;
$credentials = request_filesystem_credentials($url, $method, false, $context, $fields);
if( false === ($credentials) ) {
return false;
}
//check if credentials are correct or not.
if( ! WP_Filesystem( $credentials ) )
{
request_filesystem_credentials( $url, $method, true, $context );
return false;
}
return true;
}
/**
* Checks whether we're on WPMU DEV Hosting
*
* @return bool
*/
public static function is_wpmu_hosting() {
return isset( $_SERVER['WPMUDEV_HOSTED'] ) && ! empty( $_SERVER['WPMUDEV_HOSTED'] );
}
/**
* Checks whether we're on WPEngine
*
* @return bool
*/
public static function is_wpengine_hosting() {
return defined('WPE_APIKEY');
}
/**
* Return converted UTC to local hosting backup time
*
* @return false|string
*/
public static function get_hosting_backup_local_time() {
// Currently backup time is hardcoded to 2:00AM UTC
$time = '2:00';
// Convert to local time
$time = Snapshot_Helper_Utility::show_date_time( strtotime( $time ), 'g:ia' );
return $time;
}
/**
* Checks whether the S3 request handler is properly spawned.
*
* @param $s3
*
* @return bool
*/
public static function spawned_S3_handler( $s3 ) {
if ( false === $s3 ) {
Snapshot_Helper_Log::error( 'Error spawning the S3 request handler, most probably due to a plugin conflict' );
return false;
} else {
return true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment