<?php backupbuddy_core::verifyAjaxAccess(); pb_backupbuddy::load(); if (false === ($results = backupbuddy_core::php_runtime_test_results())) { $tested_runtime_sofar = ''; $test_file = backupbuddy_core::getLogDirectory() . 'php_runtime_test.txt'; if (file_exists($test_file)) { if (false !== ($tested_runtime = @file_get_contents($test_file))) { if (is_numeric(trim($tested_runtime))) { $tested_runtime_sofar = ' ' . $tested_runtime . ' ' . __('secs so far.', 'it-l10n-backupbuddy'); } } } die(__('This may take a few minutes...', 'it-l10n-backupbuddy') . $tested_runtime_sofar); } else { die($results); }
// Check if running PHP 5.3+. $php_minimum = 5.3; if (version_compare(PHP_VERSION, $php_minimum, '<')) { // Server's PHP is insufficient. echo '<br>'; pb_backupbuddy::alert('<h3>' . __('We have a problem...', 'it-l10n-backupbuddy') . '</h3><br>' . __('<span style="font-size:1.5em;font-weight:bold;">Uh oh!</span><br />BackupBuddy Stash Live requires PHP version 5.3 or newer to run. Please upgrade your PHP version or contact your host for details on upgrading.', 'it-l10n-backupbuddy') . ' ' . __('Current PHP version', 'it-l10n-backupbuddy') . ': ' . PHP_VERSION); return; } if (!function_exists('curl_version')) { echo '<br>'; pb_backupbuddy::alert('<h3>' . __('We have a problem...', 'it-l10n-backupbuddy') . '</h3><br>' . __('BackupBuddy Stash Live requires the PHP "curl" extension to run. Please install or contact your host to install curl. This is a standard extension and should be available on all hosts.', 'it-l10n-backupbuddy')); return; } // No PHP runtime calculated yet. Try to see if test is finished. if (0 == pb_backupbuddy::$options['tested_php_runtime']) { backupbuddy_core::php_runtime_test_results(); } $liveDestinationID = false; foreach (pb_backupbuddy::$options['remote_destinations'] as $destination_id => $destination) { if ('live' == $destination['type']) { $liveDestinationID = $destination_id; break; } } // Handle disconnect. if ('disconnect' == pb_backupbuddy::_GET('live_action') && false !== $liveDestinationID) { // If disconnecting and not already disconnected. $disconnected = false; require_once pb_backupbuddy::plugin_path() . '/destinations/live/live_periodic.php'; require_once pb_backupbuddy::plugin_path() . '/destinations/stash2/class.itx_helper2.php'; $destination_settings = backupbuddy_live_periodic::get_destination_settings();
public static function run_periodic_process($preferredStep = '', $preferredStepArgs = array()) { require_once pb_backupbuddy::plugin_path() . '/destinations/live/live.php'; $previous_status_serial = pb_backupbuddy::get_status_serial(); // Hold current serial. pb_backupbuddy::set_status_serial('live_periodic'); // Redirect logging output to a certain log file. global $wp_version; $liveID = backupbuddy_live::getLiveID(); $logging_disabled = isset(pb_backupbuddy::$options['remote_destinations'][$liveID]['disable_logging']) && '1' == pb_backupbuddy::$options['remote_destinations'][$liveID]['disable_logging']; if (!$logging_disabled) { pb_backupbuddy::status('details', '-----'); pb_backupbuddy::status('details', 'Live periodic process starting with BackupBuddy v' . pb_backupbuddy::settings('version') . ' with WordPress v' . $wp_version . '.'); } // Make sure we are not PAUSED. if ('1' == pb_backupbuddy::$options['remote_destinations'][$liveID]['pause_periodic']) { pb_backupbuddy::status('details', 'Aborting periodic process as it is currently PAUSED based on settings.'); // Undo log redirect. pb_backupbuddy::set_status_serial($previous_status_serial); return false; } // Logging disabled. if ($logging_disabled) { pb_backupbuddy::set_status_serial($previous_status_serial); } require_once pb_backupbuddy::plugin_path() . '/classes/core.php'; require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php'; // Register a shutdown function to catch PHP errors and log them. register_shutdown_function('backupbuddy_live_periodic::shutdown_function'); // Load state into self::$_state & fileoptions object into self::$_stateObj. if (false === self::_load_state()) { return false; } // No PHP runtime calculated yet. Try to see if test is finished. if (0 == pb_backupbuddy::$options['tested_php_runtime']) { backupbuddy_core::php_runtime_test_results(); } // Update stats and save. if (0 === self::$_state['step']['start_time']) { self::$_state['step']['start_time'] = microtime(true); } self::$_state['step']['last_run_start'] = microtime(true); // Load destination settings. $destination_settings = self::get_destination_settings(); // If wait_on_transfers was the last step running and time limit has passed then we can start from the beginning. if ('wait_on_transfers' == self::$_state['step']['function'] && self::$_state['stats']['wait_on_transfers_start'] > 0 && time() - self::$_state['stats']['wait_on_transfers_start'] > $destination_settings['max_wait_on_transfers_time'] * 60) { pb_backupbuddy::status('warning', 'Ran out of max time (`' . round((time() - self::$_state['stats']['wait_on_transfers_start']) / 60) . '` of `' . $destination_settings['max_wait_on_transfers_time'] . '` max mins) waiting for pending transfers to finish. Resetting back to beginning of periodic process.'); self::$_state['step'] = self::$_stepDefaults; // Clear step state. } // Increment attempts if running the same function exactly as before. Set preferredStep args if we are indeed on this step. //sort( self::$_state['step']['args'] ); // Make sure order is same. //sort( $preferredStepArgs ); // Make sure order is same. if ('' == $preferredStep || self::$_state['step']['function'] == $preferredStep && self::$_state['step']['args'] == $preferredStepArgs) { // If preferredStep is blank OR ( preferredStep matches next step AND arguments are the same ). self::$_state['step']['attempts']++; } if ('' != $preferredStep) { self::_set_next_step($preferredStep, $preferredStepArgs); } // If restart transient is set then restart the Live process all the way back to daily_init. This is done when settings are saved so they will take effect immediately. if (false !== ($jump_step = get_transient('backupbuddy_live_jump'))) { pb_backupbuddy::status('details', 'Restart transient exists. Clearing.'); delete_transient('backupbuddy_live_jump'); $jump_step_name = $jump_step[0]; $jump_step_args = array(); if (isset($jump_step[1]) && is_array($jump_step[1])) { $jump_step_args = $jump_step[1]; } self::_set_next_step($jump_step_name); pb_backupbuddy::status('details', 'Reset next step to `' . $jump_step_name . '` with args `' . print_r($jump_step_args, true) . '` due to backupbuddy_live_jump transient.'); } // Check if a manual snapshot is requested. if (false !== get_transient('backupbuddy_live_snapshot')) { pb_backupbuddy::status('details', 'Manual Live Snapshot requested.'); delete_transient('backupbuddy_live_snapshot'); self::_request_manual_snapshot(); } // Set first activity (creation of Live basically). if (0 == self::$_state['stats']['first_activity']) { self::$_state['stats']['first_activity'] = time(); } // Save attempt. self::$_stateObj->save(); // Run step function and process results. $schedule_next_step = false; $start_time = microtime(true); $run_function = self::$_state['step']['function']; pb_backupbuddy::status('details', 'Starting Live periodic function `' . $run_function . '`.'); if (!is_callable('self::_step_' . $run_function)) { pb_backupbuddy::status('error', 'Error #439347494: Invalid step called: `' . $run_function . '` Unknown function: `self::_step_' . $run_function . '`.'); } $function_response = call_user_func_array('self::_step_' . $run_function, self::$_state['step']['args']); // Run step function. Returns true on success, string error message on fatal failure, and array( 'status message', array( ARGS ) ) when chunking back to same step. self::$_state['step']['last_run_finish'] = microtime(true); self::$_state['stats']['last_activity'] = microtime(true); pb_backupbuddy::status('details', 'Ended Live periodic function `' . $run_function . '`.'); // Process stepfunction results. if (is_array($function_response)) { // Chunking back to same step since we got an array. Index 0 = last_status, index 1 = args. Keeps same step function. $schedule_next_step = true; self::$_state['step']['chunks']++; self::$_state['step']['last_status'] = $function_response[0]; self::$_state['step']['args'] = $function_response[1]; pb_backupbuddy::status('details', 'Function needs chunked.'); if ('update_files_list' != $run_function && pb_backupbuddy::$options['log_level'] == '3') { // Full logging enabled. Hide for update_files_list function due to its huge size. pb_backupbuddy::status('details', 'Response args due to logging level: `' . print_r($function_response, true) . '`.'); } } elseif (is_string($function_response)) { // Fatal error. pb_backupbuddy::status('error', 'Error #32893283: One or more errors encountered running Live step function. Details: `' . $function_response . '`. See log above for more details.'); backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $function_response); if (FALSE === stristr($function_response, 'Error')) { // Make sure error-prefixed if not. $function_response = 'Error #489348: ' . $function_response; } self::$_state['step']['last_status'] = $function_response; } elseif (true === $function_response) { // Success finishing this step. // Interupted by a jump for the next step. if (false !== ($jump_step = get_transient('backupbuddy_live_jump'))) { pb_backupbuddy::status('details', 'Restart transient exists. Clearing.'); delete_transient('backupbuddy_live_jump'); $jump_step_name = $jump_step[0]; $jump_step_args = array(); if (isset($jump_step[1]) && is_array($jump_step[1])) { $jump_step_args = $jump_step[1]; } self::_set_next_step($jump_step_name); pb_backupbuddy::status('details', 'Reset next step to `' . $jump_step_name . '` with args `' . print_r($jump_step_args, true) . '` due to backupbuddy_live_jump transient.'); $schedule_next_step = true; } else { // Normal next step running (if any). if (!isset(self::$_nextFunction[$run_function])) { $schedule_next_step = false; pb_backupbuddy::status('details', 'Function reported success. No more Live steps to directly run. Finishing until next periodic restart.'); self::$_state['step'] = self::$_stepDefaults; // Clear step state. } else { $schedule_next_step = true; $nextFunction = self::$_nextFunction[$run_function]; self::_set_next_step($nextFunction); pb_backupbuddy::status('details', 'Function reported success. Scheduled next function to run, `' . $nextFunction . '`.'); } } } elseif (false === $function_response) { pb_backupbuddy::status('error', 'Error #3298338: Live (periodic) function `' . $run_function . '` failed without error message. Ending Live periodic process for this run without running more steps. See log above for details.'); $schedule_next_step = false; } else { // Unknown response. pb_backupbuddy::status('error', 'Error #98238392: Unknown periodic Live step function response `' . print_r($function_response, true) . '` for function `' . $run_function . '`. Fatal error.'); backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $function_response); self::$_state['step']['last_status'] = 'Error: ' . $function_response; $schedule_next_step = false; } // Save state. self::$_stateObj->save(); // Unlock fileoptions files if any remain locked. if (is_object(self::$_stateObj)) { self::$_stateObj->unlock(); } if (is_object(self::$_catalogObj)) { self::$_catalogObj->unlock(); } if (is_object(self::$_tablesObj)) { self::$_tablesObj->unlock(); } // Schedule the next step in the WP cron to run whichever step has been set in the state. if (true === $schedule_next_step) { pb_backupbuddy::status('details', 'Scheduling next step.'); // Schedule to run Live one more time for next chunk. $cronArgs = array(); $schedule_result = backupbuddy_core::schedule_single_event(time() - 60, 'live_periodic', $cronArgs); // Schedules 60sec in the past to push near the top. Traditional backup process is 155sec in the past for first priority. if (true === $schedule_result) { pb_backupbuddy::status('details', 'Next Live Periodic chunk step cron event scheduled.'); } else { pb_backupbuddy::status('error', 'Next Live Periodic chunk step cron event FAILED to be scheduled.'); } // Only chains the first cron. if ('1' != pb_backupbuddy::$options['skip_spawn_cron_call']) { pb_backupbuddy::status('details', 'Spawning cron now.'); update_option('_transient_doing_cron', 0); // Prevent cron-blocking for next item. spawn_cron(time() + 150); // Adds > 60 seconds to get around once per minute cron running limit. } // Schedule cron kicker (detects if it has not been too soon so we can call this judicously). self::_request_kick_cron(); } else { // Nothing left to do for now. Take a nap and wait until the next time that the periodic functionality launches and starts the process all over again. pb_backupbuddy::status('details', 'No more steps remain for this run. Not scheduling next step.'); } // Undo log redirect. pb_backupbuddy::set_status_serial($previous_status_serial); return true; }