first commit

This commit is contained in:
Roman Pyrih
2026-04-03 10:22:35 +02:00
commit 5de35e358d
8424 changed files with 2907254 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<?php
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
?><div class="dup-pro-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="dup-pro-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,23 @@
<?php
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
?><div class="dup-pro-recovery-message" >
<p class="recovery-set-message-error">
<i class="fa fa-exclamation-triangle"></i>&nbsp;<b><?php _e('Recovery Package 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_PRO_DUPLICATOR_DOCS_URL . 'how-to-handle-recovery-install-setup-launch-issues" target="_blank">',
'</a>'
);
?>
</p>
</div>

View File

@@ -0,0 +1,6 @@
<?php
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
?><div class="dup-pro-recovery-message recovery-set-message-ok" >
<!-- message from js -->
</div>

View File

@@ -0,0 +1,112 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Controllers\RecoveryController;
use Duplicator\Libs\Snap\SnapIO;
/**
* passed values
*
* @var int $recoverPackageId
* @var array<int, array{id: int, created: string, nameHash: string, name: string}> $recoveablePackages
* @var bool $selector
* @var string $subtitle
* @var bool $displayCopyLink
* @var bool $displayCopyButton
* @var bool $displayLaunch
* @var bool $displayDownload
* @var bool $displayInfo
* @var string $viewMode
* @var string $importFailMessage
*/
/** @var \Duplicator\Package\Recovery\RecoveryPackage $recoverPackage */
switch ($viewMode) {
case RecoveryController::VIEW_WIDGET_NO_PACKAGE_SET:
?>
<div class="dup-pro-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="dup-pro-recovery-status red"><?php _e('not set', 'duplicator-pro'); ?></span>
</div>
</div>
<div class="margin-bottom-1">
<?php
_e(
'A Disaster Recovery feathure 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($importFailMessage); ?>
</div>
<?php
break;
case RecoveryController::VIEW_WIDGET_VALID:
?>
<div class="dup-pro-recovery-active-link-wrapper" >
<div class="dup-pro-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="dup-pro-recovery-status green">
<?php echo $recoverPackage->getPackageLife('human'); ?>
</span>
</div>
</div>
<?php if (strlen($subtitle)) { ?>
<p>
<?php echo $subtitle; ?>
</p>
<?php } ?>
<?php if ($displayInfo) { ?>
<div class="dup-pro-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,99 @@
<?php
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\ViewHelper;
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
* passed values
*
* @var ?RecoveryPackage $recoverPackage
* @var int $recoverPackageId
* @var array<int, array{id: int, created: string, nameHash: string, name: string}> $recoveablePackages
* @var bool $selector
* @var string $subtitle
* @var bool $displayCopyLink
* @var bool $displayCopyButton
* @var bool $displayLaunch
* @var bool $displayDownload
* @var bool $displayInfo
* @var string $viewMode
* @var string $importFailMessage
*/
if (empty($recoveablePackages)) {
return;
}
$installerLink = ($recoverPackage instanceof RecoveryPackage) ? $recoverPackage->getInstallLink() : '';
$disabledClass = empty($installerLink) ? 'disabled' : '';
if ($displayCopyLink) {
$toolTipContent = __(
'The recovery point URL is the link to the recovery point package 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="fas fa-question-circle fa-sm"
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="dup-pro-recovery-buttons" >
<?php
if ($displayLaunch) { ?>
<a href="<?php echo esc_url($installerLink); ?>"
class="button button-primary dup-pro-launch <?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 ($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 button-primary dup-pro-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 ($displayCopyButton) {
?>
<button type="button" class="button button-primary dup-pro-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,245 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
use Duplicator\Libs\Snap\SnapIO;
?>
<script>
DupPro.Pack.SetRecoveryPoint = function (packageId, callbackOnSuccess, callbackOnError, topHeaderMessage) {
topHeaderMessage = (typeof topHeaderMessage !== 'undefined') ? topHeaderMessage : true;
let okMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-set-ok.php')); ?>;
let errorMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-set-error.php')); ?>;
DupPro.Pack.removeRecoveryMessages();
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_set_recovery',
recovery_package: packageId,
fromPageTab: <?php echo json_encode(\Duplicator\Core\Controllers\ControllersManager::getUniqueIdOfCurrentPage()); ?>,
nonce: '<?php echo wp_create_nonce('duplicator_pro_set_recovery'); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
if (topHeaderMessage) {
DupPro.addAdminMessage(okMsgContent, 'notice', {
updateCallback: function (msgNode) {
msgNode.find('.recovery-set-message-ok').html(funcData.adminMessage);
DuplicatorTooltip.reload();
msgNode.find('.dup-pro-recovery-download-launcher').click(function () {
DupPro.Pack.downloadLauncher();
});
}
});
}
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData, data, textStatus, jqXHR);
}
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
DupPro.addAdminMessage(errorMsgContent, 'error', {
'updateCallback': function (msgNode) {
msgNode.find('.recovery-error-message').html(data.message);
}
});
if (typeof callbackOnError === "function") {
callbackOnError(funcData, data, textStatus, jqXHR);
}
return '';
}
);
};
DupPro.Pack.ResetRecoveryPoint = function (callbackOnSuccess) {
let okMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-reset-ok.php')); ?>;
let errorMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-reset-error.php')); ?>;
DupPro.Pack.removeRecoveryMessages();
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_reset_recovery',
nonce: '<?php echo wp_create_nonce('duplicator_pro_reset_recovery'); ?>',
fromPageTab: <?php echo json_encode(\Duplicator\Core\Controllers\ControllersManager::getUniqueIdOfCurrentPage()); ?>,
},
function (result, data, funcData, textStatus, jqXHR) {
DupPro.addAdminMessage(okMsgContent, 'notice');
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData, data, textStatus, jqXHR);
}
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
DupPro.addAdminMessage(errorMsgContent, 'error', {
'updateCallback': function (msgNode) {
msgNode.find('.recovery-error-message').html(data.message);
}
});
return '';
}
);
};
DupPro.Pack.UpdatgeRecoveryWidget = function (callbackOnSuccess) {
let okMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-reset-ok.php')); ?>;
let errorMsgContent = <?php echo json_encode(SnapIO::getInclude(dirname(__FILE__) . '/recovery-message-reset-error.php')); ?>;
DupPro.Pack.removeRecoveryMessages();
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_get_recovery_widget',
nonce: '<?php echo wp_create_nonce('duplicator_pro_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')); ?>;
}
);
};
DupPro.Pack.removeRecoveryMessages = function () {
jQuery('#wpcontent .dup-pro-recovery-message').closest('.notice').remove();
};
DupPro.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('.dup-pro-import-box').find('.box-title .badge').each(function () {
if (wrapper.find('.dup-pro-recovery-active-link-header .dup-pro-recovery-status').hasClass('green')) {
jQuery(this).removeClass('badge-warn').addClass('badge-pass').text('Good');
} else {
jQuery(this).removeClass('badge-pass').addClass('badge-warn').text('Notice');
}
});
wrapper.find('.dup-pro-recovery-point-selector-area select, .dup-pro-recovery-point-actions .copy-link')
.stop()
.animate({
backgroundColor: setColor
}, setDurationAnimationStart)
.delay(setDelayAnimation)
.animate({
backgroundColor: "transparent"
}, setDurationAnimationEnd);
wrapper.find('.dup-pro-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);
DupPro.Pack.initRecoveryWidget(wrapper);
};
DupPro.Pack.downloadLauncher = function () {
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_disaster_launcher_download',
nonce: '<?php echo wp_create_nonce('duplicator_pro_disaster_launcher_download'); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
DupPro.downloadContentAsfile(funcData.fileName, funcData.fileContent, 'text/html');
} else {
DupPro.addAdminMessage(funcData.message, 'error');
}
return '';
}
);
};
DupPro.Pack.initRecoveryWidget = function (widgetWrapper) {
widgetWrapper.find('.recovery-reset').off().click(function () {
DupPro.Pack.ResetRecoveryPoint(function (funcData, data, textStatus, jqXHR) {
widgetWrapper.find('.recovery-select').val('');
DupPro.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
});
});
widgetWrapper.find('.recovery-set').off().click(function () {
let packageId = widgetWrapper.find('.recovery-select').val();
if (!packageId) {
DupPro.Pack.ResetRecoveryPoint(function (funcData, data, textStatus, jqXHR) {
DupPro.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
});
} else {
DupPro.Pack.SetRecoveryPoint(packageId,
function (funcData, data, textStatus, jqXHR) {
DupPro.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.packageDetails, '#e1f5c1');
},
function (funcData, data, textStatus, jqXHR) {
widgetWrapper.find('.recovery-select').val('');
DupPro.Pack.SetRecoveryPackageDetails(widgetWrapper, '<p class="red" >' + data.message + '</span>', '#fcc3bd');
},
false);
}
});
DuplicatorTooltip.reload();
widgetWrapper.find('.dup-pro-recovery-windget-refresh').off().click(function () {
DupPro.Pack.UpdatgeRecoveryWidget(function (funcData, data, textStatus, jqXHR) {
DupPro.Pack.SetRecoveryPackageDetails(widgetWrapper, funcData.widget, '#e1f5c1');
});
});
widgetWrapper.find('.dup-pro-recovery-download-launcher').off().click(function () {
DupPro.Pack.downloadLauncher();
});
};
jQuery(document).ready(function ($)
{
$('.dup-pro-recovery-widget-wrapper').each(function () {
let widgetWrapper = jQuery(this);
DupPro.Pack.initRecoveryWidget(widgetWrapper);
});
$('.dup-pro-open-help-link').click(function (event) {
event.stopPropagation();
let helpLink = $('#contextual-help-link');
$("html, body").animate({scrollTop: 0}, "fast");
if (helpLink.hasClass('screen-meta-active')) {
return;
}
helpLink.trigger('click');
});
});
</script>

View File

@@ -0,0 +1,107 @@
<?php
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
use Duplicator\Package\Recovery\RecoveryPackage;
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
* Variables
*
* @var RecoveryPackage $recoverPackage
* @var int $recoverPackageId
* @var array<int, array{id: int, created: string, nameHash: string, name: string}> $recoveablePackages
* @var bool $selector
* @var string $subtitle
* @var bool $displayCopyLink
* @var bool $displayCopyButton
* @var bool $displayLaunch
* @var bool $displayDownload
* @var bool $displayInfo
* @var string $viewMode
* @var string $importFailMessage
*/
if (!$selector) {
return;
}
$packagesURL = PackagesPageController::getInstance()->getPageUrl();
?>
<div class="dup-pro-recovery-point-selector">
<?php if (empty($recoveablePackages)) { ?>
<div class="dup-pro-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="dup-pro-simple-style-list" >
<li>
<?php _e('Open the ', 'duplicator-pro'); ?>
<a href="<?php echo esc_url($packagesURL); ?>" target="_blank">
<?php _e('packages screen', 'duplicator-pro'); ?>
</a>
<i class="fas fa-external-link-alt fa-small" ></i>
<?php _e('and create a valid recovery package.', 'duplicator-pro'); ?>
</li>
<li>
<?php _e('On the packages screen click the package\'s Hamburger menu and select "Set Recovery Point".', 'duplicator-pro'); ?>
</li>
<li>
<span class="dup-pro-recovery-windget-refresh link-style"><?php _e('Refresh', 'duplicator-pro'); ?></span>
<?php _e('this page to show and choose the recovery point', 'duplicator-pro'); ?>.
</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 package 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="dup-pro-recovery-point-selector-area-wrapper" >
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<span class="dup-pro-opening-packages-windows" >
<a href="<?php echo esc_url($packagesURL); ?>" >[<?php _e('Create New', 'duplicator-pro'); ?>]</a>
</span>
<?php } ?>
<label>
<i class="fas fa-question-circle fa-sm"
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="dup-pro-recovery-point-selector-area">
<select class="recovery-select" name="recovery_package" >
<option value=""> -- <?php _e('Not selected', 'duplicator-pro'); ?> -- </option>
<?php
$currentDay = null;
foreach ($recoveablePackages 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($recoverPackageId, $package['id']) ?>>
<?php echo '[' . $package['created'] . '] ' . $package['name']; ?>
</option>
<?php } ?>
</optgroup>
</select>
<button type="button" class="button recovery-reset" ><?php echo _e('Reset', 'duplicator-pro'); ?></button>
<button type="button" class="button button-primary recovery-set" ><?php echo _e('Set', 'duplicator-pro'); ?></button>
</div>
</div>
<?php } ?>
</div>

View File

@@ -0,0 +1,36 @@
<?php
use Duplicator\Package\Recovery\RecoveryPackage;
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
/**
* Variables
*
* @var RecoveryPackage $recoverPackage
* @var int $recoverPackageId
* @var array<int, array{id: int, created: string, nameHash: string, name: string}> $recoveablePackages
* @var bool $displayDetails
* @var bool $selector
* @var string $subtitle
* @var bool $displayCopyLink
* @var bool $displayCopyButton
* @var bool $displayLaunch
* @var bool $displayDownload
* @var bool $displayInfo
* @var string $viewMode
* @var string $importFailMessage
*/
?>
<div class="dup-pro-recovery-widget-wrapper" >
<?php if ($displayDetails) { ?>
<div class="dup-pro-recovery-point-details margin-bottom-1">
<?php require dirname(__FILE__) . '/recovery-widget-details.php'; ?>
</div>
<?php } ?>
<?php require dirname(__FILE__) . '/recovery-widget-selector.php'; ?>
<div class="dup-pro-recovery-point-actions">
<?php require dirname(__FILE__) . '/recovery-widget-link-actions.php'; ?>
</div>
</div>