602 lines
26 KiB
PHP
602 lines
26 KiB
PHP
<?php
|
|
|
|
/*
|
|
Duplicator Pro Plugin
|
|
Copyright (C) 2016, Snap Creek LLC
|
|
website: snapcreek.com
|
|
|
|
Duplicator Pro Plugin is distributed under the GNU General Public License, Version 3,
|
|
June 2007. Copyright (C) 2007 Free Software Foundation, Inc., 51 Franklin
|
|
St, Fifth Floor, Boston, MA 02110, USA
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
|
|
use Duplicator\Addons\ProBase\License\License;
|
|
use Duplicator\Libs\Snap\SnapURL;
|
|
use Duplicator\Libs\Snap\SnapUtil;
|
|
use Duplicator\Models\Storages\StoragesUtil;
|
|
use Duplicator\Models\SystemGlobalEntity;
|
|
|
|
class DUP_PRO_Package_Runner
|
|
{
|
|
const DEFAULT_MAX_BUILD_TIME_IN_MIN = 270;
|
|
const PACKAGE_STUCK_TIME_IN_SEC = 375; // 75 x 5;
|
|
|
|
/** @var bool */
|
|
public static $delayed_exit_and_kickoff = false;
|
|
|
|
/**
|
|
* Init package runner
|
|
*
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public static function init()
|
|
{
|
|
$kick_off_worker = false;
|
|
$global = DUP_PRO_Global_Entity::getInstance();
|
|
$system_global = SystemGlobalEntity::getInstance();
|
|
|
|
if ($global->clientside_kickoff === false) {
|
|
if ((time() - $system_global->package_check_ts) < DUP_PRO_Constants::PACKAGE_CHECK_TIME_IN_SEC) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
$locking_file = @fopen(DUPLICATOR_PRO_LOCKING_FILE_FILENAME, 'c+');
|
|
} else {
|
|
$locking_file = true;
|
|
}
|
|
|
|
DUP_PRO_Log::trace('Running package runner init');
|
|
|
|
if ($locking_file != false) {
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
$acquired_lock = (flock($locking_file, LOCK_EX | LOCK_NB) != false);
|
|
if ($acquired_lock) {
|
|
DUP_PRO_Log::trace("File lock acquired: " . DUPLICATOR_PRO_LOCKING_FILE_FILENAME);
|
|
} else {
|
|
DUP_PRO_Log::trace("File lock denied " . DUPLICATOR_PRO_LOCKING_FILE_FILENAME);
|
|
}
|
|
} else {
|
|
$acquired_lock = DUP_PRO_U::getSqlLock();
|
|
}
|
|
|
|
if ($acquired_lock) {
|
|
DUP_PRO_Log::trace("Acquired lock so executing package runner init core code");
|
|
$system_global->package_check_ts = time();
|
|
$system_global->save();
|
|
|
|
$pending_cancellations = DUP_PRO_Package::get_pending_cancellations();
|
|
|
|
self::cancel_long_running($pending_cancellations);
|
|
|
|
if (count($pending_cancellations) > 0) {
|
|
foreach ($pending_cancellations as $package_id_to_cancel) {
|
|
DUP_PRO_Log::trace("looking to cancel $package_id_to_cancel");
|
|
$package_to_cancel = DUP_PRO_Package::get_by_id((int) $package_id_to_cancel);
|
|
if ($package_to_cancel == false) {
|
|
continue;
|
|
}
|
|
|
|
if ($package_to_cancel->Status == DUP_PRO_PackageStatus::STORAGE_PROCESSING) {
|
|
$package_to_cancel->cancel_all_uploads();
|
|
$package_to_cancel->process_storages();
|
|
$package_to_cancel->set_status(DUP_PRO_PackageStatus::STORAGE_CANCELLED);
|
|
} else {
|
|
$package_to_cancel->set_status(DUP_PRO_PackageStatus::BUILD_CANCELLED);
|
|
}
|
|
|
|
$package_to_cancel->post_scheduled_build_failure();
|
|
}
|
|
|
|
DUP_PRO_Package::clear_pending_cancellations();
|
|
}
|
|
|
|
if (empty($_REQUEST['action']) || $_REQUEST['action'] != 'duplicator_pro_process_worker') {
|
|
self::process_schedules();
|
|
$kick_off_worker = DUP_PRO_Package::isPackageRunning();
|
|
}
|
|
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
if (!flock($locking_file, LOCK_UN)) {
|
|
DUP_PRO_Log::trace("File lock cant release " . $locking_file);
|
|
} else {
|
|
DUP_PRO_Log::trace("File lock released " . $locking_file);
|
|
}
|
|
fclose($locking_file);
|
|
} else {
|
|
DUP_PRO_U::releaseSqlLock();
|
|
}
|
|
}
|
|
} else {
|
|
DUP_PRO_Log::trace("Problem opening locking file so auto switching to SQL lock mode");
|
|
$global->lock_mode = DUP_PRO_Thread_Lock_Mode::SQL_Lock;
|
|
$global->save();
|
|
exit();
|
|
}
|
|
|
|
if ($kick_off_worker || self::$delayed_exit_and_kickoff) {
|
|
self::kick_off_worker();
|
|
} elseif (is_admin() && (isset($_REQUEST['page']) && (strpos($_REQUEST['page'], DUP_PRO_Constants::PLUGIN_SLUG) !== false))) {
|
|
DUP_PRO_Log::trace("************kicking off slug worker");
|
|
// If it's one of our pages force it to kick off the client
|
|
self::kick_off_worker(true);
|
|
}
|
|
|
|
if (self::$delayed_exit_and_kickoff) {
|
|
self::$delayed_exit_and_kickoff = false;
|
|
exit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add javascript for cliean side Kick off
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function add_kickoff_worker_javascript()
|
|
{
|
|
$global = DUP_PRO_Global_Entity::getInstance();
|
|
$custom_url = strtolower($global->custom_ajax_url);
|
|
$CLIENT_CALL_PERIOD_IN_MS = 20000;
|
|
// How often client calls into the service
|
|
|
|
if ($global->ajax_protocol == 'custom') {
|
|
if (DUP_PRO_STR::startsWith($custom_url, 'http')) {
|
|
$ajax_url = $custom_url;
|
|
} else {
|
|
// Revert to http standard if they don't have the url correct
|
|
$ajax_url = admin_url('admin-ajax.php', 'http');
|
|
DUP_PRO_Log::trace("Even though custom ajax url configured, incorrect url set so reverting to $ajax_url");
|
|
}
|
|
} else {
|
|
$ajax_url = admin_url('admin-ajax.php', $global->ajax_protocol);
|
|
}
|
|
|
|
$gateway = array(
|
|
'ajaxurl' => $ajax_url,
|
|
'client_call_frequency' => $CLIENT_CALL_PERIOD_IN_MS,
|
|
'duplicator_pro_process_worker_nonce' => wp_create_nonce('duplicator_pro_process_worker'),
|
|
);
|
|
wp_register_script('dup-pro-kick', DUPLICATOR_PRO_PLUGIN_URL . 'assets/js/dp-kick.js', array('jquery'), DUPLICATOR_PRO_VERSION);
|
|
wp_localize_script('dup-pro-kick', 'dp_gateway', $gateway);
|
|
DUP_PRO_Log::trace('KICKOFF: Client Side');
|
|
wp_enqueue_script('dup-pro-kick');
|
|
}
|
|
|
|
/**
|
|
* Checks active packages for being stuck or running too long and adds them for canceling
|
|
*
|
|
* @param int[] $pending_cancellations List of package ids to be cancelled
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function cancel_long_running(&$pending_cancellations)
|
|
{
|
|
if (!DUP_PRO_Package::isPackageRunning()) {
|
|
return;
|
|
}
|
|
|
|
$active_package = DUP_PRO_Package::get_next_active_package();
|
|
if ($active_package === null) {
|
|
DUP_PRO_Log::trace("Active package returned null");
|
|
return;
|
|
}
|
|
|
|
$global = DUP_PRO_Global_Entity::getInstance();
|
|
$system_global = SystemGlobalEntity::getInstance();
|
|
$buildStarted = $active_package->timer_start > 0;
|
|
$active_package->timer_start = $buildStarted ? $active_package->timer_start : DUP_PRO_U::getMicrotime();
|
|
$elapsed_sec = $buildStarted ? DUP_PRO_U::getMicrotime() - $active_package->timer_start : 0;
|
|
$elapsed_minutes = $elapsed_sec / 60;
|
|
$addedForCancelling = false;
|
|
|
|
if ($buildStarted && $global->max_package_runtime_in_min > 0 && $elapsed_minutes > $global->max_package_runtime_in_min) {
|
|
if ($active_package->build_progress->current_build_mode != DUP_PRO_Archive_Build_Mode::DupArchive) {
|
|
$system_global->addQuickFix(
|
|
__('Package was cancelled because it exceeded Max Build Time.', 'duplicator-pro'),
|
|
sprintf(
|
|
__(
|
|
'Click button to switch to the DupArchive engine. Please see this %1$sFAQ%2$s for other possible solutions.',
|
|
'duplicator-pro'
|
|
),
|
|
'<a href="' . DUPLICATOR_PRO_DUPLICATOR_DOCS_URL . 'how-to-resolve-schedule-build-failures" target="_blank">',
|
|
'</a>'
|
|
),
|
|
array(
|
|
'global' => array(
|
|
'archive_build_mode' => DUP_PRO_Archive_Build_Mode::DupArchive,
|
|
),
|
|
)
|
|
);
|
|
} elseif ($global->max_package_runtime_in_min < self::DEFAULT_MAX_BUILD_TIME_IN_MIN) {
|
|
$system_global->addQuickFix(
|
|
__('Package was cancelled because it exceeded Max Build Time.', 'duplicator-pro'),
|
|
sprintf(
|
|
__(
|
|
'Click button to increase Max Build Time. Please see this %1$sFAQ%2$s for other possible solutions.',
|
|
'duplicator-pro'
|
|
),
|
|
'<a href="' . DUPLICATOR_PRO_DUPLICATOR_DOCS_URL . 'how-to-resolve-schedule-build-failures" target="_blank">',
|
|
'</a>'
|
|
),
|
|
array(
|
|
'global' => array(
|
|
'max_package_runtime_in_min' => self::DEFAULT_MAX_BUILD_TIME_IN_MIN,
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
DUP_PRO_Log::infoTrace("Package $active_package->ID has been going for $elapsed_minutes minutes so cancelling. ($elapsed_sec)");
|
|
array_push($pending_cancellations, $active_package->ID);
|
|
$addedForCancelling = true;
|
|
}
|
|
|
|
if ((($active_package->Status == DUP_PRO_PackageStatus::AFTER_SCAN) || ($active_package->Status == DUP_PRO_PackageStatus::PRE_PROCESS)) && ($global->clientside_kickoff == false)) {
|
|
// Traditionally package considered stuck if > 75 but that was with time % 5 so multiplying by 5 to compensate now
|
|
if ($elapsed_sec > self::PACKAGE_STUCK_TIME_IN_SEC) {
|
|
DUP_PRO_Log::trace("*** STUCK");
|
|
$showDefault = true;
|
|
if (isset($_SERVER['AUTH_TYPE']) && $_SERVER['AUTH_TYPE'] == 'Basic' && !$global->basic_auth_enabled) {
|
|
$system_global->addQuickFix(
|
|
__('Set authentication username and password', 'duplicator-pro'),
|
|
__('Automatically set basic auth username and password', 'duplicator-pro'),
|
|
array(
|
|
'special' => array('set_basic_auth' => 1),
|
|
)
|
|
);
|
|
$showDefault = false;
|
|
}
|
|
|
|
if (SnapURL::isCurrentUrlSSL() && $global->ajax_protocol == 'http') {
|
|
$system_global->addQuickFix(
|
|
__('Communication to AJAX is blocked.', 'duplicator-pro'),
|
|
__('Click button to configure plugin to use HTTPS.', 'duplicator-pro'),
|
|
array(
|
|
'special' => array('stuck_5percent_pending_fix' => 1),
|
|
)
|
|
);
|
|
} elseif (!SnapURL::isCurrentUrlSSL() && $global->ajax_protocol == 'https') {
|
|
$system_global->addQuickFix(
|
|
__('Communication to AJAX is blocked.', 'duplicator-pro'),
|
|
__('Click button to configure plugin to use HTTP.', 'duplicator-pro'),
|
|
array(
|
|
'special' => array('stuck_5percent_pending_fix' => 1),
|
|
)
|
|
);
|
|
} elseif ($global->ajax_protocol == 'custom') {
|
|
$system_global->addQuickFix(
|
|
__('Communication to AJAX is blocked.', 'duplicator-pro'),
|
|
__('Click button to fix the admin-ajax URL setting.', 'duplicator-pro'),
|
|
array(
|
|
'special' => array('stuck_5percent_pending_fix' => 1),
|
|
)
|
|
);
|
|
} elseif ($showDefault) {
|
|
$system_global->addTextFix(
|
|
__('Communication to AJAX is blocked.', 'duplicator-pro'),
|
|
sprintf(
|
|
"%s <a href='" . DUPLICATOR_PRO_DUPLICATOR_DOCS_URL . "how-to-resolve-builds-getting-stuck-at-a-certain-point/' target='_blank'>%s</a>",
|
|
__('See FAQ:', 'duplicator-pro'),
|
|
__('Why is the package build stuck at 5%?', 'duplicator-pro')
|
|
)
|
|
);
|
|
}
|
|
|
|
DUP_PRO_Log::infoTrace("Package $active_package->ID has been stuck for $elapsed_minutes minutes so cancelling. ($elapsed_sec)");
|
|
array_push($pending_cancellations, $active_package->ID);
|
|
$addedForCancelling = true;
|
|
}
|
|
}
|
|
|
|
if ($addedForCancelling) {
|
|
$active_package->buildFail(
|
|
'Package was cancelled because it exceeded Max Build Time.',
|
|
false
|
|
);
|
|
} else {
|
|
$active_package->save();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Kick off worker
|
|
*
|
|
* @param bool $run_only_if_client If true then only kick off worker if the request came from the client
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function kick_off_worker($run_only_if_client = false)
|
|
{
|
|
/* @var $global DUP_PRO_Global_Entity */
|
|
$global = DUP_PRO_Global_Entity::getInstance();
|
|
if (!$run_only_if_client || $global->clientside_kickoff) {
|
|
$calling_function_name = SnapUtil::getCallingFunctionName();
|
|
DUP_PRO_Log::trace("Kicking off worker process as requested by $calling_function_name");
|
|
$custom_url = strtolower($global->custom_ajax_url);
|
|
if ($global->ajax_protocol == 'custom') {
|
|
if (DUP_PRO_STR::startsWith($custom_url, 'http')) {
|
|
$ajax_url = $custom_url;
|
|
} else {
|
|
// Revert to http standard if they don't have the url correct
|
|
$ajax_url = admin_url('admin-ajax.php', 'http');
|
|
DUP_PRO_Log::trace("Even though custom ajax url configured, incorrect url set so reverting to $ajax_url");
|
|
}
|
|
} else {
|
|
$ajax_url = admin_url('admin-ajax.php', $global->ajax_protocol);
|
|
}
|
|
|
|
DUP_PRO_Log::trace("Attempting to use ajax url $ajax_url");
|
|
if ($global->clientside_kickoff) {
|
|
add_action('wp_enqueue_scripts', 'DUP_PRO_Package_Runner::add_kickoff_worker_javascript');
|
|
add_action('admin_enqueue_scripts', 'DUP_PRO_Package_Runner::add_kickoff_worker_javascript');
|
|
} else {
|
|
// Server-side kickoff
|
|
$ajax_url = SnapURL::appendQueryValue($ajax_url, 'action', 'duplicator_pro_process_worker');
|
|
$ajax_url = SnapURL::appendQueryValue($ajax_url, 'now', time());
|
|
// $duplicator_pro_process_worker_nonce = wp_create_nonce('duplicator_pro_process_worker');
|
|
//require_once(ABSPATH.'wp-includes/pluggable.php');
|
|
//$ajax_url = wp_nonce_url($ajax_url, 'duplicator_pro_process_worker', 'nonce');
|
|
|
|
DUP_PRO_Log::trace('KICKOFF: Server Side');
|
|
if ($global->basic_auth_enabled) {
|
|
$sglobal = DUP_PRO_Secure_Global_Entity::getInstance();
|
|
$args = array(
|
|
'blocking' => false,
|
|
'headers' => array('Authorization' => 'Basic ' . base64_encode($global->basic_auth_user . ':' . $sglobal->basic_auth_password)),
|
|
);
|
|
} else {
|
|
$args = array('blocking' => false);
|
|
}
|
|
$args['sslverify'] = false;
|
|
wp_remote_get($ajax_url, $args);
|
|
}
|
|
|
|
DUP_PRO_Log::trace("after sent kickoff request");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process schedules by cron
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function process()
|
|
{
|
|
if (!defined('WP_MAX_MEMORY_LIMIT')) {
|
|
define('WP_MAX_MEMORY_LIMIT', '512M');
|
|
}
|
|
|
|
if (SnapUtil::isIniValChangeable('memory_limit')) {
|
|
@ini_set('memory_limit', WP_MAX_MEMORY_LIMIT);
|
|
}
|
|
|
|
@set_time_limit(7200);
|
|
@ignore_user_abort(true);
|
|
if (SnapUtil::isIniValChangeable('pcre.backtrack_limit')) {
|
|
@ini_set('pcre.backtrack_limit', (string) PHP_INT_MAX);
|
|
}
|
|
|
|
if (SnapUtil::isIniValChangeable('default_socket_timeout')) {
|
|
@ini_set('default_socket_timeout', '7200');
|
|
// 2 Hours
|
|
}
|
|
|
|
/* @var $global DUP_PRO_Global_Entity */
|
|
$global = DUP_PRO_Global_Entity::getInstance();
|
|
if ($global->clientside_kickoff) {
|
|
DUP_PRO_Log::trace("PROCESS: From client");
|
|
session_write_close();
|
|
} else {
|
|
DUP_PRO_Log::trace("PROCESS: From server");
|
|
}
|
|
|
|
// Only attempt to process schedules if manual isn't running
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
$locking_file = fopen(DUPLICATOR_PRO_LOCKING_FILE_FILENAME, 'c+');
|
|
} else {
|
|
$locking_file = true;
|
|
}
|
|
|
|
if ($locking_file == false) {
|
|
DUP_PRO_Log::trace("Problem opening locking file so auto switching to SQL lock mode");
|
|
$global->lock_mode = DUP_PRO_Thread_Lock_Mode::SQL_Lock;
|
|
$global->save();
|
|
exit();
|
|
}
|
|
|
|
// Here we know that $locking_file != false
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
$acquired_lock = (flock($locking_file, LOCK_EX | LOCK_NB) != false);
|
|
if ($acquired_lock) {
|
|
DUP_PRO_Log::trace("File lock acquired " . $locking_file);
|
|
} else {
|
|
DUP_PRO_Log::trace("File lock denied " . $locking_file);
|
|
}
|
|
} else {
|
|
// DUP_PRO_U::getSqlLock will write details into trace log, logging is not needed here
|
|
$acquired_lock = DUP_PRO_U::getSqlLock();
|
|
}
|
|
|
|
if (!$acquired_lock) {
|
|
// File locked so another cron already running so just skip
|
|
DUP_PRO_Log::trace("File locked so skipping");
|
|
return;
|
|
}
|
|
|
|
// Here we know that $acquired_lock == true
|
|
self::process_schedules();
|
|
$package = DUP_PRO_Package::get_next_active_package();
|
|
|
|
if ($package != null) {
|
|
StoragesUtil::getDefaultStorage()->initStorageDirectory(true);
|
|
$dup_tests = self::get_requirements_tests();
|
|
if ($dup_tests['Success'] == true) {
|
|
$start_time = time();
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID:PROCESSING");
|
|
ignore_user_abort(true);
|
|
if ($package->Status < DUP_PRO_PackageStatus::AFTER_SCAN) {
|
|
// Scan step built into package build - used by schedules - NOT manual build where scan is done in web service.
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID:SCANNING");
|
|
//After scanner runs. Save FilterInfo (unreadable, warnings, globals etc)
|
|
$package->create_scan_report();
|
|
$package->update();
|
|
//del if($package->Archive->ScanStatus == DUP_PRO_Archive::ScanStatusComplete){
|
|
$dupe_package = DUP_PRO_Package::get_by_id($package->ID);
|
|
$dupe_package->set_status(DUP_PRO_PackageStatus::AFTER_SCAN);
|
|
//del }
|
|
|
|
$end_time = time();
|
|
$scan_time = $end_time - $start_time;
|
|
//del $end_time = DUP_PRO_U::getMicrotime();
|
|
//
|
|
// $scan_time = $end_time - $package->Archive->ScanTimeStart;
|
|
|
|
DUP_PRO_Log::trace("SCAN TIME=$scan_time seconds");
|
|
} elseif ($package->Status < DUP_PRO_PackageStatus::COPIEDPACKAGE) {
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID:BUILDING");
|
|
$package->run_build();
|
|
$end_time = time();
|
|
$build_time = $end_time - $start_time;
|
|
DUP_PRO_Log::trace("BUILD TIME=$build_time seconds");
|
|
} elseif ($package->Status < DUP_PRO_PackageStatus::COMPLETE) {
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID:STORAGE PROCESSING");
|
|
$package->set_status(DUP_PRO_PackageStatus::STORAGE_PROCESSING);
|
|
$package->process_storages();
|
|
$end_time = time();
|
|
$build_time = $end_time - $start_time;
|
|
DUP_PRO_Log::trace("STORAGE CHUNK PROCESSING TIME=$build_time seconds");
|
|
if ($package->Status == DUP_PRO_PackageStatus::COMPLETE) {
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID COMPLETE");
|
|
} elseif ($package->Status == DUP_PRO_PackageStatus::ERROR) {
|
|
DUP_PRO_Log::trace("PACKAGE $package->ID IN ERROR STATE");
|
|
}
|
|
|
|
$packageCompleteStatuses = array(
|
|
DUP_PRO_PackageStatus::COMPLETE,
|
|
DUP_PRO_PackageStatus::ERROR,
|
|
);
|
|
if (in_array($package->Status, $packageCompleteStatuses)) {
|
|
$info = "\n";
|
|
$info .= "********************************************************************************\n";
|
|
$info .= "********************************************************************************\n";
|
|
$info .= "DUPLICATOR PRO PACKAGE CREATION OR MANUAL STORAGE TRANSFER END: " . @date("Y-m-d H:i:s") . "\n";
|
|
$info .= "NOTICE: Do NOT post to public sites or forums \n";
|
|
$info .= "********************************************************************************\n";
|
|
$info .= "********************************************************************************\n";
|
|
DUP_PRO_Log::infoTrace($info);
|
|
}
|
|
}
|
|
|
|
ignore_user_abort(false);
|
|
} else {
|
|
DUP_PRO_Log::open($package->NameHash);
|
|
|
|
if ($dup_tests['RES']['INSTALL'] == 'Fail') {
|
|
DUP_PRO_Log::info('Installer files still present on site. Remove using Tools > Stored Data > "Remove Installer Files".');
|
|
}
|
|
|
|
DUP_PRO_Log::error(__('Requirements Failed', 'duplicator-pro'), print_r($dup_tests, true), false);
|
|
DUP_PRO_Log::traceError('Requirements didn\'t pass so can\'t perform backup!');
|
|
$package->post_scheduled_build_failure($dup_tests);
|
|
$package->set_status(DUP_PRO_PackageStatus::REQUIREMENTS_FAILED);
|
|
}
|
|
}
|
|
|
|
//$kick_off_worker = (DUP_PRO_Package::get_next_active_package() != null);
|
|
$kick_off_worker = DUP_PRO_Package::isPackageRunning();
|
|
if ($global->lock_mode == DUP_PRO_Thread_Lock_Mode::Flock) {
|
|
DUP_PRO_Log::trace("File lock released");
|
|
if (!flock($locking_file, LOCK_UN)) {
|
|
DUP_PRO_Log::trace("File lock cant release " . $locking_file);
|
|
} else {
|
|
DUP_PRO_Log::trace("File lock released " . $locking_file);
|
|
}
|
|
fclose($locking_file);
|
|
} else {
|
|
DUP_PRO_U::releaseSqlLock();
|
|
}
|
|
|
|
if ($kick_off_worker) {
|
|
self::kick_off_worker();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the requirements tests
|
|
*
|
|
* @return array<string,mixed>
|
|
*/
|
|
public static function get_requirements_tests()
|
|
{
|
|
$dup_tests = DUP_PRO_Server::getRequirments();
|
|
if ($dup_tests['Success'] != true) {
|
|
DUP_PRO_Log::traceObject('requirements', $dup_tests);
|
|
}
|
|
|
|
return $dup_tests;
|
|
}
|
|
|
|
/**
|
|
* Calculates the earliest schedule run time
|
|
*
|
|
* @return int
|
|
*/
|
|
public static function calculate_earliest_schedule_run_time()
|
|
{
|
|
if (!License::can(License::CAPABILITY_SCHEDULE)) {
|
|
return -1;
|
|
}
|
|
|
|
$next_run_time = PHP_INT_MAX;
|
|
$schedules = DUP_PRO_Schedule_Entity::get_active();
|
|
foreach ($schedules as $schedule) {
|
|
if ($schedule->next_run_time == -1) {
|
|
$schedule->updateNextRuntime();
|
|
}
|
|
|
|
if ($schedule->next_run_time !== -1 && $schedule->next_run_time < $next_run_time) {
|
|
$next_run_time = $schedule->next_run_time;
|
|
}
|
|
}
|
|
|
|
if ($next_run_time == PHP_INT_MAX) {
|
|
$next_run_time = -1;
|
|
}
|
|
|
|
return $next_run_time;
|
|
}
|
|
|
|
/**
|
|
* Start schedule package creation
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function process_schedules()
|
|
{
|
|
// Hack fix - observed issue on a machine where schedule process bombs
|
|
$next_run_time = self::calculate_earliest_schedule_run_time();
|
|
if ($next_run_time != -1 && ($next_run_time <= time())) {
|
|
$schedules = DUP_PRO_Schedule_Entity::get_active();
|
|
foreach ($schedules as $schedule) {
|
|
$schedule->process();
|
|
}
|
|
}
|
|
}
|
|
}
|