first commit

This commit is contained in:
Roman Pyrih
2026-04-21 15:48:41 +02:00
commit 7483681901
10216 changed files with 3236626 additions and 0 deletions

View File

@@ -0,0 +1,317 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Models\GlobalEntity;
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\CapMng;
use Duplicator\Models\StaticGlobal;
use Duplicator\Utils\Logging\DupLog;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$trace_log_filepath = DupLog::getTraceFilepath();
$trace_filename = basename($trace_log_filepath);
$logs = ToolsPageController::getLogsList();
$global = GlobalEntity::getInstance();
$logname = (isset($_GET['logname'])) ? trim($_GET['logname']) : "";
$refresh = (isset($_POST['refresh']) && $_POST['refresh'] == 1) ? 1 : 0;
$auto = (isset($_POST['auto']) && $_POST['auto'] == 1) ? 1 : 0;
//Check for invalid file
if (isset($_GET['logname'])) {
$validFiles = array_map('basename', $logs);
if (validate_file($logname, $validFiles) > 0) {
unset($logname);
}
unset($validFiles);
}
if (!isset($logname) || !$logname) {
$logname = (count($logs) > 0) ? basename($logs[0]) : "";
}
$nocache = @date("ymdHis");
$logurl = DUPLICATOR_LOGS_URL . "/{$logname}?{$nocache}";
$logurl_base = DUPLICATOR_LOGS_URL . "/{$logname}";
$logfound = strlen($logname) > 0;
?>
<script>
jQuery(document).ready(function($) {
DupliJs.Tools.FullLog = function() {
var $panelL = $('#dupli-log-pnl-left');
var $panelR = $('#dupli-log-pnl-right');
if ($panelR.is(":visible")) {
$panelR.hide(400);
$panelL.css({
width: '100%'
});
} else {
$panelR.show(200);
$panelL.css({
width: '75%'
});
}
}
DupliJs.Tools.Refresh = function() {
$('#refresh').val(1);
$('#dup-form-logs').submit();
}
DupliJs.Tools.RefreshAuto = function() {
if ($("#dup-auto-refresh").is(":checked")) {
$('#auto').val(1);
startTimer();
} else {
$('#auto').val(0);
}
}
DupliJs.Tools.WinResize = function() {
var height = $(window).height() - 210;
$("#dupli-log-content").css({
height: height + 'px'
});
}
var duration = 9;
var count = duration;
var timerInterval;
function timer() {
count = count - 1;
$("#dup-refresh-count").html(count.toString());
if (!$("#dup-auto-refresh").is(":checked")) {
clearInterval(timerInterval);
$("#dup-refresh-count").text(count.toString().trim());
return;
}
if (count <= 0) {
count = duration + 1;
DupliJs.Tools.Refresh();
}
}
function startTimer() {
timerInterval = setInterval(timer, 1000);
}
//INIT Events
$(window).resize(DupliJs.Tools.WinResize);
$('#dup-options').click(DupliJs.Tools.FullLog);
$("#dup-refresh").click(DupliJs.Tools.Refresh);
$("#dup-auto-refresh").click(DupliJs.Tools.RefreshAuto);
$("#dup-refresh-count").html(duration.toString());
//INIT
DupliJs.Tools.WinResize();
<?php if ($refresh) : ?>
//Scroll to Bottom
$('#dupli-log-content').on('load', function() {
var $contents = $('#dupli-log-content').contents();
$contents.scrollTop($contents.height());
});
<?php if ($auto) : ?>
$("#dup-auto-refresh").prop('checked', true);
DupliJs.Tools.RefreshAuto();
<?php endif; ?>
<?php endif; ?>
// formatting log
$('#dupli-log-content').on('load', function() {
$('#dupli-log-content').contents().find("head")
.append($("<style type='text/css'>pre {line-height: 2;white-space: pre;}</style>"));
});
});
</script>
<form id="dup-form-logs" method="post" action="">
<input type="hidden" id="refresh" name="refresh" value="<?php echo ($refresh) ? 1 : 0 ?>" />
<input type="hidden" id="auto" name="auto" value="<?php echo ($auto) ? 1 : 0 ?>" />
<?php if (!$logfound) : ?>
<div style="padding:20px">
<h2>
<?php
esc_html_e(
"Log file not found or unreadable.",
'duplicator-pro'
);
?>
</h2>
<?php
printf(
esc_html__(
"Try to create a Backup, since no log files were found in the %s directory ending in *_log.txt",
'duplicator-pro'
),
'<b>' . esc_html(DUPLICATOR_SSDIR_NAME) . '</b>'
);
?>.<br /><br />
<?php
esc_html_e(
"Reasons for log file not showing",
'duplicator-pro'
);
?>: <br />
-
<?php
esc_html_e(
"The web server does not support returning .txt file extensions",
'duplicator-pro'
);
?>.<br />
-
<?php
printf(
esc_html__(
"The %s directory does not have the correct permissions to write files. Try setting the permissions to 755",
'duplicator-pro'
),
'<b>' . esc_html(DUPLICATOR_SSDIR_NAME) . '</b>'
);
?>. <br />
-
<?php
esc_html_e(
"The process that PHP runs under does not have enough permissions to create files.
Please contact your hosting provider for more details",
'duplicator-pro'
);
?>. <br />
</div>
<?php else : ?>
<table id="dupli-log-pnls">
<tr>
<td id="dupli-log-pnl-left">
<div class="name"><i class="fas fa-file-contract fa-fw"></i> <?php echo basename($logurl); ?></div>
<div class="opts">
<a href="javascript:void(0)" id="dup-options">
<?php esc_html_e("Options", 'duplicator-pro') ?> <i class="fa fa-angle-double-right"></i>
</a> &nbsp;
</div>
<br style="clear:both" />
<iframe id="dupli-log-content" src="<?php echo esc_url($logurl); ?>"></iframe>
</td>
<td id="dupli-log-pnl-right">
<h2><?php esc_html_e("Options", 'duplicator-pro') ?></h2>
<div class="dupli-opts-items">
<input
type="button"
class="button secondary hollow tiny margin-0"
id="dup-refresh"
value="<?php esc_attr_e("Refresh", 'duplicator-pro') ?>"> &nbsp;
<div style="display:inline-block;margin-top:1px;">
<input type='checkbox' id="dup-auto-refresh" class="margin-0" />
<label id="dup-auto-refresh-lbl" for="dup-auto-refresh">
<?php esc_html_e("Auto Refresh", 'duplicator-pro') ?> [<span id="dup-refresh-count"></span>]
</label>
</div>
</div>
<div class="dupli-log-hdr">
<?php esc_html_e('Trace Log:', 'duplicator-pro') ?> &nbsp;
<span style="font-size:11px; font-weight: normal">
<?php
$trace_on = StaticGlobal::getTraceLogEnabledOption();
$txt_clear_trace = esc_html__('Clear', 'duplicator-pro');
$txt_profile = '';
$html = "";
if (CapMng::can(CapMng::CAP_SETTINGS, false)) {
if (!$trace_on) {
$url = SettingsPageController::getInstance()->getTraceActionUrl(true);
$html = '<a href="' . esc_url($url) . '" target="_blank">' . __("Turn On", 'duplicator-pro') . $txt_profile . '</a>';
} else {
$url = SettingsPageController::getInstance()->getTraceActionUrl(false);
$html = '<a href="' . esc_url($url) . '" target="_blank">' . __("Turn Off", 'duplicator-pro') . $txt_profile . '</a>';
}
$html .= " | ";
}
if (CapMng::can(CapMng::CAP_CREATE, false)) {
$html .= "<a href='javascript:void(0)' onclick='DupliJs.UI.ClearTraceLog(1);'>{$txt_clear_trace}</a>";
}
echo $html;
?>
</span>
</div>
<div class="dupli-log-file-list">
<?php
$trace_log_filepath = DupLog::getTraceFilepath();
if (file_exists($trace_log_filepath)) {
$time = date('m/d/y h:i:s', @filemtime($trace_log_filepath));
} else {
$time = __('No trace log found', 'duplicator-pro');
}
$active_filename = basename($logurl_base);
$trace_log_url = ControllersManager::getMenuLink(
ControllersManager::TOOLS_SUBMENU_SLUG,
ToolsPageController::L2_SLUG_LOGS,
null,
['logname' => $trace_filename]
);
$is_trace_active = ($active_filename == $trace_filename);
echo ($is_trace_active)
? '<div class="dupli-trace-log-link-green"><i class="fa fa-caret-right"></i> ' . $time . '</div>'
: '<a href="' . esc_url($trace_log_url) . '">' . $time . '</a>';
?>
</div>
<br />
<div class="dupli-log-hdr">
<?php esc_html_e('Backup Logs', 'duplicator-pro'); ?>
<small><?php esc_html_e('Top 20', 'duplicator-pro'); ?></small>
</div>
<div class="dupli-log-file-list" style="white-space: nowrap">
<?php
$count = 0;
$active = basename($logurl_base);
foreach ($logs as $log) {
$time = date('m/d/y h:i:s', filemtime($log));
$name = sanitize_text_field(basename($log));
$url = ControllersManager::getMenuLink(
ControllersManager::TOOLS_SUBMENU_SLUG,
ToolsPageController::L2_SLUG_LOGS,
null,
['logname' => $name]
);
if ($name !== $trace_filename) {
$shortname = substr($name, 0, 15) . '***.log';
echo ($active == $name)
? '<span title="' . esc_attr($name) . '"><i class="fa fa-caret-right"></i> ' . $time . '-' . $shortname . '</span><br/>'
: '<a href="' . esc_url($url) . '" title="' . esc_attr($name) . '">' . $time . '-' . $shortname . '</a><br/>';
if ($count > 20) {
break;
}
$count++;
}
}
?>
</div>
</td>
</tr>
</table>
<?php endif; ?>
</form>

View File

@@ -0,0 +1,314 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Ajax\ServicesTools;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\CapMng;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Package\PackageUtils;
use Duplicator\Utils\Support\SupportToolkit;
use Duplicator\Views\UI\UiDialog;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$orphaned_filepaths = PackageUtils::getOrphanedPackageFiles();
$tplMng->render('admin_pages/diagnostics/purge_orphans_message');
$tplMng->render('admin_pages/diagnostics/clean_tmp_cache_message');
$tplMng->render('parts/migration/migration-message');
$resetPackagesDialog = new UiDialog();
$resetPackagesDialog->title = __('Reset Backups ?', 'duplicator-pro');
$resetPackagesDialog->message = __('This will clear and reset all of the current temporary Backups. Would you like to continue?', 'duplicator-pro');
$resetPackagesDialog->progressText = __('Resetting settings, Please Wait...', 'duplicator-pro');
$resetPackagesDialog->jsCallback = 'DupliJs.Pack.ResetPackages()';
$resetPackagesDialog->progressOn = false;
$resetPackagesDialog->okText = __('Yes', 'duplicator-pro');
$resetPackagesDialog->cancelText = __('No', 'duplicator-pro');
$resetPackagesDialog->closeOnConfirm = true;
$resetPackagesDialog->initConfirm();
$maxAjaxBackupsChecksMessage = sprintf(
__(
'Maximum number of backup checks reached (%d).
Process stopped. You can start the check again to update the remaining backups.',
'duplicator-pro'
),
ServicesTools::MAX_AJAX_BACKUP_REMOTE_STORAGE_CHECKS
);
?>
<form id="dup-tools-form" action="<?php echo ControllersManager::getCurrentLink(); ?>" method="post">
<h2>
<?php esc_html_e('General Tools', 'duplicator-pro'); ?>
</h2>
<hr>
<div class="dup-settings-wrapper">
<label class="lbl-larger">
<?php esc_html_e('Diagnostic Data', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<button
type="button"
id="download-diagnostic-data-btn"
class="button secondary small margin-bottom-0"
data-url="<?php echo esc_attr(SupportToolkit::getSupportToolkitDownloadUrl()); ?>"
<?php disabled(!SupportToolkit::isAvailable()); ?>>
<?php esc_html_e('Get Diagnostic Data', 'duplicator-pro'); ?>
</button>
<p class="description">
<?php if (SupportToolkit::isAvailable()) : ?>
<?php esc_html_e('Downloads a ZIP archive with all relevant diagnostic information.', 'duplicator-pro'); ?>
<?php else : ?>
<i class="fa fa-question-circle data-size-help" data-tooltip-title="Diagnostic Data" data-tooltip="
<?php esc_attr_e(
'It is currently not possible to download the diagnostic data from your system,
as the ZipArchive extensions is required to create it.',
'duplicator-pro'
); ?>" aria-expanded="false">
</i>
<?php printf(
esc_html__(
'If you were asked to include the diagnostic data to a support ticket,
please instead provide available %1$sBackup%2$s, %3$strace%4$s and debug logs.',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-do-i-read-the-package-build-log/') . '" target="_blank">',
'</a>',
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-do-i-read-the-package-trace-log/') . '" target="_blank">',
'</a>'
); ?>
<?php endif; ?>
</p>
</div>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<label class="lbl-larger">
<?php esc_html_e('Backups Cleanup', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<table class="dupli-reset-opts">
<tr valign="top">
<td>
<button
class="dupli-store-fixed-btn button secondary hollow tiny margin-bottom-0"
onclick="DupliJs.Pack.ConfirmResetPackages(); return false;">
<?php esc_attr_e('Delete Incomplete Backups', 'duplicator-pro'); ?>
</button>
</td>
<td>
<?php esc_html_e("Delete all unfinished Backups. So those with error and being created.", 'duplicator-pro'); ?>
<div class="maring-bottom-1">&nbsp;</div>
</td>
</tr>
<tr valign="top">
<td>
<button
id="check-remote-backups"
type="button"
class="dupli-store-fixed-btn button secondary hollow tiny margin-bottom-0">
<?php esc_html_e("Check Remote Backups", 'duplicator-pro'); ?>
</button>
</td>
<td>
<?php esc_html_e("Check if backups still exist in remote storages.", 'duplicator-pro'); ?>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e('Check Remote Backups', 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e('This will check if backups marked as stored in remote storages still exist in those storages.
If a backup is not found in a storage, it will be removed from that storage\'s list.', 'duplicator-pro'); ?>"
data-tooltip-width="400"></i>
<div class="maring-bottom-1">&nbsp;</div>
</td>
</tr>
<tr valign="top">
<td>
<a
type="button"
class="dupli-store-fixed-btn button secondary hollow tiny margin-bottom-0"
href="<?php echo esc_url(ToolsPageController::getInstance()->getPurgeOrphanActionUrl()); ?>">
<?php esc_html_e("Delete Backup Orphans", 'duplicator-pro'); ?>
</a>
</td>
<td>
<?php esc_html_e("Removes all Backup files NOT found in the Backups screen.", 'duplicator-pro'); ?>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Delete Backup Orphans", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tplMng->render('admin_pages/tools/parts/delete_backups_orphans_tooltip', [], false)); ?>"
data-tooltip-width="400"></i>
<div class="maring-bottom-1">&nbsp;</div>
</td>
</tr>
</table>
</div>
<?php } ?>
<label class="lbl-larger">
<?php esc_html_e('General Cleanup', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<table class="dupli-reset-opts">
<tr valign="top">
<td>
<button
type="button"
class="dupli-store-fixed-btn button secondary hollow tiny margin-bottom-0"
id="dupli-remove-installer-files-btn"
onclick="DupliJs.Tools.removeInstallerFiles()">
<?php esc_html_e("Delete Installation Files", 'duplicator-pro'); ?>
</button>
</td>
<td>
<?php esc_html_e("Removes all reserved installation files.", 'duplicator-pro'); ?>&nbsp;
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Delete Installation Files", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tplMng->render('admin_pages/tools/parts/delete_install_file_tooltip', [], false)); ?>"
data-tooltip-width="400"></i>
<div class="maring-bottom-1">&nbsp;</div>
</td>
</tr>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<tr>
<td>
<button
type="button"
class="dupli-store-fixed-btn button secondary hollow tiny margin-bottom-0"
onclick="DupliJs.Tools.ClearBuildCache()">
<?php esc_html_e("Clear Build Cache", 'duplicator-pro'); ?>
</button>
</td>
<td>
<?php esc_html_e('Removes all build data from:', 'duplicator-pro'); ?>&nbsp;
<b><?php echo esc_html(DUPLICATOR_SSDIR_PATH_TMP); ?></b>
</td>
</tr>
<?php } ?>
</table>
</div>
<?php $tplMng->render('admin_pages/tools/general_validator'); ?>
</div>
</form>
<?php
$deleteOptConfirm = new UiDialog();
$deleteOptConfirm->title = __('Are you sure you want to delete?', 'duplicator-pro');
$deleteOptConfirm->message = __('Delete this option value.', 'duplicator-pro');
$deleteOptConfirm->progressText = __('Removing, Please Wait...', 'duplicator-pro');
$deleteOptConfirm->jsCallback = 'DupliJs.Settings.DeleteThisOption(this)';
$deleteOptConfirm->initConfirm();
$removeCacheConfirm = new UiDialog();
$removeCacheConfirm->title = __('This process will remove all build cache files.', 'duplicator-pro');
$removeCacheConfirm->message = __('Be sure no Backups are currently building or else they will be cancelled.', 'duplicator-pro');
$removeCacheConfirm->progressText = $deleteOptConfirm->progressText;
$removeCacheConfirm->jsCallback = 'DupliJs.Tools.ClearBuildCacheRun()';
$removeCacheConfirm->initConfirm();
?>
<script>
jQuery(document).ready(function($) {
DupliJs.Tools.removeInstallerFiles = function() {
window.location = <?php echo json_encode(ToolsPageController::getInstance()->getCleanFilesAcrtionUrl()); ?>;
return false;
};
DupliJs.Tools.ClearBuildCache = function() {
<?php $removeCacheConfirm->showConfirm(); ?>
};
DupliJs.Tools.ClearBuildCacheRun = function() {
window.location = <?php echo json_encode(ToolsPageController::getInstance()->getRemoveCacheActionUrl()); ?>;
};
DupliJs.Pack.CheckRemoteBackups = function(processed = 0, displayMessage = true, callbackAfterCheck = null) {
if (processed >= <?php echo ServicesTools::MAX_AJAX_BACKUP_REMOTE_STORAGE_CHECKS; ?>) {
if (displayMessage) {
DupliJs.addAdminMessage("<?php echo esc_js($maxAjaxBackupsChecksMessage); ?>", 'warning');
}
DupliJs.Util.ajaxProgressHide();
return;
}
DupliJs.Util.ajaxProgressShow();
DupliJs.Util.ajaxWrapper({
action: 'duplicator_check_remote_backups',
nonce: "<?php echo esc_js(wp_create_nonce('duplicator_check_remote_backups')); ?>",
totalProcessed: processed
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData.processed > 0) {
DupliJs.Pack.CheckRemoteBackups(funcData.totalProcessed, displayMessage, callbackAfterCheck);
} else {
DupliJs.Util.ajaxProgressHide();
if (displayMessage) {
if (funcData.processed === -1) {
DupliJs.addAdminMessage(funcData.message, 'error');
} else {
DupliJs.addAdminMessage(funcData.message);
}
}
if (callbackAfterCheck) {
callbackAfterCheck();
}
}
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData && funcData.message) {
return funcData.message;
}
return data.message;
}, {
showProgress: false
}
);
};
$('#download-diagnostic-data-btn').click(function() {
window.location = $(this).data('url');
});
DupliJs.Pack.ConfirmResetPackages = function() {
<?php $resetPackagesDialog->showConfirm(); ?>
};
DupliJs.Pack.ResetPackages = function() {
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_reset_packages',
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_reset_packages')); ?>'
},
success: function(result) {
if (result.success) {
var message = '<?php esc_html_e('Backups successfully reset', 'duplicator-pro'); ?>';
DupliJs.addAdminMessage(message);
} else {
var message = '<?php esc_html_e('RESPONSE ERROR!', 'duplicator-pro'); ?>' + '<br><br>' + result.data.message;
DupliJs.addAdminMessage(message, 'error');
}
},
error: function(result) {
var message = '<?php esc_html_e('Ajax request error', 'duplicator-pro'); ?>';
DupliJs.addAdminMessage(message, 'error');
}
});
};
$('#check-remote-backups').click(function() {
DupliJs.Pack.CheckRemoteBackups();
});
});
</script>

View File

@@ -0,0 +1,158 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\CapMng;
use Duplicator\Views\UI\UiDialog;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
if (!CapMng::can(CapMng::CAP_CREATE, false)) {
return;
}
$confirm1 = new UiDialog();
$confirm1->title = __('Run Validator', 'duplicator-pro');
$confirm1->message = __('This will run the scan validation check. This may take several minutes. Do you want to Continue?', 'duplicator-pro');
$confirm1->progressOn = false;
$confirm1->jsCallback = 'DupliJs.Tools.runScanValidator()';
$confirm1->initConfirm();
?>
<label class="lbl-larger">
<?php esc_html_e('Scan Validator', 'duplicator-pro'); ?>
</label>
<div>
<button
id="scan-run-btn"
type="button"
class="button secondary small margin-bottom-0"
onclick="DupliJs.Tools.ConfirmScanValidator()">
<?php esc_html_e("Run Scan Integrity Validation", 'duplicator-pro'); ?>
</button>
<p class="description">
<?php esc_html_e('This utility identifies unreadable files and sys-links, potentially causing scanning issues.', 'duplicator-pro'); ?>
</p>
<script id="hb-template" type="text/x-handlebars-template">
<b><?php esc_html_e('Scan Paths:', 'duplicator-pro'); ?></b><br/>
{{#if scanData.scanPaths}}
{{#each scanData.scanPaths}}
&nbsp; &nbsp; {{@index}} : {{this}}<br/>
{{/each}}
{{else}}
<i><?php esc_html_e('Empty scan path', 'duplicator-pro'); ?></i> <br/>
{{/if}}
<br/>
<b><?php esc_html_e('Scan Results', 'duplicator-pro'); ?></b><br/>
<table>
<tr>
<td><b><?php esc_html_e('Files:', 'duplicator-pro'); ?></b></td>
<td>{{scanData.fileCount}} </td>
<td> &nbsp; </td>
<td><b><?php esc_html_e('Dirs:', 'duplicator-pro'); ?></b></td>
<td>{{scanData.dirCount}} </td>
</tr>
</table>
<br/>
<b><?php esc_html_e('Unreadable Dirs/Files:', 'duplicator-pro') ?></b> <br/>
{{#if scanData.unreadable}}
{{#each scanData.unreadable}}
&nbsp; &nbsp; {{@index}} : {{this}}<br/>
{{/each}}
{{else}}
<i><?php esc_html_e('No Unreadable items found', 'duplicator-pro'); ?></i> <br/>
{{/if}}
<br/>
<b><?php esc_html_e('Symbolic Links:', 'duplicator-pro'); ?></b> <br/>
{{#if scanData.symLinks}}
{{#each scanData.symLinks}}
&nbsp; &nbsp; {{@index}} : {{this}}<br/>
{{/each}}
{{else}}
<i><?php esc_html_e('No Sym-links found', 'duplicator-pro') ?></i> <br/>
<small> <?php esc_html_e("Note: Symlinks are not discoverable on Windows OS with PHP", 'duplicator-pro'); ?></small> <br/>
{{/if}}
<br/>
<b><?php esc_html_e('Directory Name Checks:', 'duplicator-pro') ?></b> <br/>
{{#if scanData.nameTestDirs}}
{{#each scanData.nameTestDirs}}
&nbsp; &nbsp; {{@index}} : {{this}}<br/>
{{/each}}
{{else}}
<i><?php esc_html_e('No name check warnings located for directory paths', 'duplicator-pro'); ?></i> <br/>
{{/if}}
<br/>
<b><?php esc_html_e('File Name Checks:', 'duplicator-pro') ?></b> <br/>
{{#if scanData.nameTestFiles}}
{{#each scanData.nameTestFiles}}
&nbsp; &nbsp; {{@index}} : {{this}}<br/>
{{/each}}
{{else}}
<i><?php esc_html_e('No name check warnings located for directory paths', 'duplicator-pro'); ?></i> <br/>
{{/if}}
<br/>
</script>
<div id="hb-result"></div>
</div>
<script>
jQuery(document).ready(function($) {
DupliJs.Tools.ConfirmScanValidator = function() {
<?php $confirm1->showConfirm(); ?>
}
//Run request to: admin-ajax.php?action=DUP_CTRL_Tools_runScanValidator
DupliJs.Tools.runScanValidator = function() {
tb_remove();
var data = {
action: 'duplicator_tool_scan_validator',
nonce: '<?php echo wp_create_nonce('duplicator_tool_scan_validator'); ?>',
'scan-recursive': 1
};
$('#hb-result').html('<?php esc_html_e("Scanning Environment... This may take a few minutes.", 'duplicator-pro'); ?>');
$('#scan-run-btn').html('<i class="fas fa-circle-notch fa-spin fa-fw"></i> <?php echo esc_js(__('Running Please Wait...', 'duplicator-pro')) ?>');
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: data,
success: function(data) {
DupliJs.Tools.IntScanValidator(data);
},
error: function(data) {
console.log(data)
},
done: function(data) {
console.log(data)
}
});
}
//Process Ajax Template
DupliJs.Tools.IntScanValidator = function(data) {
var template = $('#hb-template').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#hb-result').html(html);
$('#scan-run-btn').html('<?php esc_html_e("Run Scan Integrity Validation", 'duplicator-pro'); ?>');
}
});
</script>

View File

@@ -0,0 +1,37 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Package\PackageUtils;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$orphaned_filepaths = PackageUtils::getOrphanedPackageFiles();
if (count($orphaned_filepaths) > 0) {
esc_html_e(
"Clicking on the 'Delete Backup Orphans' button will remove the following files.
Orphaned files are typically generated from previous installations of Duplicator.
They may also exist if they did not get properly removed when they were selected from the main Backups screen.
The files below are no longer associated with active Backups in the main Backups screen and should be safe to remove.
<b>IMPORTANT: Don't click button if you want to retain any of the following files:</b>",
'duplicator-pro'
);
echo "<br/><br/>";
foreach ($orphaned_filepaths as $filepath) {
echo "<div class='failed'><i class='fa fa-exclamation-triangle'></i> " . esc_html($filepath) . " </div>";
}
} else {
esc_html_e('No orphaned Backup files found.', 'duplicator-pro');
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\MigrationMng;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<p>
<?php
esc_html_e(
"Clicking on the 'Remove Installation Files' button will remove the following installation files.
These files are typically from a previous Duplicator install.
If you are unsure of the source, please validate the files.
These files should never be left on production systems for security reasons.
Below is a list of all the installation files used by Duplicator.
Please be sure these are removed from your server.",
'duplicator-pro'
);
?>
<p>
<ul>
<?php
foreach (MigrationMng::getGenericInstallerFiles() as $instFileName) {
?>
<li>
<?php echo esc_html($instFileName); ?>
</li>
<?php
}
?>
</ul>

View File

@@ -0,0 +1,386 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Libs\Snap\SnapWP;
use Duplicator\Utils\Logging\PhpLogMng;
use Duplicator\Views\UI\UiDialog;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
if (isset($_POST['clear_log']) && $_POST['clear_log'] == 'true') {
PhpLogMng::clearLog();
}
$refresh = (isset($_POST['refresh']) && $_POST['refresh'] == 1) ? 1 : 0;
$auto = (isset($_POST['auto']) && $_POST['auto'] == 1) ? 1 : 0;
$filter = $_POST['filter'] ?? '';
$error = false;
$lines = 200;
$log_path = PhpLogMng::getPath(null, true);
$error_log = PhpLogMng::getLog($lines, "M d, H:i:s");
$log_path_size = 0;
if ($log_path !== false) {
$log_path_size = @filesize($log_path);
if (!is_readable($log_path)) {
$error = sprintf(
__(
"PHP error log is available on location %s but is not readable. Try setting the permissions to 755.",
'duplicator-pro'
),
'<b>' . esc_html($log_path) . '</b>'
);
} elseif ($error_log === false) {
if ($log_path > (PHP_INT_MAX / 2)) {
$error = sprintf(
__(
"PHP error log is available on location %1\$s but can't be read because file size is over %2\$s. You must open this file manualy.",
'duplicator-pro'
),
'<b>' . esc_html($log_path) . '</b>',
'<b>' . SnapString::byteSize($log_path_size) . '</b>'
);
} else {
$error = sprintf(
__(
"PHP error log is available on location %s but can't be read because some unexpected error.
Try to open file manually and investigate all problems what can cause this error.",
'duplicator-pro'
),
'<b>' . esc_html($log_path) . '</b>'
);
}
} else {
}
} else {
$error = __('This can be good for you because there is no errors.', 'duplicator-pro') . '<br><br>';
$error .= sprintf(
_x(
'But if you in any case experience some errors and not see log here,
that mean your error log file is placed on some unusual location or can\'t be created because some %1$s setup.
In that case you must open %2$s file and define %3$s or call your system administrator to setup it properly.',
'1 and 2 stand for the word "php.ini", 3 stands for the word "error_log"',
'duplicator-pro'
),
"<b><i>php.ini</i></b>",
"<b><i>php.ini</i></b>",
"<code>error_log</code>"
) .
'<br><br>';
$error .= sprintf(
__(
'It would be great if you define new error log path to be inside root of your WordPress
installation ( %1$s ) and name of file to be %2$s. That will solve this problem.',
'duplicator-pro'
),
'<i><b>' . SnapWP::getHomePath(true) . '</b></i>',
'<b>error.log</b>'
);
}
?>
<div id="dup-tool-php-logs-wrapper">
<?php if ($error) : ?>
<h2><?php
if ($log_path !== false) {
esc_html_e("Log file is found but have error or is unreadable", 'duplicator-pro');
} else {
esc_html_e("PHP error log not found", 'duplicator-pro');
}
?></h2>
<?php echo $error; ?>
<?php else : ?>
<table id="dupli-log-pnls">
<tr>
<td id="dupli-log-pnl-left">
<div class="name"><i class="fas fa-file-contract fa-fw"></i> <?php echo esc_html($log_path); ?></div>
<div class="opts">
<a href="javascript:void(0)" id="dup-options">
<?php esc_html_e('Options', 'duplicator-pro'); ?> <i class="fa fa-angle-double-right"></i>
</a> &nbsp;
</div>
<div id="tableContainer" class="tableContainer">
<table class="wp-list-table fixed striped" id="error-log">
<thead>
<tr>
<th scope="col" style="width: 10%; text-align: center"><?php esc_html_e('Date', 'duplicator-pro'); ?></th>
<th scope="col" style="width: 8%; text-align: center"><?php esc_html_e('Type', 'duplicator-pro'); ?></th>
<th scope="col" style="width: 34%;"><?php esc_html_e('Error', 'duplicator-pro'); ?></th>
<th scope="col" style="width: 30%;"><?php esc_html_e('File', 'duplicator-pro'); ?></th>
<th scope="col" style="width: 6%;"><?php esc_html_e('Line', 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody id="the-list" <?php echo (count($error_log) === 0) ? ' style="overflow: hidden;"' : ''; ?>>
<?php if (count($error_log) === 0) : ?>
<tr>
<td colspan="5">
<h3><?php esc_html_e('PHP Error Log is empty.', 'duplicator-pro'); ?></h3>
</td>
</tr>
<?php else : ?>
<?php foreach ($error_log as $line => $log) : ?>
<tr>
<td scope="col">
<b class="info" title="<?php echo date("Y-m-d H:i:s T (P)", strtotime($log['dateTime'])); ?>">
<?php echo esc_html($log['dateTime']); ?>
</b>
</td>
<td scope="col"><?php echo esc_html($log['type']); ?></td>
<td scope="col">
<?php echo esc_html($log['message']); ?>
<?php if (count($log['stackTrace']) > 0) : ?>
<ul>
<li class="title"><?php esc_html_e('Stack trace:', 'duplicator-pro'); ?></li>
<?php foreach ($log['stackTrace'] as $i => $trace) : ?>
<li><b>#<?php echo esc_html($i); ?></b> <?php echo esc_html($trace); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</td>
<td scope="col"><?php echo esc_html($log['file']); ?></td>
<td scope="col"><?php echo esc_html($log['line']); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</td>
<td id="dupli-log-pnl-right">
<h2><?php esc_html_e("Options", 'duplicator-pro') ?></h2>
<form id="dup-form-logs" method="post" action="">
<div class="dupli-opts-items">
<strong><?php esc_html_e('PHP Error Filter:', 'duplicator-pro'); ?></strong>
<select type="text" id="filter" name="filter" style="width:100%;">
<option value="">--- <?php esc_html_e('None', 'duplicator-pro'); ?> ---</option>
<?php
foreach (
[
'WARNING' => __('Warnings', 'duplicator-pro'),
'NOTICE' => __('Notices', 'duplicator-pro'),
'FATAL' => __('Fatal Error', 'duplicator-pro'),
'SYNTAX' => __('Syntax Error', 'duplicator-pro'),
'EXCEPTION' => __('Exceptions', 'duplicator-pro'),
] as $option => $name
) :
?>
<option value="<?php echo esc_attr($option); ?>" <?php echo ($filter == $option ? ' selected' : ''); ?>>
<?php echo esc_html($name); ?>
</option>
<?php endforeach; ?>
</select>
<hr>
<div class="horizontal-input-row">
<input
type="button"
class="button secondary hollow small" id="dup-refresh" value="<?php esc_attr_e("Refresh", 'duplicator-pro') ?>">
<input type="hidden" name="auto" id="auto" value="<?php echo $auto ? 1 : 0 ?>">
<input type='checkbox' id="dup-auto-refresh" />
<label id="dup-auto-refresh-lbl" for="dup-auto-refresh">
<?php esc_html_e("Auto Refresh", 'duplicator-pro') ?> [<span id="dup-refresh-count"></span>]
</label>
</div>
</div>
<?php if (isset($line) && $line + 30 > $lines) : ?>
<br>
<div style="color:#cc0000">
<i class="fa fa-info-circle"></i>
<?php
printf(
_x(
'You see only last %1$s logs inside %2$s file.',
'1 stands for the number of lines, 2 stands for the log file name',
'duplicator-pro'
),
$line,
esc_html(PhpLogMng::getFilename($log_path))
);
?>
</div>
<?php endif; ?>
<?php if (isset($line)) : ?>
<br>
<button class="button secondary hollow small" type="button" onclick="return DupliJs.Tools.ClearLog();">
<?php esc_html_e('Clear Log', 'duplicator-pro'); ?>
</button>
<?php endif; ?>
</form>
</td>
</tr>
</table>
<form id="dup-form-clear-log" method="post" action="">
<input type="hidden" id="clear_log" name="clear_log" value="true" />
</form>
</div>
<?php
$confirm1 = new UiDialog();
$confirm1->title = __('Clear PHP Log?', 'duplicator-pro');
$confirm1->message = __('Are you sure you want to clear PHP log??', 'duplicator-pro');
$confirm1->message .= '<br/>';
$confirm1->message .= '<small><i>' . __('Note: This action will delete all data and can\'t be stopped.', 'duplicator-pro') . '</i></small>';
$confirm1->progressText = __('Clear PHP log, Please Wait...', 'duplicator-pro');
$confirm1->jsCallback = 'DupliJs.Tools.ClearLogSubmit()';
$confirm1->initConfirm();
?>
<script>
jQuery(document).ready(function($) {
var duration = 9,
count = duration,
timerInterval;
DupliJs.Tools.errorFilter = function() {
// Declare variables
var input, filter, table, tr, td, i;
input = $("#filter");
filter = input.val().toUpperCase();
table = $("#error-log");
tr = table.find("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "table-row";
} else {
tr[i].style.display = "none";
}
}
}
}
$("#dup-refresh-count").html(duration);
function timer() {
count = count - 1;
$("#dup-refresh-count").html(count.toString());
if (!$("#dup-auto-refresh").is(":checked")) {
clearInterval(timerInterval);
$("#dup-refresh-count").text(count.toString().trim());
return;
}
if (count <= 0) {
count = duration + 1;
DupliJs.Tools.Refresh();
}
}
function startTimer() {
timerInterval = setInterval(timer, 1000);
}
DupliJs.Tools.ClearLogSubmit = function() {
$('#dup-form-clear-log').submit();
}
DupliJs.Tools.ClearLog = function() {
<?php $confirm1->showConfirm(); ?>
}
DupliJs.Tools.Refresh = function() {
$('#refresh').val(1);
$('#dup-form-logs').submit();
}
DupliJs.Tools.RefreshAuto = function() {
if ($("#dup-auto-refresh").is(":checked")) {
$('#auto').val(1);
startTimer();
} else {
$('#auto').val(0);
}
}
DupliJs.Tools.FullLog = function() {
var $panelL = $('#dupli-log-pnl-left');
var $panelR = $('#dupli-log-pnl-right');
if ($panelR.is(":visible")) {
$panelR.hide(400);
$panelL.css({
width: '100%'
});
} else {
$panelR.show(200);
$panelL.css({
width: '75%'
});
}
}
/* TABLE SIZE */
DupliJs.Tools.TableSize = function() {
var size = [],
offset = ($('#tableContainer').width() - $($('#error-log tbody tr').get(0)).width()) / ($('#error-log th').length);
$('#error-log th').each(function(i, $this) {
size[i] = $($this).width();
});
$('#error-log tr').each(function(x, $tr) {
$($tr).find('td').each(function(i, $this) {
$($this).width(size[i] + offset);
});
});
};
DupliJs.Tools.BoxHeight = function() {
var position = $('#tableContainer').position(),
winHeight = $(window).height(),
height = (winHeight - position.top - $("#wpfooter").height()) - 55;
if (height >= 500) {
$('#error-log tbody, div.tableContainer').height(height);
}
};
<?php if (count($error_log) > 0) : ?>
DupliJs.Tools.TableSize();
DupliJs.Tools.BoxHeight();
<?php endif; ?>
$(window).resize(function() {
<?php if (count($error_log) > 0) : ?>
DupliJs.Tools.TableSize();
DupliJs.Tools.BoxHeight();
<?php endif; ?>
});
$('#dup-options').click(function() {
DupliJs.Tools.FullLog();
DupliJs.Tools.TableSize();
});
$("#dup-refresh").click(DupliJs.Tools.Refresh);
$("#dup-auto-refresh").click(DupliJs.Tools.RefreshAuto);
$("#filter").on('input change select', function() {
DupliJs.Tools.errorFilter();
});
DupliJs.Tools.errorFilter();
<?php if ($auto) : ?>
$("#dup-auto-refresh").prop('checked', true);
DupliJs.Tools.RefreshAuto();
<?php endif; ?>
});
</script>
<?php endif;

View File

@@ -0,0 +1,64 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\RecoveryController;
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\ViewHelper;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var bool $blur
*/
$blur = $tplData['blur'];
$recoverPackage = RecoveryPackage::getRecoverPackage();
$recoverPackageId = RecoveryPackage::getRecoverPackageId();
$recoverablePackages = RecoveryPackage::getRecoverablesPackages();
?>
<h2 class="margin-bottom-0">
<?php ViewHelper::disasterIcon(); ?>&nbsp;<?php esc_html_e("Disaster Recovery", 'duplicator-pro'); ?>
</h2>
<hr/>
<p class="margin-bottom-1">
<?php esc_html_e("Quickly restore this site to a specific Backup in time.", 'duplicator-pro'); ?>
<span class="link-style dup-global-help">
<?php esc_html_e("Need more help?", 'duplicator-pro'); ?>
</span>
</p>
<div class="dupli-recovery-details-max-width-wrapper <?php echo ($blur ? 'dup-mock-blur' : ''); ?>" >
<?php if (RecoveryController::isDisallow()) { ?>
<p>
<?php esc_html_e("The import function is disabled", 'duplicator-pro'); ?>
</p>
<?php
return;
}
?>
<form id="dupli-recovery-form" method="post">
<?php
RecoveryController::renderRecoveryWidged([
'selector' => true,
'subtitle' => '',
'copyLink' => true,
'copyButton' => true,
'launch' => true,
'download' => true,
'info' => true,
]);
?>
</form>
</div>
<?php
$tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-scripts');

View File

@@ -0,0 +1,24 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="dupli-recovery-message" >
<p class="recovery-reset-message-error">
<i class="fa fa-exclamation-triangle"></i> <b><?php _e('Recovery Point reset issue!', 'duplicator-pro'); ?></b>
<p>
<p class="recovery-error-message">
<!-- here is set the message received from the server -->
</p>
</div>

View File

@@ -0,0 +1,7 @@
<?php
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
?><div class="dupli-recovery-message" >
<p class="recovery-reset-message-ok">
<?php _e('The Recovery Point has been reset, all previously copied Recovery URLs are no longer valid.', 'duplicator-pro'); ?>
</p>
</div>

View File

@@ -0,0 +1,37 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="dupli-recovery-message" >
<p class="recovery-set-message-error">
<i class="fa fa-exclamation-triangle"></i>&nbsp;<b><?php _e('Recovery Backup Issue Detected!', 'duplicator-pro'); ?></b>
<p>
<p class="recovery-error-message">
<!-- here is set the message received from the server -->
</p>
<p>
<?php
printf(
_x(
'For more information see %1$s[the documentation]%2$s',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-handle-recovery-install-setup-launch-issues" target="_blank">',
'</a>'
);
?>
</p>
</div>

View File

@@ -0,0 +1,19 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="dupli-recovery-message recovery-set-message-ok" >
<!-- message from js -->
</div>

View File

@@ -0,0 +1,103 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Controllers\RecoveryController;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var \Duplicator\Package\Recovery\RecoveryPackage $recoverPackage
*/
$recoverPackage = $tplData['recoverPackage'];
switch ($tplData['viewMode']) {
case RecoveryController::VIEW_WIDGET_NO_PACKAGE_SET:
?>
<div class="dupli-recovery-active-link-header">
<i class="fa-solid fa-house-fire main-icon"></i>
<div class="main-title">
<?php esc_html_e('Disaster Recovery Backup is Not Set', 'duplicator-pro'); ?>
</div>
<div class="main-subtitle margin-bottom-1">
<b><?php esc_html_e('Backup Age:', 'duplicator-pro'); ?></b>&nbsp;
<span class="dupli-recovery-status red"><?php _e('not set', 'duplicator-pro'); ?></span>
</div>
</div>
<div class="margin-bottom-1">
<?php
_e(
'A Disaster Recovery feature allows one to quickly restore the site to a prior state.
To use this, mark a Backup as the Disaster Recovery Backup, then copy and save off the associated Disaster Recovery URL.
Then, if a problem occurs, browse to the URL to launch a streamlined installer to quickly restore the site.',
'duplicator-pro'
);
?>
</div>
<?php
break;
case RecoveryController::VIEW_WIDGET_NOT_VALID:
?>
<div class="orangered margin-bottom-1">
<?php echo esc_html($tplData['importFailMessage']); ?>
</div>
<?php
break;
case RecoveryController::VIEW_WIDGET_VALID:
?>
<div class="dupli-recovery-active-link-wrapper" >
<div class="dupli-recovery-active-link-header" >
<i class="fas fa-house-fire main-icon"></i>
<div class="main-title" >
<?php _e('Disaster Recovery Backup is Set', 'duplicator-pro'); ?>
</div>
<div class="main-subtitle margin-bottom-1" >
<b><?php esc_html_e('Backup Age:', 'duplicator-pro'); ?></b>&nbsp;
<span class="dupli-recovery-status green">
<?php echo $recoverPackage->getPackageLife('human'); ?>
</span>
</div>
</div>
<?php if (strlen($tplData['subtitle'])) { ?>
<p>
<?php echo $tplData['subtitle']; ?>
</p>
<?php } ?>
<?php if ($tplData['displayInfo']) { ?>
<div class="dupli-recovery-package-info margin-bottom-1" >
<table>
<tbody>
<tr>
<td><?php _e('Name', 'duplicator-pro'); ?>:</td>
<td><b><?php echo esc_html($recoverPackage->getPackageName()); ?></b></td>
</tr>
<tr>
<td><?php _e('Date', 'duplicator-pro'); ?>:</td>
<td><b><?php echo esc_html($recoverPackage->getCreated()); ?></b></td>
</tr>
</tbody>
</table>
</div>
<?php
}
?>
</div>
<?php
break;
default:
?>
<p class="orangered">
<?php echo __('Invalid view mode.', 'duplicator-pro'); ?>
</p>
<?php
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\ViewHelper;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?Duplicator\Package\Recovery\RecoveryPackage $recoverPackage
*/
$recoverPackage = $tplData['recoverPackage'];
$installerLink = ($recoverPackage instanceof RecoveryPackage) ? $recoverPackage->getInstallLink() : '';
$disabledClass = empty($installerLink) ? 'disabled' : '';
if ($tplData['displayCopyLink']) {
$toolTipContent = __(
'The recovery point URL is the link to the recovery point Backup installer.
The link will run the installer wizard used to re-install and recover the site.
Copy this link and keep it in a safe location to easily restore this site.',
'duplicator-pro'
);
$toolTipContent .= '<br><br><b>';
$toolTipContent .= __('This URL is valid until another recovery point is set.', 'duplicator-pro');
$toolTipContent .= '</b>';
?>
<label>
<i class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Recovery Point URL", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($toolTipContent); ?>"
>
</i>
<b><?php _e('Step 2 ', 'duplicator-pro'); ?>:</b> <i><?php _e('Copy Recovery URL &amp; Store in Safe Place', 'duplicator-pro'); ?></i>
</label>
<div class="copy-link <?php echo $disabledClass; ?>"
data-dup-copy-value="<?php echo esc_url($installerLink); ?>"
data-dup-copy-title="<?php _e("Copy Recovery URL to clipboard", 'duplicator-pro'); ?>"
data-dup-copied-title="<?php _e("Recovery URL copied to clipboard", 'duplicator-pro'); ?>" >
<div class="content" >
<?php echo empty($installerLink) ? __('Please set the Recovery Point to generate the Recovery URL', 'duplicator-pro') : $installerLink; ?>
</div>
<i class="far fa-copy copy-icon"></i>
</div>
<?php } ?>
<div class="dupli-recovery-buttons" >
<?php
if ($tplData['displayLaunch']) { ?>
<a href="<?php echo esc_url($installerLink); ?>"
class="button primary hollow dupli-launch small <?php echo $disabledClass; ?>" target="_blank"
title="<?php _e('Initiates system recovery using the Recovery Point URL.', 'duplicator-pro'); ?>"
>
<?php ViewHelper::restoreIcon(); ?>&nbsp;<?php _e('Restore Backup', 'duplicator-pro'); ?>
</a>
<?php
}
if ($tplData['displayDownload']) {
$title = __(
'This button downloads a recovery launcher that allows you to perform the recovery with a simple click of the downloaded file.',
'duplicator-pro'
);
?>
<button
type="button"
class="button primary hollow small dupli-recovery-download-launcher <?php echo $disabledClass; ?>"
title="<?php echo esc_attr($title); ?>"
>
<i class="fa fa-rocket" ></i>&nbsp;<?php _e('Download Launcher', 'duplicator-pro'); ?>
</button>
<?php
}
if ($tplData['displayCopyButton']) {
?>
<button type="button" class="button primary small hollow dupli-recovery-copy-url <?php echo $disabledClass; ?>"
data-dup-copy-value="<?php echo $installerLink; ?>"
data-dup-copy-title="<?php _e("Copy Recovery URL to clipboard", 'duplicator-pro'); ?>"
data-dup-copied-title="<?php _e("Recovery URL copied to clipboard", 'duplicator-pro'); ?>" >
<i class="far fa-copy copy-icon"></i>&nbsp;<?php _e('Copy LINK', 'duplicator-pro'); ?>
</button>
<?php
}
?>
</div>

View File

@@ -0,0 +1,237 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<script>
DupliJs.Pack.SetRecoveryPoint = function (packageId, callbackOnSuccess, callbackOnError, topHeaderMessage) {
topHeaderMessage = (typeof topHeaderMessage !== 'undefined') ? topHeaderMessage : true;
let okMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-set-ok', [], false)); ?>;
let errorMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-set-error', [], false)); ?>;
DupliJs.Pack.removeRecoveryMessages();
DupliJs.Util.ajaxWrapper(
{
action: 'duplicator_set_recovery',
recovery_package: packageId,
fromPageTab: <?php echo json_encode(\Duplicator\Core\Controllers\ControllersManager::getUniqueIdOfCurrentPage()); ?>,
nonce: '<?php echo wp_create_nonce('duplicator_set_recovery'); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
if (topHeaderMessage) {
DupliJs.addAdminMessage(okMsgContent, 'notice', {
updateCallback: function (msgNode) {
msgNode.find('.recovery-set-message-ok').html(funcData.adminMessage);
DuplicatorTooltip.reload();
msgNode.find('.dupli-recovery-download-launcher').click(function () {
DupliJs.Pack.downloadLauncher();
});
}
});
}
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData, data, textStatus, jqXHR);
}
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(errorMsgContent, 'error', {
'updateCallback': function (msgNode) {
msgNode.find('.recovery-error-message').html(data.message);
}
});
if (typeof callbackOnError === "function") {
callbackOnError(funcData, data, textStatus, jqXHR);
}
return '';
}
);
};
DupliJs.Pack.ResetRecoveryPoint = function (callbackOnSuccess) {
let okMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-reset-ok', [], false)); ?>;
let errorMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-reset-error', [], false)); ?>;
DupliJs.Pack.removeRecoveryMessages();
DupliJs.Util.ajaxWrapper(
{
action: 'duplicator_reset_recovery',
nonce: '<?php echo wp_create_nonce('duplicator_reset_recovery'); ?>',
fromPageTab: <?php echo json_encode(\Duplicator\Core\Controllers\ControllersManager::getUniqueIdOfCurrentPage()); ?>,
},
function (result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(okMsgContent, 'notice');
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData, data, textStatus, jqXHR);
}
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(errorMsgContent, 'error', {
'updateCallback': function (msgNode) {
msgNode.find('.recovery-error-message').html(data.message);
}
});
return '';
}
);
};
DupliJs.Pack.UpdatgeRecoveryWidget = function (callbackOnSuccess) {
let okMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-reset-ok', [], false)); ?>;
let errorMsgContent = <?php echo json_encode($tplMng->render('admin_pages/tools/recovery/widget/recovery-message-reset-error', [], false)); ?>;
DupliJs.Pack.removeRecoveryMessages();
DupliJs.Util.ajaxWrapper(
{
action: 'duplicator_get_recovery_widget',
nonce: '<?php echo wp_create_nonce('duplicator_get_recovery_widget'); ?>',
fromPageTab: <?php echo json_encode(\Duplicator\Core\Controllers\ControllersManager::getUniqueIdOfCurrentPage()); ?>,
},
function (result, data, funcData, textStatus, jqXHR) {
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData, data, textStatus, jqXHR);
}
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
return <?php json_encode(__('Can\'t update recovery widget', 'duplicator-pro')); ?>;
}
);
};
DupliJs.Pack.removeRecoveryMessages = function () {
jQuery('#wpcontent .dupli-recovery-message').closest('.notice').remove();
};
DupliJs.Pack.SetRecoveryPackageDetails = function (wrapper, details, setColor) {
const setDelayAnimation = 1000;
const setDurationAnimationStart = 500;
const setDurationAnimationEnd = 1000;
let newDetails = jQuery(details);
wrapper.replaceWith(newDetails);
wrapper = newDetails;
wrapper.closest('.dupli-import-box').find('.box-title .badge').each(function () {
if (wrapper.find('.dupli-recovery-active-link-header .dupli-recovery-status').hasClass('green')) {
jQuery(this).removeClass('badge-warn').addClass('badge-pass').text('<?php echo esc_js(__('Good', 'duplicator-pro')) ?>');
} else {
jQuery(this).removeClass('badge-pass').addClass('badge-warn').text('<?php echo esc_js(__('Notice', 'duplicator-pro')) ?>');
}
});
wrapper.find('.dupli-recovery-point-selector-area select, .dupli-recovery-point-actions .copy-link')
.stop()
.animate({
backgroundColor: setColor
}, setDurationAnimationStart)
.delay(setDelayAnimation)
.animate({
backgroundColor: "transparent"
}, setDurationAnimationEnd);
wrapper.find('.dupli-recovery-point-details')
.stop()
.css({
'outline': '5px solid transparent',
'outline-offset': '5px'
})
.animate({
outlineColor: setColor
}, setDurationAnimationStart)
.delay(setDelayAnimation)
.animate({
outlineColor: "transparent",
'outline-width': '0',
'outline-offset': '0'
}, setDurationAnimationEnd);
DupliJs.Pack.initRecoveryWidget(wrapper);
};
DupliJs.Pack.downloadLauncher = function () {
DupliJs.Util.ajaxWrapper(
{
action: 'duplicator_disaster_launcher_download',
nonce: '<?php echo wp_create_nonce('duplicator_disaster_launcher_download'); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
DupliJs.downloadContentAsfile(funcData.fileName, funcData.fileContent, 'text/html');
} else {
DupliJs.addAdminMessage(funcData.message, 'error');
}
return '';
}
);
};
DupliJs.Pack.initRecoveryWidget = function (widgetWrapper) {
widgetWrapper.find('.recovery-reset').off().click(function () {
DupliJs.Pack.ResetRecoveryPoint(function (funcData, data, textStatus, jqXHR) {
widgetWrapper.find('.recovery-select').val('');
DupliJs.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
});
});
widgetWrapper.find('.recovery-set').off().click(function () {
let packageId = widgetWrapper.find('.recovery-select').val();
if (!packageId) {
DupliJs.Pack.ResetRecoveryPoint(function (funcData, data, textStatus, jqXHR) {
DupliJs.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
});
} else {
DupliJs.Pack.SetRecoveryPoint(packageId,
function (funcData, data, textStatus, jqXHR) {
DupliJs.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
},
function (funcData, data, textStatus, jqXHR) {
widgetWrapper.find('.recovery-select').val('');
DupliJs.Pack.SetRecoveryPackageDetails(widgetWrapper, '<p class="red" >' + data.message + '</span>', '#fcc3bd');
},
false);
}
});
DuplicatorTooltip.reload();
widgetWrapper.find('.dupli-recovery-windget-refresh').off().click(function () {
DupliJs.Pack.UpdatgeRecoveryWidget(function (funcData, data, textStatus, jqXHR) {
DupliJs.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.widget, '#e1f5c1');
});
});
widgetWrapper.find('.dupli-recovery-download-launcher').off().click(function () {
DupliJs.Pack.downloadLauncher();
});
};
jQuery(document).ready(function ($)
{
$('.dupli-recovery-widget-wrapper').each(function () {
let widgetWrapper = jQuery(this);
DupliJs.Pack.initRecoveryWidget(widgetWrapper);
});
});
</script>

View File

@@ -0,0 +1,111 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var Duplicator\Package\Recovery\RecoveryPackage $recoverPackage
*/
$recoverPackage = $tplData['recoverPackage'];
$packagesURL = PackagesPageController::getInstance()->getPageUrl();
?>
<div class="dupli-recovery-point-selector">
<?php if (empty($tplData['recoverablePackages'])) { ?>
<div class="dupli-notice-details">
<div class="margin-bottom-1" >
<b><?php _e('Would you like to create a Recovery Point before running this import?', 'duplicator-pro'); ?></b>
</div>
<b><?php _e('How to create:', 'duplicator-pro'); ?></b>
<ol class="dupli-simple-style-list" >
<li>
<?php
printf(
esc_html_x(
'Open the %1$sBackups screen%2$s and create a valid recovery Backup.',
'1 and 2 are opening and closing anchor or link tags',
'duplicator-pro'
),
'<a href="' . esc_url($packagesURL) . '" target="_blank">',
'</a><i class="fas fa-external-link-alt fa-small" ></i>'
);
?>
</li>
<li>
<?php _e('On the Backups screen click the Backup\'s Hamburger menu and select "Set Recovery Point".', 'duplicator-pro'); ?>
</li>
<li>
<?php
printf(
esc_html_x(
'%1$sRefresh%2$s this page to show and choose the recovery point.',
'1 and 2 are opening and closing span tags',
'duplicator-pro'
),
'<span class="dupli-recovery-windget-refresh link-style">',
'</span>'
);
?>
</li>
</ol>
</div>
<?php } else {
$tooltipContent = __(
'A Recovery Point allows one to quickly restore the site to a prior state.
To use this, mark a Backup as the Recovery Point, then copy and save off the associated URL.
Then, if a problem occurs, browse to the URL to launch a streamlined installer to quickly restore the site.',
'duplicator-pro'
);
?>
<div class="dupli-recovery-point-selector-area-wrapper" >
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<span class="dupli-opening-packages-windows" >
<a href="<?php echo esc_url($packagesURL); ?>" >[<?php _e('Create New', 'duplicator-pro'); ?>]</a>
</span>
<?php } ?>
<label>
<i class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Choose Recovery Point Archive", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltipContent); ?>">
</i>
<b><?php _e('Step 1 ', 'duplicator-pro'); ?>:</b> <i><?php _e('Choose Recovery Point Archive', 'duplicator-pro'); ?></i>
</label>
<div class="dupli-recovery-point-selector-area">
<select class="recovery-select" name="recovery_package" >
<option value=""> -- <?php _e('Not selected', 'duplicator-pro'); ?> -- </option>
<?php
$currentDay = null;
foreach ($tplData['recoverablePackages'] as $package) {
$packageDay = date("Y/m/d", strtotime($package['created']));
if ($packageDay != $currentDay) {
if (!is_null($currentDay)) {
?>
</optgroup>
<?php } ?>
<optgroup label="<?php echo esc_attr($packageDay); ?>">
<?php
$currentDay = $packageDay;
}
?>
<option value="<?php echo $package['id']; ?>" <?php selected($tplData['recoverPackageId'], $package['id']) ?>>
<?php echo '[' . $package['created'] . '] ' . $package['name']; ?>
</option>
<?php } ?>
</optgroup>
</select>
<button type="button" class="button secondary hollow small recovery-reset" ><?php echo _e('Reset', 'duplicator-pro'); ?></button>
<button type="button" class="button primary small recovery-set" ><?php echo _e('Set', 'duplicator-pro'); ?></button>
</div>
</div>
<?php } ?>
</div>

View File

@@ -0,0 +1,31 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="dupli-recovery-widget-wrapper" >
<?php if ($tplData['displayDetails']) { ?>
<div class="dupli-recovery-point-details margin-bottom-1">
<?php $tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-details', $tplData); ?>
</div>
<?php } ?>
<?php if ($tplData['selector']) {
$tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-selector', $tplData);
} ?>
<div class="dupli-recovery-point-actions">
<?php if ($tplData['recoverablePackages']) {
$tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-link-actions', $tplData);
} ?>
</div>
</div>

View File

@@ -0,0 +1,42 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Libs\Snap\SnapUtil;
use Duplicator\Package\BuildRequirements;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
ob_start();
SnapUtil::phpinfo();
$serverinfo = preg_replace('/.*<body>(.*?)<\/body>.*/s', '$1', ob_get_clean());
?>
<div class="dup-tool-server-info">
<h2>
<?php esc_html_e('Server Settings', 'duplicator-pro'); ?>
</h2>
<hr>
<?php
$tplMng->render(
'parts/tools/server_settings_table',
[
'serverSettings' => BuildRequirements::getServerSettingsData(),
]
);
?>
<hr>
<div id='dupli-phpinfo'>
<?php echo $serverinfo; ?>
</div>
</div>