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,9 @@
<Files *.php>
Order Deny,Allow
Deny from all
</Files>
<Files index.php>
Order Allow,Deny
Allow from all
</Files>

View File

@@ -0,0 +1,54 @@
<?php
/**
* Activity Log detail modal template
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
use Duplicator\Controllers\ActivityLogPageController;
use Duplicator\Models\ActivityLog\AbstractLogEvent;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$log = $tplMng->getDataValueObjRequired('log', AbstractLogEvent::class);
?>
<div class="dup-box dup-log-detail-modal margin-0">
<div class="dup-box-title">
<i class="fas fa-list-ul"></i> <?php echo esc_html($log->getTitle()); ?>
</div>
<div class="dup-box-panel">
<div class="dup-log-detail-meta">
<div class="dup-log-type-wrapper">
<strong><?php esc_html_e('Event:', 'duplicator-pro'); ?></strong>
<span class="dup-log-type">
<?php echo esc_html($log->getObjectTypeLabel()); ?>
</span>
</div>
<div class="dup-log-severity-wrapper">
<strong><?php esc_html_e('Type:', 'duplicator-pro'); ?></strong>
<span class="dup-log-severity <?php echo esc_attr(ActivityLogPageController::getSeverityClass($log->getSeverity())); ?>">
<?php echo esc_html($log->getSeverityLabel()); ?>
</span>
</div>
<div class="dup-log-date-wrapper">
<strong><?php esc_html_e('Activity Date:', 'duplicator-pro'); ?></strong>
<span class="dup-log-date">
<?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($log->getCreatedAt()))); ?>
</span>
</div>
</div>
<hr>
<div class="dup-log-detail-content">
<?php $log->detailHtml(); ?>
</div>
</div>
</div>

View File

@@ -0,0 +1,118 @@
<?php
/**
* Activity Log list template
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
use Duplicator\Ajax\ServicesActivityLog;
use Duplicator\Models\ActivityLog\AbstractLogEvent;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$page = $tplMng->getDataValueIntRequired('page');
$perPage = $tplMng->getDataValueInt('perPage', 50);
$totalItems = $tplMng->getDataValueIntRequired('totalItems');
$totalPages = $tplMng->getDataValueIntRequired('totalPages');
$logTypes = $tplMng->getDataValueArrayRequired('logTypes');
$severityLevels = $tplMng->getDataValueArrayRequired('severityLevels');
$filters = $tplMng->getDataValueArrayRequired('filters');
/** @var array<AbstractLogEvent> */
$logs = $tplMng->getDataValueArrayRequired('logs');
?>
<div class="wrap">
<?php $tplMng->render('admin_pages/activity_log/parts/toolbar'); ?>
<table class="widefat dup-table-list striped dup-activity-log-table">
<thead>
<tr>
<th scope="col" class="manage-column column-date"><?php esc_html_e('Date', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-severity"><?php esc_html_e('Type', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-type"><?php esc_html_e('Event', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-title"><?php esc_html_e('Title', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-description"><?php esc_html_e('Description', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-actions"><?php esc_html_e('Actions', 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody>
<?php if (empty($logs)) : ?>
<tr>
<td colspan="6" class="no-items">
<?php esc_html_e('No activity logs found.', 'duplicator-pro'); ?>
</td>
</tr>
<?php else : ?>
<?php foreach ($logs as $log) : ?>
<?php
$tplMng->render('admin_pages/activity_log/parts/table_row', ['log' => $log]);
?>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
<tfoot>
<tr>
<th scope="col" class="manage-column column-date"><?php esc_html_e('Date', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-severity"><?php esc_html_e('Type', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-type"><?php esc_html_e('Event', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-title"><?php esc_html_e('Title', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-description"><?php esc_html_e('Description', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-actions"><?php esc_html_e('Actions', 'duplicator-pro'); ?></th>
</tr>
</tfoot>
</table>
</div>
<script>
jQuery(document).ready(function($) {
DupliJs.ActivityLog = {
modalBox: null,
init: function() {
this.modalBox = new DuplicatorModalBox();
this.initEvents();
},
initEvents: function() {
$(document).on('click', '.dup-log-view-btn', function() {
const logId = $(this).data('log-id');
DupliJs.ActivityLog.openDetail(logId);
});
},
openDetail: function(logId) {
if (this.modalBox) {
this.modalBox.close();
}
DupliJs.Util.ajaxWrapper({
'action': '<?php echo esc_js(ServicesActivityLog::NONCE_GET_DETAIL); ?>',
'nonce': '<?php echo esc_js(wp_create_nonce(ServicesActivityLog::NONCE_GET_DETAIL)); ?>',
'log_id': logId
},
function(result, data, funcData) {
if (funcData.success) {
DupliJs.ActivityLog.modalBox.setOptions({
htmlContent: funcData.html,
closeInContent: true,
closeColor: '#000'
});
DupliJs.ActivityLog.modalBox.open();
} else {
DupliJs.addAdminMessage(funcData.message, 'error');
}
}
);
},
};
DupliJs.ActivityLog.init();
});
</script>

View File

@@ -0,0 +1,37 @@
<?php
/**
* Template for displaying backup log context in activity log error events
*
* @package Duplicator
* @copyright (c) 2025, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var string[] $logLines Array of log lines to display
* @var string $logUrl URL to the full log file
*/
$logLines = $tplMng->getDataValueArray('logLines', []);
$logUrl = $tplMng->getDataValueString('logUrl', '');
?>
<div class="dup-error-logs-section">
<div class="dup-error-logs-content">
<div class="dup-log-content">
<pre><?php echo esc_html(implode("\n", $logLines)); ?></pre>
</div>
<div class="dup-log-meta">
<?php printf(esc_html__('Showing %d lines from when error occurred', 'duplicator-pro'), count($logLines)); ?>
<?php if (!empty($logUrl)) : ?>
| <a href="<?php echo esc_url($logUrl); ?>" target="_blank"><?php esc_html_e('View complete log file', 'duplicator-pro'); ?></a>
<?php endif; ?>
</div>
</div>
</div>

View File

@@ -0,0 +1,83 @@
<?php
/**
* Activity Log list template
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
use Duplicator\Controllers\ActivityLogPageController;
use Duplicator\Models\ActivityLog\AbstractLogEvent;
use Duplicator\Models\ActivityLog\LogUtils;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<AbstractLogEvent> $logs Array of log events to display
*/
$severityLevels = LogUtils::getSeverityLabels();
/** @var array<AbstractLogEvent> */
$logs = $tplMng->getDataValueArrayRequired('logs');
?>
<table class="widefat dup-table-list striped dup-activity-log-table small">
<thead>
<tr>
<th scope="col" class="manage-column column-date"><?php esc_html_e('Date', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-severity"><?php esc_html_e('Type', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-title"><?php esc_html_e('Title', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-description"><?php esc_html_e('Description', 'duplicator-pro'); ?></th>
<th scope="col" class="manage-column column-duration"><?php esc_html_e('Duration', 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody>
<?php if (empty($logs)) : ?>
<tr>
<td colspan="5" class="no-items">
<?php esc_html_e('No activity logs found.', 'duplicator-pro'); ?>
</td>
</tr>
<?php else : ?>
<?php
$lastLogId = $logs[count($logs) - 1]->getId();
foreach ($logs as $currentLog) :
// Get execution time directly from current log using its atomic timing data
if (method_exists($currentLog, 'getExecutionTimeForPhase')) {
$durationFormatted = $currentLog->getExecutionTimeForPhase($currentLog->getSubType());
} else {
// Fallback for log types that don't support timing
$durationFormatted = __('N/A', 'duplicator-pro');
}
?>
<tr>
<td class="column-date">
<?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($currentLog->getCreatedAt()))); ?>
</td>
<td class="column-severity">
<span class="dup-log-severity <?php echo esc_attr(ActivityLogPageController::getSeverityClass($currentLog->getSeverity())); ?>">
<?php echo esc_html($severityLevels[$currentLog->getSeverity()] ?? __('Unknown', 'duplicator-pro')); ?>
</span>
</td>
<td class="column-title">
<?php echo esc_html($currentLog->getTitle()); ?>
</td>
<td class="column-description">
<?php echo wp_kses_post($currentLog->getShortDescription()); ?>
</td>
<td class="column-duration">
<?php if ($currentLog->getId() === $lastLogId) : ?>
<?php echo esc_html(sprintf(__('Total: %s', 'duplicator-pro'), $durationFormatted)); ?>
<?php else : ?>
<?php echo esc_html($durationFormatted); ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>

View File

@@ -0,0 +1,58 @@
<?php
/**
* Activity Log table row template
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
use Duplicator\Controllers\ActivityLogPageController;
use Duplicator\Models\ActivityLog\AbstractLogEvent;
defined("ABSPATH") || exit;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
*/
$log = $tplMng->getDataValueObjRequired('log', AbstractLogEvent::class);
$severityLevels = $tplMng->getDataValueArrayRequired('severityLevels');
$isMainEvent = ($log->getParentId() <= 0);
$rowClasses = [];
if ($isMainEvent) {
$rowClasses[] = 'main-event';
}
?>
<tr class="<?php echo esc_attr(implode(' ', $rowClasses)); ?>">
<td class="column-date">
<?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($log->getCreatedAt()))); ?>
</td>
<td class="column-severity">
<span class="dup-log-severity <?php echo esc_attr(ActivityLogPageController::getSeverityClass($log->getSeverity())); ?>">
<?php echo esc_html($severityLevels[$log->getSeverity()] ?? __('Unknown', 'duplicator-pro')); ?>
</span>
</td>
<td class="column-type">
<?php echo esc_html($log->getObjectTypeLabel()); ?>
</td>
<td class="column-title">
<span class="link-style dup-log-view-btn" data-log-id="<?php echo (int) $log->getId(); ?>">
<?php echo esc_html($log->getTitle()); ?>
</span>
</td>
<td class="column-description">
<?php echo wp_kses_post($log->getShortDescription()); ?>
</td>
<td class="column-actions">
<button type="button" class="button small secondary hollow margin-bottom-0 dup-log-view-btn" data-log-id="<?php echo (int) $log->getId(); ?>">
<?php esc_html_e('Details', 'duplicator-pro'); ?>
</button>
</td>
</tr>

View File

@@ -0,0 +1,123 @@
<?php
/**
* Activity Log toolbar template (filters and bulk actions)
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
defined("ABSPATH") || exit;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
*/
$page = $tplMng->getDataValueIntRequired('page');
$totalItems = $tplMng->getDataValueIntRequired('totalItems');
$totalPages = $tplMng->getDataValueIntRequired('totalPages');
$filters = $tplMng->getDataValueArrayRequired('filters');
$severityLevels = $tplMng->getDataValueArrayRequired('severityLevels');
$currentUrl = self_admin_url('admin.php?page=' . $_REQUEST['page']);
$showAllTitle = __(
'When enabled, shows a detailed view with all sub-events expanded. When disabled, shows a compact view with only main events.',
'duplicator-pro'
);
?>
<div class="tablenav top">
<form method="get" class="dup-activity-log-filters float-left" action="<?php echo esc_url($currentUrl); ?>">
<div class="dup-toolbar">
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>">
<input type="checkbox"
id="filter_show_all"
name="filter_show_all"
value="1"
title="<?php echo esc_attr($showAllTitle); ?>"
<?php checked(!empty($filters['show_all'])); ?>>
<label for="filter_show_all">
<?php esc_html_e('Detailed list', 'duplicator-pro'); ?>
</label>
<div class="separator"></div>
<input type="date"
id="filter_date_from"
name="filter_date_from"
title="<?php esc_attr_e('Filter by date from', 'duplicator-pro'); ?>"
value="<?php echo esc_attr($filters['date_from']); ?>">
<span> - </span>
<input type="date"
id="filter_date_to"
name="filter_date_to"
title="<?php esc_attr_e('Filter by date to', 'duplicator-pro'); ?>"
value="<?php echo esc_attr($filters['date_to']); ?>">
<div class="separator"></div>
<select id="filter_severity"
name="filter_severity"
title="<?php esc_attr_e('Filter by severity level', 'duplicator-pro'); ?>">
<option value="-1" <?php selected($filters['severity'], -1); ?>>
<?php esc_html_e('All Severities', 'duplicator-pro'); ?>
</option>
<?php foreach ($severityLevels as $severityValue => $severityLabel) : ?>
<option value="<?php echo esc_attr($severityValue); ?>" <?php selected($filters['severity'], $severityValue); ?>>
<?php echo esc_html($severityLabel); ?>
</option>
<?php endforeach; ?>
</select>
<div class="separator"></div>
<input type="submit"
name="filter_action"
class="button primary small"
value="<?php esc_attr_e('Filter', 'duplicator-pro'); ?>">
<a href="<?php echo esc_url($currentUrl); ?>"
class="button secondary small hollow">
<?php esc_html_e('Reset', 'duplicator-pro'); ?>
</a>
</div>
</form>
<?php if ($totalPages > 1) : ?>
<div class="tablenav-pages">
<span class="displaying-num">
<?php echo esc_html(sprintf(__('%d items', 'duplicator-pro'), $totalItems)); ?>
</span>
<span class="pagination-links">
<?php if ($page > 1) : ?>
<a class="first-page button" href="<?php echo esc_url(add_query_arg('paged', 1)); ?>">
<span aria-hidden="true">&laquo;</span>
</a>
<a class="prev-page button" href="<?php echo esc_url(add_query_arg('paged', $page - 1)); ?>">
<span aria-hidden="true">&lsaquo;</span>
</a>
<?php endif; ?>
<span class="paging-input">
<?php echo esc_html(sprintf(__('%1$d of %2$d', 'duplicator-pro'), $page, $totalPages)); ?>
</span>
<?php if ($page < $totalPages) : ?>
<a class="next-page button" href="<?php echo esc_url(add_query_arg('paged', $page + 1)); ?>">
<span aria-hidden="true">&rsaquo;</span>
</a>
<a class="last-page button" href="<?php echo esc_url(add_query_arg('paged', $totalPages)); ?>">
<span aria-hidden="true">&raquo;</span>
</a>
<?php endif; ?>
</span>
</div>
<?php endif; ?>
<br class="clear">
</div>

View File

@@ -0,0 +1,50 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Views\UserUIOptions;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$uiOpts = UserUIOptions::getInstance();
$perPage = $uiOpts->get(UserUIOptions::VAL_ACTIVITY_LOG_PER_PAGE);
?>
<fieldset class="screen-options margin-b-20px" >
<legend>
<?php esc_html_e('Pagination', 'duplicator-pro'); ?>
</legend>
<label for="activity_log_per_page" class="inline-display" >
<?php esc_html_e('Activity Logs Per Page', 'duplicator-pro'); ?>
</label>&nbsp;
<input
type="number"
step="1"
min="1"
max="999"
class="screen-per-page inline-display margin-0 width-small"
name="activity_log_per_page"
id="activity_log_per_page"
maxlength="3"
value="<?php echo esc_html($perPage); ?>"
>
</fieldset>
<input type="hidden" name="wp_screen_options[option]" value="activity_log_screen_options">
<input type="hidden" name="wp_screen_options[value]" value="val">
<input
type="submit"
name="screen-options-apply"
id="screen-options-apply"
class="button secondary hollow small margin-0"
value="Apply"
>

View File

@@ -0,0 +1,34 @@
<?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
*/
if (!isset($tplData['tmpCleanUpSuccess'])) {
return;
}
$messageClasses = [
'notice',
'dupli-admin-notice',
'is-dismissible',
'dupli-diagnostic-action-tmp-cache',
'notice-success',
];
?>
<div id="message" class="<?php echo esc_attr(implode(' ', $messageClasses)); ?>">
<p>
<?php esc_html_e('Build cache removed.', 'duplicator-pro'); ?>
</p>
</div>

View File

@@ -0,0 +1,53 @@
<?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
*/
if (!isset($tplData['purgeOrphansSuccess'])) {
return;
}
$messageClasses = [
'notice',
'dupli-admin-notice',
'is-dismissible',
'dupli-diagnostic-action-purge-orphans',
($tplData['purgeOrphansSuccess'] ? 'notice-success' : 'notice-error'),
];
?>
<div id="message" class="<?php echo esc_attr(implode(' ', $messageClasses)); ?>">
<p>
<?php esc_html_e('Cleaned up orphaned Backup files!', 'duplicator-pro'); ?>
</p>
<?php
foreach ($tplData['purgeOrphansFiles'] as $path => $deleted) {
if ($deleted) {
?>
<div class='success'>
<i class='fa fa-check'></i> <?php echo esc_html($path); ?>
</div>
<?php } else { ?>
<div class='failed'>
<i class='fa fa-exclamation-triangle'></i> <?php echo esc_html($path); ?>
</div>
<?php
}
}
?>
<p>
<i>
<?php esc_html_e('If any orphaned files didn\'t get removed then delete them manually', 'duplicator-pro') ?>.
</i>
</p>
</div>

View File

@@ -0,0 +1,26 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="wrap">
<h1>
<?php esc_html_e("Install Backup error", 'duplicator-pro'); ?>
</h1>
<p>
<?php esc_html_e("Error on Backup prepare, please go back and try again.", 'duplicator-pro'); ?>
</p>
</div>

View File

@@ -0,0 +1,65 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Package\Import\PackageImporter;
use Duplicator\Package\Recovery\RecoveryPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var PackageImporter $importObj
*/
$importObj = $tplData['importObj'];
/** @var string $iframeSrc */
$iframeSrc = $tplData['iframeSrc'];
$importFailMessage = '';
if (!$importObj->isImportable($importFailMessage)) {
?>
<div class="wrap dup-styles">
<h1>
<?php esc_html_e("Install Backup", 'duplicator-pro'); ?>
</h1>
<div class="dupli-import-installer-content-wrapper" >
<p class="orangered">
<?php echo esc_html($importFailMessage); ?>
</p>
</div>
</div>
<?php } else { ?>
<div id="dupli-import-installer-wrapper" class="dup-styles" >
<div id="dupli-import-installer-top-bar" class="dupli-recovery-details-max-width-wrapper" >
<a href="<?php echo esc_url(ImportPageController::getImportPageLink()); ?>" class="button secondary hollow small margin-bottom-0" >
<i class="fa fa-caret-left"></i> <?php esc_html_e("Back to Import", 'duplicator-pro'); ?>
</a>&nbsp;
<span class="link-style no-decoration recovery-copy-top-wrapper" >
<?php if (($recoverPackage = RecoveryPackage::getRecoverPackage()) !== false) { ?>
<span class="button secondary hollow small margin-bottom-0"
data-tooltip-placement="right"
data-dup-copy-value="<?php echo esc_url($recoverPackage->getInstallLink()); ?>"
data-dup-copy-title="<?php esc_attr_e("Copy Recovery URL to clipboard", 'duplicator-pro'); ?>"
data-dup-copied-title="<?php esc_attr_e("Recovery URL copied to clipboard", 'duplicator-pro'); ?>" >
<?php esc_html_e("Copy Recovery URL", 'duplicator-pro'); ?>
</span>
<?php } else { ?>
<span class="button secondary hollow disabled small margin-bottom-0">
<i class="fas fa-exclamation-circle"></i> <?php esc_html_e("Recovery Point Not Set", 'duplicator-pro'); ?>
</span>
<?php } ?>
</span>
</div>
<div id="dupli-import-installer-modal" class="no-display"></div>
<iframe id="dupli-import-installer-iframe" src="<?php echo esc_url($iframeSrc); ?>" ></iframe>
</div>
<?php
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\Controllers\ControllersManager;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$importSettingsUrl = $ctrlMng->getMenuLink(
ControllersManager::SETTINGS_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_IMPORT
);
?>
<div class="dupli-import-upload-message" >
<p class="import-upload-reset-message-error">
<i class="fa fa-exclamation-triangle"></i> <b><?php esc_html_e('UPLOAD FILE PROBLEM', 'duplicator-pro'); ?></b>
</p>
<p>
<?php esc_html_e('Error message:', 'duplicator-pro'); ?>&nbsp;
<b><span class="import-upload-error-message"><!-- here is set the message received from the server --></span></b>
</p>
<div><?php esc_html_e('Possible solutions:', 'duplicator-pro'); ?></div>
<ul class="dupli-simple-style-list" >
<li>
<?php esc_html_e('If you are using Server to Server transfer function make sure the URL is a valid URL', 'duplicator-pro'); ?>
</li>
<li>
<?php
printf(
esc_html_x(
'If you are using the upload function try to change the chunk size in %1$ssettings%2$s and try again',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url($importSettingsUrl) . '">',
'</a>'
);
?>
</li>
<li>
<?php
printf(
esc_html__('Upload the file via FTP/file manager to the "%s" folder and reload the page.', 'duplicator-pro'),
esc_html(DUPLICATOR_IMPORTS_PATH)
);
?>
</li>
</ul>
<p>
<b>
<?php
printf(
esc_html_x(
'For more information see %1$s[this FAQ item]%2$s',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-handle-import-install-upload-launch-issues') . '" target="_blank">',
'</a>'
);
?>
</b>
</p>
</div>

View File

@@ -0,0 +1,202 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Installer\Package\PComponents;
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Package\Create\BuildComponents;
use Duplicator\Package\Import\PackageImporter;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
/* passed values */
/** @var PackageImporter $importObj */
$importObj = $tplData['importObj'];
if (!$importObj instanceof PackageImporter) {
return;
}
?>
<div class="dupli-import-package-detail-content">
<?php
$errorMsg = '';
if (!$importObj->encryptCheck($errorMsg)) {
?>
<p class="maroon">
<b>
<i class="fas fa-exclamation-triangle"></i>
<?php
echo wp_kses(
$errorMsg,
[
'a' => [
'href' => [],
'target' => [],
],
]
);
?>
</b>
</p>
<?php
} elseif (!$importObj->passwordCheck()) {
?>
<p class="maroon">
<b><i class="fas fa-exclamation-triangle"></i> <?php esc_html_e('Valid password required', 'duplicator-pro'); ?></b>
</p>
<div class="dup-import-archive-password-request">
<input type="password" class="dup-import-archive-password" name="password" value="">
<button type="button" class="dup-import-set-archive-password button">
<?php esc_html_e('Submit', 'duplicator-pro'); ?>
</button>
</div>
<?php
} elseif (!$importObj->isImportable($importFailMessage)) {
?>
<p class="maroon">
<b>
<i class="fas fa-exclamation-triangle"></i>
<?php
echo wp_kses(
$importFailMessage,
[
'br' => [],
'a' => [
'href' => [],
'target' => [],
],
]
);
?>
</b>
</p>
<?php
} elseif ($importObj->haveImportWaring($importWarnMessage)) {
?>
<p class="gray">
<b><i class="fas fa-exclamation-triangle"></i> <?php echo wp_kses($importWarnMessage, ['br' => []]); ?></b>
</p>
<?php
} else {
?>
<p class="green">
<b>
<i class="fas fa-check-circle"></i>
<?php esc_html_e('This Backup is ready to install, click the continue button to proceed.', 'duplicator-pro'); ?>
</b><br />
<b><?php esc_html_e('The information below is related to the Backup and the source site where the Backup was created.', 'duplicator-pro'); ?></b>
</p>
<?php
}
if ($importObj->isValid()) {
?>
<ul class="no-bullet">
<li>
<span class="label title"><?php esc_html_e('Site Details:', 'duplicator-pro'); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('URL', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getHomeUrl()); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Path', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getHomePath()); ?></span>
</li>
<li>
<span class="label title"><?php esc_html_e('Versions:', 'duplicator-pro'); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Duplicator', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getDupVersion()); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('WordPress', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getWPVersion()); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('PHP', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getPhpVersion()); ?></span>
</li>
<?php if ($importObj->getPackageComponents() !== false) { ?>
<li>
<span class="label title"><?php esc_html_e('Backup components:', 'duplicator-pro'); ?></span>
</li>
<?php
$packComponents = $importObj->getPackageComponents();
foreach (BuildComponents::COMPONENTS_DEFAULT as $component) {
?>
<li>
<span class="label"><?php echo esc_html(BuildComponents::getLabel($component)); ?>:</span>
<span class="value">
<?php if (in_array($component, $packComponents)) { ?>
<i class="fas fa-check-circle green"></i> <?php esc_html_e('included', 'duplicator-pro'); ?>
<?php } else { ?>
<i class="fas fa-times-circle maroon"></i> <?php esc_html_e('excluded', 'duplicator-pro'); ?>
<?php } ?>
</span>
</li>
<?php } ?>
<?php } ?>
<li>
<span class="label title"><?php esc_html_e('Archive:', 'duplicator-pro'); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Created', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getCreated()); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Size', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html(SnapString::byteSize($importObj->getSize())); ?></span>
</li>
<?php if (!$importObj->isLite()) { ?>
<li>
<span class="label"><?php esc_html_e('Folders', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html(number_format($importObj->getNumFolders())); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Files', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html(number_format($importObj->getNumFiles())); ?></span>
</li>
<?php } ?>
<li>
<span class="label title"><?php esc_html_e('Database:', 'duplicator-pro'); ?></span>
</li>
<?php
if (
$importObj->getPackageComponents() === false ||
in_array(PComponents::COMP_DB, $importObj->getPackageComponents())
) {
?>
<li>
<span class="label"><?php esc_html_e('Size', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html($importObj->getDbSize()); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Tables', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo (int) $importObj->getNumTables(); ?></span>
</li>
<li>
<span class="label"><?php esc_html_e('Rows', 'duplicator-pro'); ?>:</span>
<span class="value"><?php echo esc_html(number_format($importObj->getNumRows())); ?></span>
</li>
<?php } else { ?>
<li>
<span class="label"><?php esc_html_e('Database', 'duplicator-pro'); ?>:</span>
<span class="value"><?php esc_html_e('Not Included', 'duplicator-pro'); ?></span>
</li>
<?php } ?>
</ul>
<?php } ?>
</div>

View File

@@ -0,0 +1,646 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Views\UI\UiDialog;
use Duplicator\Views\UI\UiMessages;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$packageDeteleConfirm = new UiDialog();
$packageDeteleConfirm->title = __('Delete Backup?', 'duplicator-pro');
$packageDeteleConfirm->wrapperClassButtons = 'dupli-dlg-import-detete-package-btns';
$packageDeteleConfirm->progressOn = false;
$packageDeteleConfirm->closeOnConfirm = true;
$packageDeteleConfirm->message = __('Are you sure you want to delete the selected Backup?', 'duplicator-pro');
$packageDeteleConfirm->jsCallback = 'DupliJs.ImportManager.removePackage()';
$packageDeteleConfirm->initConfirm();
$packageInvalidName = new UiMessages(
__(
'<b>Invalid archive name:</b> The archive name must follow the Duplicator Backup name pattern
e.g. BACKUP_NAME_[HASH]_[YYYYMMDDHHSS]_archive.zip (or with a .daf extension).
<br>Please make sure not to rename the archive after downloading it and try again!',
'duplicator-pro'
),
UiMessages::ERROR
);
$packageInvalidName->hide_on_init = true;
$packageInvalidName->is_dismissible = true;
$packageInvalidName->auto_hide_delay = 10000;
$packageInvalidName->initMessage();
$packageAlreadyExists = new UiMessages(
__('Archive file name already exists! <br>Please remove it and try again!', 'duplicator-pro'),
UiMessages::ERROR
);
$packageAlreadyExists->hide_on_init = true;
$packageAlreadyExists->is_dismissible = true;
$packageAlreadyExists->auto_hide_delay = 5000;
$packageAlreadyExists->initMessage();
$packageUploaded = new UiMessages(__('Backup uploaded', 'duplicator-pro'), UiMessages::NOTICE);
$packageUploaded->hide_on_init = true;
$packageUploaded->is_dismissible = true;
$packageUploaded->auto_hide_delay = 5000;
$packageUploaded->initMessage();
$packageCancelUpload = new UiMessages(__('Backup upload cancelled', 'duplicator-pro'), UiMessages::ERROR);
$packageCancelUpload->hide_on_init = true;
$packageCancelUpload->is_dismissible = true;
$packageCancelUpload->auto_hide_delay = 5000;
$packageCancelUpload->initMessage();
$packageRemoved = new UiMessages(__('Backup removed', 'duplicator-pro'), UiMessages::NOTICE);
$packageRemoved->hide_on_init = true;
$packageRemoved->is_dismissible = true;
$packageRemoved->auto_hide_delay = 5000;
$packageRemoved->initMessage();
$importChunkSize = ImportPageController::getChunkSize();
?><script>
jQuery(document).ready(function($) {
var uploadFileMessageContent = <?php $tplMng->renderJson('admin_pages/import/import-message-upload-error'); ?>;
DupliJs.ImportManager = {
uploaderWrapper: $('#dupli-import-upload-tabs-wrapper'),
uploaderDisabler: $('<div>'),
uploader: $('#dupli-import-upload-file'),
uploaderContent: $('#dupli-import-upload-file-content'),
packageRowTemplate: $('#dupli-import-row-template'),
packageRowNoFoundTemplate: $('#dupli-import-available-packages-templates .dupli-import-no-package-found'),
packagesAviable: $('#dupli-import-available-packages'),
packagesList: $('#dupli-import-available-packages .packages-list'),
packageRowUploading: null,
packageRowToDelete: null,
autoLaunchAfterUpload: false,
autoLaunchLink: false,
confirmLaunchLink: false,
startUpload: false,
lastUploadsTimes: [],
debug: true,
init: function() {
$('#dupli-import-instructions-toggle').click(function() {
$('#dupli-import-instructions-content').toggle(300);
})
DupliJs.ImportManager.uploaderWrapper.css('position', 'relative');
DupliJs.ImportManager.uploaderDisabler = $('<div>').css({
'position': 'absolute',
'top': 0,
'left': 0,
'width': '100%',
'height': '100%',
'z-index': '10',
'cursor': 'not-allowed',
'display': 'none'
});
DupliJs.ImportManager.uploaderDisabler.appendTo(DupliJs.ImportManager.uploaderWrapper);
DupliJs.ImportManager.uploader.upload({
autoUpload: true,
multiple: false,
maxSize: <?php echo empty($importChunkSize) ? (int) wp_max_upload_size() : 10737418240; ?>, //100GB get value from upload_max_filesize
maxConcurrent: 1,
maxFiles: 1,
postData: {
action: 'duplicator_import_upload',
nonce: <?php echo json_encode(wp_create_nonce('duplicator_import_upload')); ?>
},
chunkSize: <?php echo (int) $importChunkSize; ?>, // This is in kb
action: <?php echo json_encode(get_admin_url(null, 'admin-ajax.php')); ?>,
chunked: <?php echo empty($importChunkSize) ? 'false' : 'true'; ?>,
label: DupliJs.ImportManager.uploaderContent.parent().html(),
leave: '<?php echo esc_js(__('You have uploads pending, are you sure you want to leave this page?', 'duplicator-pro')); ?>'
})
.on("start.upload", DupliJs.ImportManager.onStart)
.on("complete.upload", DupliJs.ImportManager.onComplete)
.on("filestart.upload", DupliJs.ImportManager.onFileStart)
.on("fileprogress.upload", DupliJs.ImportManager.onFileProgress)
.on("filecomplete.upload", DupliJs.ImportManager.onFileComplete)
.on("fileerror.upload", DupliJs.ImportManager.onFileError)
.on("fileerror.chunkerror", DupliJs.ImportManager.onChunkError);
DupliJs.ImportManager.uploaderContent.remove();
DupliJs.ImportManager.uploaderContent = $('#dupli-import-upload-file #dupli-import-upload-file-content');
DupliJs.ImportManager.initPageButtons();
DupliJs.ImportManager.checkMaxUploadedFiles();
DupliJs.ImportManager.packagesList.on('click', '.dupli-import-action-remove', function(event) {
event.stopPropagation();
DupliJs.ImportManager.packageRowToDelete = $(this).closest('.dupli-import-package');
<?php $packageDeteleConfirm->showConfirm(); ?>
return false;
});
DupliJs.ImportManager.packagesList.on('click', '.dupli-import-action-package-detail-toggle', function(event) {
event.stopPropagation();
let button = $(this);
let details = button.closest('.dupli-import-package').find('.dupli-import-package-detail');
if (details.hasClass('no-display')) {
button.find('.fa').removeClass('fa-caret-down').addClass('fa-caret-up');
details.removeClass('no-display');
} else {
button.find('.fa').removeClass('fa-caret-up').addClass('fa-caret-down');
details.addClass('no-display');
}
return false;
});
DupliJs.ImportManager.packagesList.on('click', '.dupli-import-action-cancel-upload', function(event) {
event.stopPropagation();
DupliJs.ImportManager.abortUpload();
<?php $packageCancelUpload->showMessage(); ?>
return false;
});
DupliJs.ImportManager.packagesList.on('click', '.dupli-import-action-install', function(event) {
event.stopPropagation();
DupliJs.ImportManager.confirmLaunchLink = $(this).data('install-url');
$('#dupli-import-phase-one').addClass('no-display');
$('#dupli-import-phase-two').removeClass('no-display');
return false;
});
DupliJs.ImportManager.packagesList.on('click', '.dup-import-set-archive-password', function(event) {
event.stopPropagation();
DupliJs.ImportManager.setArchivePassword($(this));
return false;
});
DupliJs.ImportManager.initRemoteUpload();
},
initRemoteUpload: function() {
$('#dupli-import-remote-upload').click(function() {
let uploadUrl = $('#dupli-import-remote-url').val();
let parsedUrl = null;
try {
parsedUrl = new URL(uploadUrl);
} catch (error) {
DupliJs.addAdminMessage('<?php echo esc_js(__('Invalid URL', 'duplicator-pro')) ?>', 'error');
}
let files = [{
'name': parsedUrl.pathname.split('/').pop(),
'size': -1
}];
if (DupliJs.ImportManager.onStart(null, files) == false) {
DupliJs.ImportManager.onComplete(null);
return false;
}
DupliJs.ImportManager.onFileStart(null, files[0]);
DupliJs.ImportManager.remoteUploadCall(uploadUrl, null);
});
},
remoteUploadCall: function(uploadUrl, restoreDownload) {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_import_remote_download',
url: uploadUrl,
restoreDownload: (restoreDownload == null ? '' : JSON.stringify(restoreDownload)),
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_remote_download')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (DupliJs.ImportManager.packageRowUploading == null) {
// if row don't exitst the upload is aboted
DupliJs.ImportManager.onComplete(null);
return '';
}
if (funcData.status == 'complete') {
DupliJs.ImportManager.onFileComplete(null, uploadUrl, result);
DupliJs.ImportManager.onComplete(null);
} else {
DupliJs.ImportManager.updateProgress(funcData.remoteChunk.offset, funcData.remoteChunk.fullSize);
// Update filename display with real archive name from cloud processing
if (funcData.remoteChunk.extraData && funcData.remoteChunk.extraData.archiveName) {
DupliJs.ImportManager.packageRowUploading.find('.name .text').text(funcData.remoteChunk.extraData.archiveName);
}
DupliJs.ImportManager.remoteUploadCall(uploadUrl, funcData.remoteChunk);
}
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.ImportManager.uploadError(result.data.message);
DupliJs.ImportManager.onComplete(null);
return '';
}, {
timeout: 30000 // 30 seconds for large cloud file downloads
}
);
},
setArchivePassword: function(button) {
let row = button.closest('.dupli-import-package');
let archiveFile = row.data('path');
let password = row.find('.dup-import-archive-password-request .dup-import-archive-password').val();
DupliJs.Util.ajaxWrapper({
action: 'duplicator_import_set_archive_password',
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_import_set_archive_password')); ?>',
archive: archiveFile,
password: password
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.ImportManager.packageRowUploading = row;
DupliJs.ImportManager.onFileComplete(null, archiveFile, result, false);
DupliJs.ImportManager.onComplete(null);
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(data.message, 'error', {
'hideDelay': 5000
});
return '';
}
);
},
initPageButtons: function() {
$('.dupli-import-view-list').click(function(event) {
event.stopPropagation();
DupliJs.ImportManager.updateViewMode('<?php echo esc_js(ImportPageController::VIEW_MODE_ADVANCED); ?>');
});
$('.dupli-import-view-single').click(function(event) {
event.stopPropagation();
DupliJs.ImportManager.updateViewMode('<?php echo esc_js(ImportPageController::VIEW_MODE_BASIC); ?>');
});
$('#dupli-import-launch-installer-confirm').click(function(event) {
event.stopPropagation();
DupliJs.ImportManager.confirmLaunchInstaller();
});
$('#dupli-import-launch-installer-cancel').click(function(event) {
event.stopPropagation();
DupliJs.ImportManager.confirmLaunchLink = false;
$('#dupli-import-phase-two').addClass('no-display');
$('#dupli-import-phase-one').removeClass('no-display');
return false;
});
$('#wpbody-content').each(function() {
let tabWrapper = $(this);
tabWrapper.find('[data-tab-target]').click(function() {
let targetId = $(this).data('tab-target');
tabWrapper.find('[data-tab-target]').removeClass('active');
tabWrapper.find('.tab-content').addClass('no-display');
$(this).addClass('active');
tabWrapper.find('#' + targetId).removeClass('no-display');
});
});
},
confirmLaunchInstaller: function() {
window.location.href = DupliJs.ImportManager.confirmLaunchLink;
return false;
},
onStart: function(e, files) {
DupliJs.ImportManager.uploaderDisabler.show();
DupliJs.ImportManager.startUpload = true;
DupliJs.ImportManager.uploader.upload("disable");
DupliJs.ImportManager.autoLaunchLink = false;
let isValidName = true;
let alreadyExists = false;
$.each(files, function(index, value) {
if (!DupliJs.ImportManager.isValidFileName(value.name)) {
isValidName = false;
}
if (DupliJs.ImportManager.isAlreadyExists(value.name)) {
alreadyExists = true;
}
});
/*if (!isValidName) {
<?php $packageInvalidName->showMessage(); ?>
DupliJs.ImportManager.abortUpload();
return false;
}*/
if (alreadyExists) {
<?php $packageAlreadyExists->showMessage(); ?>
DupliJs.ImportManager.abortUpload();
return false;
}
return true;
},
onComplete: function(e) {
$('#dupli-import-remote-url').val('');
if (DupliJs.ImportManager.autoLaunchAfterUpload && DupliJs.ImportManager.autoLaunchLink) {
document.location.href = DupliJs.ImportManager.autoLaunchLink;
}
DupliJs.ImportManager.checkMaxUploadedFiles();
},
onFileStart: function(e, file) {
DupliJs.ImportManager.resetUploadTimes();
DupliJs.ImportManager.packagesList.find('.dupli-import-no-package-found').remove();
DupliJs.ImportManager.packageRowUploading = DupliJs.ImportManager.packageRowTemplate.clone().prependTo(DupliJs.ImportManager.packagesList);
DupliJs.ImportManager.packageRowUploading.removeAttr('id');
DupliJs.ImportManager.packageRowUploading.find('.name .text').text(file.name);
DupliJs.ImportManager.packageRowUploading.find('.size').text(DupliJs.Util.humanFileSize(file.size));
DupliJs.ImportManager.packageRowUploading.find('.created').html("<i><?php esc_html_e('loading...', 'duplicator-pro'); ?></i>");
let loader = DupliJs.ImportManager.packageRowUploading.find('.funcs .dupli-loader').removeClass('no-display');
loader.find('.dupli-meter > span').css('width', '0%');
loader.find('.text').text('0%');
},
onFileProgress: function(e, file, percent, eventObj) {
let position = 0;
if ('currentChunk' in file) {
position = file.currentChunk * file.chunkSize;
} else {
if (eventObj.lengthComputable) {
position = eventObj.loaded || eventObj.position;
} else {
position = false;
}
}
DupliJs.ImportManager.updateProgress(position, file.size);
},
onFileComplete: function(e, file, response, showMessage = true) {
let result = null;
if (typeof response === 'string' || response instanceof String) {
result = JSON.parse(response);
} else {
result = response;
}
DupliJs.ImportManager.resetUploadTimes();
if (result.success == false) {
DupliJs.ImportManager.uploadError(result.data.message);
return;
}
DupliJs.ImportManager.packageRowUploading.data('path', result.data.funcData.archivePath);
if (result.data.funcData.isImportable) {
DupliJs.ImportManager.packageRowUploading.addClass('is-importable');
DupliJs.ImportManager.packageRowUploading
.find('.dupli-import-action-install')
.prop('disabled', false)
.data('install-url', result.data.funcData.installerPageLink);
DupliJs.ImportManager.autoLaunchLink = result.data.funcData.installerPageLink;
} else {
DupliJs.ImportManager.autoLaunchLink = false;
DupliJs.ImportManager.packageRowUploading.find('.dupli-import-action-package-detail-toggle').trigger('click');
}
DupliJs.ImportManager.packageRowUploading.find('.dupli-import-package-detail').html(result.data.funcData.htmlDetails);
DupliJs.ImportManager.packageRowUploading.find('.size').text(DupliJs.Util.humanFileSize(result.data.funcData.archiveSize));
DupliJs.ImportManager.packageRowUploading.find('.created').text(result.data.funcData.created);
DupliJs.ImportManager.packageRowUploading.find('.funcs .dupli-loader').addClass('no-display');
DupliJs.ImportManager.packageRowUploading.find('.funcs .actions').removeClass('no-display');
DupliJs.ImportManager.packageRowUploading = null;
if (showMessage) {
<?php $packageUploaded->showMessage(); ?>
}
},
onFileError: function(e, file, error) {
if (error === 'abort') {
// no message for abort
DupliJs.ImportManager.uploadError(null);
} else if (error === 'size') {
DupliJs.ImportManager.uploadError(<?php echo json_encode(__('The file size exceeds the maximum upload limit.', 'duplicator-pro')); ?>);
} else {
DupliJs.ImportManager.uploadError(error);
}
},
getTimeLeft: function(sizeToFinish) {
if (DupliJs.ImportManager.lastUploadsTimes.length < 2) {
return false;
}
let pos1 = DupliJs.ImportManager.lastUploadsTimes[0].pos;
let time1 = DupliJs.ImportManager.lastUploadsTimes[0].time;
let index = DupliJs.ImportManager.lastUploadsTimes.length - 1
let pos2 = DupliJs.ImportManager.lastUploadsTimes[index].pos;
let time2 = DupliJs.ImportManager.lastUploadsTimes[index].time;
let deltaPos = pos2 - pos1;
let deltaTime = time2 - time1;
return deltaTime / deltaPos * sizeToFinish;
},
millisecToTime: function(s) {
if (s <= 0) {
return '<?php echo esc_js(__('loading...', 'duplicator-pro')) ?>';
}
var ms = s % 1000;
s = (s - ms) / 1000;
var secs = s % 60;
s = (s - secs) / 60;
var mins = s % 60;
var hrs = (s - mins) / 60;
let result = '';
if (hrs > 0) {
result += ' ' + hrs + ' <?php echo esc_js(__('hr', 'duplicator-pro')) ?>';
}
if (mins > 0) {
result += ' ' + (mins + 1) + ' <?php echo esc_js(__('min', 'duplicator-pro')) ?>';
return result;
}
return secs + ' <?php echo esc_js(__('sec', 'duplicator-pro')) ?>';
},
resetUploadTimes: function() {
DupliJs.ImportManager.lastUploadsTimes = [];
},
addUploadTime: function(postion) {
if (DupliJs.ImportManager.lastUploadsTimes.length > 20) {
DupliJs.ImportManager.lastUploadsTimes.shift();
}
DupliJs.ImportManager.lastUploadsTimes.push({
'pos': postion,
'time': Date.now()
});
},
updateProgress: function(position, total) {
let percent = 0;
if (position !== false) {
DupliJs.ImportManager.addUploadTime(position);
percent = Math.round((position / total) * 100 * 10) / 10;
percent = Number.isInteger(percent) ? percent + ".0" : percent;
}
DupliJs.ImportManager.packageRowUploading.find('.size').text(DupliJs.Util.humanFileSize(total));
let timeLeft = DupliJs.ImportManager.getTimeLeft(total - position);
let loader = DupliJs.ImportManager.packageRowUploading.find('.funcs .dupli-loader');
loader.find('.dupli-meter > span').css("width", percent + "%");
loader.find('.text').text(percent + "% - " + DupliJs.ImportManager.millisecToTime(timeLeft));
},
updateContentMessage: function(icon, line1, line2) {
DupliJs.ImportManager.uploaderContent.find('.message').html('<i class="fas ' + icon + ' fa-sm"></i> ' + line1 + '<br>' + line2);
},
uploadError: function(message) {
DupliJs.ImportManager.removeRow(DupliJs.ImportManager.packageRowUploading);
DupliJs.ImportManager.packageRowUploading = null;
if (message != null) {
DupliJs.addAdminMessage(uploadFileMessageContent, 'error', {
'hideDelay': 60000,
'updateCallback': function(msgNode) {
msgNode.find('.import-upload-error-message').text(message);
}
});
}
},
isAlreadyExists: function(name) {
let alreadyExists = false;
DupliJs.ImportManager.packagesList.find('tbody .name .text').each(function() {
if (name === $(this).text()) {
alreadyExists = true;
}
});
return alreadyExists;
},
isValidFileName: function(name) {
if (!name.match(<?php echo wp_json_encode(DUPLICATOR_ARCHIVE_REGEX_PATTERN); ?>)) {
return false;
}
return true;
},
abortUpload: function() {
try {
DupliJs.ImportManager.uploader.upload("abort");
} catch (err) {
// prevent abort error
}
DupliJs.ImportManager.removeRow(DupliJs.ImportManager.packageRowUploading);
DupliJs.ImportManager.packageRowUploading = null;
},
removePackage: function() {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_import_package_delete',
path: DupliJs.ImportManager.packageRowToDelete.data('path'),
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_import_package_delete')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.ImportManager.removeRow(DupliJs.ImportManager.packageRowToDelete);
<?php $packageRemoved->showMessage(); ?>;
return '';
}
);
},
removeRow: function(row) {
if (!row) {
return;
}
row.fadeOut(
'fast',
function() {
row.remove();
if (DupliJs.ImportManager.packagesList.find('.dupli-import-package').length === 0) {
DupliJs.ImportManager.packageRowNoFoundTemplate.clone().appendTo(DupliJs.ImportManager.packagesList);
}
DupliJs.ImportManager.checkMaxUploadedFiles();
}
);
},
checkMaxUploadedFiles: function() {
let limit = 0; // 0 no limit
let numPackages = $('.packages-list .dupli-import-package').length;
if ($('#dupli-import-available-packages').hasClass('view-single-item')) {
limit = 1;
}
if (limit > 0 && numPackages >= limit) {
DupliJs.ImportManager.uploaderDisabler.show();
DupliJs.ImportManager.uploader.upload("disable");
} else {
DupliJs.ImportManager.uploaderDisabler.hide();
DupliJs.ImportManager.uploader.upload("enable");
}
},
disableWrapper: function() {
DupliJs.ImportManager.uploaderWrapper
},
updateViewMode: function(viewMode) {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_import_set_view_mode',
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_import_set_view_mode')); ?>',
view_mode: viewMode
},
function(result, data, funcData, textStatus, jqXHR) {
switch (funcData) {
case '<?php echo esc_js(ImportPageController::VIEW_MODE_ADVANCED); ?>':
$('.dupli-import-view-single').removeClass('active');
$('.dupli-import-view-list').addClass('active');
$('#dupli-basic-mode-message').addClass('no-display');
DupliJs.ImportManager.packagesAviable.removeClass('view-single-item').addClass('view-list-item');
break;
case '<?php echo esc_js(ImportPageController::VIEW_MODE_BASIC); ?>':
$('.dupli-import-view-list').removeClass('active');
$('.dupli-import-view-single').addClass('active');
$('#dupli-basic-mode-message').removeClass('no-display');
DupliJs.ImportManager.packagesAviable.removeClass('view-list-item').addClass('view-single-item');
break;
default:
throw '<?php echo esc_js(__('Invalid view mode', 'duplicator-pro')); ?>';
}
DupliJs.ImportManager.checkMaxUploadedFiles();
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(data.message, 'error', {
'hideDelay': 5000
});
return '';
}
);
},
console: function() {
if (this.debug) {
if (arguments.length > 1) {
console.log(arguments[0], arguments[1]);
} else {
console.log(arguments[0]);
}
}
}
};
// wait form stone init, it's not a great method but for now I haven't found a better one.
window.setTimeout(DupliJs.ImportManager.init, 500);
$('.dupli-import-box.closable').each(function() {
let box = $(this);
let title = $(this).find('.box-title');
let content = $(this).find('.box-content');
title.click(function() {
if (box.hasClass('opened')) {
box.removeClass('opened').addClass('closed');
} else {
box.removeClass('closed').addClass('opened');
}
});
});
});
</script>

View File

@@ -0,0 +1,126 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\RecoveryController;
use Duplicator\Libs\Snap\SnapWP;
use Duplicator\Package\Recovery\RecoveryPackage;
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$postTypeCount = SnapWP::getPostTypesCount();
if (
($recoverPackage = RecoveryPackage::getRecoverPackage()) == false ||
$recoverPackage->isOutToDate()
) {
$badgeClass = 'badge-warn';
$badgeLabel = 'Notice';
} else {
$badgeClass = 'badge-pass';
$badgeLabel = 'Good';
}
?>
<div class="dupli-import-header" >
<h2 class="title">
<b>
<?php printf(esc_html__("Step %s of 2: Confirmation", 'duplicator-pro'), '<span class="red">2</span>'); ?>
</b>
</h2>
</div>
<div class="dupli-recovery-details-max-width-wrapper" >
<div class="dupli-import-box closable opened" >
<div class="box-title" >
<?php esc_html_e('Disaster Recovery', 'duplicator-pro'); ?>
<div class="badge <?php echo esc_attr($badgeClass); ?> margin-right-1">
<?php echo esc_html($badgeLabel); ?>
</div>
</div>
<div class="box-content">
<div id="dupli-recovery-details-select-entry" class="dupli-recovery-info-set" >
<?php
RecoveryController::renderRecoveryWidged([
'selector' => true,
'subtitle' => '',
'copyLink' => true,
'copyButton' => true,
'launch' => false,
'download' => true,
'info' => true,
]);
?>
</div>
<hr>
<div class="dupli-recovery-not-required">
<i class="far fa-arrow-alt-circle-right"></i>
<?php
esc_html_e(
'The Recovery Point is not mandatory to perform an import.
However, it can assist in restoring this site if there is a problem during install.
If you have no need to recover this site then you can continue without creating the Recovery Point.',
'duplicator-pro'
);
?>
</div>
</div>
</div><br/>
<div class="dupli-import-box closable opened" >
<div class="box-title" >
<?php esc_html_e('System Overview', 'duplicator-pro'); ?>
</div>
<div class="box-content">
<div id="dupli-recovery-details-overview" >
<div>
<?php esc_html_e("This site currently contains", 'duplicator-pro'); ?>:
</div>
<table class="margin-left-2" >
<?php foreach ($postTypeCount as $label => $count) { ?>
<tr>
<td><?php echo esc_html($label); ?></td>
<td class="text-right"><?php echo (int) $count; ?></td>
</tr>
<?php } ?>
</table>
<p>
<?php esc_html_e("This process will:", 'duplicator-pro') ?>
</p>
<ul>
<li>
<i class="far fa-check-circle"></i>&nbsp;
<?php esc_html_e("Launch the interactive installer wizard to install this new Backup.", 'duplicator-pro'); ?>
</li>
</ul>
</div>
</div>
</div>
<div class="dupli-import-confirm-buttons">
<input
id="dupli-import-launch-installer-cancel"
type="button" class="button secondary hollow small recovery-reset"
value="<?php esc_attr_e('Cancel', 'duplicator-pro'); ?>"
>&nbsp;
<button
id="dupli-import-launch-installer-confirm"
type="button"
class="button primary small"
onclick="DupliJs.ImportManager.confirmLaunchInstaller();"
>
<i class="fa fa-bolt fa-sm"></i> <?php esc_html_e('Launch Installer', 'duplicator-pro'); ?>
</button>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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-tab-content-wrapper" >
<div id="dupli-import-phase-one" >
<?php $tplMng->render('admin_pages/import/step1/import-step1'); ?>
</div>
<div id="dupli-import-phase-two" class="no-display" >
<?php $tplMng->render('admin_pages/import/import-step2'); ?>
</div>
</div>
<?php
$tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-scripts');
$tplMng->render('admin_pages/import/import-scripts');

View File

@@ -0,0 +1,80 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Core\Controllers\SubMenuItem;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string,mixed> $tplData
* @var string $pageTitle
*/
$pageTitle = $tplData['pageTitle'];
/** @var string */
$templateSecondaryPart = ($tplData['templateSecondaryPart'] ?? '');
/** @var array<string,mixed> */
$templateSecondaryArgs = ($tplData['templateSecondaryArgs'] ?? []);
/** @var bool $blur */
$blur = $tplData['blur'];
$importSettingsUrl = $ctrlMng->getMenuLink(
ControllersManager::SETTINGS_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_IMPORT
);
$items = [];
$item = new SubMenuItem(
'mode-upload-tab',
__('Import File', 'duplicator-pro'),
'',
true
);
$item->link = '';
$item->active = true;
$item->attributes = ['data-tab-target' => "dupli-import-upload-file-tab"];
$items[] = $item;
$item = new SubMenuItem(
'mode-remote-tab',
__('Import Link', 'duplicator-pro'),
'',
true
);
$item->link = '';
$item->active = false;
$item->attributes = ['data-tab-target' => "dupli-import-remote-file-tab"];
$items[] = $item;
$item = new SubMenuItem(
'import-settings',
__('Settings', 'duplicator-pro'),
'',
true
);
$item->link = $importSettingsUrl;
$item->active = false;
$items[] = $item;
?>
<div class="dup-body-header">
<h1><?php echo esc_html($pageTitle); ?></h1>
<?php
if (!$blur) {
$tplMng->render('parts/tabs_menu_l2', ['menuItemsL2' => $items]);
}
if (strlen($templateSecondaryPart) > 0) {
$tplMng->render($templateSecondaryPart, $templateSecondaryArgs);
}
?>
</div>
<hr class="wp-header-end margin-top-0">

View File

@@ -0,0 +1,124 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Models\GlobalEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
if (GlobalEntity::getInstance()->import_chunk_size == 0) {
$footerChunkInfo = sprintf(__('<b>Chunk Size:</b> N/A &nbsp;|&nbsp; <b>Max Size:</b> %s', 'duplicator-pro'), size_format(wp_max_upload_size()));
$toolTipContent = __('If you need to upload a larger file, go to [Settings > Import] and set Upload Chunk Size', 'duplicator-pro');
} else {
$footerChunkInfo = sprintf(
__(
'<b>Chunk Size:</b> %s &nbsp;|&nbsp; <b>Max Size:</b> No Limit',
'duplicator-pro'
),
size_format(ImportPageController::getChunkSize() * 1024)
);
$toolTipContent = __(
'The max file size limit is ignored when chunk size is enabled.
Use a large chunk size with fast connections and a small size with slower connections.
You can change the chunk size by going to [Settings > Import].',
'duplicator-pro'
);
}
/** @var string */
$openTab = $tplData['defSubtab'];
$hlpUpload = __(
'Upload speeds can be affected by different server connections and settings.
The chunk size can also impact upload speed [Settings > Import].
If adjusting the chunk size doesn\'t help, try these steps to manually upload the archive:',
'duplicator-pro'
);
$hlpUpload .= '<ul>' .
'<li>' . __('1. Cancel the current upload.', 'duplicator-pro') . '</li>' .
'<li>' . __('2. Manually upload the archive to:<br/> &nbsp; &nbsp; <i>/wp-content/duplicator-backups/imports/</i>', 'duplicator-pro') . '</li>' .
'<li>' . __('3. Refresh the Import screen.', 'duplicator-pro') . '</li>' .
'</ul>';
?>
<!-- ==============================
DRAG/DROP AREA -->
<div id="dupli-import-upload-tabs-wrapper" class="dupli-tabs-wrapper margin-bottom-2">
<div
id="dupli-import-upload-file-tab"
class="tab-content <?php echo ($openTab == ImportPageController::L2_TAB_UPLOAD ? '' : 'no-display'); ?>">
<div id="dupli-import-upload-file" class="dupli-import-upload-box"></div>
<div class="no-display">
<div id="dupli-import-upload-file-content" class="center-xy">
<i class="fa fa-download fa-2x"></i>
<span class="dup-drag-drop-message">
<?php esc_html_e("Drag & Drop Backup File Here", 'duplicator-pro'); ?>
</span>
<input
id="dup-import-dd-btn"
type="button"
class="button secondary hollow button-default dup-import-button margin-0"
name="dupli-files"
value="<?php esc_attr_e("Select File...", 'duplicator-pro'); ?>">
</div>
</div>
<div id="dupli-import-upload-file-footer">
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_html_e("Upload Chunk Size", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($toolTipContent); ?>"></i>&nbsp;<?php echo wp_kses($footerChunkInfo, ['b' => []]); ?>&nbsp;|&nbsp;
<span
class="pointer link-style"
data-tooltip-title="<?php esc_html_e("Improve Upload Speed", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($hlpUpload); ?>">
<i><?php esc_html_e('Slow Upload', 'duplicator-pro'); ?></i>&nbsp;<i class="fa-solid fa-question-circle fa-sm dark-gray-color"></i>
</span>
</div>
</div>
<div
id="dupli-import-remote-file-tab"
class="tab-content <?php echo ($openTab == ImportPageController::L2_TAB_REMOTE_URL ? '' : 'no-display'); ?>">
<div class="dupli-import-upload-box">
<div class="center-xy">
<i class="fa fa-download fa-2x"></i>
<span class="dup-drag-drop-message">
<?php esc_html_e("Import From Link", 'duplicator-pro'); ?>
</span>
<input
type="text"
id="dupli-import-remote-url"
class="inline-display margin-bottom-0"
placeholder="<?php esc_attr_e('Enter Full URL to Archive', 'duplicator-pro'); ?>">
<button id="dupli-import-remote-upload" type="button" class="button primary button-default dup-import-button margin-bottom-0">
<?php esc_html_e("Upload", 'duplicator-pro'); ?>
</button> <br />
<small>
<?php
printf(
esc_html_x(
'For additional help visit the %1$sonline faq%2$s.',
'%1$s and %2$s are <a> tags',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-handle-import-install-upload-launch-issues')
. '" target="_blank">',
'</a>'
);
?>
</small>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,40 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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'];
if ($tplData['adminMessageViewModeSwtich'] && !$blur) {
$tplMng->render('admin_pages/import/step1/message-view-mode-switch');
}
?>
<div class="dupli-import-header" >
<h2 class="title">
<b>
<?php printf(esc_html__("Step %s of 2: Upload Backup", 'duplicator-pro'), '<span class="red">1</span>'); ?>
</b>
</h2>
</div>
<div class="dup-import-header-content-wrapper <?php echo ($blur ? 'dup-mock-blur' : ''); ?>" >
<?php $tplMng->render('admin_pages/import/step1/add-file-area'); ?>
<?php $tplMng->render('admin_pages/import/step1/packages-list'); ?>
</div>

View File

@@ -0,0 +1,32 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?><div class="notice notice-success is-dismissible dupli-admin-notice">
<p>
<?php
printf(
esc_html_x(
'The mode has %1$sswitched to advanced%2$s because more backups have been detected in the import folder.',
'%1$s and %2$s are opening and closing bold tags (<b> and </b>)',
'duplicator-pro'
),
'<b>',
'</b>'
);
?>
</p>
</div>

View File

@@ -0,0 +1,31 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<tr class="dupli-import-no-package-found">
<td colspan="4" >
<div class="dupli-import-no-package-found-msg">
<b><?php esc_html_e("No archive files found!", 'duplicator-pro'); ?></b><br/><br/>
<?php esc_html_e("Please upload a Duplicator archive.zip/daf in the area above.", 'duplicator-pro'); ?><br/>
<?php esc_html_e("This will start the import process to overwrite the current site.", 'duplicator-pro'); ?>
<br/><br/>
<a href="<?php echo esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'import-install'); ?>" target="_blank">
<?php esc_html_e('How does this work?', 'duplicator-pro'); ?>
</a>
</div>
</td>
</tr>

View File

@@ -0,0 +1,99 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Package\Import\PackageImporter;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
/** @var PackageImporter $importObj */
$importObj = $tplData['importObj'];
if ($importObj instanceof PackageImporter) {
$name = $importObj->getName();
$size = $importObj->getSize();
$created = $importObj->getCreated();
$archivePath = $importObj->getFullPath();
$installPakageUrl = $importObj->getInstallerPageLink();
$isImportable = $importObj->isImportable();
$funcsEnalbed = true;
} else {
$name = '';
$size = 0;
$created = '';
$archivePath = '';
$installPakageUrl = '';
$isImportable = false;
$funcsEnalbed = false;
}
$rowClasses = ['dupli-import-package'];
if ($isImportable) {
$rowClasses[] = 'is-importable';
}
?>
<tr <?php echo strlen($tplData['idRow']) ? 'id="' . esc_attr($tplData['idRow']) . '" ' : ''; ?>
class="<?php echo esc_attr(implode(' ', $rowClasses)) ?>"
data-path="<?php echo esc_attr($archivePath); ?>">
<td class="name">
<span class="text"><b><?php echo esc_html($name); ?></b></span>
<div class="dupli-import-package-detail no-display">
<?php
if ($funcsEnalbed) {
$importObj->getHtmlDetails();
}
?>
</div>
</td>
<td class="size">
<span title="<?php printf(esc_attr__('Total %d bytes', 'duplicator-pro'), (int) $size); ?>">
<?php echo esc_html(SnapString::byteSize($size)); ?>
</span>
</td>
<td class="created">
<?php echo esc_html($created); ?>
</td>
<td class="funcs">
<div class="actions <?php echo $funcsEnalbed ? '' : 'no-display'; ?>">
<button type="button" class="button secondary hollow margin-bottom-0 small dupli-import-action-package-detail-toggle">
<i class="fa fa-caret-down"></i> <?php esc_html_e('Details', 'duplicator-pro'); ?>
</button>
<span class="separator"></span>
<button type="button" class="dupli-import-action-remove button secondary hollow small margin-bottom-0 ">
<i class="fa fa-ban"></i> <?php esc_html_e('Remove', 'duplicator-pro'); ?>
</button>
<span class="separator"></span>
<button type="button" class="dupli-import-action-install button primary small margin-bottom-0"
data-install-url="<?php echo esc_url($installPakageUrl); ?>"
<?php echo $isImportable ? '' : 'disabled'; ?>>
<i class="fa fa-bolt fa-sm"></i> <?php esc_html_e('Continue', 'duplicator-pro'); ?>
</button>
</div>
<div class="invalid no-display">
<?php esc_html_e('Backup Invalid', 'duplicator-pro'); ?>
</div>
<div class="dupli-loader no-display">
<div class="dupli-meter-wrapper">
<div class="dupli-meter green">
<span style="width: 0%"></span>
</div>
<span class="text">0%</span>
</div>
<a href="" class="dupli-import-action-cancel-upload button secondary hollow small margin-bottom-0 button-cancel">
<i class="fa fa-ban"></i> <?php esc_html_e('Cancel', 'duplicator-pro'); ?>
</a>
</div>
</td>
</tr>

View File

@@ -0,0 +1,75 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Package\Import\PackageImporter;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
switch ($tplData['viewMode']) {
case ImportPageController::VIEW_MODE_ADVANCED:
$viewModeClass = 'view-list-item';
break;
case ImportPageController::VIEW_MODE_BASIC:
default:
$viewModeClass = 'view-single-item';
break;
}
?>
<div id="dupli-import-available-packages" class="<?php echo esc_attr($viewModeClass); ?>" >
<table class="dup-import-avail-packs packages-list">
<thead>
<tr>
<th class="name"><?php esc_html_e("Backups", 'duplicator-pro'); ?></th>
<th class="size"><?php esc_html_e("Size", 'duplicator-pro'); ?></th>
<th class="created"><?php esc_html_e("Created", 'duplicator-pro'); ?></th>
<th class="funcs"><?php esc_html_e("Status", 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody>
<?php
$importObjs = PackageImporter::getArchiveObjects();
if (count($importObjs) === 0) {
$tplMng->render('admin_pages/import/step1/package-row-no-found');
} else {
foreach ($importObjs as $importObj) {
$tplMng->render(
'admin_pages/import/step1/package-row',
[
'importObj' => $importObj,
'idRow' => '',
]
);
}
}
?>
</tbody>
</table>
<div class="no-display" >
<table id="dupli-import-available-packages-templates">
<?php
$tplMng->render(
'admin_pages/import/step1/package-row',
[
'importObj' => null,
'idRow' => 'dupli-import-row-template',
]
);
$tplMng->render('admin_pages/import/step1/package-row-no-found');
?>
</table>
</div>
</div>

View File

@@ -0,0 +1,70 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\CapMng;
use Duplicator\Core\Controllers\ControllersManager;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$importSettingsUrl = $ctrlMng->getMenuLink(
ControllersManager::SETTINGS_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_IMPORT
);
?>
<div id="dupli-import-vews-and-opt-wrapper" >
<ul class="dupli-toggle-sub-menu">
<li>
<span class="dupli-toggle" >
<span class="button" >
<i class="fas fa-bars fa-lg"></i><span class="screen-reader-text">Options</span>
</span>
</span>
<ul>
<li class="title"><?php esc_html_e('VIEWS', 'duplicator-pro'); ?></li>
<li>
<span class="link-style no-decoration dupli-import-view-list <?php echo $tplData['viewMode'] == 'list' ? 'active' : ''; ?>">
<?php esc_html_e('Advanced mode', 'duplicator-pro'); ?>
<span class="description"><?php esc_html_e('View multiple Backups', 'duplicator-pro') ?></span>
</span>
</li>
<li>
<span class="link-style no-decoration dupli-import-view-single <?php echo $tplData['viewMode'] == 'single' ? 'active' : ''; ?>">
<?php esc_html_e('Basic mode', 'duplicator-pro') ?>
<span class="description"><?php esc_html_e('View last uploaded Backup', 'duplicator-pro'); ?></span>
</span>
</li>
<li class="title separator"><?php esc_html_e('TOOLS', 'duplicator-pro'); ?></li>
<?php if (CapMng::can(CapMng::CAP_SETTINGS, false)) { ?>
<li>
<a class="no-decoration" href="<?php echo esc_url($importSettingsUrl); ?>" target="_blank">
<?php esc_html_e('Import Settings', 'duplicator-pro'); ?>
</a>&nbsp;
<i class="fas fa-external-link-alt fa-small" ></i>
</li>
<?php } ?>
<li>
<span class="link-style no-decoration dupli-open-help-link">
<a href="<?php echo esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'import-install'); ?>" target="_blank">
<?php esc_html_e('Quick Start', 'duplicator-pro'); ?>
</a>&nbsp;
<i class="fas fa-external-link-alt fa-small" ></i>
</span>
</li>
</ul>
</li>
</ul>
</div>

View File

@@ -0,0 +1,100 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
use Duplicator\Package\AbstractPackage;
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
* @var \Duplicator\Package\DupPackage $package
*/
$package = $tplData['package'];
/** @var string */
$innerPage = $tplData['currentInnerPage'];
$enable_transfer_tab = (
$package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_INSTALLER) !== false &&
$package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) !== false
);
$packagesListUrl = PackagesPageController::getInstance()->getMenuLink();
$packgeDefailsUrl = PackagesPageController::getInstance()->getPackageDetailsUrl($package->getId());
$packgeTransferUrl = PackagesPageController::getInstance()->getPackageTransferUrl($package->getId());
?>
<h2 class="nav-tab-wrapper">
<a
href="<?php echo esc_url($packgeDefailsUrl); ?>"
class="nav-tab <?php echo ($innerPage == PackagesPageController::LIST_INNER_PAGE_DETAILS) ? 'nav-tab-active' : '' ?>">
<?php esc_html_e('Details', 'duplicator-pro'); ?>
</a>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<a
href="<?php echo esc_url($packgeTransferUrl); ?>"
class="nav-tab <?php echo ($innerPage == PackagesPageController::LIST_INNER_PAGE_TRANSFER) ? 'nav-tab-active' : '' ?>"
<?php if ($enable_transfer_tab === false) { ?>
onclick="DupliJs.Pack.TransferDisabled(); return false;"
<?php } ?>>
<?php esc_html_e('Transfer', 'duplicator-pro'); ?>
</a>
<?php } ?>
</h2>
<div class="dup-details-packages-list">
<a href="<?php echo esc_url($packagesListUrl); ?>">[<?php esc_html_e('Backups', 'duplicator-pro'); ?>]</a>
</div>
<?php if ($package->getStatus() == AbstractPackage::STATUS_ERROR) { ?>
<div id='dupli-error' class="error">
<p>
<b>
<?php
printf(
esc_html_x(
'Error encountered building Backup, please review %1$sBackup log%2$s for details.',
'1 and 2 are opening and closing anchor tags',
'duplicator-pro'
),
'<a target="_blank" href="' . esc_url($package->getLogUrl()) . '">',
'</a>'
);
?>
</b>
<br />
<?php
printf(
esc_html_x(
'For more help read the %1$sFAQ pages%2$s or submit a %3$shelp ticket%4$s.',
'1 and 3 are opening, 2 and 4 are closing anchor/link tags',
'duplicator-pro'
),
'<a target="_blank" href="' . esc_url(DUPLICATOR_TECH_FAQ_URL) . '">',
'</a>',
'<a target="_blank" href="' . esc_url(DUPLICATOR_BLOG_URL . 'my-account/support/') . '">',
'</a>'
);
?>
</p>
</div>
<?php
}
$alertTransferDisabled = new UiDialog();
$alertTransferDisabled->title = __('Transfer Error', 'duplicator-pro');
$alertTransferDisabled->message = __('No Backup in default location so transfer is disabled.', 'duplicator-pro');
$alertTransferDisabled->initAlert();
?>
<script>
DupliJs.Pack.TransferDisabled = function() {
<?php $alertTransferDisabled->showAlert(); ?>
}
</script>

View File

@@ -0,0 +1,125 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
use Duplicator\Core\Controllers\SubMenuItem;
use Duplicator\Package\AbstractPackage;
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
* @var string $pageTitle
*/
$pageTitle = $tplData['pageTitle'];
/** @var \Duplicator\Package\DupPackage $package */
$package = $tplData['package'];
/** @var string */
$templateSecondaryPart = ($tplData['templateSecondaryPart'] ?? '');
/** @var array<string,mixed> */
$templateSecondaryArgs = ($tplData['templateSecondaryArgs'] ?? []);
/** @var string */
$innerPage = $tplData['currentInnerPage'];
$items = [];
$item = new SubMenuItem(
PackagesPageController::LIST_INNER_PAGE_LIST,
__('Backups', 'duplicator-pro'),
'',
true
);
$item->link = PackagesPageController::getInstance()->getMenuLink();
$item->active = ($innerPage == PackagesPageController::LIST_INNER_PAGE_LIST);
$items[] = $item;
$item = new SubMenuItem(
PackagesPageController::LIST_INNER_PAGE_DETAILS,
__('Details', 'duplicator-pro'),
'',
true
);
$item->link = PackagesPageController::getInstance()->getPackageDetailsUrl($package->getId());
$item->active = ($innerPage == PackagesPageController::LIST_INNER_PAGE_DETAILS);
$items[] = $item;
$item = new SubMenuItem(
PackagesPageController::LIST_INNER_PAGE_TRANSFER,
__('Transfer', 'duplicator-pro'),
'',
CapMng::can(CapMng::CAP_CREATE, false)
);
$item->link = PackagesPageController::getInstance()->getPackageTransferUrl($package->getId());
$item->active = ($innerPage == PackagesPageController::LIST_INNER_PAGE_TRANSFER);
$items[] = $item;
?>
<div class="dup-body-header">
<?php
$tplMng->render('parts/tabs_menu_l2', ['menuItemsL2' => $items]);
if (strlen($templateSecondaryPart) > 0) {
$tplMng->render($templateSecondaryPart, $templateSecondaryArgs);
}
?>
</div>
<hr class="wp-header-end margin-top-0">
<h1>
<?php echo esc_html($pageTitle); ?>
</h1>
<?php if ($package->getStatus() == AbstractPackage::STATUS_ERROR) { ?>
<div id='dupli-error' class="error">
<p>
<b>
<?php
printf(
esc_html_x(
'Error encountered building Backup, please review %1$sBackup log%2$s for details.',
'1 and 2 are opening and closing anchor tags',
'duplicator-pro'
),
'<a target="_blank" href="' . esc_url($package->getLogUrl()) . '">',
'</a>'
);
?>
</b>
<br />
<?php
printf(
esc_html_x(
'For more help read the %1$sFAQ pages%2$s or submit a %3$shelp ticket%4$s.',
'1 and 3 are opening, 2 and 4 are closing anchor/link tags',
'duplicator-pro'
),
'<a target="_blank" href="' . esc_url(DUPLICATOR_TECH_FAQ_URL) . '">',
'</a>',
'<a target="_blank" href="' . esc_url(DUPLICATOR_BLOG_URL . 'my-account/support/') . '">',
'</a>'
);
?>
</p>
</div>
<?php
}
$alertTransferDisabled = new UiDialog();
$alertTransferDisabled->title = __('Transfer Error', 'duplicator-pro');
$alertTransferDisabled->message = __('No Backup in default location so transfer is disabled.', 'duplicator-pro');
$alertTransferDisabled->initAlert();
?>
<script>
DupliJs.Pack.TransferDisabled = function() {
<?php $alertTransferDisabled->showAlert(); ?>
}
</script>

View File

@@ -0,0 +1,29 @@
<?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
*/
?>
<br/><br/>
<div id='dupli-error' class="error">
<p>
<?php echo sprintf(
esc_html__(
"Unable to find Backup id %d. The Backup does not exist or was deleted.",
'duplicator-pro'
),
esc_html($tplData['packageId'])
); ?>
<br/>
</p>
</div>

View File

@@ -0,0 +1,454 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\StoragePageController;
use Duplicator\Core\CapMng;
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Models\Storages\StoragesUtil;
use Duplicator\Package\AbstractPackage;
use Duplicator\Views\UI\UiDialog;
use Duplicator\Views\UI\UiViewState;
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'];
/** @var \Duplicator\Package\DupPackage */
$package = $tplData['package'];
$storage_list = AbstractStorageEntity::getAll(0, 0, [StoragesUtil::class, 'sortByPriority']);
$newStorageEditUrl = StoragePageController::getEditUrl();
$transfer_occurring = (
($package->getStatus() >= AbstractPackage::STATUS_STORAGE_PROCESSING) &&
($package->getStatus() < AbstractPackage::STATUS_COMPLETE)
);
$view_state = UiViewState::getArray();
$ui_css_transfer_log = (isset($view_state['dup-transfer-transfer-log']) && $view_state['dup-transfer-transfer-log']) ? 'display:block' : 'display:none';
$installer_name = $package->Installer->getInstallerName();
$archive_name = $package->Archive->getFileName();
?>
<div class="transfer-panel <?php echo ($blur ? 'dup-mock-blur' : ''); ?>">
<div class="transfer-hdr">
<h2 class="title">
<i class="fas fa-exchange-alt"></i> <?php esc_html_e('Manual Transfer', 'duplicator-pro'); ?>
<button id="dup-trans-ovr" type="button" class="dup-btn-borderless"
title="<?php esc_html_e('Show file details', 'duplicator-pro'); ?>"
onclick="DupliJs.Pack.Transfer.toggleOverview()">
<i class="fas fa-chevron-left fa-fw fa-sm"></i> <?php esc_html_e('Details', 'duplicator-pro') ?>
</button>
</h2>
<hr />
</div>
<!-- ===================
OVERVIEW -->
<div id="step1-ovr">
<h3><?php esc_html_e('File Overview', 'duplicator-pro'); ?></h3>
<small>
<?php esc_html_e('These files will be transferred to the selected storage locations. Links are sensitive. Keep them safe!', 'duplicator-pro'); ?>
</small>
<label>
<i class="far fa-file-archive fa-fw"></i>
<b><?php esc_html_e('Backup File', 'duplicator-pro'); ?></b>
<?php echo '&nbsp;(' . esc_html(SnapString::byteSize($package->Archive->Size)) . ')'; ?><br />
<div class="horizontal-input-row">
<input class="margin-right-1" type="text" value="<?php echo esc_attr($archive_name) ?>" readonly="readonly" />
<span onclick="jQuery(this).parent().find('input').select();">
<span class="copy-button" data-dup-copy-value="<?php echo esc_attr($archive_name); ?>">
<i class='far fa-copy dup-cursor-pointer'></i> <?php esc_html_e('Copy Name', 'duplicator-pro'); ?>
</span>
</span>
</div>
</label>
<label>
<i class="fa fa-bolt fa-fw"></i>
<b><?php esc_html_e('Backup Installer', 'duplicator-pro'); ?></b>
<?php echo '&nbsp;(' . esc_html(SnapString::byteSize($package->Installer->Size)) . ')'; ?><br />
<div class="horizontal-input-row">
<input class="margin-right-1" type="text" value="<?php echo esc_attr($installer_name) ?>" readonly="readonly" />
<span onclick="jQuery(this).parent().find('input').select();">
<span class="copy-button" data-dup-copy-value="<?php echo esc_attr($installer_name); ?>">
<i class='far fa-copy dup-cursor-pointer'></i> <?php esc_html_e('Copy Name', 'duplicator-pro'); ?>
</span>
</span>
</div>
</label>
</div>
<!-- ===================
STEP 1 -->
<div id="step2-section">
<div style="margin:0px 0 0px 0">
<h3><?php esc_html_e('Step 1: Choose Location', 'duplicator-pro') ?></h3>
<input style="display:none" type="radio" name="location" id="location-storage" checked="checked" onclick="DupliJs.Pack.Transfer.ToggleLocation()" />
<label style="display:none" for="location-storage"><?php esc_html_e('Storage', 'duplicator-pro'); ?></label>
<input style="display:none" type="radio" name="location" id="location-quick" onclick="DupliJs.Pack.Transfer.ToggleLocation()" />
<label style="display:none" for="location-quick"><?php esc_html_e('Quick FTP Connect', 'duplicator-pro'); ?></label>
</div>
<!-- STEP 1: STORAGE -->
<div id="location-storage-opts">
<?php $tplMng->render(
'parts/storage/select_list',
['filteredStorageIds' => [StoragesUtil::getDefaultStorageId()]]
); ?>
</div>
</div>
<!-- ===================
STEP 2 -->
<div id="step3-section">
<h3>
<?php esc_html_e('Step 2: Transfer Files', 'duplicator-pro') ?>
<button style="<?php echo ($transfer_occurring ? 'none' : 'default'); ?>"
id="dupli-transfer-btn" type="button"
class="button primary small"
onclick="DupliJs.Pack.Transfer.StartTransfer();">
<?php esc_attr_e('Start Transfer', 'duplicator-pro') ?> &nbsp; <i class="fas fa-upload"></i>
</button>
</h3>
<div style="width:700px; text-align: center; margin-left: auto; margin-right: auto" class="dupli-active-status-area">
<div style="display:none; font-size:20px; font-weight:bold" id="dupli-progress-bar-percent"></div>
<div style="font-size:14px" id="dupli-progress-bar-text"><?php esc_html_e('Processing', 'duplicator-pro') ?></div>
<div id="dupli-progress-bar-percent-help">
<small><?php esc_html_e('Full Backup percentage shown on Backups screen', 'duplicator-pro'); ?></small>
</div>
</div>
<div class="dupli-progress-bar-container">
<div id="dupli-progress-bar-area" class="dupli-active-status-area">
<div class="dupli-meter-wrapper">
<div class="dupli-meter green dupli-fullsize">
<span></span>
</div>
<span class="text"></span>
</div>
<button disabled id="dupli-stop-transfer-btn" type="button" class="button primary dupli-btn-stop" value=""
onclick="DupliJs.Pack.Transfer.StopBuild();">
<i class="fa fa-times fa-sm"></i> &nbsp; <?php esc_html_e('Stop Transfer', 'duplicator-pro'); ?>
</button>
</div>
</div>
</div>
<!-- ===============================
TRANSFER LOG -->
<div class="dup-box">
<div class="dup-box-title">
<i class="fas fa-file-contract fa-fw fa-sm"></i>
<?php esc_html_e('Transfer Log', 'duplicator-pro') ?>
<button class="dup-box-arrow">
<span class="screen-reader-text">
<?php esc_html_e('Toggle panel:', 'duplicator-pro') ?> <?php esc_html_e('Transfer Log', 'duplicator-pro') ?>
</span>
</button>
</div>
<div class="dup-box-panel" id="dup-transfer-transfer-log" style="<?php echo esc_attr($ui_css_transfer_log) ?>">
<table class="widefat package-tbl dup-table-list small">
<thead>
<tr>
<th style='width:150px'><?php esc_html_e('Started', 'duplicator-pro') ?></th>
<th style='width:150px'><?php esc_html_e('Stopped', 'duplicator-pro') ?></th>
<th style="white-space: nowrap"><?php esc_html_e('Status', 'duplicator-pro') ?></th>
<th style="white-space: nowrap"><?php esc_html_e('Type', 'duplicator-pro') ?></th>
<th style="width: 60%; white-space: nowrap"><?php esc_html_e('Description', 'duplicator-pro') ?></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5" id="dup-pack-details-trans-log-count"></td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<?php
$alert1 = new UiDialog();
$alert1->title = __('Storage Warning!', 'duplicator-pro');
$alert1->message = __('At least one storage location must be selected.', 'duplicator-pro');
$alert1->initAlert();
$alert2 = new UiDialog();
$alert2->title = __('Transfer Failure!', 'duplicator-pro');
$alert2->message = __('Transfer failure when calling duplicator_manual_transfer_storage.', 'duplicator-pro');
$alert2->initAlert();
$alert3 = new UiDialog();
$alert3->title = __('Build Error', 'duplicator-pro');
$alert3->message = __('Failed to stop build', 'duplicator-pro');
$alert3->initAlert();
$alert4 = new UiDialog();
$alert4->title = $alert3->title;
$alert4->message = __('Failed to stop build due to AJAX error.', 'duplicator-pro');
$alert4->initAlert();
$alert5 = new UiDialog();
$alert5->title = __('An error occurred', 'duplicator-pro');
$alert5->message = ''; // javascript inserted message
$alert5->initAlert();
$alert6 = new UiDialog();
$alert6->title = __('INFO!', 'duplicator-pro');
$alert6->message = ''; // javascript inserted message
$alert6->initAlert();
?>
<script>
DupliJs.Pack.Transfer = {};
jQuery(document).ready(function($) {
var transferRequestedTimestamp = 0;
var activePackageId = -1;
DupliJs.Pack.Transfer.toggleOverview = function() {
$('div#step1-ovr').toggle();
var $i = $('#dup-trans-ovr i');
if ($($i).hasClass('fa-chevron-left')) {
$($i).removeClass('fa-chevron-left').addClass('fa-chevron-down');
} else {
$($i).removeClass('fa-chevron-down').addClass('fa-chevron-left');
}
}
DupliJs.Pack.Transfer.GetTimeStamp = function() {
return Math.floor(Date.now() / 1000);
}
/* METHOD: Starts the data transfer */
DupliJs.Pack.Transfer.StartTransfer = function() {
if (jQuery('#location-storage-opts input[type=checkbox]:checked').length == 0) {
<?php $alert1->showAlert(); ?>
} else {
$(".dupli-active-status-area").show(500);
var selected_storage_ids = $.map($(':checkbox[name=_storage_ids\\[\\]]:checked'), function(n, i) {
return n.value;
});
console.log("sending to selected storages " + selected_storage_ids);
transferRequestedTimestamp = DupliJs.Pack.Transfer.GetTimeStamp();
$("#dupli-progress-bar-text").text("<?php echo esc_html__('Initiating transfer. Please wait.', 'duplicator-pro') ?>");
$("#dupli-progress-bar-percent").text('');
DupliJs.Pack.Transfer.SetUIState(true);
var data = {
action: 'duplicator_manual_transfer_storage',
package_id: <?php echo (int) $package->getId(); ?>,
storage_ids: selected_storage_ids,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_manual_transfer_storage')); ?>'
}
$.ajax({
type: "POST",
url: ajaxurl,
cache: false,
timeout: 10000000,
data: data,
success: function(parsedData) {
if (!parsedData.success) {
if (parsedData.data && parsedData.data.message && parsedData.data.message !== '') {
<?php $alert5->showAlert(); ?>
$("#<?php echo esc_js($alert5->getID()); ?>_message").html(parsedData.data.message);
}
transferRequestedTimestamp = 0;
DupliJs.Pack.Transfer.SetUIState(false);
DupliJs.Pack.Transfer.GetPackageState();
}
},
error: function(respData) {
<?php $alert2->showAlert(); ?>
transferRequestedTimestamp = 0;
DupliJs.Pack.Transfer.SetUIState(false);
console.log(respData);
}
});
}
};
/* METHOD: Starts the data transfer */
DupliJs.Pack.Transfer.StopBuild = function() {
$("#dupli-stop-transfer-btn").prop("disabled", true);
DupliJs.Util.ajaxWrapper({
action: 'duplicator_package_stop_build',
package_id: activePackageId,
nonce: '<?php echo esc_js(wp_create_nonce("duplicator_package_stop_build")); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (!funcData.success) {
<?php $alert3->showAlert(); ?>
$("#dupli-stop-transfer-btn").prop("disabled", false);
}
DupliJs.addAdminMessage(
"<?php esc_html_e('Backups transfer cancellation was initiated.', 'duplicator-pro'); ?>",
'notice', {
hideDelay: 3000
}
);
console.log(funcData.message);
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
<?php $alert4->showAlert(); ?>
$("#dupli-stop-transfer-btn").prop("disabled", false);
return '';
}
);
};
/* METHOD: Progress bar display state*/
DupliJs.Pack.Transfer.SetUIState = function(activeProcessing) {
if (activeProcessing) {
$(".dupli-active-status-area").show(500);
$("#dupli-transfer-btn").hide();
$("#location-storage input").prop("disabled", true);
//$("#location-storage-opts input").prop("disabled", true);
} else {
$("#dupli-stop-transfer-btn").prop("disabled", true);
// Only allow to revert after enough time has past since the last transfer request
currentTimestamp = DupliJs.Pack.Transfer.GetTimeStamp();
if ((currentTimestamp - transferRequestedTimestamp) > 10) {
$("#location-storage input").prop("disabled", false);
//$("#location-storage-opts input").prop("disabled", false);
$("#dupli-transfer-btn").show();
$(".dupli-active-status-area").hide();
}
}
}
/* METHOD: Retreive Backup state */
DupliJs.Pack.Transfer.GetPackageState = function() {
var package_id = <?php echo (int) $package->getId(); ?>;
DupliJs.Util.ajaxWrapper({
action: 'duplicator_packages_details_transfer_get_package_vm',
package_id: package_id,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_packages_details_transfer_get_package_vm')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
var vm = funcData.vm;
// vm - view model for this screen
// vm.active_package_id: Active Backup id (-1 for none)
// vm.percent_text: Percent through the current transfer
// vm.text: Text to display
// vm.transfer_logs: array of transfer request vms (start, stop, status, message)
if (activePackageId != vm.active_package_id) {
// Once we have an active Backup ID allow the stop button to be clicked
$("#dupli-stop-transfer-btn").prop("disabled", false);
}
activePackageId = vm.active_package_id;
if (vm.active_package_id == -1) {
// No backups are running
DupliJs.Pack.Transfer.SetUIState(false);
} else if (vm.active_package_id == package_id) {
// This Backup is running
if (vm.percent_text != '') {
$("#dupli-progress-bar-percent").text(vm.percent_text);
} else {
$("#dupli-progress-bar-percent").text('');
}
$("#dupli-progress-bar-text").html(vm.text);
DupliJs.Pack.Transfer.SetUIState(true);
} else {
// A package other than this one is running
$("#dupli-progress-bar-text").html(vm.text);
DupliJs.Pack.Transfer.SetUIState(true);
}
DupliJs.Pack.Transfer.UpdateTransferLog(vm);
},
function(result, data, funcData, textStatus, jqXHR) {
if (data.message != '') {
<?php $alert6->showAlert(); ?>
$("#<?php echo esc_js($alert6->getID()); ?>_message").html(data.message);
}
DupliJs.Pack.Transfer.SetUIState(false);
console.log(data);
}, {
showProgress: false
}
);
};
/* METHOD: Updates the transfer log with the information from the view model */
DupliJs.Pack.Transfer.UpdateTransferLog = function(vm) {
$("#dup-transfer-transfer-log table tbody").empty();
var row_style, row_html;
for (var i = 0; i < vm.transfer_logs.length; i++) {
var transfer_log = vm.transfer_logs[i];
console.log(transfer_log);
row_style = (i % 2) ? ' alternate' : '';
switch (transfer_log.status_text) {
case 'Pending':
row_style += ' status-pending';
break;
case 'Running':
row_style += ' status-running';
break;
case 'Failed':
row_style += ' status-failed';
break;
default:
row_style += ' status-normal';
break;
}
row_html =
`<tr class="package-row ${row_style}">
<td>${transfer_log.started}</td>
<td>${transfer_log.stopped}</td>
<td>${transfer_log.status_text}</td>
<td>${transfer_log.storage_type_text}</td>
<td>${transfer_log.message}</td>
</tr>`;
$("#dup-transfer-transfer-log table tbody").append(row_html);
$('#dup-pack-details-trans-log-count').html('<?php esc_html_e('Log Items:', 'duplicator-pro') ?> ' + (i + 1));
}
if (i == 0) {
var row_html = '<tr><td colspan="5" style="text-align:center">' +
'<?php esc_html_e('- No transactions found for this Backup -', 'duplicator-pro'); ?></td></tr>';
$("#dup-transfer-transfer-log table tbody").append(row_html);
}
};
//INIT
DupliJs.Pack.Transfer.GetPackageState();
setInterval(DupliJs.Pack.Transfer.GetPackageState, 8000);
});
</script>

View File

@@ -0,0 +1,128 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined('ABSPATH') || exit;
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\Views\TplMng;
use Duplicator\Core\Views\Notifications;
use Duplicator\Models\GlobalEntity;
use Duplicator\Models\SystemGlobalEntity;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
use Duplicator\Package\PackageUtils;
use Duplicator\Views\PackageListTable;
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var bool $blur
*/
$tplMng = TplMng::getInstance();
$system_global = SystemGlobalEntity::getInstance();
// Filter out failed backups (status < 0) from the main backup list
$statusConditions = [
[
'op' => '>=',
'status' => 0,
],
];
$totalElements = PackageUtils::getNumPackages([DupPackage::getBackupType()], $statusConditions);
$statusActive = DupPackage::isPackageRunning();
$activePackage = DupPackage::getNextActive();
$isTransfer = $activePackage === null ? false : $activePackage->getStatus() == AbstractPackage::STATUS_STORAGE_PROCESSING;
$pager = new PackageListTable();
$perPage = $pager->get_per_page();
$currentPage = $statusActive && !$isTransfer ? 1 : $pager->get_pagenum();
$offset = ($currentPage - 1) * $perPage;
$global = GlobalEntity::getInstance();
do_action('duplicator_before_packages_table_action');
?>
<form
id="form-duplicator"
method="post"
class="<?php echo esc_attr($tplData['blur'] ? 'dup-mock-blur' : ''); ?>">
<?php PackagesPageController::getInstance()
->getActionByKey(PackagesPageController::ACTION_STOP_BUILD)->getActionNonceFileds(); ?>
<input type="hidden" id="stop-backup-id" name="stop-backup-id" />
<?php $tplMng->render('admin_pages/packages/toolbar'); ?>
<table class="widefat dup-table-list dup-packtbl striped" aria-label="Backup List">
<?php
$tplMng->render(
'admin_pages/packages/packages_table_head',
['totalElements' => $totalElements]
);
if ($totalElements == 0) {
$tplMng->render('admin_pages/packages/no_elements_row');
} else {
DupPackage::dbSelectByStatusCallback(
function (DupPackage $package): void {
TplMng::getInstance()->render(
'admin_pages/packages/package_row',
['package' => $package]
);
},
$statusConditions,
$perPage,
$offset,
'`id` DESC',
[
PackageUtils::DEFAULT_BACKUP_TYPE,
]
);
}
$tplMng->render(
'admin_pages/packages/packages_table_foot',
['totalElements' => $totalElements]
); ?>
</table>
</form>
<?php if ($totalElements > $perPage) { ?>
<form id="form-duplicator-nav" method="post">
<div class="dup-paged-nav tablenav">
<?php if ($statusActive > 0) : ?>
<div id="dupli-paged-progress" style="padding-right: 10px">
<i class="fas fa-circle-notch fa-spin fa-lg fa-fw"></i>
<i><?php esc_html_e('Paging disabled during build...', 'duplicator-pro'); ?></i>
</div>
<?php else : ?>
<div id="dupli-paged-buttons">
<?php $pager->display_pagination($totalElements, $perPage); ?>
</div>
<?php endif; ?>
</div>
</form>
<?php } else { ?>
<div style="float:right; padding:10px 5px">
<?php echo esc_html(sprintf(_n('%s item', '%s items', $totalElements, 'duplicator-pro'), $totalElements)); ?>
</div>
<?php
}
$tplMng->render(
'admin_pages/packages/packages_scripts',
[
'perPage' => $perPage,
'offset' => $offset,
'currentPage' => $currentPage,
'stattiBackupType' => DupPackage::getBackupType(),
]
);

View File

@@ -0,0 +1,38 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<tr class="dupli-nopackages">
<td colspan="11" class="dup-list-nopackages">
<br />
<i class="fa fa-archive fa-sm"></i>
<?php esc_html_e("No Backups Found", 'duplicator-pro'); ?><br />
<i><?php esc_html_e("Click 'Add New' to Backup Site", 'duplicator-pro'); ?></i>
<div class="dup-quick-start">
<b><?php esc_html_e("New to Duplicator?", 'duplicator-pro'); ?></b><br />
<a
class="dup-quick-start-link"
href="<?php echo esc_url(DUPLICATOR_BLOG_URL . 'knowledge-base-article-categories/quick-start/'); ?>"
target="_blank">
<?php esc_html_e("Visit the 'Quick Start' guide!", 'duplicator-pro'); ?>
</a>
</div>
<div style="height:75px">&nbsp;</div>
</td>
</tr>

View File

@@ -0,0 +1,47 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
if ($tplMng->getDataValueBoolRequired('blur')) {
return;
}
$disableCreate = DupPackage::isPackageRunning() || DupPackage::isPackageCancelling();
if (CapMng::can(CapMng::CAP_CREATE, false)) {
$tipContent = __(
'Create a new backup. If a backup is currently running then this button will be disabled.',
'duplicator-pro'
);
?>
<span
class="dup-new-package-wrapper"
data-tooltip="<?php echo esc_attr($tipContent); ?>">
<a
href="<?php echo esc_url(PackagesPageController::getInstance()->getPackageBuildS1Url()); ?>"
id="dupli-create-new"
class="button primary tiny font-bold margin-bottom-0 <?php echo $disableCreate ? 'disabled' : ''; ?>">
<b><?php esc_html_e('Add New', 'duplicator-pro'); ?></b>
</a>
</span>
<?php
}
do_action('duplicator_backups_page_header_after');

View File

@@ -0,0 +1,33 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
*/
$package = $tplMng->getDataValueObjRequired('package', DupPackage::class);
$pendingCancelIds = $tplMng->getDataValueArray('pending_cancelled_package_ids');
// If its in the pending cancels consider it stopped
if (in_array($package->getId(), $pendingCancelIds)) {
$status = AbstractPackage::STATUS_PENDING_CANCEL;
} else {
$status = $package->getStatus();
}
if ($package->getStatus() >= AbstractPackage::STATUS_COMPLETE) {
$tplMng->render('admin_pages/packages/package_row_complete', ['status' => $status]);
} else {
$tplMng->render('admin_pages/packages/package_row_incomplete', ['status' => $status]);
}
$tplMng->render('admin_pages/packages/package_row_building', ['status' => $status]);

View File

@@ -0,0 +1,87 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\CapMng;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplData['package'];
/** @var int */
$status = $tplData['status'];
if ($status <= AbstractPackage::STATUS_PRE_PROCESS || $status >= AbstractPackage::STATUS_COMPLETE) {
return;
}
?>
<?php
$progress = $package->getProgress();
$packageId = (int) $package->getId();
?>
<tr class="dup-row-progress" data-package-id="<?php echo (int) $packageId; ?>">
<td colspan="11">
<div class="wp-filter dup-build-msg">
<!-- PROGRESS -->
<div class="dupli-progress-status-message">
<div class="status-hdr">
<span class="phase-name-<?php echo (int) $packageId; ?>">
<?php echo esc_html($progress['phaseName']); ?>
</span>&nbsp;
<i class="fa fa-gear fa-sm fa-spin"></i>&nbsp;
<span class="status-progress-<?php echo (int) $packageId; ?>">
<?php
if ($progress['percent'] > 0) {
echo (float) round($progress['percent'], 1) . '%';
}
?>
</span>
<span class="status-<?php echo (int) $packageId; ?> no-display">
<?php echo (int) $status; ?>
</span>
</div>
<small class="xsmall phase-message-<?php echo (int) $packageId; ?>">
<?php echo esc_html($progress['message']); ?>
</small>
</div>
<div class="dup-progress-bar-area">
<div class="dupli-meter-wrapper">
<div class="dupli-meter green dupli-fullsize">
<span></span>
</div>
<span class="text"></span>
</div>
</div>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<button
onclick="DupliJs.Pack.StopBuild(<?php echo (int) $package->getId(); ?>); return false;"
class="button hollow secondary small dup-build-stop-btn display-inline">
<i class="fa fa-times fa-sm"></i>&nbsp;
<?php
if ($status >= AbstractPackage::STATUS_STORAGE_PROCESSING) {
esc_html_e('Stop Transfer', 'duplicator-pro');
} elseif ($status > AbstractPackage::STATUS_PRE_PROCESS) {
esc_html_e('Stop Build', 'duplicator-pro');
} else {
esc_html_e('Cancel Pending', 'duplicator-pro');
}
?>
</button>
<?php } ?>
</div>
</td>
</tr>

View File

@@ -0,0 +1,137 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\PackageUtils;
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\UserUIOptions;
use Duplicator\Models\GlobalEntity;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplData['package'];
/** @var int */
$status = $tplData['status'];
if ($status < AbstractPackage::STATUS_COMPLETE) {
return;
}
$global = GlobalEntity::getInstance();
$isRecoverable = RecoveryPackage::isPackageIdRecoverable($package->getId());
$isRecoverPoint = (RecoveryPackage::getRecoverPackageId() === $package->getId());
$pack_name = $package->getName();
$pack_archive_size = $package->Archive->Size;
$pack_dbonly = $package->isDBOnly();
$brand = $package->Brand;
//Links
$uniqueid = $package->getNameHash();
$archive_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) != false);
$installer_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_INSTALLER) != false);
$progress_error = '';
//ROW CSS
$rowClasses = [''];
$rowClasses[] = 'dup-row';
$rowClasses[] = 'dup-row-complete';
$rowClasses[] = ($isRecoverPoint) ? 'dup-recovery-package' : '';
$rowCSS = trim(implode(' ', $rowClasses));
//ArchiveInfo
$archive_name = $package->Archive->getFileName();
$archiveDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_ARCHIVE);
$installerDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_INSTALLER);
$installerFullName = $package->Installer->getInstallerName();
$isBackupAvailable = ($package->haveRemoteStorage() || $package->haveLocalStorage());
//Lang Values
$txt_DatabaseOnly = __('Database Only', 'duplicator-pro');
$txt_BackupNotAvailable = __('Backup doesn\'t exist', 'duplicator-pro');
switch ($package->getExecutionType()) {
case DupPackage::EXEC_TYPE_MANUAL:
$package_type_string = __('Manual', 'duplicator-pro');
break;
case DupPackage::EXEC_TYPE_SCHEDULED:
$package_type_string = __('Schedule', 'duplicator-pro');
break;
case DupPackage::EXEC_TYPE_RUN_NOW:
$lang_schedule = __('Schedule', 'duplicator-pro');
$lang_title = __('This Backup was started manually from the schedules page.', 'duplicator-pro');
$package_type_string = "{$lang_schedule}<span><sup>&nbsp;<i class='fas fa-cog fa-sm pointer' title='{$lang_title}'></i>&nbsp;</sup><span>";
break;
default:
$package_type_string = __('Unknown', 'duplicator-pro');
break;
}
$packageDetailsURL = PackagesPageController::getInstance()->getPackageDetailsURL($package->getId());
$createdFormat = UserUIOptions::getInstance()->get(UserUIOptions::VAL_CREATED_DATE_FORMAT);
?>
<tr
id="dup-row-pack-id-<?php echo (int) $package->getId(); ?>"
data-package-id="<?php echo (int) $package->getId(); ?>"
class="<?php echo esc_attr($rowCSS); ?>">
<td class="dup-check-column dup-cell-chk">
<label for="<?php echo (int) $package->getId(); ?>">
<input
name="delete_confirm"
type="checkbox"
id="<?php echo (int) $package->getId(); ?>"
data-archive-name="<?php echo esc_attr($archive_name); ?>"
data-installer-name="<?php echo esc_attr($installerFullName); ?>" />
</label>
</td>
<td class="dup-name-column dup-cell-name">
<?php echo esc_html($pack_name); ?>
</td>
<td class="dup-note-column">
<?php echo esc_html($package->notes); ?>
</td>
<td class="dup-storages-column">
</td>
<td class="dup-flags-column">
<?php $tplMng->render('admin_pages/packages/row_parts/falgs_cell'); ?>
</td>
<td class="dup-size-column">
<?php echo esc_html(SnapString::byteSize($pack_archive_size)); ?>
</td>
<td class="dup-created-column">
<?php echo esc_html(PackageUtils::formatLocalDateTime($package->getCreated(), $createdFormat)); ?>
</td>
<td class="dup-age-column">
<?php echo esc_html($package->getPackageLife('human')); ?>
</td>
<td class="dup-cell-btns dup-download-column" <?php echo $isBackupAvailable ? '' : 'data-tooltip="' . esc_attr($txt_BackupNotAvailable) . '"'; ?>>
<?php $tplMng->render('admin_pages/packages/row_parts/download_buttons'); ?>
</td>
<td class="dup-cell-btns dup-restore-column" <?php echo $isBackupAvailable ? '' : 'data-tooltip="' . esc_attr($txt_BackupNotAvailable) . '"'; ?>>
<?php $tplMng->render('admin_pages/packages/row_parts/restore_backup_button'); ?>
</td>
<td class="dup-cell-btns dup-cell-toggle-btn dup-toggle-details dup-details-column">
<span class="full-cell-button link-style">
<i class="fa-solid fa-plus"></i>
</span>
</td>
</tr>
<tr id="dup-row-pack-id-<?php echo (int) $package->getId(); ?>-details" class="dup-row-details no-display">
<?php $tplMng->render('admin_pages/packages/row_parts/details_package'); ?>
</tr>

View File

@@ -0,0 +1,143 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\PackageUtils;
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\UserUIOptions;
use Duplicator\Models\GlobalEntity;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplData['package'];
$global = GlobalEntity::getInstance();
/** @var int */
$status = $tplData['status'];
if ($status >= AbstractPackage::STATUS_COMPLETE) {
return;
}
$isRecoverable = RecoveryPackage::isPackageIdRecoverable($package->getId());
$isRecoverPoint = (RecoveryPackage::getRecoverPackageId() === $package->getId());
$pack_name = $package->getName();
$pack_archive_size = $package->Archive->Size;
$pack_namehash = $package->getNameHash();
$pack_dbonly = $package->isDBOnly();
$brand = $package->Brand;
//Links
$uniqueid = $package->getNameHash();
$archive_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) != false);
$installer_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_INSTALLER) != false);
$progress_error = '';
//ROW CSS
$rowClasses = [''];
$rowClasses[] = 'dup-row';
$rowClasses[] = 'dup-row-incomplete';
$rowClasses[] = ($isRecoverPoint) ? 'dup-recovery-package' : '';
$rowCSS = trim(implode(' ', $rowClasses));
//ArchiveInfo
$archive_name = $package->Archive->getFileName();
$archiveDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_ARCHIVE);
$installerDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_INSTALLER);
$installerFullName = $package->Installer->getInstallerName();
$createdFormat = UserUIOptions::getInstance()->get(UserUIOptions::VAL_CREATED_DATE_FORMAT);
//Lang Values
$txt_DatabaseOnly = __('Database Only', 'duplicator-pro');
$cellErrCSS = '';
if ($status < AbstractPackage::STATUS_COPIEDPACKAGE) {
// In the process of building
$size = 0;
$tmpSearch = glob(DUPLICATOR_SSDIR_PATH_TMP . "/{$pack_namehash}_*");
if (is_array($tmpSearch)) {
$result = @array_map('filesize', $tmpSearch);
$size = array_sum($result);
}
$pack_archive_size = $size;
}
if ($status < 0) {
//FAILURES AND CANCELLATIONS
switch ($status) {
case AbstractPackage::STATUS_ERROR:
$cellErrCSS = 'dup-cell-err';
break;
case AbstractPackage::STATUS_BUILD_CANCELLED:
case AbstractPackage::STATUS_STORAGE_CANCELLED:
$cellErrCSS = 'dup-cell-cancelled';
break;
}
}
?>
<tr
id="dup-row-pack-id-<?php echo (int) $package->getId(); ?>"
data-package-id="<?php echo (int) $package->getId(); ?>"
data-status="<?php echo (int) $status; ?>"
class="<?php echo esc_attr($rowCSS); ?>">
<td class="dup-check-column dup-cell-chk">
<label for="<?php echo (int) $package->getId(); ?>">
<input name="delete_confirm"
type="checkbox" id="<?php echo (int) $package->getId(); ?>"
<?php echo ($status >= AbstractPackage::STATUS_PRE_PROCESS) ? 'disabled="disabled"' : ''; ?> />
</label>
</td>
<td class="dup-name-column dup-cell-name">
<?php echo esc_html($pack_name); ?>
</td>
<td class="dup-note-column">
</td>
<td class="dup-storages-column">
</td>
<td class="dup-flags-column">
<?php $tplMng->render('admin_pages/packages/row_parts/falgs_cell'); ?>
</td>
<td class="dup-size-column">
<?php if ($status >= AbstractPackage::STATUS_PRE_PROCESS) {
echo esc_html($package->getBuildSize());
} else {
esc_html_e('N/A', 'duplicator-pro');
} ?>
</td>
<td class="dup-created-column">
<?php echo esc_html(PackageUtils::formatLocalDateTime($package->getCreated(), $createdFormat)); ?>
</td>
<td class="dup-age-column">
<?php echo esc_html($package->getPackageLife('human')); ?>
</td>
<td class="dup-cell-incomplete <?php echo esc_attr($cellErrCSS); ?> no-select" colspan="3">
<?php if ($status >= AbstractPackage::STATUS_PRE_PROCESS) { ?>
<i><?php esc_html_e('Creating Backup ...', 'duplicator-pro'); ?></i>
<?php } else {
$tplMng->render(
'admin_pages/packages/row_parts/package_progress_error',
[
'package' => $package,
'status' => $status,
]
);
} ?>
</td>
</tr>

View File

@@ -0,0 +1,677 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Controllers\StoragePageController;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Libs\Snap\SnapJson;
use Duplicator\Views\UI\UiDialog;
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$perPage = $tplMng->getDataValueInt('perPage', 10);
$offset = $tplMng->getDataValueInt('offset', 0);
$currentPage = $tplMng->getDataValueInt('currentPage', 1);
$statiiType = $tplMng->getDataValueStringRequired('stattiBackupType');
$tplMng->render('admin_pages/tools/recovery/widget/recovery-widget-scripts');
$tplMng->render('admin_pages/packages/remote_download/scripts');
$transferBaseUrl = PackagesPageController::getInstance()->getPackageTransferUrl();
$reloadPackagesURL = $ctrlMng->getCurrentLink(
['paged' => $currentPage]
);
/* ------------------------------------------
* ALERT: Remote > Storage items */
$remoteDlg = new UiDialog();
$remoteDlg->width = 750;
$remoteDlg->height = 475;
$remoteDlg->title = __('Storage Locations', 'duplicator-pro');
$remoteDlg->message = __('Loading. Please Wait...', 'duplicator-pro');
$remoteDlg->boxClass = 'dup-packs-remote-store-dlg';
$remoteDlg->initAlert();
/* ------------------------------------------
* ALERT: Bulk action > no selection */
$alert1 = new UiDialog();
$alert1->title = __('Bulk Action Required', 'duplicator-pro');
$alert1->templatePath = 'parts/dialogs/contents/bulk-action-not-selected';
$alert1->initAlert();
/* ------------------------------------------
* ALERT: Bulk action > no backup selected */
$alert2 = new UiDialog();
$alert2->title = __('Selection Required', 'duplicator-pro');
$alert2->wrapperClassButtons = 'dupli-dlg-nopackage-sel-bulk-action-btns';
$alert2->templatePath = 'parts/dialogs/contents/bulk-action-delete-not-selected';
$alert2->initAlert();
/* ------------------------------------------
* ALERT: Process > Error undefined */
$alert4 = new UiDialog();
$alert4->title = __('ERROR!', 'duplicator-pro');
$alert4->message = __('Got an error or a warning: undefined', 'duplicator-pro');
$alert4->initAlert();
/* ------------------------------------------
* ALERT: Process > Error no details */
$alert5 = new UiDialog();
$alert5->title = $alert4->title;
$alert5->message = __('Failed to get details.', 'duplicator-pro');
$alert5->initAlert();
/* ------------------------------------------
* CONFIRM: Delete Backups? */
$confirm1 = new UiDialog();
$confirm1->height = 280;
$confirm1->title = __('Delete Backups?', 'duplicator-pro');
$confirm1->wrapperClassButtons = 'dupli-dlg-detete-packages-btns';
$confirm1->message = __('Are you sure you want to delete the selected Backup(s)?', 'duplicator-pro');
$confirm1->message .= '<br/><br/>';
$confirm1->message .= '<small><i>' . __(
'Note: This action removes only Backups located on this server. If a remote Backup was created then it will not be removed or affected.',
'duplicator-pro'
) . '</i></small>';
$confirm1->progressText = __('Removing Backups, Please Wait...', 'duplicator-pro');
$confirm1->jsCallback = 'DupliJs.Pack.Delete()';
$confirm1->initConfirm();
/* ------------------------------------------
* ALERT: Recovery > toolbar button */
$toolBarRecoveryButtonInfo = new UiDialog();
$toolBarRecoveryButtonInfo->showButtons = false;
$toolBarRecoveryButtonInfo->height = 600;
$toolBarRecoveryButtonInfo->width = 600;
$toolBarRecoveryButtonInfo->title = __('Disaster Recovery', 'duplicator-pro');
$toolBarRecoveryButtonInfo->templatePath = 'admin_pages/packages/recovery_info/info';
$toolBarRecoveryButtonInfo->initAlert();
/* ------------------------------------------
* ALERT: Recovery */
$availableRecoveryBox = new UiDialog();
$availableRecoveryBox->title = __('Disaster Recovery Available', 'duplicator-pro');
$availableRecoveryBox->boxClass = 'dup-recovery-box-info';
$availableRecoveryBox->showButtons = false;
$availableRecoveryBox->width = 600;
$availableRecoveryBox->height = 400;
$availableRecoveryBox->message = '';
$availableRecoveryBox->initAlert();
$unavailableRecoveryBox = new UiDialog();
$unavailableRecoveryBox->title = __('Disaster Recovery Unavailable', 'duplicator-pro');
$unavailableRecoveryBox->boxClass = 'dup-recovery-box-info';
$unavailableRecoveryBox->showButtons = false;
$unavailableRecoveryBox->width = 600;
$unavailableRecoveryBox->height = 700;
$unavailableRecoveryBox->message = '';
$unavailableRecoveryBox->initAlert();
/* ------------------------------------------
* ALERT: Package overeview > Help */
$linkInfoDlg = new UiDialog();
$linkInfoDlg->width = 700;
$linkInfoDlg->height = 550;
$linkInfoDlg->title = __('Duplicator Pro Tutorial', 'duplicator-pro');
$linkInfoDlg->templatePath = 'admin_pages/packages/packages_overview_help';
$linkInfoDlg->initAlert();
$baseStorageEditURL = StoragePageController::getInstance()->getMenuLink(
null,
null,
[
ControllersManager::QUERY_STRING_INNER_PAGE => StoragePageController::INNER_PAGE_EDIT,
]
);
?>
<script>
jQuery(document).ready(function($) {
DupliJs.Pack.RestorePackageId = null;
DupliJs.PackagesTable = $('.dup-packtbl');
/**
* Click event to expands each row and show Backup details
*
* @returns void
*/
$('th#dup-header-chkall').on('click', function() {
var $this = $(this);
var $icon = $this.find('i');
if ($icon.hasClass('fa-plus')) {
$icon.removeClass('fa-plus').addClass('fa-minus');
$("tr.dup-row-complete").each(function() {
$(this).find('.dup-cell-toggle-btn i').removeClass('fa-plus').addClass('fa-minus');
$(this).next('tr').removeClass('no-display');
});
} else {
$icon.removeClass('fa-minus').addClass('fa-plus');
$("tr.dup-row-complete").each(function() {
$(this).find('.dup-cell-toggle-btn i').removeClass('fa-minus').addClass('fa-plus');
$(this).next('tr').addClass('no-display');
});
}
});
/**
* Click event to expands each row and show Backup details
*
* @returns void
*/
$('td.dup-cell-toggle-btn').on('click', function(e) {
var $this = $(this);
var $icon = $this.find('i');
if ($icon.hasClass('fa-plus')) {
$icon.removeClass('fa-plus').addClass('fa-minus');
$(this).closest('tr').next('tr').removeClass('no-display');
} else {
$icon.removeClass('fa-minus').addClass('fa-plus');
$(this).closest('tr').next('tr').addClass('no-display');
}
});
$('.dupli-quick-fix-notice').on('click', '.dupli-quick-fix', function() {
var $this = $(this),
params = JSON.parse($this.attr('data-param')),
toggle = $this.attr('data-toggle'),
id = $this.attr('data-id'),
fix = $(toggle),
button = {
loading: function() {
$this.prop('disabled', true)
.addClass('disabled')
.html('<i class="fas fa-circle-notch fa-spin fa-fw"></i> <?php esc_html_e('Please Wait...', 'duplicator-pro') ?>');
},
reset: function() {
$this.prop('disabled', false)
.removeClass('disabled')
.html("<i class='fa fa-wrench' aria-hidden='true'></i>&nbsp; <?php esc_html_e('Resolve This', 'duplicator-pro') ?>");
}
},
error = {
message: function(text) {
fix.append(
"&nbsp; <span style='color:#cc0000' id='" +
toggle.replace('#', '') +
"-error'><i class='fa fa-exclamation-triangle'></i>&nbsp; " + text + "</span>"
);
},
remove: function() {
if ($(toggle + "-error"))
$(toggle + "-error").remove();
}
};
error.remove();
button.loading();
DupliJs.Util.ajaxWrapper({
action: 'duplicator_quick_fix',
setup: params,
id: id,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_quick_fix')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
fix.remove();
// If there is no fixes and notifications - remove container
if (typeof funcData.recommended_fixes != 'undefined') {
if (funcData.recommended_fixes == 0) {
$('.dupli-quick-fix-notice').remove();
}
}
DupliJs.addAdminMessage(
"<?php esc_html_e('Successfully applied quick fix!', 'duplicator-pro'); ?>",
'success', {
hideDelay: 5000
}
);
} else {
button.reset();
error.message(funcData.message);
}
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
button.reset();
error.message('<?php esc_html_e('Unexpected Error!', 'duplicator-pro') ?>');
console.log(data);
return '';
}
);
});
$('.dupli-toolbar-recovery-info').click(function() {
if ($(this).hasClass('dup-recovery-unset')) {
<?php $toolBarRecoveryButtonInfo->showAlert(); ?>
} else {
let openUrl = <?php echo json_encode($ctrlMng->getMenuLink($ctrlMng::TOOLS_SUBMENU_SLUG, ToolsPageController::L2_SLUG_RECOVERY)); ?>;
window.open(openUrl, "_self");
}
});
//DOWNLOAD MENU
$('button.dup-dnload-btn').click(function(e) {
var $menu = $(this).parent().find('nav.dup-dnload-menu-items');
if ($menu.is(':visible')) {
$menu.addClass('no-display');
} else {
$('nav.dup-dnload-menu-items').addClass('no-display');
$menu.removeClass('no-display');
}
return false;
});
$(document).click(function(e) {
var className = e.target.className;
if (className != 'dupli-menu-x') {
$('nav.dup-dnload-menu-items').addClass('no-display');
}
});
$("nav.dup-dnload-menu-items button").each(function() {
$(this).addClass('dupli-menu-x');
});
$("nav.dup-dnload-menu-items button span").each(function() {
$(this).addClass('dupli-menu-x');
});
/* Creats a comma seperate list of all selected Backup ids */
DupliJs.Pack.GetDeleteList = function() {
var arr = [];
$("input[name=delete_confirm]:checked").each(function() {
arr.push(this.id);
});
return arr;
}
DupliJs.Pack.BackupRestore = function() {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_restore_backup_prepare',
packageId: DupliJs.Pack.RestorePackageId,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_restore_backup_prepare')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
window.location.href = data.funcData;
},
function(result, data, funcData, textStatus, jqXHR) {
alert('FAIL');
}
);
};
/* Provides the correct confirmation items when deleting Backups */
DupliJs.Pack.ConfirmDelete = function() {
$('#dupli-dlg-confirm-delete-btns input').removeAttr('disabled');
if ($("#dup-pack-bulk-actions").val() != "delete") {
<?php $alert1->showAlert(); ?>
return;
}
var list = DupliJs.Pack.GetDeleteList();
if (list.length == 0) {
<?php $alert2->showAlert(); ?>
return;
}
<?php $confirm1->showConfirm(); ?>
}
/* Removes all selected Backup sets with ajax call */
DupliJs.Pack.Delete = function() {
var packageIds = DupliJs.Pack.GetDeleteList();
var pageCount = $('#current-page-selector').val();
var pageItems = $('input[name="delete_confirm"]');
DupliJs.Util.ajaxWrapper({
action: 'duplicator_package_delete',
package_ids: packageIds,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_package_delete')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
//Increment back a page-set if no items are left
if ($('#form-duplicator-nav').length) {
if (pageItems.length == packageIds.length)
$('#current-page-selector').val(pageCount - 1);
$('#form-duplicator-nav').submit();
} else {
window.location.reload();
}
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(okMsgContent, 'notice');
return '';
}
);
}
/* Toogles the Bulk Action Check boxes */
DupliJs.Pack.SetDeleteAll = function() {
var state = $('input#dup-chk-all').is(':checked') ? 1 : 0;
$("input[name=delete_confirm]").each(function() {
this.checked = (state) ? true : false;
});
}
/* Stops the build from running */
DupliJs.Pack.StopBuild = function(packageID) {
$('#stop-backup-id').val(packageID);
$('#form-duplicator').submit();
$('.dup-build-stop-btn').html('<?php esc_html_e("Cancelling...", 'duplicator-pro'); ?>');
$('.dup-build-stop-btn').prop('disabled', true);
}
/* Redirects to the Backups detail screen using the Backup id */
DupliJs.Pack.OpenPackTransfer = function(id) {
window.location.href = '<?php echo esc_url_raw(SnapJson::jsonEncode($transferBaseUrl)) ?>' + '&id=' + id;
}
/* Shows remote storage location dialogs */
DupliJs.Pack.ShowRemote = function(package_id, name) {
<?php $remoteDlg->showAlert(); ?>
DupliJs.Util.ajaxWrapper({
action: 'duplicator_get_storage_details',
package_id: package_id,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_get_storage_details')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (!funcData.success) {
var text = "<?php esc_html_e('Got an error or a warning', 'duplicator-pro'); ?>: " + funcData.message;
$('#TB_window .dupli-dlg-alert-txt').html(text);
return false;
}
var info = '<div class="dup-dlg-store-remote">';
for (storage_provider_key in funcData.storage_providers) {
var store = funcData.storage_providers[storage_provider_key];
info += store.infoHTML;
}
info += '</div>';
info += "<small><a href='" + funcData.logURL + "' class='dup-dlg-store-log-link' target='_blank'>" +
'<?php echo esc_html__('[Backup Build Log]', 'duplicator-pro'); ?>' + "</a></small>";
$('#TB_window .dupli-dlg-alert-txt').html(info);
},
function(data) {
<?php $alert5->showAlert(); ?>
console.log(data);
return '';
}
);
return false;
};
$('.dup-restore-backup').click(function(event) {
event.preventDefault();
let packageId = $(this).data('package-id');
if ($(this).data('needs-download') == true) {
DupliJs.Pack.ShowRemoteDownloadOptions(packageId, 'restore');
} else {
DupliJs.Pack.ShowRestoreModal(packageId);
}
});
$('.dup-remote-download').click(function(event) {
event.preventDefault();
let packageId = $(this).data('package-id');
DupliJs.Pack.ShowRemoteDownloadOptions(packageId, 'download');
});
DupliJs.Pack.ShowRestoreModal = function(packageId) {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_backup_redirect',
packageId: packageId,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_backup_redirect')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
let box = new DuplicatorModalBox({
url: data.funcData.redirect_url,
openCallback: function(iframe, modalObj) {
let body = $(iframe.contentWindow.document.body);
// For old Backups
body.find("#content").css('background-color', 'white');
body.on("click", "#s1-deploy-btn", function() {
modalObj.disableClose();
});
}
});
box.open();
//window.location.href = data.funcData.redirect_url;
} else {
DupliJs.addAdminMessage(funcData.message, 'error');
}
return '';
},
function(data) {
<?php $alert5->showAlert(); ?>
console.log(data);
return '';
}
);
return false;
}
<?php if (isset($tplData['triggerRestore']) && $tplData['triggerRestore'] !== -1) : ?>
setTimeout(function() {
DupliJs.Pack.ShowRestoreModal(<?php echo (int) $tplData['triggerRestore']; ?>);
}, 500);
<?php endif; ?>
/* Virtual states that UI uses for easier tracking of the three general states a Backup can be in*/
DupliJs.Pack.ProcessingStats = {
PendingCancellation: -3,
Pending: 0,
Building: 1,
Storing: 2,
Finished: 3,
}
DupliJs.Pack.setIntervalID = -1;
DupliJs.Pack.SetUpdateInterval = function(period) {
if (DupliJs.Pack.setIntervalID != -1) {
clearInterval(DupliJs.Pack.setIntervalID);
DupliJs.Pack.setIntervalID = -1
}
DupliJs.Pack.setIntervalID = setInterval(DupliJs.Pack.UpdateUnfinishedPackages, period * 1000);
}
DupliJs.Pack.UpdateUnfinishedPackages = function() {
let packagesTables = $('.dup-packtbl');
var data = {
action: 'duplicator_get_package_statii',
nonce: '<?php echo esc_js(wp_create_nonce("duplicator_get_package_statii")); ?>',
offset: <?php echo (int) $offset; ?>,
limit: <?php echo (int) $perPage; ?>,
backupType: '<?php echo esc_js($statiiType); ?>',
}
$.ajax({
type: "POST",
url: ajaxurl,
timeout: 10000000,
data: data,
complete: function() {},
success: function(result) {
let packagesTable = $('.dup-packtbl');
let currentFirstPackageId = -1;
let statiiFistPackageId = -1;
if (packagesTables.find('.dup-row').length) {
currentFirstPackageId = packagesTables.find('.dup-row').first().data('package-id');
}
let statusInfo = result.data.funcData;
if (statusInfo.length) {
statiiFistPackageId = statusInfo[0].ID;
}
if (currentFirstPackageId != statiiFistPackageId) {
window.location = <?php echo wp_json_encode($reloadPackagesURL); ?>;
}
let activePackagePresent = false;
for (package_info_key in statusInfo) {
let package_info = statusInfo[package_info_key];
let statusNode = packagesTable.find('.status-' + package_info.ID);
let sizeNode = packagesTable.find('#dup-row-pack-id-' + package_info.ID + ' .dup-size-column');
let packageNode = packagesTable.find('#dup-row-pack-id-' + package_info.ID);
let currentStatus = parseInt(packageNode.data('status'));
if ((currentStatus >= 0 && currentStatus < 100) || currentStatus == -3) {
activePackagePresent = true;
}
let currentProcessingState;
if (currentStatus == -3) {
currentProcessingState = DupliJs.Pack.ProcessingStats.PendingCancellation;
} else if (currentStatus == 0) {
currentProcessingState = DupliJs.Pack.ProcessingStats.Pending;
} else if ((currentStatus >= 0) && (currentStatus < 75)) {
currentProcessingState = DupliJs.Pack.ProcessingStats.Building;
} else if ((currentStatus >= 75) && (currentStatus < 100)) {
currentProcessingState = DupliJs.Pack.ProcessingStats.Storing;
} else {
// Has to be negative(error) or 100 - both mean complete
currentProcessingState = DupliJs.Pack.ProcessingStats.Finished;
}
if (currentProcessingState == DupliJs.Pack.ProcessingStats.Pending) {
if (package_info.status != 0) {
window.location = window.location.href;
}
} else if (currentProcessingState == DupliJs.Pack.ProcessingStats.Building ||
currentProcessingState == DupliJs.Pack.ProcessingStats.Storing) {
// Check for completion
if (package_info.status == 100 || package_info.status < 0) {
if (DupliJs.Pack.IsRemoteDownloadModalOpen() && package_info.status == 100) {
// do a dynamic form submission to start the restore/download
$('.status-progress-' + package_info.ID).text(100);
DupliJs.Pack.afterRemoteDownloadAction();
} else {
// Backup completed or error - reload to show final state
window.location = window.location.href;
}
break;
} else {
// Update progress - unified logic for all phases
packageNode.data('status', package_info.status);
// Show percentage only if > 0
var progressSpan = $('.status-progress-' + package_info.ID);
if (package_info.status_progress > 0) {
progressSpan.text(package_info.status_progress + '%');
} else {
progressSpan.text('');
}
sizeNode.fadeOut(100, function() {
$(this).text(package_info.size).fadeIn(1000);
});
$('.phase-name-' + package_info.ID).text(package_info.phase_name);
$('.phase-message-' + package_info.ID).html(package_info.status_progress_text);
}
} else if (currentProcessingState == DupliJs.Pack.ProcessingStats.PendingCancellation) {
if ((package_info.status == -2) || (package_info.status == -4)) {
// refresh when its gone to cancelled
window.location = window.location.href;
}
} else if (currentProcessingState == DupliJs.Pack.ProcessingStats.Finished) {
// IF something caused the Backup to come out of finished refresh everything (has to be out of finished or error state)
if ((package_info.status != 100) && (package_info.status > 0)) {
// wait one miutes to prevent a realod loop
setTimeout(function() {
window.location = window.location.href;
}, 60000);
}
}
}
if (activePackagePresent) {
$('#dupli-create-new').addClass('disabled');
packagesTable.find(".dup-restore-backup").prop('disabled', true);
packagesTable.find(".dup-dnload-btn").prop('disabled', true);
packagesTable.find(".dup-remote-download").prop('disabled', true);
DupliJs.Pack.SetUpdateInterval(5);
} else {
$('#dupli-create-new').removeClass('disabled');
packagesTable.find(".dup-restore-backup.can-enabled").prop('disabled', false);
packagesTable.find(".dup-dnload-btn.can-enabled").prop('disabled', false);
packagesTable.find(".dup-remote-download.can-enabled").prop('disabled', false);
// Kick refresh down to 60 seconds if nothing is being actively worked on
DupliJs.Pack.SetUpdateInterval(60);
}
},
error: function(data) {
DupliJs.Pack.SetUpdateInterval(60);
console.log(data);
}
});
};
//Init
DupliJs.UI.Clock(DupliJs._WordPressInitTime);
DupliJs.Pack.SetUpdateInterval(5); // Start with frequent polling, will be adjusted by first response
DupliJs.Pack.UpdateUnfinishedPackages();
$('.dupli-btn-open-recovery-box').click(function(event) {
event.preventDefault();
let packageId = $(this).data('package-id');
DupliJs.Util.ajaxWrapper({
action: 'duplicator_get_recovery_box_content',
packageId: packageId,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_get_recovery_box_content')); ?>'
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
let boxContent = funcData.content;
if (funcData.isRecoverable) {
<?php
$availableRecoveryBox->updateMessage('boxContent');
$availableRecoveryBox->showAlert();
?>
$('.dupli-recovery-download-launcher').off().click(function() {
DupliJs.Pack.downloadLauncher();
});
} else {
<?php
$unavailableRecoveryBox->updateMessage('boxContent');
$unavailableRecoveryBox->showAlert();
?>
}
} else {
DupliJs.addAdminMessage(funcData.message, 'error');
}
return '';
}
);
return false;
});
});
</script>

View File

@@ -0,0 +1,51 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\GlobalEntity;
use Duplicator\Models\Storages\StoragesUtil;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$global = GlobalEntity::getInstance();
$maxDefaultPackages = StoragesUtil::getDefaultStorage()->getMaxPackages();
$toolTipContent = sprintf(
esc_attr__(
'The number of Backups to keep is set at [%d]. To change this setting go to
Duplicator Pro > Storage > Default > Max Backups and change the value, otherwise this note can be ignored.',
'duplicator-pro'
),
$maxDefaultPackages
);
?>
<tfoot>
<tr>
<th colspan="11">
<div class="dup-pack-status-info">
<?php if ($maxDefaultPackages < $tplData['totalElements'] && $maxDefaultPackages != 0) { ?>
<?php echo esc_html__("Note: max backups retention enabled", 'duplicator-pro'); ?>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Storage Backups", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($toolTipContent); ?>">
</i>
<?php } else { ?>
&nbsp;
<?php } ?>
</div>
</th>
</tr>
</tfoot>

View File

@@ -0,0 +1,79 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$tooltipStatusContent = $tplMng->render('admin_pages/packages/packages_table_head_status_icons', [], false);
$tooltopCreatedContent = __(
'Backup date and time expressed in UTC (Coordinated Universal Time).
The displayed date corresponds to the server\'s international time, independent of local time zones.',
'duplicator-pro'
);
?>
<h2 class="screen-reader-text"><?php esc_html_e('Backups list', 'duplicator-pro') ?></h2>
<thead>
<tr>
<th class="dup-check-column" style="width:10px;">
<input
type="checkbox"
id="dup-chk-all"
title="<?php esc_attr_e("Select all Backups", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.SetDeleteAll()"
>
</th>
<th class="dup-name-column" >
<?php esc_html_e("Name", 'duplicator-pro') ?>
</th>
<th class="dup-note-column">
<?php esc_html_e("Note", 'duplicator-pro') ?>
</th>
<th class="dup-storages-column">
<?php esc_html_e("Storages", 'duplicator-pro') ?>
</th>
<th class="dup-flags-column">
<?php esc_html_e("Status", 'duplicator-pro') ?>&nbsp;
<i
class="fa-solid fa-circle-info"
data-tooltip-title="<?php esc_attr_e("Status Icons", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltipStatusContent); ?>"
></i>
</th>
<th class="dup-size-column">
<?php esc_html_e("Size", 'duplicator-pro') ?>
</th>
<th class="dup-created-column">
<?php esc_html_e("Created", 'duplicator-pro') ?>&nbsp;
<i
class="fa-solid fa-circle-info"
data-tooltip-title="<?php esc_attr_e('Backup Date/Time', 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltopCreatedContent); ?>"
></i>
</th>
<th class="dup-age-column">
<?php esc_html_e("Age", 'duplicator-pro') ?>
</th>
<th class="dup-download-column" style="width:75px;"></th>
<th class="dup-restore-column" style="width:25px;"></th>
<th id="dup-header-chkall" class="dup-details-column" >
<?php if ($tplData['totalElements'] > 0) { ?>
<span class="link-style" title="<?php esc_attr_e('Expand/Collapse All', 'duplicator-pro'); ?>" >
<i class="fa-solid fa-plus"></i>
</span>
<?php } ?>
</th>
</tr>
</thead>

View File

@@ -0,0 +1,79 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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
*/
?>
<ul class="dup-status-icons-list no-bullet" >
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-hand" ></i></span>
<?php esc_html_e('Manual Backup', 'duplicator-pro'); ?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-clock" ></i></span>
<?php esc_attr_e('Schedule Backup', 'duplicator-pro') ?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-hard-drive"></i></span>
<?php
echo wp_kses(
__('The Backup is in a Local Storage <b>[clickable]</b>', 'duplicator-pro'),
ViewHelper::GEN_KSES_TAGS
);
?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-cloud"></i></span>
<?php
echo wp_kses(
__('The Backup is in a Remote Storage <b>[clickable]</b>', 'duplicator-pro'),
ViewHelper::GEN_KSES_TAGS
);
?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-database"></i></span>
<?php esc_attr_e('Database Only Backup', 'duplicator-pro') ?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-images"></i></span>
<?php esc_attr_e('Media Only Backup', 'duplicator-pro') ?>
</li>
<li>
<span class="icon-wrapper" ><?php ViewHelper::disasterIcon(true, 'link-style no-decoration'); ?></span>
<?php
echo wp_kses(
__('This Backup is available for Disaster Recovery <b>[clickable]</b>', 'duplicator-pro'),
ViewHelper::GEN_KSES_TAGS
);
?>
</li>
<li>
<span class="icon-wrapper" ><?php ViewHelper::disasterIcon(true, 'green'); ?></span>
<?php
echo wp_kses(
__('Disaster Recovery URL is set on this Backup <b>[clickable]</b>', 'duplicator-pro'),
ViewHelper::GEN_KSES_TAGS
);
?>
</li>
<li>
<span class="icon-wrapper" ><i class="fa-solid fa-clock-rotate-left maroon"></i></span>
<?php esc_attr_e('This Backup is created after the Last Restored Backup', 'duplicator-pro') ?>
</li>
</ul>

View File

@@ -0,0 +1,41 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\RecoveryController;
use Duplicator\Package\Recovery\RecoveryPackage;
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-toolbar-recovery-info margin-bottom-1">
<?php
if (RecoveryPackage::getRecoverPackageId() === false) {
$tplMng->render('admin_pages/packages/recovery_info/no_recovery_set');
} else {
RecoveryController::renderRecoveryWidged(
[
'selector' => false,
'subtitle' => '',
'copyLink' => true,
'copyButton' => true,
'launch' => true,
'download' => true,
'info' => true,
]
);
}
?>
</div>

View File

@@ -0,0 +1,88 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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
*/
?>
<h3 class="dup-title maroon">
<?php ViewHelper::disasterIcon(); ?>&nbsp;<?php esc_html_e('Disaster Recovery - None Set', 'duplicator-pro'); ?>
</h3>
<?php
esc_html_e(
'The recovery point can quickly restore a site to a prior state for any reason. To activate a recovery point follow these steps:',
'duplicator-pro'
);
?>
<ol>
<li>
<?php
printf(
esc_html__('Select a Recovery Backup with the icon %s displayed*.', 'duplicator-pro'),
wp_kses(
ViewHelper::disasterIcon(false),
['i' => ['class' => []]]
)
);
?>
</li>
<li>
<?php
printf(
esc_html_x(
'Open details area %1$s and click the "Recover Backup ..." button.',
'%1$s represents an icon',
'duplicator-pro'
),
'<i class="fas fa-chevron-left fa-sm fa-fw"></i>'
);
?>
</li>
<li>
<?php esc_html_e('Follow the prompts and choose the action to perform.', 'duplicator-pro'); ?>
</li>
</ol>
<hr/>
<p>
<b><?php esc_html_e('Additional Details:', 'duplicator-pro'); ?></b>
<?php
esc_html_e(
'Once a recovery point is set you can save the "Recovery Key" URL in a safe place for restoration later in the event your site goes down, gets
hacked or basically any reason you need to restore a site. In the event you still have access to your site you can also launch the recover
wizard from the details menu.',
'duplicator-pro'
);
?>
</p>
<small>
<i>
<?php
printf(
esc_html__(
'*Note: If you do not see a Recovery Backup %s icon in the Backups List.
Then be sure to build a full Backup that does not exclude any of the core WordPress files or database tables.
These core files and tables are required to build a valid recovery point.',
'duplicator-pro'
),
wp_kses(
ViewHelper::disasterIcon(false),
['i' => ['class' => []]]
)
);
?>
</i>
</small>

View File

@@ -0,0 +1,66 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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\DupPackage $package
*/
$package = $tplData['package'];
$isRecoverable = RecoveryPackage::isPackageIdRecoverable($package->getId());
if ($isRecoverable) {
$tplMng->render('admin_pages/packages/recovery_info/row_recovery_box_available');
} else {
$tplMng->render('admin_pages/packages/recovery_info/row_recovery_box_unavailable');
}
?>
<hr class="margin-top-1 margin-bottom-1">
<small><i>
<?php
echo wp_kses(
sprintf(
_x(
'%1$sDisaster Recovery%2$s makes it quick and easy to restore your site during an emergency.
You dont need WordPress to be working for this.
Just keep the Disaster Recovery Link in a safe spot and use it when needed, or use the Launcher to restore your backup.',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'tools-recovery') . '" target="_blank">',
'</a>'
),
ViewHelper::GEN_KSES_TAGS
);
?>
<br>
<?php
echo wp_kses(
sprintf(
_x(
'If your backup isnt eligible for Disaster Recovery, you can still use the %1$sRestore Backup button.%2$s',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'restoring-your-backup') . '" target="_blank">',
'</a>'
),
ViewHelper::GEN_KSES_TAGS
);
?>
</i></small>

View File

@@ -0,0 +1,78 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Controllers\RecoveryController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Core\Views\TplMng;
use Duplicator\Package\Recovery\RecoveryPackage;
use Duplicator\Views\ViewHelper;
/**
* Variables
*
* @var ControllersManager $ctrlMng
* @var TplMng $tplMng
* @var array<string, mixed> $tplData
* @var \Duplicator\Package\DupPackage $package
*/
$package = $tplData['package'];
$isRecoverPoint = (RecoveryPackage::getRecoverPackageId() === $package->getId());
$colorClass = ($isRecoverPoint ? 'green' : '');
?>
<h3 class="dup-title margin-top-0">
<?php ViewHelper::disasterIcon(true, $colorClass); ?>&nbsp;
<?php
if ($isRecoverPoint) {
esc_html_e('Disaster Recovery - Is Set on this Backup', 'duplicator-pro');
} else {
esc_html_e('Disaster Recovery - Is Available for this Backup', 'duplicator-pro');
}
?>
</h3>
<?php $tplMng->render('parts/recovery/package_info_mini'); ?>
<hr class="margin-top-1 margin-bottom-1">
<?php if ($isRecoverPoint) {
RecoveryController::renderRecoveryWidged([
'details' => false,
'selector' => false,
'subtitle' => '',
'copyLink' => false,
'copyButton' => true,
'launch' => false,
'download' => true,
'info' => true,
]);
} else { ?>
<form method="post" action="<?php PackagesPageController::getInstance()->getPageUrl(); ?>">
<?php PackagesPageController::getInstance()->getActionByKey(PackagesPageController::ACTION_SET_RECOVERY_POINT)->getActionNonceFileds(); ?>
<input type="hidden" name="recovery_package" value="<?php echo (int) $package->getId(); ?>">
<div class="dupli-recovery-widget-wrapper">
<div class="dupli-recovery-point-actions">
<div class="dupli-recovery-buttons">
<button
class="button primary dupli-btn-set-recovery margin-0"
type="submit">
<span><?php ViewHelper::disasterIcon(); ?>&nbsp;
<?php esc_html_e("Set Disaster Recovery", 'duplicator-pro'); ?></span>&nbsp;
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color dup-base-color white"
data-tooltip-title="<?php esc_attr_e("Activate Recovery", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e("This action will set this Backup as the active Disaster Recovery Backup.", 'duplicator-pro'); ?>"
aria-expanded="false">
</i>
</button>
</div>
</div>
</div>
</form>
<?php }

View File

@@ -0,0 +1,49 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Package\Recovery\RecoveryStatus;
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\DupPackage $package
*/
$package = $tplData['package'];
$tooltipContent = __('A Backup Recovery Point status is not required to be enabled and in some cases is desirable.', 'duplicator-pro') . ' ' .
__('For example you may want to backup only your database.', 'duplicator-pro') . ' ' .
__(
'In this case you can still run a database only install, however the ability to use the recovery point installer will be unavailable.',
'duplicator-pro'
);
?>
<h3 class="dup-title margin-top-0">
<?php ViewHelper::disasterIcon(true, 'maroon'); ?>&nbsp;
<?php esc_html_e('Disaster Recovery - Isn\'t Available for this Backup', 'duplicator-pro'); ?>
<sup>
<i class="fas fa-question-circle fa-xs"
data-tooltip-title="<?php esc_attr_e('Recovery', 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltipContent); ?>">
</i>
</sup>
</h3>
<?php $tplMng->render('parts/recovery/package_info_mini'); ?>
<hr class="margin-top-1 margin-bottom-1">
<?php
$recoverStatus = new RecoveryStatus($package);
$tplMng->render('parts/recovery/exclude_data_box', ['recoverStatus' => $recoverStatus]);

View File

@@ -0,0 +1,29 @@
<?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 id="dup-remote-package-download-wrapper">
<div class="dup-download-progress">
<p><?php esc_html_e('No download is currently in progress.', 'duplicator-pro'); ?></p>
</div>
</div>
<script>
jQuery(document).ready(function ($) {
let content = $('tr.dup-row-progress').find('td').html();
if (content && content.length > 0) {
$('.dup-download-progress').html(content);
}
});
</script>

View File

@@ -0,0 +1,94 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Models\Storages\AbstractStorageEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var AbstractStorageEntity[] $storages
*/
$storages = $tplData['storages'];
/** @var int */
$packageId = $tplData['packageId'];
/** @var string */
$packageName = $tplData['packageName'];
/** @var bool */
$isStorageFull = $tplData['isStorageFull'];
?>
<div id="dup-remote-package-download">
<form method="POST" action="">
<input type="hidden" name="package_id" value="<?php echo (int) $packageId; ?>">
<input type="hidden" name="download" value="1">
<input type="hidden" name="action" value="<?php echo esc_attr(PackagesPageController::ACTION_START_DOWNLOAD); ?>">
<?php PackagesPageController::getInstance()->getActionByKey(PackagesPageController::ACTION_START_DOWNLOAD)->getActionNonceFileds(); ?>
<input type="hidden" name="afterDownloadAction" value="">
<p>
<?php
printf(
wp_kses(
__('The <b>%s</b> backup isn\'t in a local storage, it\'s possible to download it on local server.', 'duplicator-pro'),
[
'b' => [],
]
),
esc_html($packageName)
);
?>
</p>
<?php
$tplMng->render('admin_pages/packages/remote_download/remote_storages_list');
if ($isStorageFull) {
?>
<p>
<small>
<i class="maroon">
<?php
esc_html_e(
'The maximum number of backups for the default local storage has been reached.
The oldest backup will be deleted automatically, after the download finishes.
Alternatively you can delete a backup to make room for the download.',
'duplicator-pro'
);
?>
</i>
</small>
</p>
<?php } ?>
<hr class="margin-top-1 margin-bottom-1" >
<div class="dup-buttons-container">
<button id="dup-remote-package-cancel-btn" class="button gray hollow">
<?php esc_html_e('Cancel', 'duplicator-pro'); ?>
</button>
<button
id="dup-remote-package-download-btn"
class="button primary"
type="submit"
>
<?php esc_html_e('Download', 'duplicator-pro'); ?>
</button>
</div>
</form>
</div>
<script>
jQuery(document).ready(function ($) {
$('input[name="storage_ids[]"]').click(function(event) {
$('#dup-remote-package-download-btn').prop('disabled', false);
});
$('#dup-remote-package-cancel-btn').click(function(event) {
event.preventDefault();
tb_remove();
});
});
</script>

View File

@@ -0,0 +1,94 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Models\Storages\AbstractStorageEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var AbstractStorageEntity[] $storages
*/
$storages = $tplData['storages'];
/** @var int */
$packageId = $tplData['packageId'];
/** @var string */
$packageName = $tplData['packageName'];
/** @var bool */
$isStorageFull = $tplData['isStorageFull'];
?>
<div id="dup-remote-package-download">
<form method="POST" action="">
<input type="hidden" name="package_id" value="<?php echo (int) $packageId; ?>">
<input type="hidden" name="download" value="1">
<input type="hidden" name="action" value="<?php echo esc_attr(PackagesPageController::ACTION_START_DOWNLOAD); ?>">
<?php PackagesPageController::getInstance()->getActionByKey(PackagesPageController::ACTION_START_DOWNLOAD)->getActionNonceFileds(); ?>
<input type="hidden" name="afterDownloadAction" value="<?php echo esc_attr(PackagesPageController::ACTION_START_RESTORE); ?>">
<p>
<?php
printf(
wp_kses(
__('To restore the <b>%s</b> backup, it is necessary to download it locally before proceeding with the restoration.', 'duplicator-pro'),
[
'b' => [],
]
),
esc_html($packageName)
);
?>
</p>
<?php
$tplMng->render('admin_pages/packages/remote_download/remote_storages_list');
if ($isStorageFull) {
?>
<p>
<small>
<i class="maroon">
<?php
esc_html_e(
'The maximum number of backups for the default local storage has been reached.
The oldest backup will be deleted automatically, after the download finishes.
Alternatively you can delete a backup to make room for the download.',
'duplicator-pro'
);
?>
</i>
</small>
</p>
<?php } ?>
<hr class="margin-top-1 margin-bottom-1" >
<div class="dup-buttons-container">
<button id="dup-remote-package-cancel-btn" class="button button-secondary">
<?php esc_html_e('Cancel', 'duplicator-pro'); ?>
</button>
<button
id="dup-remote-package-download-btn"
class="button primary"
type="submit"
>
<?php esc_html_e('Download', 'duplicator-pro'); ?>
</button>
</div>
</form>
</div>
<script>
jQuery(document).ready(function ($) {
$('input[name="storage_ids[]"]').click(function(event) {
$('#dup-remote-package-download-btn').prop('disabled', false);
});
$('#dup-remote-package-cancel-btn').click(function(event) {
event.preventDefault();
tb_remove();
});
});
</script>

View File

@@ -0,0 +1,65 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Models\Storages\AbstractStorageEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var AbstractStorageEntity[] $storages
*/
$storages = $tplData['storages'];
?>
<p>
<?php esc_html_e('Select the remote storage from which to download the Backup:', 'duplicator-pro'); ?>
</p>
<div class="dup-remote-storage-options">
<?php
for ($i = 0; $i < count($storages); $i++) {
$storage = $storages[$i];
?>
<div class="storage-option horizontal-input-row">
<input
type="radio"
id="storage-option-<?php echo (int) $storage->getId(); ?>"
name="storage_ids[]"
value="<?php echo (int) $storage->getId(); ?>"
<?php checked($i === 0); ?>
>
<label for="storage-option-<?php echo (int) $storage->getId(); ?>">
<?php echo wp_kses(
$storage->getSTypeIcon(),
[
'i' => [
'class' => [],
],
'img' => [
'src' => [],
'class' => [],
'alt' => [],
],
]
); ?>&nbsp;
<b><?php echo esc_html($storage->getName()); ?></b>&nbsp;
<?php echo wp_kses(
'(' . $storage->getHtmlLocationLink() . ')',
[
'a' => [
'href' => [],
'target' => [],
],
'span' => [],
]
);?>
</label>
</div>
<?php } ?>
</div>

View File

@@ -0,0 +1,164 @@
<?php
/**
* Duplicator Pro remote download scripts
*
* @package Duplicator
* @copyright (c) 2024, Snap Creek LLC
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Views\UI\UiDialog;
use Duplicator\Models\GlobalEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$afterDownloadAction = $tplData['afterDownloadAction'] ?? '';
$remoteDownloadPackageId = isset($tplData['remoteDownloadPackageId']) ? (int) $tplData['remoteDownloadPackageId'] : -1;
$downloadStarted = $remoteDownloadPackageId > 0;
$afterDownloadActionNonce = strlen($afterDownloadAction) > 0 ? PackagesPageController::getInstance()->getActionByKey($afterDownloadAction)->getNonce() : '';
$alreadyDownloadDlg = new UiDialog();
$alreadyDownloadDlg->width = 550;
$alreadyDownloadDlg->height = 200;
$alreadyDownloadDlg->showButtons = true;
$alreadyDownloadDlg->title = __('Backup is already being downloaded', 'duplicator-pro');
$alreadyDownloadDlg->message = __('The backup is currently being downloaded. Please wait for the download to finish.', 'duplicator-pro');
$alreadyDownloadDlg->boxClass = 'duplication-remote-download-options-dlg';
$alreadyDownloadDlg->initAlert();
$remoteDownloadOptionsDlg = new UiDialog();
$remoteDownloadOptionsDlg->width = 750;
$remoteDownloadOptionsDlg->height = 395;
$remoteDownloadOptionsDlg->showButtons = false;
$remoteDownloadOptionsDlg->title = __('Download From Remote Storage', 'duplicator-pro');
$remoteDownloadOptionsDlg->message = __('Loading Please Wait...', 'duplicator-pro');
$remoteDownloadOptionsDlg->boxClass = 'duplicatior-remote-download-options-dlg';
$remoteDownloadOptionsDlg->initAlert();
$downloadProgressDlg = new UiDialog();
$downloadProgressDlg->height = 475;
$downloadProgressDlg->width = 750;
$downloadProgressDlg->showButtons = false;
$downloadProgressDlg->title = __('Downloading Backup...', 'duplicator-pro');
$downloadProgressDlg->templatePath = 'admin_pages/packages/remote_download/download_progress';
$downloadProgressDlg->boxClass = 'dupli-download-progress-dlg';
$downloadProgressDlg->initAlert();
$removeBackupRecordConfirm = new UiDialog();
$removeBackupRecordConfirm->title = __('Remove Backup Record?', 'duplicator-pro');
$removeBackupRecordConfirm->message = __('The backup does not exist in any storage. Would you like to remove the backup record?', 'duplicator-pro');
$removeBackupRecordConfirm->progressText = __('Removing Backup Record, Please Wait...', 'duplicator-pro');
$removeBackupRecordConfirm->jsCallback = 'DupliJs.Pack.DeleteBackupRecord(this)';
$removeBackupRecordConfirm->progressOn = false;
$removeBackupRecordConfirm->okText = __('Yes', 'duplicator-pro');
$removeBackupRecordConfirm->cancelText = __('No', 'duplicator-pro');
$removeBackupRecordConfirm->closeOnConfirm = true;
$removeBackupRecordConfirm->initConfirm();
?>
<script>
jQuery(document).ready(function($) {
let remoteDownloadModal = $('.<?php echo esc_html($remoteDownloadOptionsDlg->boxClass); ?>');
let remoteDownloadInProgress = <?php echo wp_json_encode($downloadStarted); ?>;
let remoteDownloadModalOpen = false;
if (remoteDownloadInProgress) {
setTimeout(function() {
<?php $downloadProgressDlg->showAlert(); ?>
remoteDownloadModalOpen = true;
}, 500);
}
$(document).on('thickbox:removed', function() {
if (!remoteDownloadInProgress && !remoteDownloadModalOpen) {
return;
}
remoteDownloadModalOpen = false;
});
DupliJs.Pack.DeleteBackupRecord = function(e) {
var id = $(e).attr('data-id');
$("tr[data-package-id=" + id + "] input[type=checkbox]").prop('checked', true);
DupliJs.Pack.Delete()
}
DupliJs.Pack.IsRemoteDownloadModalOpen = function() {
return remoteDownloadModalOpen;
}
DupliJs.Pack.afterRemoteDownloadAction = function() {
let packageId = <?php echo wp_json_encode($remoteDownloadPackageId); ?>;
let action = <?php echo wp_json_encode($afterDownloadAction); ?>;
let nonceVal = <?php echo wp_json_encode($afterDownloadActionNonce); ?>;
if (action.length === 0 || nonceVal.length === 0 || packageId <= 0) {
location.reload();
} else {
DupliJs.Util.dynamicFormSubmit('', 'post', {
packageId: packageId,
action: action,
_wpnonce: nonceVal
});
}
}
/**
* Show remote download options in modal window
*
* @param {number} packageId
* @param {string} remoteAction
*
* @return {boolean}
*/
DupliJs.Pack.ShowRemoteDownloadOptions = function(
packageId,
remoteAction,
) {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_get_remote_restore_download_options',
packageId: packageId,
remoteAction: remoteAction,
nonce: "<?php echo esc_js(wp_create_nonce('duplicator_get_remote_restore_download_options')); ?>"
},
function(result, data, funcData, textStatus, jqXHR) {
if (funcData.alreadyInUse) {
<?php $alreadyDownloadDlg->showAlert(); ?>
} else if (!funcData.packageExists) {
<?php if (GlobalEntity::getInstance()->getPurgeBackupRecords() === AbstractStorageEntity::BACKUP_RECORDS_REMOVE_ALL) {
$removeBackupRecordConfirm->showConfirm();
} else { ?>
DupliJs.addAdminMessage(funcData.message, 'error');
<?php } ?>
$("#<?php echo esc_js($removeBackupRecordConfirm->getID()); ?>-confirm").attr('data-id', packageId);
$("tr[data-package-id='" + packageId + "'] button[data-needs-download]").prop('disabled', true);
$("#dup-row-pack-id-" + packageId + " .remote-storage-flag").remove();
} else {
<?php $remoteDownloadOptionsDlg->showAlert(); ?>
remoteDownloadModal.html(data.funcData.content);
}
return '';
},
function(result, data, funcData, textStatus, jqXHR) {
DupliJs.addAdminMessage(data.message, 'error');
console.log(data);
return '';
}, {
timeout: 300000
} //Fetching validity of multiple storages can take a while
);
return false;
}
});
</script>

View File

@@ -0,0 +1,220 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Controllers\StoragePageController;
use Duplicator\Core\CapMng;
use Duplicator\Models\GlobalEntity;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplMng->getDataValueObjRequired('package', AbstractPackage::class);
$archive_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) != false);
$installer_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_INSTALLER) != false);
$archiveDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_ARCHIVE);
$installerDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_INSTALLER);
$defaultStorageUrl = StoragePageController::getEditDefaultUrl();
$global = GlobalEntity::getInstance();
$txt_RequiresRemote = sprintf(
_x(
'This option requires the Backup to use the built-in default %1$sstorage location %2$s%3$s',
'1 and 3 are opening and closing anchor/link tags, 2 is an icon',
'duplicator-pro'
),
'<a href="' . esc_url($defaultStorageUrl) . '" target="_blank">',
'<i class="far fa-hdd fa-fw fa-sm"></i>',
'</a>'
);
?>
<div class="dup-ovr-ctrls-hdrs clearfix">
<h3 class="font-bold margin-bottom-0">
<i class="fas fa-link fa-fw"></i> <?php esc_html_e('Install Resources', 'duplicator-pro'); ?>
</h3>
<small class="xsmall dark-gray-color">
<i><?php esc_html_e('Links are sensitive. Keep them safe!', 'duplicator-pro'); ?></i>
</small>
<?php if (CapMng::can(CapMng::CAP_STORAGE, false)) { ?>
<small class="float-right">
<a
class="dup-ovr-ref-links-more"
href="javascript:void(0)"
onclick="DupliJs.Pack.ShowRemote(<?php echo (int) $package->getId(); ?>, '<?php echo esc_js($package->getNameHash()); ?>');">
<i class="fas fa-server fa-xs"></i> <?php esc_html_e('Storages', 'duplicator-pro'); ?>
</a>
</small>
<?php } ?>
</div>
<!-- =======================
ARCHIVE FILE: -->
<div class="dup-ovr-copy-flex-box">
<div class="flex-item">
<i class="far fa-file-archive fa-fw"></i>
<b class="black-color">
<?php esc_html_e('Backup File', 'duplicator-pro'); ?>
</b>
<sup>
<?php
$archiveFileToolTipTitle = sprintf(
esc_html_x(
'This link is used with the %1$sImport Link Install%2$s feature.
Use the Copy Link button to copy this URL Backup File link to import on another WordPress site.',
'1 and 2 are opening and closing anchor tags',
'duplicator-pro'
),
'<a href="' . esc_url(ImportPageController::getInstance()->getMenuLink()) . '">',
'</a>'
);
?>
<i class="fas fa-question-circle fa-xs fa-fw dup-archive-help"
data-tooltip-title="<?php esc_attr_e("Backup File", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($archiveFileToolTipTitle); ?>"></i>
</sup>
</div>
<div class="flex-item"></div>
</div>
<div class="dup-ovr-copy-flex-box dup-box-file">
<?php if ($archive_exists) : ?>
<div class="flex-item">
<input type="text" class="dup-ovr-ref-links margin-bottom-0" readonly="readonly"
value="<?php echo esc_attr($archiveDownloadURL); ?>"
title="<?php echo esc_attr($archiveDownloadURL); ?>"
onfocus="jQuery(this).select();" />
<span class="fas fa-arrow-alt-circle-down dup-ovr-ref-links-icon"
title="<?php esc_attr_e('Archive Import Link (URL)', 'duplicator-pro'); ?>"></span>
</div>
<div class="flex-item">
<span onclick="jQuery(this).parent().parent().find('.dup-ovr-ref-links').select();">
<span data-dup-copy-value="<?php echo esc_attr($archiveDownloadURL); ?>"
class="button hollow small gray dup-ovr-ref-copy no-select">
<i class='far fa-copy dup-cursor-pointer'></i>
<?php esc_html_e('Copy Link', 'duplicator-pro'); ?>
</span>
</span>
<span class="dup-ovr-ref-dwnld button hollow small gray "
aria-label="<?php esc_html_e("Download Archive", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.DownloadFile('<?php echo esc_attr($archiveDownloadURL); ?>',
'<?php echo esc_attr($package->getArchiveFilename()); ?>');">
<i class="fas fa-download"></i> <?php esc_html_e('Download', 'duplicator-pro'); ?>
</span>
</div>
<?php else : ?>
<div class="flex-item maroon">
<?php
echo wp_kses(
$txt_RequiresRemote,
[
'a' => [
'href' => [],
'target' => [],
],
'i' => [
'class' => [],
],
]
);
?>.
</div>
<?php endif; ?>
</div>
<!-- =======================
ARCHIVE INSTALLER: -->
<?php
switch ($global->installer_name_mode) {
case GlobalEntity::INSTALLER_NAME_MODE_SIMPLE:
$settingsPackageUrl = SettingsPageController::getInstance()->getMenuLink(SettingsPageController::L2_SLUG_PACKAGE);
$lockIcon = 'fa-lock-open';
$installerToolTipTitle = sprintf(
__(
'Using standard installer name. To improve security, switch to hashed change in %1$sSettings%2$s',
'duplicator-pro'
),
'<a href="' . esc_url($settingsPackageUrl) . '" >',
'</a>'
);
break;
case GlobalEntity::INSTALLER_NAME_MODE_WITH_HASH:
default:
$lockIcon = 'fa-lock';
$installerToolTipTitle = __('Using more secure, hashed installer name.', 'duplicator-pro');
break;
}
$installerName = $package->Installer->getDownloadName();
?>
<i class="fas fa-bolt fa-fw"></i>
<b class="black-color">
<?php esc_html_e('Backup Installer', 'duplicator-pro'); ?>
</b>
<sup>
<i class="fas <?php echo esc_attr($lockIcon); ?> dup-cursor-pointer fa-fw fa-xs dup-installer-help"
style="padding-left:3px"
data-tooltip="<?php echo esc_html($installerToolTipTitle); ?>"></i>
</sup>
<div class="dup-ovr-copy-flex-box dup-box-installer">
<?php if ($installer_exists) : ?>
<div class="flex-item">
<input type="text" class="dup-ovr-ref-links margin-bottom-0" readonly="readonly"
value="<?php echo esc_attr($installerName); ?>"
title="<?php echo esc_attr($installerName); ?>"
onfocus="jQuery(this).select();">
<small class="dup-info-msg01 xsmall dark-gray-color">
<i><?php esc_html_e('These links contain highly sensitive data. Share with extra caution!', 'duplicator-pro'); ?></i>
</small>
</div>
<div class="flex-item">
<span onclick="jQuery(this).parent().parent().find('.dup-ovr-ref-links').select();">
<span data-dup-copy-value="<?php echo esc_attr($installerName); ?>"
class="dup-ovr-ref-copy no-select button hollow small gray">
<i class='far fa-copy dup-cursor-pointer'></i>
<?php esc_html_e('Copy Name', 'duplicator-pro'); ?>
</span>
</span>
<span class="dup-ovr-ref-dwnld button hollow small gray "
aria-label="<?php esc_html_e("Download Installer", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.DownloadFile('<?php echo esc_attr($installerDownloadURL); ?>');">
<i class="fas fa-download"></i> <?php esc_html_e('Download', 'duplicator-pro'); ?>
</span>
</div>
<?php else : ?>
<div class="flex-item maroon">
<?php
echo wp_kses(
$txt_RequiresRemote,
[
'a' => [
'href' => [],
'target' => [],
],
'i' => [
'class' => [],
],
]
);
?>.
</div>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,144 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\CapMng;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
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 ?DupPackage $package
*/
$package = $tplData['package'];
$pack_dbonly = $package->isDBOnly();
$pack_format = strtolower($package->Archive->Format);
$packageDetailsURL = PackagesPageController::getInstance()->getPackageDetailsURL($package->getId());
$txt_DBOnly = __('DB Only', 'duplicator-pro');
$archive_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) != false);
$isRecoverable = RecoveryPackage::isPackageIdRecoverable($package->getId());
?>
<td colspan="11">
<div class="dup-package-row-details-wrapper">
<div class="dup-ovr-hdr">
<h3 class="font-bold">
<i class="fas fa-archive"></i>
<?php esc_html_e('Backup Overview', 'duplicator-pro'); ?>
</h3>
</div>
<div class="dup-ovr-bar-flex-box">
<div>
<label><?php esc_html_e('WordPress', 'duplicator-pro'); ?></label>
<?php echo esc_html($package->VersionWP); ?> &nbsp;
</div>
<div>
<label><?php esc_html_e('Duplicator', 'duplicator-pro'); ?></label>
<?php echo esc_html($package->getVersion()); ?> &nbsp;
</div>
<div>
<label><?php esc_html_e('Format', 'duplicator-pro'); ?></label>
<?php echo esc_html(strtoupper($pack_format)); ?>
</div>
<div>
<label><?php esc_html_e('Files', 'duplicator-pro'); ?></label>
<?php echo ($pack_dbonly)
? '<i>' . esc_html($txt_DBOnly) . '</i>'
: number_format($package->Archive->FileCount); ?>
</div>
<div>
<label><?php esc_html_e('Folders', 'duplicator-pro'); ?></label>
<?php echo ($pack_dbonly)
? '<i>' . esc_html($txt_DBOnly) . '</i>'
: number_format($package->Archive->DirCount) ?>
</div>
<div>
<label><?php esc_html_e('Tables', 'duplicator-pro'); ?></label>
<?php
printf(
esc_html_x(
'%1$d of %2$d',
'Example: 7 of 10',
'duplicator-pro'
),
(int) $package->Database->info->tablesFinalCount,
(int) $package->Database->info->tablesBaseCount
);
?>
</div>
</div>
<div class="dup-ovr-ctrls-flex-box">
<div class="flex-item">
<?php
if (CapMng::can(CapMng::CAP_EXPORT, false)) {
$tplMng->render('admin_pages/packages/row_parts/details_download_block');
}
?>
</div>
<div class="flex-item dup-ovr-opts">
<div class="dup-ovr-ctrls-hdrs">
<h3 class="font-bold margin-bottom-0">
<?php esc_html_e('Options', 'duplicator-pro'); ?>
</h3>
<small class="xsmall dark-gray-color">
<i><?php esc_html_e('Backup actions.', 'duplicator-pro'); ?></i>
</small>
</div>
<ul class="no-bullet">
<li>
<a
aria-label="<?php esc_attr_e("Go to Backup details screen", 'duplicator-pro') ?>"
class="button hollow secondary expanded dup-details"
href="<?php echo esc_url($packageDetailsURL); ?>">
<span><i class="fas fa-search"></i> <?php esc_html_e("View Details", 'duplicator-pro') ?></span>
</a>
</li>
<?php if (CapMng::can(CapMng::CAP_STORAGE, false)) { ?>
<li>
<?php if ($archive_exists) : ?>
<button class="button hollow secondary expanded dup-transfer"
aria-label="<?php esc_attr_e('Go to Backup transfer screen', 'duplicator-pro') ?>"
onclick="DupliJs.Pack.OpenPackTransfer(<?php echo (int) $package->getId(); ?>); return false;">
<span><i class="fa fa-exchange-alt fa-fw"></i> <?php esc_html_e("Transfer Backup", 'duplicator-pro') ?></span>
</button>
<?php else : ?>
<span title="<?php esc_attr_e('Transfer Backups requires the use of built-in default storage!', 'duplicator-pro') ?>">
<button class="button hollow secondary expanded disabled">
<span><i class="fa fa-exchange-alt fa-fw"></i> <?php esc_html_e("Transfer Backup", 'duplicator-pro') ?></span>
</button>
</span>
<?php endif; ?>
</li>
<?php } ?>
<?php if (CapMng::can(CapMng::CAP_BACKUP_RESTORE, false)) { ?>
<li>
<button
aria-label="<?php esc_attr_e("Recover this Backup", 'duplicator-pro') ?>"
class="button hollow secondary expanded dupli-btn-open-recovery-box <?php echo ($isRecoverable) ? '' : 'maroon' ?>"
data-package-id="<?php echo (int) $package->getId(); ?>">
<?php ViewHelper::disasterIcon(true); ?>
<?php esc_html_e("Disaster Recovery", 'duplicator-pro'); ?>
</button>
</li>
<?php } ?>
</ul>
</div>
</div>
</td>

View File

@@ -0,0 +1,96 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\CapMng;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplData['package'];
$archive_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_ARCHIVE) != false);
$installer_exists = ($package->getLocalPackageFilePath(AbstractPackage::FILE_TYPE_INSTALLER) != false);
$archiveDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_ARCHIVE);
$installerDownloadURL = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_INSTALLER);
$pack_format = strtolower($package->Archive->Format);
if (!CapMng::can(CapMng::CAP_EXPORT, false)) {
return;
}
$isRunning = DupPackage::isPackageRunning();
$canEnabled = ($package->haveRemoteStorage() || $package->haveLocalStorage());
if ($archive_exists) : ?>
<nav class="dup-dnload-menu">
<button
class="dup-dnload-btn full-cell-button link-style no-select can-enabled"
type="button"
aria-haspopup="true"
data-tooltip="<?php esc_attr_e('Download Backup.', 'duplicator-pro') ?>"
<?php disabled(!$canEnabled || $isRunning); ?>>
<i class="fa fa-download"></i>&nbsp;
<span><?php esc_html_e("Download", 'duplicator-pro'); ?></span>
</button>
<nav class="dup-dnload-menu-items no-display">
<button
aria-label="<?php esc_html_e("Download Installer and Archive", 'duplicator-pro') ?>"
title="<?php echo ($installer_exists ? '' : esc_html__("Unable to locate both Backup files!", 'duplicator-pro')); ?>"
onclick="DupliJs.Pack.DownloadFile('<?php echo esc_attr($archiveDownloadURL); ?>',
'<?php echo esc_attr($package->getArchiveFilename()); ?>');
setTimeout(function () {DupliJs.Pack.DownloadFile('<?php echo esc_attr($installerDownloadURL); ?>');}, 700);
jQuery(this).parent().addClass('no-display');
return false;"
class="dup-dnload-both">
<i class="fa fa-fw <?php echo ($installer_exists ? 'fa-download' : 'fa-exclamation-triangle') ?>"></i>
&nbsp;<?php esc_html_e("Both Files", 'duplicator-pro') ?>
</button>
<button
aria-label="<?php esc_html_e("Download Installer", 'duplicator-pro') ?>"
title="<?php echo ($installer_exists) ? '' : esc_html__("Unable to locate installer Backup file!", 'duplicator-pro'); ?>"
onclick="DupliJs.Pack.DownloadFile('<?php echo esc_attr($installerDownloadURL); ?>');
jQuery(this).parent().addClass('no-display');
return false;"
class="dup-dnload-installer">
<i class="fa fa-fw <?php echo ($installer_exists ? 'fa-bolt' : 'fa-exclamation-triangle') ?>"></i>&nbsp;
<?php esc_html_e("Installer", 'duplicator-pro') ?>
</button>
<button
aria-label="<?php esc_html_e("Download Archive", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.DownloadFile('<?php echo esc_attr($archiveDownloadURL); ?>',
'<?php echo esc_attr($package->getArchiveFilename()); ?>');
jQuery(this).parent().addClass('no-display');
return false;"
class="dup-dnload-archive">
<i class="fa-fw far fa-file-archive"></i>&nbsp;
<?php echo esc_html__('Archive', 'duplicator-pro') . ' (' . esc_html($pack_format) . ')'; ?>
</button>
</nav>
</nav>
<?php else :
?>
<button
type="button"
class="full-cell-button link-style dup-remote-download <?php echo ($canEnabled ? 'can-enabled' : ''); ?>"
data-package-id="<?php echo (int) $package->getId(); ?>"
data-needs-download="<?php echo $package->haveLocalStorage() ? "false" : "true"; ?>"
aria-label="<?php esc_attr_e("Download Backup", 'duplicator-pro') ?>"
data-tooltip="<?php esc_attr_e("Download Backup.", 'duplicator-pro') ?>"
<?php disabled(!$canEnabled || $isRunning); ?>>
<i class="fas fa-download fa-fw"></i> <?php esc_html_e("Download", 'duplicator-pro'); ?>
</button>
<?php endif; ?>

View File

@@ -0,0 +1,86 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\CapMng;
use Duplicator\Package\DupPackage;
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 ?DupPackage $package
*/
$package = $tplData['package'];
?>
<div class="dup-package-flags">
<?php if ($package->hasFlag(DupPackage::FLAG_MANUAL) || $package->hasFlag(DupPackage::FLAG_SCHEDULE_RUN_NOW)) { ?>
<span class="icon-wrapper" title="<?php esc_attr_e('Manual Backup', 'duplicator-pro') ?>">
<i class="fa-solid fa-hand"></i>
</span>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_SCHEDULE)) { ?>
<span class="icon-wrapper" title="<?php esc_attr_e('Schedule Backup', 'duplicator-pro') ?>">
<i class="fa-solid fa-clock"></i>
</span>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_HAVE_LOCAL)) { ?>
<span
class="icon-wrapper cursor-pointer"
title="<?php esc_attr_e('The Backup is in Local Storage', 'duplicator-pro') ?>"
onclick="DupliJs.Pack.ShowRemote(<?php echo (int) $package->getId(); ?>, '<?php echo esc_js($package->getNameHash()); ?>');">
<i class="fa-solid fa-hard-drive"></i>
</span>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_HAVE_REMOTE)) { ?>
<span
class="icon-wrapper cursor-pointer remote-storage-flag"
title="<?php esc_attr_e('The Backup is in Remote Storage', 'duplicator-pro') ?>"
onclick="DupliJs.Pack.ShowRemote(<?php echo (int) $package->getId(); ?>, '<?php echo esc_js($package->getNameHash()); ?>');">
<i class="fa-solid fa-cloud"></i>
</span>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_DB_ONLY)) { ?>
<span class="icon-wrapper" title="<?php esc_attr_e('Database Only Backup', 'duplicator-pro') ?>">
<i class="fa-solid fa-database"></i>
</span>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_MEDIA_ONLY)) { ?>
<span class="icon-wrapper" title="<?php esc_attr_e('Media Only Backup', 'duplicator-pro') ?>">
<i class="fa-solid fa-images"></i>
</span>
<?php } ?>
<?php if (CapMng::can(CapMng::CAP_BACKUP_RESTORE, false)) { ?>
<?php if ($package->hasFlag(DupPackage::FLAG_DISASTER_AVAIABLE) || $package->hasFlag(DupPackage::FLAG_DISASTER_SET)) {
if ($package->hasFlag(DupPackage::FLAG_DISASTER_SET)) {
$title = __("Disaster Recovery URL is set on this Backup", 'duplicator-pro');
$colorClass = 'green';
} else {
$colorClass = '';
$title = __('This Backup is available for Disaster Recovery', 'duplicator-pro');
}
?>
<span
class="dupli-btn-open-recovery-box icon-wrapper link-style no-decoration"
aria-label="<?php echo esc_attr($title); ?>"
title="<?php echo esc_attr($title); ?>"
data-package-id="<?php echo (int) $package->getId(); ?>">
<?php ViewHelper::disasterIcon(true, $colorClass); ?>
</span>
<?php } ?>
<?php } ?>
<?php if ($package->hasFlag(DupPackage::FLAG_CREATED_AFTER_RESTORE)) { ?>
<span class="icon-wrapper" title="<?php esc_attr_e('This Backup is created after the Last Restored Backup', 'duplicator-pro') ?>">
<i class="fa-solid fa-clock-rotate-left maroon"></i>
</span>
<?php } ?>
</div>

View File

@@ -0,0 +1,78 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Package\AbstractPackage;
use Duplicator\Package\DupPackage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var ?DupPackage $package
*/
$package = $tplData['package'];
/** @var int */
$status = $tplData['status'];
?>
<div class="progress-error text-center">
<?php
switch ($status) {
case AbstractPackage::STATUS_ERROR:
$packageDetailsURL = PackagesPageController::getInstance()->getPackageDetailsURL($package->getId());
?>
<a type="button" class="dup-cell-err-btn" href="<?php echo esc_url($packageDetailsURL) ?>">
<i class="fa fa-exclamation-triangle fa-xs"></i>&nbsp;
<?php esc_html_e('Error Processing', 'duplicator-pro') ?>
</a>
<?php
break;
case AbstractPackage::STATUS_BUILD_CANCELLED:
?>
<i class="fas fa-info-circle fa-sm"></i>&nbsp;
<?php esc_html_e('Build Cancelled', 'duplicator-pro') ?>
<?php
break;
case AbstractPackage::STATUS_PENDING_CANCEL:
?>
<i class="fas fa-info-circle fa-sm"></i>
<?php esc_html_e('Cancelling Build', 'duplicator-pro') ?>
<?php
break;
case AbstractPackage::STATUS_STORAGE_CANCELLED:
?>
<i class="fas fa-info-circle fa-sm"></i>&nbsp;
<?php esc_html_e('Storage Cancelled', 'duplicator-pro') ?>
<?php
break;
case AbstractPackage::STATUS_REQUIREMENTS_FAILED:
$logFileExists = file_exists($package->getSafeLogFilepath());
if ($logFileExists) {
$baseUrl = rtrim($package->StoreURL, '/');
$logsDir = DUPLICATOR_LOGS_DIR_NAME;
$fileName = $package->getLogFilename();
$logLink = "{$baseUrl}/{$logsDir}/{$fileName}";
?>
<a href="<?php echo esc_url($logLink) ?>" target="_blank">
<i class="fas fa-info-circle"></i> <?php esc_html_e('Requirements Failed', 'duplicator-pro') ?>
</a>
<?php
} else {
?>
<i class="fas fa-info-circle"></i> <?php esc_html_e('Requirements Failed', 'duplicator-pro') ?>
<?php
}
break;
default:
break;
}
?>
</div>

View File

@@ -0,0 +1,40 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\CapMng;
use Duplicator\Package\DupPackage;
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 ?DupPackage $package
*/
$package = $tplData['package'];
if (!CapMng::can(CapMng::CAP_BACKUP_RESTORE, false)) {
return;
}
$isRunning = DupPackage::isPackageRunning();
$canEnabled = ($package->haveRemoteStorage() || $package->haveLocalStorage());
?>
<button
type="button"
class="full-cell-button dup-restore-backup link-style <?php echo ($canEnabled ? 'can-enabled' : ''); ?>"
data-package-id="<?php echo (int) $package->getId(); ?>"
data-needs-download="<?php echo $package->haveLocalStorage() ? "false" : "true"; ?>"
aria-label="<?php esc_attr_e("Restore backup", 'duplicator-pro') ?>"
title="<?php esc_attr_e("Restore backup.", 'duplicator-pro') ?>"
<?php disabled(!$canEnabled || $isRunning); ?>>
<?php ViewHelper::restoreIcon(); ?> <?php esc_html_e("Restore", 'duplicator-pro'); ?>
</button>

View File

@@ -0,0 +1,55 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Libs\Snap\SnapWP;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<br>
<b><?php esc_html_e('Please Retry:', 'duplicator-pro'); ?></b><br>
<?php esc_html_e('Unable to perform a full scan and read JSON file, please try the following actions.', 'duplicator-pro'); ?><br>
<?php esc_html_e('1. Go back and create a root path directory filter to validate the site is scan-able.', 'duplicator-pro'); ?><br>
<?php esc_html_e('2. Continue to add/remove filters to isolate which path is causing issues.', 'duplicator-pro'); ?><br>
<?php esc_html_e('3. This message will go away once the correct filters are applied.', 'duplicator-pro'); ?><br>
<br>
<b><?php esc_html_e('Common Issues:', 'duplicator-pro'); ?></b><br>
<?php
esc_html_e(
'- On some budget hosts scanning over 30k files can lead to timeout/gateway issues.
Consider scanning only your main WordPress site and avoid trying to backup other external directories.',
'duplicator-pro'
);
?><br>
<?php
esc_html_e(
'- Symbolic link recursion can cause timeouts. Ask your server admin if any are present in the scan path.
If they are add the full path as a filter and try running the scan again.',
'duplicator-pro'
); ?><br>
<br>
<b><?php esc_html_e('Details:', 'duplicator-pro'); ?></b><br>
<?php esc_html_e('JSON Service:', 'duplicator-pro'); ?> /wp-admin/admin-ajax.php?action=duplicator_package_scan<br>
<?php esc_html_e('Scan Path:', 'duplicator-pro'); ?> [<?php echo esc_html(SnapWP::getHomePath(true)); ?>]<br><br>
<b><?php esc_html_e('More Information:', 'duplicator-pro'); ?></b><br>
<?php
printf(
esc_html__(
'Please see the online FAQ titled %1$s"How to resolve scanner warnings/errors and timeout issues?"%2$s',
'duplicator-pro'
),
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-resolve-scanner-warnings-errors-and-timeout-issues') . '" target="_blank">',
'</a>'
);

View File

@@ -0,0 +1,74 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div id="addonsites-block" class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Addon Sites', 'duplicator-pro');?></div>
<div id="data-arc-status-addonsites"></div>
</div>
<div class="info">
<div style="margin-bottom:10px;">
<?php esc_html_e(
'An "Addon Site" is a separate WordPress site(s) residing in subdirectories within this site.
If you confirm these to be separate sites, then it is recommended that you exclude them by checking
the corresponding boxes below and clicking the \'Add Filters & Rescan\' button. To backup the other
sites install the plugin on the sites needing to be backed-up.',
'duplicator-pro'
); ?>
</div>
<script id="hb-addon-sites" type="text/x-handlebars-template">
<div class="container">
<div class="hdrs">
<span style="font-weight:bold">
<?php esc_html_e('Quick Filters', 'duplicator-pro'); ?>
</span>
</div>
<div class="data">
{{#if ARC.FilterInfo.Dirs.AddonSites.length}}
{{#each ARC.FilterInfo.Dirs.AddonSites as |path|}}
<div class="directory horizontal-input-row">
<input type="checkbox" name="dir_paths[]" value="{{path}}" id="as_dir_{{@index}}"/>
<label for="as_dir_{{@index}}" title="{{path}}">
{{path}}
</label>
</div>
{{/each}}
{{else}}
<div class="data-padded">
<?php esc_html_e('No add on sites found.', 'duplicator-pro'); ?>
</div>
{{/if}}
</div>
</div>
<div class="apply-btn">
<div class="apply-warn">
<?php esc_html_e('*Checking a directory will exclude all items in that path recursively.', 'duplicator-pro'); ?>
</div>
<button
type="button"
class="button gray hollow tiny dupli-quick-filter-btn"
disabled="disabled"
onclick="DupliJs.Pack.applyFilters(this, 'addon')"
>
<i class="fa fa-filter fa-sm"></i> <?php esc_html_e('Add Filters &amp; Rescan', 'duplicator-pro');?>
</button>
</div>
</script>
<div id="hb-addon-sites-result" class="hb-files-style"></div>
</div>
</div>

View File

@@ -0,0 +1,172 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Libs\Snap\SnapString;
use Duplicator\Package\Archive\PackageArchive;
use Duplicator\Models\GlobalEntity;
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\DupPackage $package
*/
$package = $tplData['package'];
$global = GlobalEntity::getInstance();
$totalSizeMax = ($global->getBuildMode() == PackageArchive::BUILD_MODE_ZIP_ARCHIVE)
? DUPLICATOR_SCAN_SITE_ZIP_ARCHIVE_WARNING_SIZE
: DUPLICATOR_SCAN_SITE_WARNING_SIZE;
?>
<div class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Size Checks', 'duplicator-pro'); ?></div>
<div id="data-arc-status-size"></div>
</div>
<div class="info" id="scan-item-file-size">
<b><?php esc_html_e('Size', 'duplicator-pro'); ?>:</b> <span id="data-arc-size2"></span> &nbsp; | &nbsp;
<b><?php esc_html_e('Files', 'duplicator-pro'); ?>:</b> <span id="data-arc-files"></span> &nbsp; | &nbsp;
<b><?php esc_html_e('Directories ', 'duplicator-pro'); ?>:</b> <span id="data-arc-dirs"></span> &nbsp; | &nbsp;
<b><?php esc_html_e('Total', 'duplicator-pro'); ?>:</b> <span id="data-arc-fullcount"></span>
<br />
<?php echo wp_kses(
__('Compressing larger sites on <i>some budget hosts</i> may cause timeouts.', 'duplicator-pro'),
['i' => []]
); ?>
<i>
<a href="javascipt:void(0)" onclick="jQuery('#size-more-details').toggle(100); return false;">
[<?php esc_html_e('more details...', 'duplicator-pro'); ?>]
</a>
</i>
<div id="size-more-details">
<b><?php esc_html_e('Overview', 'duplicator-pro'); ?>:</b><br />
<?php echo wp_kses(
sprintf(
__(
'This notice is triggered at <b>%s</b> and can be ignored on most hosts.
If the build process hangs or is unable to complete then this host has strict processing limits.
Below are some options you can take to overcome constraints setup on this host.',
'duplicator-pro'
),
SnapString::byteSize($totalSizeMax)
),
['b' => []]
); ?>
<br /><br />
<b><?php esc_html_e('Timeout Options', 'duplicator-pro'); ?>: </b><br />
<ul>
<li><?php esc_html_e('Apply the "Quick Filters" below or click the back button to apply on previous page.', 'duplicator-pro'); ?> </li>
<li>
<?php esc_html_e('See the FAQ link to adjust this hosts timeout limits: ', 'duplicator-pro'); ?>
&nbsp;<a href="<?php echo esc_html(DUPLICATOR_DUPLICATOR_DOCS_URL); ?>how-to-handle-server-timeout-issues" target="_blank">
<?php esc_html_e('What can I try for Timeout Issues?', 'duplicator-pro'); ?>
</a>
</li>
</ul>
</div>
<div id="hb-files-large-result" class="dup-tree-section hb-files-style">
<div class="container">
<div class="hdrs">
<span style="font-weight:bold">
<?php esc_html_e('Quick Filters', 'duplicator-pro'); ?>
<sup>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Large Files", 'duplicator-pro'); ?>"
data-tooltip="<?php
echo wp_kses(
sprintf(
__(
'Files over %1$s are listed below. Larger files such as movies or zipped content
can cause timeout issues on some budget hosts. If you are having issues creating
a Backup try excluding the directory paths below or go back to Step 1 and add them.
<br><br><b>Right click on tree node to open the bulk actions menu</b>',
'duplicator-pro'
),
SnapString::byteSize(DUPLICATOR_SCAN_WARN_FILE_SIZE)
),
[
'br' => [],
'b' => [],
]
); ?>">
</i>
</sup>
</span>
<div class='hdrs-up-down'>
<i
class="fa fa-caret-up fa-lg dup-nav-toggle"
onclick="DupliJs.Pack.toggleAllDirPath(this, 'hide')"
title="<?php esc_attr_e("Hide All", 'duplicator-pro'); ?>">
</i>
<i
class="fa fa-caret-down fa-lg dup-nav-toggle"
onclick="DupliJs.Pack.toggleAllDirPath(this, 'show')"
title="<?php esc_attr_e("Show All", 'duplicator-pro'); ?>">
</i>
</div>
</div>
<div class="tree-nav-bar">
<div class="container">
<button
type="button"
id="hb-files-large-tree-full-load"
class="tree-full-load-button dup-tree-show-all button gray hollow small margin-bottom-0">
<?php esc_html_e('Show All', 'duplicator-pro') ?>
</button>
<span class="size"><?php esc_html_e('Size', 'duplicator-pro') ?></span>
<span class="nodes"><?php esc_html_e('Nodes', 'duplicator-pro') ?></span>
</div>
</div>
<div class="data">
<div id="hb-files-large-jstree" class="dup-tree-main-wrapper"></div>
</div>
</div>
<div class="apply-btn">
<div class="apply-warn">
<?php esc_html_e('*Checking a directory will exclude all items in that path recursively.', 'duplicator-pro'); ?>
</div>
<button
type="button"
class="button gray hollow tiny dupli-quick-filter-btn"
disabled="disabled" onclick="DupliJs.Pack.applyFilters(this, 'large')">
<i class="fa fa-filter fa-sm"></i> <?php esc_html_e('Add Filters &amp; Rescan', 'duplicator-pro'); ?>
</button>
<button
type="button"
class="button gray hollow tiny"
onclick="DupliJs.Pack.showPathsDlg('large')"
title="<?php esc_attr_e('Copy Paths to Clipboard', 'duplicator-pro'); ?>">
<i class="fa far fa-clipboard" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</div>
<!-- =======================
DIALOG: PATHS COPY & PASTE -->
<div id="dup-archive-paths" style="display:none">
<b><i class="fa fa-folder"></i> <?php esc_html_e('Directories', 'duplicator-pro'); ?></b>
<div class="copy-butto float-right">
<button type="button" class="button secondary hollow tiny" onclick="DupliJs.Pack.copyText(this, '.arc-paths-dlg textarea.path-dirs')">
<i class="fa far fa-clipboard"></i> <?php esc_html_e('Click to Copy', 'duplicator-pro'); ?>
</button>
</div>
<textarea class="path-dirs"></textarea>
<b><i class="fa fa-files fa-sm"></i> <?php esc_html_e('Files', 'duplicator-pro'); ?></b>
<div class="copy-button float-right">
<button type="button" class="button secondary hollow tiny" onclick="DupliJs.Pack.copyText(this, '.arc-paths-dlg textarea.path-files')">
<i class="fa far fa-clipboard"></i> <?php esc_html_e('Click to Copy', 'duplicator-pro'); ?>
</button>
</div>
<textarea class="path-files"></textarea>
<small><?php esc_html_e('Copy the paths above and apply them as needed on Step 1 &gt; Archive &gt; Files section.', 'duplicator-pro'); ?></small>
</div>

View File

@@ -0,0 +1,27 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item ">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Database only', 'duplicator-pro'); ?></div>
<div id="only-db-scan-status"><div class="badge badge-warn"><?php esc_html_e("Notice", 'duplicator-pro'); ?></div></div>
</div>
<div class="info">
<?php esc_html_e("Only the database and a copy of the installer.php will be included in the Backup file.", 'duplicator-pro'); ?>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item ">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('File checks skipped', 'duplicator-pro'); ?></div>
<div id="skip-archive-scan-status"><div class="badge badge-warn"><?php esc_html_e("Notice", 'duplicator-pro'); ?></div></div>
</div>
<div class="info">
<?php esc_html_e("All file checks are skipped. This could cause problems during extraction if problematic files are included.", 'duplicator-pro'); ?>
<br><br>
<b><?php esc_html_e("To enable, uncheck Backups > Advanced Settings > Scan File Checks > \"Skip\" to enable.", 'duplicator-pro'); ?></b>
</div>
</div>

View File

@@ -0,0 +1,77 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\GlobalEntity;
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\DupPackage $package
*/
$package = $tplData['package'];
$global = GlobalEntity::getInstance();
?>
<!-- ================================================================
ARCHIVE
================================================================ -->
<div class="details-title">
<i class="far fa-file-archive fa-sm fa-fw"></i>&nbsp;<?php esc_html_e('Archive', 'duplicator-pro'); ?>
<sup class="dup-small-ext-type">
<?php if ($package->Installer->isSecure()) : ?>
<i class="fas fa-lock fa-fw fa-sm" title="<?php esc_html_e('Requires Password to Extract', 'duplicator-pro'); ?>"></i>&nbsp;
<?php endif; ?>
<?php echo esc_html($global->getArchiveExtensionType()); ?>
</sup>
</div>
<div class="scan-header scan-item-first">
<i class="fas fa-folder-open fa-sm"></i>
<?php esc_html_e("Files", 'duplicator-pro'); ?>
<div class="scan-header-details">
<div class="dup-scan-filter-status">
<?php if ($package->isDBOnly()) { ?>
<i class="fa fa-filter fa-sm"></i> <?php esc_html_e('Database Only', 'duplicator-pro'); ?>
<?php } elseif ($package->Archive->FilterOn) { ?>
<i class="fa fa-filter fa-sm"></i> <?php esc_html_e('Enabled', 'duplicator-pro'); ?>
<?php } ?>
</div>
<div id="data-arc-size1"></div>
<i class="fa fa-question-circle data-size-help"
data-tooltip-title="<?php esc_attr_e("File Size:", 'duplicator-pro'); ?>"
data-tooltip="<?php
esc_html_e(
'The files size represents only the included files before compression is applied.
It does not include the size of the database script and in most cases the Backup size
once completed will be smaller than this number unless shell execution zip with no compression is enabled.',
'duplicator-pro'
); ?>"></i>
<div class="dup-data-size-uncompressed"><?php esc_html_e("uncompressed", 'duplicator-pro'); ?></div>
</div>
</div>
<?php if ($package->isDBOnly()) {
$tplMng->render('admin_pages/packages/scan/items/archive/files_db_only');
} elseif ($global->skip_archive_scan) {
$tplMng->render('admin_pages/packages/scan/items/archive/files_skip_scan');
} else {
// SIZE CHECKS
$tplMng->render('admin_pages/packages/scan/items/archive/files');
// ADDON SITES
$tplMng->render('admin_pages/packages/scan/items/archive/addons');
// UNREADABLE FILES
$tplMng->render('admin_pages/packages/scan/items/archive/unreadable');
} ?>
<?php if (is_multisite()) {
$tplMng->render('admin_pages/packages/scan/items/archive/multisite');
} ?>

View File

@@ -0,0 +1,82 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div id="network-filters-scan-item" class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Network Site Filters', 'duplicator-pro');?></div>
<div id="data-arc-status-network"></div>
</div>
<div class="info">
<script id="hb-filter-network-sites" type="text/x-handlebars-template">
<div class="container">
<div class="data">
{{#if ARC.Status.HasFilteredSites}}
<p class="red">
<?php esc_html_e(
"Some sites have been excluded from the network.
With this backup it will not be possible to restore the network but only perform subsite to standalone conversions.",
'duplicator-pro'
); ?>
</p>
<b><?php esc_html_e('EXCLUDED SITES', 'duplicator-pro'); ?></b>
<ol>
{{#each ARC.FilteredSites as |site|}}
<li>{{site.blogname}} </li>
{{/each}}
</ol>
{{else}}
<?php esc_html_e("No network sites has been excluded from the Backup.", 'duplicator-pro'); ?>
{{/if}}
{{#if ARC.Status.HasNotImportableSites}}
<p class="red">
<?php esc_html_e(
"Tables and/or paths have been manually excluded from some sites so the Backup will not be
compatible with the Drag and Drop import. An install using the installer.php can still be performed, however.",
'duplicator-pro'
); ?>
</p>
{{#each ARC.Subsites as |site|}}
{{#compare site.filteredTables.length '||' site.filteredPaths.length}}
<p><b>{{site.blogname}}</b></p>
<div class="subsite-filter-info">
{{#compare site.filteredTables.length '>' 0}}
<?php esc_html_e('Tables:', 'duplicator-pro'); ?>
<ol>
{{#each site.filteredTables as |filteredTable|}}
<li>{{filteredTable}}</li>
{{/each}}
</ol>
{{/compare}}
{{#compare site.filteredPaths.length '>' 0}}
<?php esc_html_e('Paths:', 'duplicator-pro'); ?>
<ol>
{{#each site.filteredPaths as |filteredPath|}}
<li>{{filteredPath}}</li>
{{/each}}
</ol>
{{/compare}}
</div>
{{/compare}}
{{/each}}
{{/if}}
</div>
</div>
</script>
<div id="hb-filter-network-sites-result"></div>
</div>
</div>

View File

@@ -0,0 +1,85 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div id="scan-unreadable-items" class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Read Checks', 'duplicator-pro');?></div>
<div id="data-arc-status-unreadablefiles"></div>
</div>
<div class="info">
<?php
echo wp_kses(
__(
'PHP is unable to read the following items and they will <u>not</u> be included in the Backup.
Please work with your host to adjust the permissions or resolve the symbolic-link(s) shown in the lists below.
If these items are not needed then this notice can be ignored.',
'duplicator-pro'
),
['u' => []]
);
?>
<script id="unreadable-files" type="text/x-handlebars-template">
<div class="container">
<div class="data-padded">
<b><?php esc_html_e('Unreadable Items:', 'duplicator-pro');?></b> <br/>
<div class="directory">
{{#if ARC.UnreadableItems}}
{{#each ARC.UnreadableItems as |uitem|}}
<i class="fa fa-lock fa-sm"></i> {{uitem}} <br/>
{{/each}}
{{else}}
<i>
<?php esc_html_e('No unreadable items found.', 'duplicator-pro'); ?>
<br>
</i>
{{/if}}
</div>
<b><?php esc_html_e('Recursive Links:', 'duplicator-pro');?></b> <br/>
<div class="directory">
{{#if ARC.RecursiveLinks}}
{{#each ARC.RecursiveLinks as |link|}}
<i class="fa fa-lock fa-sm"></i> {{link}} <br/>
{{/each}}
{{else}}
<i>
<?php esc_html_e('No recursive sym-links found.', 'duplicator-pro'); ?>
<br>
</i>
{{/if}}
</div>
<b><?php esc_html_e('Open Basedir Restricted Items:', 'duplicator-pro');?></b> <br/>
<div class="directory">
{{#if ARC.PathsOutOpenbaseDir}}
{{#each ARC.PathsOutOpenbaseDir as |openBaseDiritem|}}
<i class="fa fa-lock fa-sm"></i> {{openBaseDiritem}} <br/>
{{/each}}
{{else}}
<i>
<?php esc_html_e('No open_basedir restricted items found.', 'duplicator-pro'); ?>
<br>
</i>
{{/if}}
</div>
</div>
</div>
</script>
<div id="unreadable-files-result" class="hb-files-style"></div>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item">
<div class="title" onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Database excluded', 'duplicator-pro');?></div>
<div id="data-db-status-size1"></div>
</div>
<div class="info">
<?php esc_html_e(
'The database is excluded from the Backup build process.
To include it make sure to check the "Database" Backup component checkbox at Step 1 of the build process.',
'duplicator-pro'
); ?>
</div>
</div>

View File

@@ -0,0 +1,72 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Libs\WpUtils\WpDbUtils;
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\DupPackage $package
*/
$package = $tplData['package'];
?>
<!-- ================================================================
DATABASE
================================================================ -->
<div class="scan-header">
<i class="fas fa-database fa-fw fa-sm"></i>
<?php esc_html_e("Database", 'duplicator-pro'); ?>
<div class="scan-header-details">
<small style="font-weight:normal; font-size:12px">
<?php if ($package->Database->Compatible) { ?>
<i style="color:maroon"><?php esc_html_e('Compatibility Mode Enabled', 'duplicator-pro'); ?></i>
<?php } ?>
</small>
<div class="dup-scan-filter-status">
<?php if ($package->Database->FilterOn) { ?>
<i class="fa fa-filter fa-sm"></i>
<?php esc_html_e('Enabled', 'duplicator-pro'); ?>
<?php } ?>
</div>
<div id="data-db-size1"></div>
<i class="fa fa-question-circle data-size-help"
data-tooltip-title="<?php esc_attr_e("Database Size:", 'duplicator-pro'); ?>"
data-tooltip="<?php
esc_html_e(
'The database size represents only the included tables. The process for gathering the size uses the query SHOW TABLE STATUS.
The overall size of the database file can impact the final size of the Backup.',
'duplicator-pro'
); ?>"></i>
<div class="dup-data-size-uncompressed"><?php esc_html_e("uncompressed", 'duplicator-pro'); ?></div>
</div>
</div>
<div id="dup-scan-db">
<?php if ($package->isDBExcluded()) {
$tplMng->render('admin_pages/packages/scan/items/database/excluded');
} else {
$tplMng->render('admin_pages/packages/scan/items/database/tables');
if (WpDbUtils::getBuildMode() == WpDbUtils::BUILD_MODE_MYSQLDUMP) {
$tplMng->render('admin_pages/packages/scan/items/database/mysqldump');
}
if (count($tplData['procedures']) > 0 || count($tplData['functions']) > 0) {
$tplMng->render('admin_pages/packages/scan/items/database/procedures');
}
if (count($tplData['triggers'])) {
$tplMng->render('admin_pages/packages/scan/items/database/triggers');
}
} ?>
</div>

View File

@@ -0,0 +1,121 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SettingsPageController;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$settingsPackageUrl = SettingsPageController::getInstance()->getMenuLink(SettingsPageController::L2_SLUG_PACKAGE);
?>
<div class="scan-item" id="mysqldump-limit-result"></div>
<script id="hb-mysqldump-limit-result" type="text/x-handlebars-template">
<div class="title" onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text">
<i class="fa fa-caret-right"></i> <?php esc_html_e('Mysqldump memory check', 'duplicator-pro'); ?>
</div>
<div id="data-db-status-mysqldump-limit">
{{#if DB.Status.mysqlDumpMemoryCheck}}
<div class="badge badge-pass"><?php esc_html_e('Good', 'duplicator-pro'); ?></div>
{{else}}
<div class="badge badge-warn"><?php esc_html_e('Notice', 'duplicator-pro'); ?></div>
{{/if}}
</div>
</div>
{{#if DB.Status.mysqlDumpMemoryCheck}}
<div class="info">
<p class="green">
<?php esc_html_e('The database size is within the allowed mysqldump size limit.', 'duplicator-pro'); ?>
</p>
<?php
echo wp_kses(
sprintf(
_x(
'If you encounter any issues with mysqldump please change the setting SQL Mode to PHP Code.
You can do that by opening %1$sDuplicator Pro > Settings > Backups.%2$s',
'1$s and 2$s represent opening and closing anchor tags',
'duplicator-pro'
),
'<a href="' . esc_url($settingsPackageUrl) . '" target="_blank">',
'</a>'
),
[
'a' => [
'href' => [],
'target' => [],
],
]
);
?>
</div>
{{else}}
<div class="info" style="display:block;">
<p class="red">
<?php esc_html_e('The database size exceeds the allowed mysqldump size limit.', 'duplicator-pro'); ?>
</p>
<?php
esc_html_e(
'The database size is larger than the PHP memory_limit value.
This can lead into issues when building a Backup, during which the system can run out of memory.
To fix this issue please consider doing one of the below mentioned recommendations.',
'duplicator-pro'
);
?>
<hr size="1" />
<p>
<b><?php esc_html_e('RECOMMENDATIONS:', 'duplicator-pro'); ?></b>
</p>
<ul class="dupli-simple-style-disc" >
<li>
<?php echo wp_kses(
sprintf(
_x(
'Please change the setting SQL Mode to PHP Code.
You can do that by opening %1$sDuplicator Pro > Settings > Backups.%2$s',
'%1$s and %2$s represent opening and closing anchor tags',
'duplicator-pro'
),
'<a href="' . esc_url($settingsPackageUrl) . '" target="_blank">',
'</a>'
),
[
'a' => [
'href' => [],
'target' => [],
],
]
); ?>
</li>
<li>
<?php echo wp_kses(
sprintf(
_x(
'If you want to build the backup with mysqldump, increase the PHP <b>memory_limit</b>
value in your php.ini file to at least %1$s.',
'%1$s represents the memory limit value (e.g. 256MB)',
'duplicator-pro'
),
'<b><span id="data-db-size3">{{DB.Status.requiredMysqlDumpLimit}}</span></b>'
),
[
'b' => [],
'span' => ['id' => []],
]
); ?>
</li>
</ul>
</div>
{{/if}}
</script>

View File

@@ -0,0 +1,51 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Object Access', 'duplicator-pro');?></div>
<div id="data-arc-status-showcreatefunc"></div>
</div>
<div class="info">
<script id="hb-showcreatefunc-result" type="text/x-handlebars-template">
<div class="container">
<div class="data">
{{#if ARC.Status.showCreateFunc}}
<?php esc_html_e(
"The database user for this WordPress site has sufficient permissions to write stored procedures
and functions to the sql file of the archive. [The commands SHOW CREATE PROCEDURE/FUNCTION will work.]",
'duplicator-pro'
); ?>
{{else}}
<span style="color: red;">
<?php
esc_html_e(
"The database user for this WordPress site does NOT have sufficient permissions to write stored
procedures to the sql file of the archive. [The command SHOW CREATE FUNCTION will NOT work.]",
'duplicator-pro'
);
?>
</span>
{{/if}}
</div>
</div>
</script>
<div id="showcreatefunc-package-result"></div>
</div>
</div>

View File

@@ -0,0 +1,163 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Libs\Snap\SnapString;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var \Duplicator\Package\DupPackage $package
*/
$package = $tplData['package'];
$settingsPackageUrl = SettingsPageController::getInstance()->getMenuLink(SettingsPageController::L2_SLUG_PACKAGE);
/** @var wpdb $wpdb */
global $wpdb;
?>
<div class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Overview', 'duplicator-pro'); ?></div>
<div id="data-db-status-size1"></div>
</div>
<div class="info">
<b> <?php esc_html_e('TOTAL SIZE', 'duplicator-pro'); ?> &nbsp; &#8667; &nbsp; </b>
<b><?php esc_html_e('Size', 'duplicator-pro'); ?>:</b> <span id="data-db-size2"></span> &nbsp; | &nbsp;
<b><?php esc_html_e('Tables', 'duplicator-pro'); ?>:</b> <span id="data-db-tablecount"></span> &nbsp; | &nbsp;
<b><?php esc_html_e('Records', 'duplicator-pro'); ?>:</b> <span id="data-db-rows"></span> <br />
<?php echo wp_kses(
sprintf(
__(
'Total size and row count are approximate values. The thresholds that trigger warnings are
<i>%1$s OR %2$s records</i> total for the entire database. Large databases take time to process
and can cause issues with server timeout and memory settings on some budget hosts. If your server
supports popen or exec and mysqldump you can try to enable Shell Execution from the settings menu.',
'duplicator-pro'
),
SnapString::byteSize(DUPLICATOR_SCAN_DB_ALL_SIZE),
number_format(DUPLICATOR_SCAN_DB_ALL_ROWS)
),
['i' => []]
); ?>
<br />
<br />
<hr size="1" />
<b><?php esc_html_e('TABLE DETAILS:', 'duplicator-pro'); ?></b><br />
<?php
echo wp_kses(
sprintf(
__(
'The notices for tables are <i>%1$s, %2$s records or names with upper-case characters</i>.
Individual tables will not trigger a notice message, but can help narrow down issues if they occur later on.',
'duplicator-pro'
),
SnapString::byteSize(DUPLICATOR_SCAN_DB_TBL_SIZE),
number_format(DUPLICATOR_SCAN_DB_TBL_ROWS)
),
['i' => []]
);
?>
<p>
<b><?php echo esc_html(sprintf(__('Exclude all tables without prefix "%s"', 'duplicator-pro'), $tplData['prefix'])); ?>:</b>&nbsp;
<i class="maroon">
<?php echo ($tplData['prefixFilter'] ?
esc_html_e('Enabled', 'duplicator-pro') :
esc_html_e('Disabled', 'duplicator-pro')
); ?>
</i><br>
<?php if (is_multisite()) { ?>
<b><?php esc_html_e('Exclude not existing subsite filter', 'duplicator-pro'); ?>:</b>&nbsp;
<i class="red">
<?php echo ($tplData['prefixSubFilter'] ?
esc_html_e('Enabled', 'duplicator-pro') :
esc_html_e('Disabled', 'duplicator-pro')
); ?>
</i>
<?php } ?>
</p>
<div id="dup-scan-db-info">
<div id="data-db-tablelist"></div>
</div>
<br />
<hr size="1" />
<b><?php esc_html_e('RECOMMENDATIONS:', 'duplicator-pro'); ?></b><br />
<i>
<?php esc_html_e(
'The following recommendations are not needed unless you are having issues building or installing the Backup.',
'duplicator-pro'
); ?>
</i>
<br />
<div style="padding:5px">
<?php echo wp_kses(
sprintf(
_x(
'1. Run a %1$srepair and optimization%2$s on the table to improve the overall size and performance.',
'1$s and 2$s represent opening and closing anchor tags',
'duplicator-pro'
),
'<a href="' . admin_url('maint/repair.php') . '" target="_blank">',
'</a>'
),
[
'a' => [
'href' => [],
'target' => [],
],
]
); ?>
<br /><br />
<?php esc_html_e(
'2. Remove post revisions and stale data from tables. Tables such as logs, statistical or other non-critical data should be cleared.',
'duplicator-pro'
); ?>
<br /><br />
<?php echo wp_kses(
sprintf(
_x(
'3. %1$sEnable mysqldump%2$s if this host supports the option.',
'1$s and 2$s represent opening and closing anchor tags',
'duplicator-pro'
),
'<a href="' . esc_url($settingsPackageUrl) . '" target="_blank">',
'</a>'
),
[
'a' => [
'href' => [],
'target' => [],
],
]
); ?>
<br /><br />
<?php echo wp_kses(
sprintf(
_x(
'4. Restoring mixed-case tables can cause problems on some servers. If you experience a
problem installing the backup change the %1$s system variable on the destination site\'s MySQL Server.',
'1$s represents an anchor tag with the variable name',
'duplicator-pro'
),
'<a href="http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_lower_case_table_names" target="_blank">
lower_case_table_names</a>'
),
[
'a' => [
'href' => [],
'target' => [],
],
]
); ?>
</div>
</div>
</div>

View File

@@ -0,0 +1,43 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Triggers', 'duplicator-pro');?></div>
<div id="data-arc-status-triggers"></div>
</div>
<div class="info">
<script id="hb-triggers-result" type="text/x-handlebars-template">
<div class="container">
<div class="data">
<span class="red">
<?php
esc_html_e(
"The database contains triggers which will have to be manually imported at install time.
No action needs to be performed at this time. During the install process you will be
presented with the proper trigger SQL statements that you can optionally run.",
'duplicator-pro'
); ?>
</span>
</div>
</div>
</script>
<div id="triggers-result"></div>
</div>
</div>

View File

@@ -0,0 +1,31 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
use Duplicator\Core\Views\TplMng;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
*/
?>
<div class="details-title">
<i class="fas fa-tasks fa-sm fa-fw"></i> <?php esc_html_e("Setup", 'duplicator-pro'); ?>
<div class="dup-more-details">
<a href="site-health.php" target="_blank" title="<?php esc_attr_e('Site Health', 'duplicator-pro'); ?>">
<i class="fas fa-file-medical-alt"></i>
</a>
</div>
</div>
<?php
TplMng::getInstance()->render('admin_pages/packages/scan/items/setup/system');
TplMng::getInstance()->render('admin_pages/packages/scan/items/setup/wordpress');
TplMng::getInstance()->render('admin_pages/packages/scan/items/setup/restore');

View File

@@ -0,0 +1,84 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div id="migration-status-scan-item" class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('Import Status', 'duplicator-pro');?></div>
<div id="data-arc-status-migratepackage"></div>
</div>
<div class="info">
<script id="hb-migrate-package-result" type="text/x-handlebars-template">
<div class="container">
<div class="data">
{{#if ARC.Status.PackageIsNotImportable}}
<hr>
<p>
<span class="maroon">
<?php esc_html_e("This Backup is not compatible with", 'duplicator-pro'); ?>
<i data-tooltip-title="<?php esc_attr_e("Drag and Drop Import", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e('The Drag and Drop import method is a way to migrate Backups.
You can find it under Duplicator Pro > Import.', 'duplicator-pro'); ?>">
<u><?php esc_html_e("Drag and Drop import", 'duplicator-pro'); ?></u>.&nbsp;
</i>
<?php esc_html_e("However it can still be used to perform a database migration.", 'duplicator-pro'); ?>
</span>
{{#if ARC.Status.IsDBOnly}}
<?php
esc_attr_e(
"Database only Backups can only be installed via the installer.php file.
The Drag and Drop interface only processes Backups that have all WordPress core directories and all database tables.",
'duplicator-pro'
);
?>
{{else}}
<?php esc_attr_e(
"To make the Backup compatible with Drag and Drop import don't filter any tables or core directories.",
'duplicator-pro'
); ?>
{{/if}}
</p>
{{#if ARC.Status.HasFilteredCoreFolders}}
<p>
<b><?php esc_attr_e("FILTERED CORE DIRS:", 'duplicator-pro'); ?></b>
</p>
<ol>
{{#each ARC.FilteredCoreDirs as |dir|}}
<li>{{dir}} </li>
{{/each}}
</ol>
{{/if}}
{{#if ARC.Status.HasFilteredSiteTables}}
<b><?php esc_attr_e("FILTERED SITE TABLES:", 'duplicator-pro'); ?></b>
<div class="dup-scan-files-migrae-status">
<ol>
{{#each DB.FilteredTables as |table|}}
<li>{{table}} </li>
{{/each}}
</ol>
</div>
{{/if}}
{{else}}
<?php esc_html_e("The Backup you are about to create is compatible with Drag and Drop import.", 'duplicator-pro'); ?>
{{/if}}
</div>
</div>
</script>
<div id="migrate-package-result"></div>
</div>
</div>

View File

@@ -0,0 +1,184 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Addons\ProBase\License\License;
use Duplicator\Core\Constants;
use Duplicator\Libs\Snap\SnapOpenBasedir;
use Duplicator\Libs\Snap\SnapServer;
use Duplicator\Libs\Snap\SnapUtil;
use Duplicator\Models\DynamicGlobalEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$webServers = implode(', ', Constants::SERVER_LIST);
$serverSoftware = SnapUtil::sanitizeTextInput(INPUT_SERVER, 'SERVER_SOFTWARE', 'unknown');
$fopenEnabled = SnapServer::isURLFopenEnabled() ? '1' : '0';
$isCurlEnabled = SnapUtil::isCurlEnabled() ? __('True', 'duplicator-pro') : __('False', 'duplicator-pro');
$openBaseDir = SnapOpenBasedir::isEnabled() ? esc_html__('on', 'duplicator-pro') : esc_html__('off', 'duplicator-pro');
$maxExecutionTime = set_time_limit(0) === true ? 0 : @ini_get('max_execution_time');
$memoryLimit = @ini_get('memory_limit');
$architecture = SnapUtil::getArchitectureString();
?>
<div class="scan-item scan-item-first">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('System', 'duplicator-pro'); ?></div>
<div id="data-srv-php-all"></div>
</div>
<div class="info">
<div class="scan-system-divider"><i class="fa fa-list"></i>&nbsp; <?php esc_html_e('General Checks', 'duplicator-pro'); ?></div>
<?php if (License::can(License::CAPABILITY_BRAND)) : ?>
<span id="data-srv-brand-check"></span>&nbsp;
<b><?php esc_html_e('Brand', 'duplicator-pro'); ?>: </b>
<span id="data-srv-brand-name"><?php esc_html_e('Default', 'duplicator-pro'); ?></span>
<br />
<div class="scan-system-subnote" id="data-srv-brand-note">
<?php esc_html_e('The default content used when a brand is not defined.', 'duplicator-pro'); ?>
</div>
<hr size="1" />
<?php endif; ?>
<span id="data-srv-php-websrv"></span>
&nbsp;<b><?php esc_html_e('Web Server', 'duplicator-pro') ?>:</b>
&nbsp; <?php echo esc_html($serverSoftware); ?><br />
<div class="scan-system-subnote">
<?php esc_html_e("Supported Web Servers:", 'duplicator-pro'); ?>&nbsp;<?php echo esc_html($webServers); ?>
</div>
<hr size="1" />
<span id="data-srv-php-mysqli"></span>&nbsp;<b><?php esc_html_e('MySQLi', 'duplicator-pro'); ?></b><br />
<div class="scan-system-subnote">
<?php esc_html_e(
'Creating the Backup does not require the mysqli module. However the installer file requires
that the PHP module mysqli be installed on the server it is deployed on.',
'duplicator-pro'
); ?>
<i><a href="http://php.net/manual/en/mysqli.installation.php" target="_blank">[<?php esc_html_e('details', 'duplicator-pro'); ?>]</a></i>
</div>
<div class="scan-system-divider margin-top-1"><i class="fa fa-list"></i>&nbsp;<?php esc_html_e('PHP Checks', 'duplicator-pro'); ?></div>
<span id="data-srv-php-version"></span>&nbsp;<b><?php esc_html_e('PHP Version: ', 'duplicator-pro'); ?> </b> <?php echo PHP_VERSION; ?> <br />
<div class="scan-system-subnote">
<?php
echo esc_html(
sprintf(
__(
'The minimum PHP version supported by Duplicator is %1$s, however it is highly
recommended to use PHP %2$s or higher for improved stability.',
'duplicator-pro'
),
DUPLICATOR_PRO_PHP_MINIMUM_VERSION,
DUPLICATOR_PRO_PHP_SUGGESTED_VERSION
)
); ?>
</div>
<hr size="1" />
<span id="data-srv-php-openbase"></span>&nbsp;
<b><?php esc_html_e('PHP Open Base Dir', 'duplicator-pro'); ?>:</b>&nbsp;<?php echo esc_html($openBaseDir); ?>
<br />
<div class="scan-system-subnote">
<?php esc_html_e(
'When [open_basedir] is enabled, issues may arise if there are symbolic links pointing outside the open_basedir restrictions.
To view a list of unreadable files, please consult the Read Checks section.
If you encounter problems while building a Backup,
consider working with your server admin or hosting provider to disable this setting in the php.ini file.',
'duplicator-pro'
); ?>
&nbsp;
<i>
<a href="http://php.net/manual/en/ini.core.php#ini.open-basedir" target="_blank">[<?php esc_html_e('details', 'duplicator-pro'); ?>]</a>
</i>
<br />
</div>
<hr size="1" />
<span id="data-srv-php-maxtime"></span>&nbsp;
<b><?php esc_html_e('PHP Max Execution Time', 'duplicator-pro'); ?>:</b>&nbsp; <?php echo esc_html($maxExecutionTime); ?>
<br />
<div class="scan-system-subnote">
<?php
esc_html(
sprintf(
__(
'Issues might occur for larger Backups when the [max_execution_time] value in the php.ini is too low.
The minimum recommended timeout is "%1$s" seconds or higher.
An attempt is made to override this value if the server allows it. A value of 0 (recommended) indicates that PHP has no time limits.',
'duplicator-pro'
),
DUPLICATOR_SCAN_TIMEOUT
)
); ?>
&nbsp;
<i>
<a href="http://www.php.net/manual/en/info.configuration.php#ini.max-execution-time" target="_blank">
[<?php esc_html_e('details', 'duplicator-pro'); ?>]
</a>
</i>
</div>
<hr size="1" />
<span id="data-srv-php-minmemory"></span>&nbsp;
<b><?php esc_html_e('PHP Memory Limit', 'duplicator-pro'); ?>:</b>&nbsp; <?php echo esc_html($memoryLimit); ?>
<br />
<div class="scan-system-subnote">
<?php
echo wp_kses(
sprintf(
_x(
'Issues might occur for larger Backups when the [memory_limit] value in the php.ini is too low.
The minimum recommended memory limit is "%1$s" or higher. An attempt is made to override this value if the server allows it.
To manually increase the memory limit have a look at this %2$s[FAQ item]%3$s',
'1: memory limit, 2: link start, 3: link end',
'duplicator-pro'
),
DUPLICATOR_MIN_MEMORY_LIMIT,
"<i><a href='" . DUPLICATOR_DUPLICATOR_DOCS_URL . "how-to-manage-server-resources-cpu-memory-disk' target='_blank'>",
"</a></i>"
),
[
'a' => [
'href' => [],
'target' => [],
],
'i' => [],
]
); ?>
</div>
<hr size="1" />
<span id="data-srv-php-arch64bit"></span>&nbsp;
<b><?php esc_html_e('PHP 64 Bit Architecture', 'duplicator-pro'); ?>:</b>&nbsp; <?php echo esc_html($architecture); ?><br />
<div class="scan-system-subnote">
<?php
echo wp_kses(
sprintf(
_x(
'Servers that run a PHP 32-bit architecture are not capable of creating Backups larger than 2GB.
If you need to create a Backup that is larger than 2GB in size talk with your host or server admin
to change your version of PHP to 64-bit. %1$s[FAQ item]%2$s',
'1: link start, 2: link end',
'duplicator-pro'
),
"<i><a href='" . DUPLICATOR_DUPLICATOR_DOCS_URL . "how-to-resolve-file-io-related-build-issues' target='_blank'>",
"</a></i>"
),
[
'a' => [
'href' => [],
'target' => [],
],
'i' => [],
]
); ?>
</div>
<br />
</div>
</div>

View File

@@ -0,0 +1,136 @@
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
use Duplicator\Addons\ProBase\License\License;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<div class="scan-item">
<div class='title' onclick="DupliJs.Pack.toggleScanItem(this);">
<div class="text"><i class="fa fa-caret-right"></i> <?php esc_html_e('WordPress', 'duplicator-pro'); ?></div>
<div id="data-srv-wp-all"></div>
</div>
<div class="info">
<span id="data-srv-wp-version"></span>&nbsp;
<b><?php esc_html_e('WordPress Version', 'duplicator-pro'); ?>:</b>&nbsp;<?php echo esc_html(get_bloginfo('version')); ?> <br />
<hr size="1" /><span id="data-srv-wp-core"></span>&nbsp;<b> <?php esc_html_e('Core Files', 'duplicator-pro'); ?></b> <br />
<?php if (count($tplData['filteredCoreDirs']) > 0) : ?>
<div id="data-srv-wp-core-missing-dirs">
<?php echo wp_kses(
__(
"The core WordPress directories below will <u>not</u> be included in the archive.
These paths are required for WordPress to function!",
'duplicator-pro'
),
['u' => []]
); ?>
<br />
<?php foreach ($tplData['filteredCoreDirs'] as $coreDir) : ?>
<b class="margin-left-1"><i class="fa fa-exclamation-circle scan-warn margin-right-1"></i><?php echo esc_html($coreDir); ?></b><br />
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (count($tplData['filteredCoreFiles']) > 0) : ?>
<div id="data-srv-wp-core-missing-dirs">
<?php echo wp_kses(
__(
"The core WordPress files below will <u>not</u> be included in the archive.
These files are required for WordPress to function!",
'duplicator-pro'
),
['u' => []]
); ?>
<br />
<?php foreach ($tplData['filteredCoreFiles'] as $coreFile) : ?>
<b class="margin-left-1"><i class="fa fa-exclamation-circle scan-warn margin-right-1"></i><?php echo esc_html($coreFile); ?></b>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (count($tplData['filteredCoreDirs']) > 0 || count($tplData['filteredCoreFiles']) > 0) : ?>
<div class="scan-system-subnote">
<?php esc_html_e(
'Note: Please change the file and directory filters if you wish to include the WordPress core files
otherwise the data will have to be manually copied to the new location for the site to function properly.',
'duplicator-pro'
); ?>
</div>
<?php endif; ?>
<?php if (empty($tplData['filteredCoreDirs']) && empty($tplData['filteredCoreFiles'])) : ?>
<div class="scan-system-subnote">
<?php esc_html_e(
"If the scanner is unable to locate the wp-config.php file in the root directory,
then you will need to manually copy it to its new location.
This check will also look for core WordPress paths that should be included in the archive for WordPress to work correctly.",
'duplicator-pro'
); ?>
</div>
<?php endif; ?>
<?php if (!is_multisite()) { ?>
<hr size="1" />
<span>
<div class="dup-scan-good"><i class="fa fa-check"></i></div>
</span>
<b> <?php esc_html_e('Multisite: N/A', 'duplicator-pro'); ?></b> <br />
<div class="scan-system-subnote">
<?php esc_html_e('Multisite was not detected on this site. It is currently configured as a standard WordPress site.', 'duplicator-pro'); ?>
<i><a href='https://codex.wordpress.org/Create_A_Network' target='_blank'> [<?php esc_html_e('details', 'duplicator-pro'); ?>]</a></i>
</div>
<?php } elseif (License::can(License::CAPABILITY_MULTISITE_PLUS)) { ?>
<hr size="1" />
<span>
<div class="dup-scan-good"><i class="fa fa-check"></i></div>
</span>
<b> <?php esc_html_e('Multisite: Detected', 'duplicator-pro'); ?></b> <br />
<div class="scan-system-subnote">
<?php esc_html_e('This license level has full access to all Multisite Plus+ features.', 'duplicator-pro'); ?>
</div>
<?php } else { ?>
<hr size="1" />
<span>
<div class="dup-scan-warn"><i class="fa fa-exclamation-triangle fa-sm"></i></div>
</span>
<b><?php esc_html_e('Multisite: Detected', 'duplicator-pro'); ?> </b> <br />
<div class="scan-system-subnote">
<?php esc_html(
sprintf(
__(
'Duplicator Pro is at the %1$s license level which allows for backups and migrations of an entire Multisite network.&nbsp;',
'duplicator-pro'
),
License::getLicenseToString()
)
); ?>
<br>
<?php echo wp_kses(
__(
"To unlock all <b>Multisite Plus</b> features please upgrade the license before building a Backup.",
'duplicator-pro'
),
['b' => []]
); ?>
<br />
<a href="<?php echo esc_url(License::getUpsellURL()); ?>" target='_blank'>
<?php esc_html_e('Upgrade Here', 'duplicator-pro'); ?>
</a>&nbsp;|&nbsp;
<a href="<?php echo esc_html(DUPLICATOR_DUPLICATOR_DOCS_URL); ?>how-does-duplicator-handle-multisite-support" target="_blank">
<?php esc_html_e('Multisite Plus Feature Overview', 'duplicator-pro'); ?>
</a>
</div>
<?php } ?>
</div>
</div>

View File

@@ -0,0 +1,124 @@
<?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
*/
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Core\Controllers\ControllersManager;
$blur = $tplData['blur'];
$package_list_url = ControllersManager::getMenuLink(ControllersManager::PACKAGES_SUBMENU_SLUG);
?>
<form
id="form-duplicator"
class="<?php echo ($blur ? 'dup-mock-blur' : ''); ?> scan-result"
method="post"
action="<?php echo esc_attr($package_list_url); ?>"
>
<?php PackagesPageController::getInstance()->getActionByKey(PackagesPageController::ACTION_CREATE_FROM_TEMP)->getActionNonceFileds(); ?>
<div id="dup-progress-area">
<!-- PROGRESS BAR -->
<div class="dup-progress-bar-area">
<div class="dupli-title" >
<?php esc_html_e('Scanning Site', 'duplicator-pro'); ?>
</div>
<div class="dupli-meter-wrapper" >
<div class="dupli-meter green dupli-fullsize">
<span></span>
</div>
<span class="text"></span>
</div>
<b><?php esc_html_e('Please Wait...', 'duplicator-pro'); ?></b><br/><br/>
<i><?php esc_html_e('Keep this window open during the scan process.', 'duplicator-pro'); ?></i><br/>
<i><?php esc_html_e('This can take several minutes.', 'duplicator-pro'); ?></i><br/>
</div>
<!-- SCAN DETAILS REPORT -->
<div id="dup-msg-success" style="display:none">
<div style="text-align:center">
<div class="dup-hdr-success">
<i class="far fa-check-square fa-nr"></i> <?php esc_html_e('Scan Complete', 'duplicator-pro'); ?>
</div>
<div id="dup-msg-success-subtitle">
<?php esc_html_e("Process Time:", 'duplicator-pro'); ?> <span id="data-rpt-scantime"></span>
</div>
</div>
<div class="details">
<?php $tplMng->render('admin_pages/packages/scan/items/setup/main'); ?>
<br/>
<?php $tplMng->render('admin_pages/packages/scan/items/archive/main'); ?>
<?php $tplMng->render('admin_pages/packages/scan/items/database/main'); ?>
</div>
</div>
<!-- ERROR MESSAGE -->
<div id="dup-msg-error" style="display:none">
<div class="dup-hdr-error"><i class="fa fa-exclamation-circle"></i> <?php esc_html_e('Scan Error', 'duplicator-pro'); ?></div>
<i><?php esc_html_e('Please try again!', 'duplicator-pro'); ?></i><br/>
<div style="text-align:left">
<b><?php esc_html_e("Server Status:", 'duplicator-pro'); ?></b> &nbsp;
<div id="dup-msg-error-response-status" style="display:inline-block"></div><br/>
<b><?php esc_html_e("Error Message:", 'duplicator-pro'); ?></b>
<div id="dup-msg-error-response-text"></div>
</div>
</div>
</div>
<!-- WARNING CONTINUE -->
<div id="dupli-scan-warning-continue">
<div class="msg2">
<?php esc_html_e("Scan checks are not required to pass, however they could cause issues on some systems.", 'duplicator-pro'); ?>
<br/>
<?php esc_html_e("Please review the details for each section by clicking on the detail title.", 'duplicator-pro'); ?>
</div>
</div>
<div id="dupli-confirm-area">
<?php esc_html_e('Do you want to continue?', 'duplicator-pro'); ?>
<br/>
<?php esc_html_e('At least one or more checkboxes were checked in "Quick Filters".', 'duplicator-pro') ?>
<br/>
<i style="font-weight:normal">
<?php esc_html_e('To apply a "Quick Filter" click the "Add Filters & Rescan" button', 'duplicator-pro') ?>
</i><br/>
<input
type="checkbox"
id="dupli-confirm-check"
onclick="jQuery('#dup-build-button').removeAttr('disabled');"
class="margin-bottom-0"
>
<?php esc_html_e('Yes. Continue without applying any file filters.', 'duplicator-pro') ?>
</div>
<div class="dup-button-footer" style="display:none">
<input
type="button"
class="button hollow secondary small dup-go-back-to-new1"
value="&#9664; <?php esc_html_e("Back", 'duplicator-pro') ?>"
>
<input
type="button"
class="button hollow secondary small"
value="<?php esc_attr_e("Rescan", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.reRunScanner()"
>
<input
type="button"
onclick="DupliJs.Pack.startBuild();"
class="button primary small"
id="dup-build-button"
value='<?php esc_attr_e("Create Backup", 'duplicator-pro') ?> &#9654'
>
</div>
</form>
<?php $tplMng->render('admin_pages/packages/scan/scripts'); ?>

View File

@@ -0,0 +1,922 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Ajax\ServicesPackage;
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Libs\Snap\SnapWP;
use Duplicator\Views\UI\UiDialog;
use Duplicator\Models\GlobalEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$alert2 = new UiDialog();
$alert2->height = 485;
$alert2->width = 650;
$alert2->title = __('Copy Quick Filter Paths', 'duplicator-pro');
$alert2->boxClass = 'arc-paths-dlg';
$alert2->message = "";
$alert2->initAlert();
$alert3 = new UiDialog();
$alert3->title = __('WARNING!', 'duplicator-pro');
$alert3->message = __('Manual copy of selected text required on this browser.', 'duplicator-pro');
$alert3->initAlert();
$alert4 = new UiDialog();
$alert4->title = $alert3->title;
$alert4->message = __('Error applying filters. Please go back to Step 1 to add filter manually!', 'duplicator-pro');
$alert4->initAlert();
$messageText = $tplMng->render('admin_pages/packages/scan/error_message', [], false);
?>
<script>
jQuery(document).ready(function($) {
var large_tree = $('#hb-files-large-jstree').length ? $('#hb-files-large-jstree') : null;
Handlebars.registerHelper('stripWPRoot', function(path) {
return path.replace('<?php echo esc_js(SnapWP::getHomePath(true)) ?>', '');
});
Handlebars.registerHelper('ifAllOr', function(v1, v2, v3, options) {
if (v1 || v2 || v3) {
return options.fn(this);
}
return options.inverse(this);
});
Handlebars.registerHelper('compare', function(v1, operator, v2, options) {
'use strict';
var operators = {
'==': v1 == v2 ? true : false,
'===': v1 === v2 ? true : false,
'!=': v1 != v2 ? true : false,
'!==': v1 !== v2 ? true : false,
'>': v1 > v2 ? true : false,
'>=': v1 >= v2 ? true : false,
'<': v1 < v2 ? true : false,
'<=': v1 <= v2 ? true : false,
'||': v1 || v2 ? true : false,
'&&': v1 && v2 ? true : false
}
if (operators.hasOwnProperty(operator)) {
if (operators[operator]) {
return options.fn(this);
}
return options.inverse(this);
}
return console.error('Error: Expression "' + operator + '" not found');
});
//Opens a dialog to show scan details
DupliJs.Pack.filesOff = function(dir) {
var $checks = $(dir).parent('div.directory').find('div.files input[type="checkbox"]');
$(dir).is(':checked') ?
$.each($checks, function() {
$(this).attr({
disabled: true,
checked: false,
title: "<?php esc_html_e('Directory applied filter set.', 'duplicator-pro'); ?>"
});
}) :
$.each($checks, function() {
$(this).removeAttr('disabled checked title');
});
}
DupliJs.Pack.FilterButton = {
loading: function(btn) {
$(btn).html('<i class="fas fa-circle-notch fa-spin"></i> <?php esc_html_e('Initializing Please Wait...', 'duplicator-pro'); ?>');
$(btn).prop('disabled', true);
$('#dup-build-button').prop('disable', true);
},
reset: function(btn) {
$(btn).html('<i class="fa fa-filter fa-sm"></i> <?php esc_html_e("Add Filters &amp; Rescan", "duplicator-pro"); ?>');
$(btn).prop('disabled', true);
$('#dup-build-button').prop('disable', false);
}
};
//Opens a dialog to show scan details
DupliJs.Pack.showPathsDlg = function(type) {
var filters = DupliJs.Pack.getFiltersLists(type);
var dirFilters = filters.dir;
var fileFilters = filters.file;
var $dirs = $('#dup-archive-paths textarea.path-dirs');
var $files = $('#dup-archive-paths textarea.path-files');
(dirFilters.length > 0) ?
$dirs.text(dirFilters.join(";\n")): $dirs.text("<?php esc_html_e('No directories have been selected!', 'duplicator-pro'); ?>");
(fileFilters.length > 0) ?
$files.text(fileFilters.join(";\n")): $files.text("<?php esc_html_e('No files have been selected!', 'duplicator-pro'); ?>");
$('.arc-paths-dlg').html($('#dup-archive-paths').html());
<?php $alert2->showAlert(); ?>
return;
};
//Toggles a directory path to show files
DupliJs.Pack.toggleDirPath = function(item) {
var $dir = $(item).parents('div.directory');
var $files = $dir.find('div.files');
var $arrow = $dir.find('i.dup-nav');
if ($files.is(":hidden")) {
$arrow.addClass('fa-caret-down').removeClass('fa-caret-right');
$files.show();
} else {
$arrow.addClass('fa-caret-right').removeClass('fa-caret-down');
$files.hide(250);
}
}
//Toggles a directory path to show files
DupliJs.Pack.toggleAllDirPath = function(chkBox, toggle) {
(toggle == 'hide') ?
$('#hb-files-large-jstree').jstree().close_all(): $('#hb-files-large-jstree').jstree().open_all();
}
DupliJs.Pack.copyText = function(btn, query) {
$(query).select();
try {
document.execCommand('copy');
$(btn).css({
color: '#fff',
backgroundColor: 'green'
});
$(btn).text("<?php esc_html_e('Copied to Clipboard!', 'duplicator-pro'); ?>");
} catch (err) {
<?php $alert3->showAlert(); ?>
}
}
DupliJs.Pack.getFiltersLists = function(type) {
var result = {
'dir': [],
'file': []
};
switch (type) {
case 'large':
console.log(large_tree);
if (large_tree) {
$.each(large_tree.jstree("get_checked", null, true), function(index, value) {
var original = large_tree.jstree(true).get_node(value).original;
if (original.type.startsWith('folder')) {
result.dir.push(original.fullPath);
} else {
result.file.push(original.fullPath);
}
});
}
break;
case 'addon':
var id = '#hb-addon-sites-result';
if ($(id).length) {
$(id + " input[name='dir_paths[]']:checked").each(function() {
result.dir.push($(this).val());
});
$(id + " input[name='file_paths[]']:checked").each(function() {
result.file.push($(this).val());
});
}
break;
}
return result;
};
DupliJs.Pack.applyFilters = function(btn, type) {
var filterButton = btn;
var filters = DupliJs.Pack.getFiltersLists(type);
var dirFilters = filters.dir;
var fileFilters = filters.file;
if (dirFilters.length === 0 && fileFilters.length === 0) {
alert('No filter selected');
return false;
}
dirFilters = dirFilters.map(function(path) {
return path.slice(-1) !== '\/' ? path + '\/' : path;
});
DupliJs.Pack.FilterButton.loading(filterButton);
var data = {
action: 'duplicator_add_quick_filters',
nonce: <?php echo json_encode(wp_create_nonce('duplicator_add_quick_filters')); ?>,
dir_paths: dirFilters.join(";"),
file_paths: fileFilters.join(";")
};
$.ajax({
type: "POST",
cache: false,
dataType: 'json',
url: ajaxurl,
timeout: 100000,
data: data,
complete: function() {},
success: function(data) {
DupliJs.Pack.reRunScanner(function() {
DupliJs.Pack.FilterButton.reset(filterButton);
DupliJs.Pack.fullLoadButtonInit();
});
},
error: function(data) {
console.log(data);
<?php $alert4->showAlert(); ?>
}
});
return false;
};
DupliJs.Pack.treeContextMenu = function(node) {
var items = {};
if (node.type.startsWith('folder')) {
items = {
selectAll: {
label: "<?php esc_html_e('Select all childs files and folders', 'duplicator-pro'); ?>",
action: function(obj) {
$(obj.reference).parent().find('> .jstree-children .warning-node > .jstree-anchor:not(.jstree-checked) .jstree-checkbox')
.each(function() {
var _this = $(this);
if (_this.parents('.selected-node').length === 0) {
_this.trigger('click');
}
});
}
},
selectAllFiles: {
label: "<?php esc_html_e('Select only all childs files', 'duplicator-pro'); ?>",
action: function(obj) {
$(obj.reference).parent().find('> .jstree-children .file-node.warning-node > .jstree-anchor:not(.jstree-checked) .jstree-checkbox')
.each(function() {
var _this = $(this);
if (_this.parents('.selected-node').length === 0) {
_this.trigger('click');
}
});
}
},
unselectAll: {
label: "<?php esc_html_e('Unselect all childs elements', 'duplicator-pro'); ?>",
action: function(obj) {
$(obj.reference).parent().find('> .jstree-children .jstree-node > .jstree-anchor.jstree-checked .jstree-checkbox').trigger('click');
}
}
};
}
return items;
};
DupliJs.Pack.getTreeFolderUrlData = function(folder, excludeList) {
if (excludeList === undefined) {
excludeList = [];
}
return {
'nonce': <?php echo json_encode(wp_create_nonce('duplicator_get_folder_children')); ?>,
'action': 'duplicator_get_folder_children',
'folder': folder,
'exclude': excludeList
};
};
DupliJs.Pack.getTreeFolderUrl = function(folder, excludeList) {
return ajaxurl + '?' + $.param(DupliJs.Pack.getTreeFolderUrlData(folder, excludeList));
};
DupliJs.Pack.fullLoadNodes = null;
DupliJs.Pack.fullLoadFolder = function(tree, index, sectionContainer) {
if (Array.isArray(DupliJs.Pack.fullLoadNodes) && index < DupliJs.Pack.fullLoadNodes.length) {
var parent = DupliJs.Pack.fullLoadNodes[index];
if (index === 0 && sectionContainer) {
sectionContainer.append('<div class="tree-loader" >' +
'<div class="container-wrapper" >' +
'<i class="fa fa-cog fa-lg fa-spin"></i> <span></span>' +
'</div>' +
'</div>');
}
sectionContainer.find('.tree-loader span').text("<?php echo esc_js(__('Loading ', 'duplicator-pro')) ?>" + parent.original.fullPath);
} else {
DupliJs.Pack.fullLoadNodes = null;
if (sectionContainer) {
sectionContainer.find('.tree-loader').remove();
}
return;
}
var excludeList = [];
var parentClass = parent.li_attr.class;
if (parentClass.indexOf('root-node') !== -1 && parentClass.indexOf('no-warnings') !== -1) {
tree.delete_node(parent.children[0]);
} else {
for (i = 0; i < parent.children.length; i++) {
excludeList.push(tree.get_node(parent.children[i]).original.fullPath.replace(/^.*[\\\/]/, ''));
}
}
var data = DupliJs.Pack.getTreeFolderUrlData(parent.original.fullPath, excludeList);
$.ajax({
type: "GET",
cache: false,
data: data,
dataType: "json",
url: ajaxurl,
timeout: 100000,
//data: data,
complete: function() {},
success: function(data) {
try {
for (i = 0; i < data.length; i++) {
tree.create_node(parent, data[i]);
}
DupliJs.Pack.fullLoadFolder(tree, index + 1, sectionContainer);
} catch (err) {
console.error(err);
console.error('JSON parse failed for response data: ' + respData);
console.log(respData);
<?php $alert4->showAlert(); ?>
return false;
}
},
error: function(data) {
console.log(data);
<?php $alert4->showAlert(); ?>
}
});
};
function resetTreeLoadButton() {
$('.tree-full-load-button')
.removeClass('isLoaded dup-tree-hide-all')
.addClass('dup-tree-show-all')
.text("<?php echo esc_js(__('show all', 'duplicator-pro')); ?>")
}
DupliJs.Pack.fullLoadButtonInit = function() {
resetTreeLoadButton();
$('.tree-full-load-button')
.off()
.click(function() {
var sectionContainer = $(this).closest('.dup-tree-section').find('> .container');
var cObj = $(this);
var domTree = sectionContainer.find(".dup-tree-main-wrapper");
var tree = domTree.jstree(true);
if (cObj.hasClass('dup-tree-show-all')) {
cObj.removeClass('dup-tree-show-all')
.addClass('dup-tree-hide-all')
.text("<?php echo esc_js(__('show warning only', 'duplicator-pro')) ?>");
if (!cObj.hasClass('isLoaded')) {
cObj.addClass('isLoaded');
DupliJs.Pack.fullLoadNodes = [];
domTree.find(".folder-node[data-full-loaded=false]").each(function() {
var parent = tree.get_node($(this));
if (parent.state.loaded === false) {
// If loaded it is false the folder has never been opened then it will be loaded by jstree if it is opened.
return;
}
DupliJs.Pack.fullLoadNodes.push(parent);
});
if (DupliJs.Pack.fullLoadNodes.length) {
DupliJs.Pack.fullLoadFolder(tree, 0, sectionContainer);
} else {
DupliJs.Pack.fullLoadNodes = null;
}
} else {
domTree.find(".root-node .jstree-node:not(.warning-childs):not(.warning-node)").each(function() {
// don't use the tree functions show_node and hide_node are too slow.
$(this).removeClass('jstree-hidden');
});
}
} else {
cObj.removeClass('dup-tree-hide-all').addClass('dup-tree-show-all')
.text("<?php echo esc_js(__('show all', 'duplicator-pro')); ?>");
domTree.find(".root-node .jstree-node:not(.warning-node):not(.warning-childs)").each(function() {
// don't use the tree functions show_node and hide_node are too slow.
$(this).addClass('jstree-hidden');
});
}
// recalculate the last child manually
domTree.find(".jstree-children").each(function() {
$(this).find('> li:not(.jstree-hidden)').removeClass('jstree-last').last().addClass('jstree-last');
});
});
};
DupliJs.Pack.initTree = function(tree, data, filterBtn) {
var treeObj = tree;
var nameData = data;
console.log('nameData', nameData);
treeObj.jstree('destroy');
treeObj.jstree({
'core': {
"check_callback": true,
'cache': false,
//'data' : nameData,
"themes": {
"name": "snap",
"dots": true,
"icons": true,
"stripes": true,
},
'data': {
'url': function(node) {
var folder = (node.id === '#') ? '' : node.original.fullPath;
return DupliJs.Pack.getTreeFolderUrl(folder);
},
'data': function(node) {
return {
'id': node.id
};
}
}
},
'types': {
"folder": {
"icon": "jstree-icon jstree-folder",
"li_attr": {
"class": 'folder-node'
}
},
"file": {
"icon": "jstree-icon jstree-file",
"li_attr": {
"class": 'file-node'
}
},
"info-text": {
"icon": "jstree-noicon",
"li_attr": {
"class": 'info-node'
}
}
},
"checkbox": {
// a boolean indicating if checkboxes should be visible (can be changed at a later time using
// `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`.
visible: true,
// a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`.
three_state: false,
// a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`.
whole_node: false,
keep_selected_style: false, // a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`.
// This setting controls how cascading and undetermined nodes are applied.
// If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled,
// if 'undetermined' is in the string - undetermined nodes will be used.
// If `three_state` is set to `true` this setting is automatically set to 'up+down+undetermined'. Defaults to ''.
cascade: '',
// This setting controls if checkbox are bound to the general tree selection or
// to an internal array maintained by the checkbox plugin. Defaults to `true`, only set to `false` if you know exactly what you are doing.
tie_selection: false,
cascade_to_disabled: false, // This setting controls if cascading down affects disabled checkboxes
cascade_to_hidden: false //This setting controls if cascading down affects hidden checkboxes
},
"contextmenu": {
"items": DupliJs.Pack.treeContextMenu
},
"plugins": [
"checkbox",
"contextmenu",
"types",
//"dnd",
//"massload",
//"search",
//"sort",
//"state",
//"types",
//"unique",
//"wholerow",
"changed",
//"conditionalselect"
]
}).on('check_node.jstree', function(e, data) {
treeObj.find('#' + data.node.id).addClass('selected-node');
filterBtn.prop("disabled", false);
}).on('uncheck_node.jstree', function(e, data) {
treeObj.find('#' + data.node.id).removeClass('selected-node');
if (treeObj.jstree("get_selected").length === 0) {
filterBtn.prop("disabled", true);
}
}).on('ready.jstree', function() {
// insert data
tree.jstree(true).create_node(null, nameData);
});
};
DupliJs.Pack.initArchiveFilesData = function(data) {
//TOTAL SIZE
$('#data-arc-size1').text(data.ARC.Size || errMsg);
$('#data-arc-size2').text(data.ARC.Size || errMsg);
$('#data-arc-files').text(data.ARC.FileCount || errMsg);
$('#data-arc-dirs').text(data.ARC.DirCount || errMsg);
$('#data-arc-fullcount').text(data.ARC.FullCount || errMsg);
//LARGE FILES
if ($("#hb-files-large-result").length) {
DupliJs.Pack.initTree(
large_tree,
data.ARC.FilterInfo.TreeSize,
$("#hb-files-large-result .dupli-quick-filter-btn")
);
}
//ADDON SITES
if ($("#hb-addon-sites").length) {
var template = $('#hb-addon-sites').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#hb-addon-sites-result').html(html);
}
//UNREADABLE FILES
if ($("#unreadable-files").length) {
var template = $('#unreadable-files').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#unreadable-files-result').html(html);
}
//SCANNER DETAILS: Dirs
if ($("#hb-filter-file-list").length) {
var template = $('#hb-filter-file-list').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('div.hb-filter-file-list-result').html(html);
}
//NETWORK SITES
if ($("#hb-filter-network-sites").length) {
var template = $('#hb-filter-network-sites').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#hb-filter-network-sites-result').html(html);
}
//MIGRATE PACKAGE
if ($("#hb-migrate-package-result").length) {
var template = $('#hb-migrate-package-result').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#migrate-package-result').html(html);
}
//Security Plugins
if ($("#hb-dup-security-plugins").length) {
var template = $('#hb-dup-security-plugins').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#dup-security-plugins').html(html);
}
//SHOW CREATE
if ($("#hb-showcreatefunc-result").length) {
var template = $('#hb-showcreatefunc-result').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#showcreatefunc-package-result').html(html);
}
//TRIGGERS
if ($("#hb-triggers-result").length) {
var template = $('#hb-triggers-result').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#triggers-result').html(html);
}
//MYSQLDUMP LIMIT
if ($("#hb-mysqldump-limit-result").length) {
var template = $('#hb-mysqldump-limit-result').html();
var templateScript = Handlebars.compile(template);
var html = templateScript(data);
$('#mysqldump-limit-result').html(html);
}
DuplicatorTooltip.reload();
};
DupliJs.Pack.fullLoadButtonInit();
$("#form-duplicator").on('change', "#hb-files-large-result input[type='checkbox'], #hb-addon-sites-result input[type='checkbox']", function() {
if ($("#hb-addon-sites-result input[type='checkbox']:checked").length) {
var addon_disabled_prop = false;
} else {
var addon_disabled_prop = true;
}
$("#hb-addon-sites-result .dupli-quick-filter-btn").prop("disabled", addon_disabled_prop);
});
DupliJs.Pack.WebServiceStatus = {
Pass: <?php echo json_encode(ServicesPackage::EXEC_STATUS_PASS); ?>,
Warn: <?php echo json_encode(ServicesPackage::EXEC_STATUS_WARN); ?>, //deprecated
Error: <?php echo json_encode(ServicesPackage::EXEC_STATUS_FAIL); ?>,
MoreToScan: <?php echo json_encode(ServicesPackage::EXEC_STATUS_MORE_TO_SCAN); ?>,
ScheduleRunning: <?php echo json_encode(ServicesPackage::EXEC_STATUS_SCHEDULE_RUNNING); ?>
}
let errorMessage = <?php echo json_encode($messageText); ?>;
let scanTimeoutInSec = <?php echo json_encode(GlobalEntity::getInstance()->php_max_worker_time_in_sec); ?>;
let scanTimeout = (scanTimeoutInSec + 10) * 1000; // Add 10 seconds to the backend timeout
DupliJs.Pack.runScanner = function(callbackOnSuccess, firstChunk = false) {
DupliJs.Util.ajaxWrapper({
action: 'duplicator_package_scan',
firstChunk: firstChunk,
nonce: <?php echo json_encode(wp_create_nonce('duplicator_package_scan')); ?>
},
function(result, data, funcData, textStatus, jqXHR) {
var status = funcData.Status || 3;
var message = funcData.Message ||
"Unable to read JSON from service. <br/> See: /wp-admin/admin-ajax.php?action=duplicator_package_scan";
if (status == DupliJs.Pack.WebServiceStatus.MoreToScan) {
console.log('Continue with next scan chunk...');
DupliJs.Pack.runScanner(callbackOnSuccess);
return;
}
// Scan finished, parse results
if (status == DupliJs.Pack.WebServiceStatus.Pass) {
DupliJs.Pack.loadScanData(funcData);
if (typeof callbackOnSuccess === "function") {
callbackOnSuccess(funcData);
}
$('.dup-button-footer').show();
} else if (status == DupliJs.Pack.WebServiceStatus.ScheduleRunning) {
console.log('Scan is already running...');
window.location.href = <?php echo json_encode(PackagesPageController::getInstance()->getPackageBuildS1Url()); ?>;
} else {
$('.dup-progress-bar-area, #dup-build-button').hide();
$('#dup-msg-error-response-status').html(status);
$('#dup-msg-error-response-text').html(message + errorMessage);
$('#dup-msg-error').show();
$('.dup-button-footer').show();
}
},
function(result, data, funcData, textStatus, jqXHR) {
var status = data.status + ' -' + data.statusText;
$('.dup-progress-bar-area, #dup-build-button').hide();
$('#dup-msg-error-response-status').html(status)
$('#dup-msg-error-response-text').html(data.message + errorMessage);
$('#dup-msg-error, .dup-button-footer').show();
console.log(data);
}, {
showProgress: false,
timeout: scanTimeout
}
);
}
DupliJs.Pack.reRunScanner = function(callbackOnSuccess) {
$('#dup-msg-success,#dup-msg-error,.dup-button-footer,#dupli-confirm-area').hide();
$('#dupli-confirm-check').prop('checked', false);
$('.dup-progress-bar-area').show();
$('#dupli-scan-warning-continue').hide();
resetTreeLoadButton();
DupliJs.Pack.runScanner(callbackOnSuccess, true);
}
DupliJs.Pack.loadScanData = function(data) {
try {
var errMsg = "unable to read";
$('.dup-progress-bar-area').hide();
//****************
// BRAND
// #data-srv-brand-check
// #data-srv-brand-name
// #data-srv-brand-note
$("#data-srv-brand-name").text(data.SRV.Brand.Name);
if (data.SRV.Brand.LogoImageExists) {
$("#data-srv-brand-note").html(data.SRV.Brand.Notes);
} else {
$("#data-srv-brand-note")
.html(`<?php
esc_html_e(
"WARNING! Logo images no longer can be found inside brand. Please edit this brand and place new images.
After that you can build your Backup with this brand.",
"duplicator-pro"
); ?>`);
}
//****************
//REPORT
var base = $('#data-rpt-scanfile').attr('href');
$('#data-rpt-scanfile').attr('href', base + '&scanfile=' + data.RPT.ScanFile);
$('#data-rpt-scantime').text(data.RPT.ScanTime || 0);
DupliJs.Pack.initArchiveFilesData(data);
DupliJs.Pack.setScanStatus(data);
//Addon Sites
if (data.ARC.FilterInfo.Dirs.AddonSites !== undefined && data.ARC.FilterInfo.Dirs.AddonSites.length > 0) {
$("#addonsites-block").show();
}
$('#dup-msg-success').show();
//****************
//DATABASE
var html = "";
var DB_TableRowMax = <?php echo (int) DUPLICATOR_SCAN_DB_TBL_ROWS; ?>;
var DB_TableSizeMax = <?php echo (int) DUPLICATOR_SCAN_DB_TBL_SIZE; ?>;
if (data.DB.DBExcluded && data.DB.Status.Success) {
$('#data-db-size1').text(data.DB.Size || errMsg);
} else if (data.DB.Status.Success) {
$('#data-db-size1').text(data.DB.Size || errMsg);
$('#data-db-size2').text(data.DB.Size || errMsg);
$('#data-db-rows').text(data.DB.Rows || errMsg);
$('#data-db-tablecount').text(data.DB.TableCount || errMsg);
//Table Details
if (data.DB.TableList == undefined || data.DB.TableList.length == 0) {
html = '<?php esc_html_e("Unable to report on any tables", 'duplicator-pro') ?>';
} else {
$.each(data.DB.TableList, function(i) {
html += '<b>' + i + '</b><br/>';
html += '<table><tr>';
$.each(data.DB.TableList[i], function(key, val) {
switch (key) {
case 'Case':
color = (val == 1) ? 'maroon' : 'black';
html += '<td style="color:' + color + '"><?php echo esc_js(__('Uppercase:', 'duplicator-pro')) ?> ' + val + '</td>';
break;
case 'Rows':
color = (val > DB_TableRowMax) ? 'red' : 'black';
html += '<td style="color:' + color + '"><?php echo esc_js(__('Rows:', 'duplicator-pro')) ?> ' + val + '</td>';
break;
case 'USize':
color = (parseInt(val) > DB_TableSizeMax) ? 'red' : 'black';
html += '<td style="color:' + color + '">';
html += '<?php echo esc_js(__('Size:', 'duplicator-pro')) ?> ' + data.DB.TableList[i]['Size'];
html += '</td>';
break;
}
});
html += '</tr></table>';
});
}
$('#data-db-tablelist').html(html);
} else {
html = '<?php esc_html_e("Unable to report on database stats", 'duplicator-pro') ?>';
$('#dup-scan-db').html(html);
}
var isWarn = false;
for (key in data.ARC.Status) {
if (!data.ARC.Status[key]) {
isWarn = true;
}
}
if (!isWarn) {
if (!data.DB.Status.Size) {
isWarn = true;
}
}
if (!isWarn && !data.DB.Status.Rows) {
isWarn = true;
}
if (!isWarn && !data.SRV.PHP.ALL) {
isWarn = true;
}
if (!isWarn && (data.SRV.WP.version == false || data.SRV.WP.core == false)) {
isWarn = true;
}
if (isWarn) {
$('#dupli-scan-warning-continue').show();
} else {
$('#dupli-scan-warning-continue').hide();
$('#dup-build-button').prop("disabled", false);
}
} catch (err) {
err += '<br/> Please try again!'
$('#dup-msg-error-response-status').html("n/a")
$('#dup-msg-error-response-text').html(err);
$('#dup-msg-error, .dup-button-footer').show();
$('#dup-build-button').hide();
}
}
//Starts the build process
DupliJs.Pack.startBuild = function() {
// disable to prevent double click
$('#dup-build-button').prop('disabled', true);
if ($('#dupli-confirm-check').is(":checked")) {
$('#form-duplicator').submit();
}
var sizeChecks = $('#hb-files-large-jstree').length ? $('#hb-files-large-jstree').jstree(true).get_checked() : 0;
var addonChecks = $('#hb-addon-sites-result input:checked');
var utf8Checks = $('#hb-files-utf8-jstree').length ? $('#hb-files-utf8-jstree').jstree(true).get_checked() : 0;
if (sizeChecks.length > 0 || addonChecks.length > 0 || utf8Checks.length > 0) {
$('#dupli-confirm-area').show();
} else {
$('#form-duplicator').submit();
}
}
//Toggles each scan item to hide/show details
DupliJs.Pack.toggleScanItem = function(item) {
var $info = $(item).parents('div.scan-item').children('div.info');
var $text = $(item).find('div.text i.fa');
if ($info.is(":hidden")) {
$text.addClass('fa-caret-down').removeClass('fa-caret-right');
$info.show();
} else {
$text.addClass('fa-caret-right').removeClass('fa-caret-down');
$info.hide(250);
}
}
//Set Good/Warn Badges and checkboxes
DupliJs.Pack.setScanStatus = function(data) {
let subTestSelectorMappings = {
'#data-srv-php-websrv': data.SRV.PHP.websrv,
'#data-srv-php-openbase': data.SRV.PHP.openbase || !data.ARC.PathsOutOpenbaseDir.length,
'#data-srv-php-maxtime': data.SRV.PHP.maxtime,
'#data-srv-php-minmemory': data.SRV.PHP.minMemory,
'#data-srv-php-arch64bit': data.SRV.PHP.arch64bit,
'#data-srv-php-mysqli': data.SRV.PHP.mysqli,
'#data-srv-php-openssl': data.SRV.PHP.openssl,
'#data-srv-php-allowurlfopen': data.SRV.PHP.allowurlfopen,
'#data-srv-php-curlavailable': data.SRV.PHP.curlavailable,
'#data-srv-php-version': data.SRV.PHP.version,
'#data-srv-wp-version': data.SRV.WP.version,
'#data-srv-brand-check': data.SRV.Brand.LogoImageExists,
'#data-srv-wp-core': data.SRV.WP.core
};
for (let selector in subTestSelectorMappings) {
if (subTestSelectorMappings[selector]) {
$(selector).html('<div class="scan-good"><i class="fa fa-check"></i></div>');
} else {
$(selector).html('<div class="scan-warn"><i class="fa fa-exclamation-triangle fa-sm"></i></div>');
}
}
let testSelectorMappings = {
'#data-srv-php-all': data.SRV.PHP.ALL,
'#data-srv-wp-all': data.SRV.WP.ALL,
'#data-arc-status-size': data.ARC.Status.Size,
'#data-arc-status-unreadablefiles': data.ARC.Status.UnreadableItems,
'#data-arc-status-showcreatefunc': data.ARC.Status.showCreateFuncStatus,
'#data-arc-status-network': data.ARC.Status.Network,
'#data-arc-status-triggers': data.DB.Status.Triggers,
'#data-arc-status-migratepackage': !data.ARC.Status.PackageIsNotImportable,
'#data-arc-status-addonsites': data.ARC.Status.AddonSites,
'#data-db-status-size1': data.DB.DBExcluded && data.DB.Status.Success ? data.DB.Status.Excluded : data.DB.Status.Size,
}
const GoodText = "<?php esc_html_e('Good', 'duplicator-pro'); ?>";
const WarnText = "<?php esc_html_e('Notice', 'duplicator-pro'); ?>";
for (let selector in testSelectorMappings) {
if (testSelectorMappings[selector]) {
$(selector).html(`<div class="badge badge-pass">${GoodText}</div>`);
} else {
$(selector).html(`<div class="badge badge-warn">${WarnText}</div>`);
}
}
}
//Allows user to continue with build if warnings found
DupliJs.Pack.warningContinue = function(checkbox) {
($(checkbox).is(':checked')) ?
$('#dup-build-button').prop('disabled', false): $('#dup-build-button').prop('disabled', true);
}
//Page Init:
DupliJs.Pack.runScanner(null, true);
$('.dup-go-back-to-new1').click(function(event) {
event.preventDefault();
window.location.href = <?php echo json_encode(PackagesPageController::getInstance()->getPackageBuildS1Url()); ?>;
});
});
</script>

View File

@@ -0,0 +1,45 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Core\Controllers\ControllersManager;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<form
id="form-duplicator scan-result"
method="post"
action="<?php echo esc_attr(ControllersManager::getMenuLink(ControllersManager::PACKAGES_SUBMENU_SLUG)); ?>"
>
<!-- ERROR MESSAGE -->
<div id="dup-msg-error">
<div class="dup-hdr-error"><i class="fa fa-exclamation-circle"></i> <?php esc_html_e('Input fields not valid', 'duplicator-pro'); ?></div>
<i><?php esc_html_e('Please try again!', 'duplicator-pro'); ?></i><br/>
<div style="text-align:left">
<b><?php esc_html_e("Server Status:", 'duplicator-pro'); ?></b> &nbsp;
<div id="dup-msg-error-response-status" style="display:inline-block"></div><br/>
<b><?php esc_html_e("Error Message:", 'duplicator-pro'); ?></b>
<div id="dup-msg-error-response-text">
<ul>
<?php $tplData['validator']->getErrorsFormat("<li>%s</li>"); ?>
</ul>
</div>
</div>
</div>
<input
type="button"
value="&#9664; <?php esc_html_e("Back", 'duplicator-pro') ?>"
class="button hollow secondary dup-go-back-to-new1"
>
</form>

View File

@@ -0,0 +1,152 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Views\UserUIOptions;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$uiOpts = UserUIOptions::getInstance();
$perPage = $uiOpts->get(UserUIOptions::VAL_PACKAGES_PER_PAGE);
$dateFormat = $uiOpts->get(UserUIOptions::VAL_CREATED_DATE_FORMAT);
$showNote = $uiOpts->get(UserUIOptions::VAL_SHOW_COL_NOTE);
$showSize = $uiOpts->get(UserUIOptions::VAL_SHOW_COL_SIZE);
$showCreated = $uiOpts->get(UserUIOptions::VAL_SHOW_COL_CREATED);
$showAge = $uiOpts->get(UserUIOptions::VAL_SHOW_COL_AGE);
?>
<fieldset class="metabox-prefs">
<legend>
<?php esc_html_e('Columns', 'duplicator-pro'); ?>
</legend>
<label class="inline-display" >
<input
class="dup-hide-column-tog margin-0"
name="dupli-note-hide"
type="checkbox"
id="dupli-note-hide"
value="1"
<?php checked($showNote); ?>
data-target-colum="dup-note-column"
>
<?php esc_html_e('Note', 'duplicator-pro'); ?>
</label>
<label class="inline-display" >
<input
class="dup-hide-column-tog margin-0"
name="dupli-size-hide"
type="checkbox"
id="dupli-size-hide"
value="1" <?php checked($showSize); ?>
data-target-colum="dup-size-column"
>
<?php esc_html_e('Size', 'duplicator-pro'); ?>
</label>
<label class="inline-display" >
<input
class="dup-hide-column-tog margin-0"
name="dupli-created-hide"
type="checkbox"
id="dupli-created-hide"
value="1"
<?php checked($showCreated); ?>
data-target-colum="dup-created-column"
>
<?php esc_html_e('Created', 'duplicator-pro'); ?>
</label>
<label class="inline-display" >
<input
class="dup-hide-column-tog margin-0"
name="dupli-age-hide"
type="checkbox"
id="dupli-age-hide"
value="1"
<?php checked($showAge); ?>
data-target-colum="dup-age-column"
>
<?php esc_html_e('Age', 'duplicator-pro'); ?>
</label>
</fieldset>
<fieldset class="screen-options" >
<legend>
<?php esc_html_e('Pagination', 'duplicator-pro'); ?>
</legend>
<label for="dupli_opts_per_page" class="inline-display" >
<?php esc_html_e('Backups Per Page', 'duplicator-pro'); ?>
</label>&nbsp;
<input
type="number"
step="1"
min="1"
max="999"
class="screen-per-page inline-display margin-0 width-small"
name="dupli-per-page"
id="dupli-per-page"
maxlength="3"
value="<?php echo esc_html($perPage); ?>"
>
</fieldset>
<fieldset class="screen-options">
<legend>
<?php esc_html_e('Created Format', 'duplicator-pro'); ?>
</legend>
<div class="metabox-prefs">
<input type="hidden" name="wp_screen_options[option]" value="package_screen_options">
<input type="hidden" name="wp_screen_options[value]" value="val">
<div class="created-format-wrapper">
<select name="dupli-created-format" class="width-medium" >
<!-- YEAR -->
<optgroup label="By Year">
<option value="1" <?php selected($dateFormat, 1); ?> >Y-m-d H:i &nbsp; [2000-01-05 12:00]</option>
<option value="2" <?php selected($dateFormat, 2); ?> >Y-m-d H:i:s [2000-01-05 12:00:01]</option>
<option value="3" <?php selected($dateFormat, 3); ?> >y-m-d H:i &nbsp; [00-01-05 12:00]</option>
<option value="4" <?php selected($dateFormat, 4); ?> >y-m-d H:i:s [00-01-05 12:00:01]</option>
</optgroup>
<!-- MONTH -->
<optgroup label="By Month">
<option value="5" <?php selected($dateFormat, 5); ?> >m-d-Y H:i &nbsp; [01-05-2000 12:00]</option>
<option value="6" <?php selected($dateFormat, 6); ?> >m-d-Y H:i:s [01-05-2000 12:00:01]</option>
<option value="7" <?php selected($dateFormat, 7); ?> >m-d-y H:i &nbsp; [01-05-00 12:00]</option>
<option value="8" <?php selected($dateFormat, 8); ?> >m-d-y H:i:s [01-05-00 12:00:01]</option>
</optgroup>
<!-- DAY -->
<optgroup label="By Day">
<option value="9" <?php selected($dateFormat, 9); ?> > d-m-Y H:i &nbsp; [05-01-2000 12:00]</option>
<option value="10" <?php selected($dateFormat, 10); ?> >d-m-Y H:i:s [05-01-2000 12:00:01]</option>
<option value="11" <?php selected($dateFormat, 11); ?> >d-m-y H:i &nbsp; [05-01-00 12:00]</option>
<option value="12" <?php selected($dateFormat, 12); ?> >d-m-y H:i:s [05-01-00 12:00:01]</option>
</optgroup>
</select>
</div>
</div>
</fieldset>
<input
type="submit"
name="screen-options-apply"
id="screen-options-apply"
class="button secondary hollow small margin-0"
value="Apply"
>
<script>
jQuery(document).ready(function($) {
$('.dup-hide-column-tog').on('change', function() {
let node = $(this);
let columns = $('.' + node.data('target-colum'));
if (node.is(':checked')) {
columns.show();
} else {
columns.hide();
}
});
});
</script>

View File

@@ -0,0 +1,119 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Addons\ProBase\License\License;
use Duplicator\Libs\WpUtils\WpUtilsMultisite;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
if (!is_multisite()) {
return;
}
?>
<div class="filter-mu-tab-content <?php echo (License::can(License::CAPABILITY_MULTISITE_PLUS) ? '' : 'disabled'); ?>">
<div style="max-width:900px">
<?php if (!License::can(License::CAPABILITY_MULTISITE_PLUS)) { ?>
<div class="dupli-panel-optional-txt alert-disabled" style="text-align: center">
<b><?php esc_html_e("Notice:", 'duplicator-pro'); ?></b>
<?php
printf(
esc_html__(
'This option isn\'t available at the %1$s license level.',
'duplicator-pro'
),
esc_html(License::getLicenseToString())
);
?>
<br>
<?php
printf(
esc_html_x(
'To enable this option %1$supgrade%2$s the License.',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url(License::getUpsellURL()) . '" target="_blank">',
'</a>'
);
?>
</div>
<?php } ?>
<?php
echo '<b>' . esc_html__("Overview:", 'duplicator-pro') . '</b><br/>';
esc_html_e(
"When you want to move a full multisite network or convert a subsite to a standalone site just
create a standard Backup like you would with a single site.
Then browse to the installer and choose either 'Restore entire multisite network' or 'Convert subsite into a standalone site'.
These options will be present on Step 1 of the installer when restoring a Multisite Backup.",
'duplicator-pro'
);
?>
</div>
<table class="mu-opts">
<tr>
<td>
<b><?php esc_html_e("Included Sub-Sites", 'duplicator-pro'); ?>:</b><br />
<select name="mu-include[]" id="mu-include" multiple="true" class="mu-selector">
<?php
$subsites = License::can(License::CAPABILITY_MULTISITE_PLUS) ? WpUtilsMultisite::getSubsites() : [];
foreach ($subsites as $site) {
echo "<option value='" . (int) $site->id . "'>" . esc_html($site->domain . $site->path) . "</option>";
}
?>
</select>
</td>
<td>
<button type="button" id="mu-exclude-btn" class="mu-push-btn"><i class="fa fa-chevron-right"></i></button>
<br />
<button type="button" id="mu-include-btn" class="mu-push-btn"><i class="fa fa-chevron-left"></i></button>
</td>
<td>
<b><?php esc_html_e("Excluded Sub-Sites", 'duplicator-pro'); ?>:</b><br />
<select name="mu-exclude[]" id="mu-exclude" multiple="true" class="mu-selector"></select>
</td>
</tr>
</table>
<div class="dupli-panel-optional-txt" style="text-align: left">
<?php
echo wp_kses(
__(
"<u><b>Important:</b></u> Full network restoration is an installer option only if you include <b>all</b> subsites.
If any subsites are filtered then you may only restore individual subsites as standalones sites at install-time.",
'duplicator-pro'
),
[
'b' => [],
'u' => [],
]
);
?>
<br />
<br />
<?php
esc_html_e(
"This section allows you to control which sub-sites of a multisite network you want to include within your Backup.
The 'Included Sub-Sites' will also be available to choose from at install time.",
'duplicator-pro'
);
?>
<br />
<?php
esc_html_e(
"By default all Backups are included. The ability to exclude sub-sites are intended to help shrink your Backup if needed.",
'duplicator-pro'
);
?>
</div>
</div>

View File

@@ -0,0 +1,101 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Package\NameFormat;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$nameFormat = $tplData['nameFormat'];
$notes = $tplData['notes'];
$helpContent = $tplMng->render('admin_pages/packages/setup/name-format-help', [], false);
?>
<div>
<label for="package-name-format" class="lbl-larger large">
<?php esc_html_e('Backup Name Format', 'duplicator-pro') ?>:
</label>&nbsp;
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Backup name format", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($helpContent); ?>"
data-tooltip-width="400"
></i>
<div class="dup-notes-add">
<button
type="button"
onClick="jQuery('#dup-notes-area').toggle()"
class="clear button gray xtiny margin-bottom-0"
title="<?php esc_attr_e('Add Notes', 'duplicator-pro') ?>"
>
<i class="far fa-edit"></i>
</button>
</div>
</div>
<div class="display-flex" >
<input
type="text"
id="package-name-format"
name="package_name_format"
class="margin-0"
data-parsley-errors-container="#template_package_name_error_container"
data-parsley-required="true"
value="<?php echo esc_attr($nameFormat); ?>"
autocomplete="off"
>
<select class="dup-format-name-tags width-medium margin-left-1 margin-0 secondary-color secondary-border-color" >
<option value="" selected >
<?php esc_html_e('Dynamic Tags', 'duplicator-pro') ?>
</option>
<?php foreach (NameFormat::FORMATS as $format) { ?>
<option value="%<?php echo esc_attr($format); ?>%">
%<?php echo esc_html($format); ?>%
</option>
<?php } ?>
</select>
</div>
<div id="template_package_name_error_container" class="duplicator-error-container"></div>
<div id="dup-notes-area">
<label class="lbl-larger large">
<?php esc_html_e('Notes', 'duplicator-pro') ?>:
</label><br/>
<textarea
id="package-notes"
name="package-notes"
maxlength="300"
><?php echo esc_html($notes); ?></textarea>
</div>
<script>
jQuery(document).ready(function($) {
$('.dup-format-name-tags').change(function(e) {
e.stopPropagation();
if ($(this).val() === '') {
return;
}
let input = $('#package-name-format');
let currentValue = input.val();
let newValue = currentValue + $(this).val();
input.val(newValue);
$(this).val('');
});
})
</script>

View File

@@ -0,0 +1,70 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Package\NameFormat;
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
*/
?>
<p>
<?php esc_html_e(
'It is possible to customize the name of the backups using a fixed part and dynamic parts through tags.
The available tags are as follows:',
'duplicator-pro'
); ?>
<ul>
<?php foreach (NameFormat::getTagsDescriptions() as $tag => $description) : ?>
<li>
<strong>%<?php echo esc_html($tag); ?>%</strong> - <?php echo esc_html($description); ?>
</li>
<?php endforeach; ?>
</ul>
<p>
<?php
echo wp_kses(
__(
'Important: <b>Backup date and time expressed in UTC</b> (Coordinated Universal Time).
The displayed date corresponds to the server\'s international time, independent of local time zones.',
'duplicator-pro'
),
ViewHelper::GEN_KSES_TAGS
);
?>
</p>
<p>
<?php esc_html_e(
'Here are some examples of name formats:',
'duplicator-pro'
); ?>
</p>
<ul>
<li>
<strong>%year%%month%%day%_%sitetitle%</strong> -
<?php esc_html_e('Backup name with date and site title (\'It\'s the default)', 'duplicator-pro'); ?>
</li>
<li>
<strong>%year%%month%%day%_%hour%%minute%%second%_mytext_</strong> -
<?php esc_html_e('Backup name with date and time and fixed text', 'duplicator-pro'); ?>
</li>
<li>
<strong>%year%%month%%day%_%schedulename%</strong> -
<?php esc_html_e('Backup name with date and schedule name', 'duplicator-pro'); ?>
</li>
</ul>
</p>

View File

@@ -0,0 +1,265 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\MigrationMng;
use Duplicator\Libs\Snap\FunctionalityCheck;
use Duplicator\Libs\WpUtils\WpArchiveUtils;
use Duplicator\Libs\WpUtils\WpDbUtils;
use Duplicator\Package\BuildRequirements;
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string,mixed> $tplData
* @var array<string,mixed> $requirements
*/
$requirements = $tplData['requirements'];
if ($requirements['Success']) {
return;
}
?>
<div class="dup-box dup-requirements-wrapper">
<div class="dup-box-title">
<i class="far fa-check-circle"></i>
<?php esc_html_e("Requirements:", 'duplicator-pro'); ?> <div class="dup-sys-fail">Fail</div>
<button class="dup-box-arrow">
<span class="screen-reader-text">
<?php esc_html_e('Toggle panel:', 'duplicator-pro') ?> <?php esc_html_e('Requirements:', 'duplicator-pro') ?>
</span>
</button>
</div>
<div class="dup-box-panel">
<div class="dup-sys-section">
<i><?php esc_html_e("System requirements must pass for the Duplicator to work properly. Click each link for details.", 'duplicator-pro'); ?></i>
</div>
<!-- PHP SUPPORT -->
<div class='dup-sys-req'>
<div class='dup-sys-title'>
<a><?php esc_html_e('PHP Support', 'duplicator-pro'); ?></a>
<div><?php echo esc_html($requirements['PHP']['ALL']); ?></div>
</div>
<div class="dup-sys-info dup-info-box">
<table class="dup-sys-info-results">
<tr>
<td>
<?php esc_html_e('PHP Version', 'duplicator-pro'); ?> [<?php echo esc_html(phpversion()); ?>]
</td>
<td><?php echo esc_html($requirements['PHP']['VERSION']); ?></td>
</tr>
<?php foreach (BuildRequirements::getFunctionalitiesCheckList() as $func) { ?>
<tr>
<td>
<?php
switch ($func->getType()) {
case FunctionalityCheck::TYPE_FUNCTION:
esc_html_e('Function', 'duplicator-pro');
break;
case FunctionalityCheck::TYPE_CLASS:
esc_html_e('Class', 'duplicator-pro');
break;
default:
throw new Exception('Invalid item type');
}
?>
<a href="<?php echo esc_url($func->link); ?>" target="_blank">
<?php echo esc_html($func->getItemKey()); ?>
</a>
</td>
<td>
<?php
if ($func->check()) {
echo esc_html_e('Pass', 'duplicator-pro');
} elseif ($func->isRequired()) {
echo esc_html_e('Fail', 'duplicator-pro');
} else {
echo esc_html_e('Warning', 'duplicator-pro');
}
if (strlen($func->troubleshoot) > 0) {
echo ' &nbsp; ';
echo wp_kses(
$func->troubleshoot,
[
'a' => [
'href' => [],
'target' => [],
],
'i' => [
'class' => [],
'style' => [],
],
]
);
}
?>
</td>
</tr>
<?php } ?>
</table>
<small>
<?php
printf(
esc_html__(
"PHP versions %s+ including the listed functions are required for the plugin to create a Backup.
For additional information see our online technical FAQs.",
'duplicator-pro'
),
esc_html(DUPLICATOR_PRO_PHP_MINIMUM_VERSION)
);
?>
</small>
</div>
</div>
<!-- PERMISSIONS -->
<div class='dup-sys-req'>
<div class='dup-sys-title'>
<a><?php esc_html_e('Permissions', 'duplicator-pro'); ?></a>
<div><?php echo esc_html($requirements['IO']['ALL']); ?></div>
</div>
<div class="dup-sys-info dup-info-box">
<b><?php esc_html_e("Required Paths", 'duplicator-pro'); ?></b>
<div style="padding:3px 0px 0px 15px">
<?php
printf("<b>%s</b> &nbsp; [%s] <br/>", esc_html($requirements['IO']['WPROOT']), esc_html(WpArchiveUtils::getArchiveListPaths('home')));
printf("<b>%s</b> &nbsp; [%s] <br/>", esc_html($requirements['IO']['SSDIR']), esc_html(DUPLICATOR_SSDIR_PATH));
printf("<b>%s</b> &nbsp; [%s] <br/>", esc_html($requirements['IO']['SSTMP']), esc_html(DUPLICATOR_SSDIR_PATH_TMP));
?>
</div>
<small>
<?php
esc_html_e(
"Permissions can be difficult to resolve on some systems. If the plugin can not read the above paths here
are a few things to try. 1) Set the above paths to have permissions of 755 for directories and 644 for files.
You can temporarily try 777 however, be sure you dont leave them this way.
2) Check the owner/group settings for both files and directories.
The PHP script owner and the process owner are different. The script owner owns the PHP script but the process owner
is the user the script is running as, thus determining its capabilities/privileges in the file system.
For more details contact your host or server administrator or visit the 'Help' menu under Duplicator for additional online resources.",
'duplicator-pro'
);
?>
</small>
</div>
</div>
<!-- SERVER SUPPORT -->
<div class='dup-sys-req'>
<div class='dup-sys-title'>
<a><?php esc_html_e('Server Support', 'duplicator-pro'); ?></a>
<div><?php echo esc_html($requirements['SRV']['ALL']); ?></div>
</div>
<div class="dup-sys-info dup-info-box">
<table class="dup-sys-info-results">
<tr>
<td><?php printf("%s [%s]", esc_html__("MySQL Version", 'duplicator-pro'), esc_html(WpDbUtils::getVersion())); ?></td>
<td><?php echo esc_html($requirements['SRV']['MYSQL_VER']); ?></td>
</tr>
</table>
<small>
<?php esc_html_e(
"MySQL version 5.0+ or better is required. Contact your server administrator and request MySQL Server 5.0+ be installed.",
'duplicator-pro'
); ?>
</small>
<hr>
<table class="dup-sys-info-results">
<tr>
<td><a href="https://www.php.net/manual/en/mysqli.real-escape-string.php" target="_blank">mysqli_real_escape_string</a></td>
<td><?php echo esc_html($requirements['SRV']['MYSQL_ESC']); ?></td>
</tr>
</table>
<small>
<?php esc_html_e(
"The function mysqli_real_escape_string is not working properly.
Please consult host support and ask them to switch to a different PHP version or configuration.",
'duplicator-pro'
); ?>
</small>
</div>
</div>
<!-- INSTALLATION FILES -->
<div class='dup-sys-req'>
<div class='dup-sys-title'>
<a><?php esc_html_e('Installation Files', 'duplicator-pro'); ?></a>
<div><?php echo esc_html($requirements['RES']['INSTALL']); ?></div>
</div>
<div class="dup-sys-info dup-info-box">
<?php
if ($requirements['RES']['INSTALL'] == 'Pass') :
esc_html_e("No reserved installation files were found from a previous install. You are clear to create a new Backup.", 'duplicator-pro');
else :
?>
<form method="post" action="<?php echo esc_url(ToolsPageController::getInstance()->getCleanFilesAcrtionUrl()); ?>">
<?php
esc_html_e(
"An installer file(s) was found in the WordPress root directory.
To archive your data correctly please remove any of these files and try creating your Backup again.",
'duplicator-pro'
);
?><br />
<b><?php esc_html_e('Installer file names include', 'duplicator-pro'); ?></b>
<ul>
<?php foreach (MigrationMng::checkInstallerFilesList() as $filePath) { ?>
<li>
<?php echo esc_html($filePath); ?>
</li>
<?php } ?>
</ul>
<input
type='submit'
class='button action'
value='<?php esc_attr_e('Remove Files Now', 'duplicator-pro') ?>'
style='font-size:10px; margin-top:5px;'>
</form>
<?php endif; ?>
</div>
</div>
<!-- ONLINE SUPPORT -->
<div class="dup-sys-contact">
<?php
printf(
"<i class='fa fa-question-circle'></i> %s <a href='" . esc_attr(DUPLICATOR_TECH_FAQ_URL) . "' target='_blank'>[%s]</a>",
esc_html__("For additional help please see the ", 'duplicator-pro'),
esc_html__("online FAQs", 'duplicator-pro')
);
?>
</div>
</div>
</div>
<script>
//INIT
jQuery(document).ready(function($) {
DupliJs.Pack.ToggleSystemDetails = function(anchor) {
$(anchor).parent().siblings('.dup-sys-info').toggle();
}
//Init: Toogle for system requirment detial links
$('.dup-sys-title a').each(function() {
$(this).attr('href', 'javascript:void(0)');
$(this).click(function() {
DupliJs.Pack.ToggleSystemDetails(this);
});
$(this).prepend("<span class='ui-icon ui-icon-triangle-1-e dup-toggle' />");
});
//Init: Color code Pass/Fail/Warn items
$('.dup-sys-title div').each(function() {
$(this).addClass(($(this).text() == 'Pass') ? 'dup-sys-pass' : 'dup-sys-fail');
});
});
</script>

View File

@@ -0,0 +1,72 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Views\UI\UiViewState;
use Duplicator\Models\GlobalEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$global = GlobalEntity::getInstance();
$boxOpened = UiViewState::getValue('dup-pack-storage-panel');
?>
<div class="dup-box" id="dup-pack-storage-panel-area">
<div class="dup-box-title" id="dupli-store-title">
<i class="fas fa-server fa-sm"></i>
<?php esc_html_e('Storage', 'duplicator-pro') ?> <sup id="dupli-storage-title-count" class="dup-box-title-badge"></sup>
<button class="dup-box-arrow">
<span class="screen-reader-text">
<?php esc_html_e('Toggle panel:', 'duplicator-pro') ?> <?php esc_html_e('Storage Options', 'duplicator-pro') ?>
</span>
</button>
</div>
<div id="dup-pack-storage-panel" class="dup-box-panel <?php echo ($boxOpened ? '' : 'no-display'); ?>">
<p>
<?php esc_html_e('Choose the storage location(s) where the Backup and Installer files will be saved.', 'duplicator-pro') ?>
</p>
<?php $tplMng->render(
'parts/storage/select_list',
[
'selectedStorageIds' => $global->getManualModeStorageIds(),
'recoveryPointMsg' => true,
]
); ?>
</div>
</div>
<script>
jQuery(function($) {
DupliJs.Pack.UpdateStorageCount = function() {
var store_count = $('#dup-pack-storage-panel input[name="_storage_ids[]"]:checked').length;
$('#dupli-storage-title-count').html('(' + store_count + ')');
(store_count == 0) ?
$('#dupli-storage-title-count').css({
'color': 'red',
'font-weight': 'bold'
}): $('#dupli-storage-title-count').css({
'color': '#444',
'font-weight': 'normal'
});
}
$('#dup-pack-storage-panel input[name="_storage_ids[]"]').on('change', function() {
DupliJs.Pack.UpdateStorageCount();
});
});
//INIT
jQuery(document).ready(function($) {
DupliJs.Pack.UpdateStorageCount();
});
</script>

View File

@@ -0,0 +1,58 @@
<?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
*/
echo esc_html(
__('When enabled the archive file will be encrypted with a password that is required to open.', 'duplicator-pro') . ' ' .
__('The installer will also prompt for the password at install time.', 'duplicator-pro') . ' ' .
__('Encryption is a general deterrent and should not be substituted for properly keeping your files secure.', 'duplicator-pro') . ' ' .
__('Be sure to remove all installer files when the install process is completed.', 'duplicator-pro')
);
?>
<ul>
<li>
<b>
<?php esc_html_e('None:', 'duplicator-pro'); ?>
</b>
<?php esc_html_e(
"No protection system activated! The installer or archive files can be accessed by any resource that knows the full URL to either file.",
'duplicator-pro'
); ?>
</li>
<li>
<b>
<?php esc_html_e('Installer password:', 'duplicator-pro'); ?>
</b>
<?php esc_html_e(
'The archive is NOT encrypted. When the installer starts, it will prompt for a password to prevent anyone from running the installer.',
'duplicator-pro'
); ?>
</li>
<li>
<b>
<?php esc_html_e('Archive encryption:', 'duplicator-pro'); ?>
</b>
<?php
esc_html_e(
'The archive IS encrypted with a password, and the installer will ask for a password when started.',
'duplicator-pro'
);
esc_html_e(
'This option is the recommended maximum level of security.',
'duplicator-pro'
);
?>
</li>
</ul>

View File

@@ -0,0 +1,374 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Libs\WpUtils\WpDbUtils;
use Duplicator\Package\PackageUtils;
use Duplicator\Models\TemplateEntity;
use Duplicator\Views\UI\UiDialog;
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string,mixed> $tplData
* @var array<string,mixed> $requirements
*/
$requirements = $tplData['requirements'];
/** @var bool */
$blur = $tplData['blur'];
$manual_template = TemplateEntity::getManualTemplate();
$templates = TemplateEntity::getAll();
$default_name1 = PackageUtils::getDefaultPackageName();
$default_name2 = PackageUtils::getDefaultPackageName(false);
$default_notes = $manual_template->notes;
$dbbuild_mode = WpDbUtils::getBuildMode();
$templatesUrl = ToolsPageController::getInstance()->getMenuLink(ToolsPageController::L2_SLUG_TEMPLATE);
$templateEditBaseUrl = ToolsPageController::getTemplateEditURL();
$tplMng->render('admin_pages/packages/setup/section-requirements');
$form_action_url = PackagesPageController::getInstance()->getPackageBuildS2Url();
?>
<form
id="dup-form-opts"
class="<?php echo ($blur ? 'dup-mock-blur' : ''); ?>"
method="post"
action="<?php echo esc_attr($form_action_url); ?>"
data-parsley-validate data-parsley-ui-enabled="true">
<?php $tplMng->getAction(PackagesPageController::ACTION_UPDATE_TEMPLATE)->getActionNonceFileds(); ?>
<div class="dupli-general-area">
<?php
$tplMng->render(
'admin_pages/packages/setup/name-format-controls',
[
'nameFormat' => '',
'notes' => '',
]
);
?>
<div>
<label for="template_id" class="lbl-larger large">
<?php esc_html_e('Template', 'duplicator-pro') ?>:
</label>&nbsp;
<i class="fa-solid fa-question-circle fa-sm dark-gray-color margin-bottom-0"
data-tooltip-title="<?php esc_attr_e("Apply Template", 'duplicator-pro'); ?>"
data-tooltip="<?php
esc_attr_e(
'An optional template configuration that can be applied to this backup setup.
An [Unassigned] template will retain the settings from the last scan/build.',
'duplicator-pro'
); ?>">
</i>
<div class="float-right">
<a
href="<?php echo esc_url($templatesUrl); ?>"
class="clear button gray xtiny margin-bottom-0"
title="<?php esc_attr_e("List All Templates", 'duplicator-pro') ?>">
<i class="fa-regular fa-clone"></i>
</a>
<button
type="button"
onclick="DupliJs.Pack.EditTemplate()"
class="clear button gray xtiny margin-bottom-0"
title="<?php esc_attr_e("Edit Selected Template", 'duplicator-pro') ?>">
<i class="fa-solid fa-pen-to-square"></i>
</button>
</div>
</div>
<div>
<select
data-parsley-ui-enabled="false"
onChange="DupliJs.Pack.EnableTemplate();"
name="template_id" id="template_id"
aria-label="Prefill option with selected template">
<option value="<?php echo intval($manual_template->getId()); ?>"><?php echo '[' . esc_html__('Unassigned', 'duplicator-pro') . ']' ?></option>
<?php
if (count($templates) == 0) {
?>
<option value="-1">
<?php echo esc_html_e('No Templates', 'duplicator-pro'); ?>
</option>
<?php
} else {
foreach ($templates as $template) {
if ($template->is_manual) {
continue;
}
?>
<option value="<?php echo (int) $template->getId(); ?>">
<?php echo esc_html($template->name); ?>
</option>
<?php
}
}
?>
</select>
</div>
</div>
<?php
$tplMng->render('admin_pages/packages/setup/section_storages');
$tplMng->render(
'parts/packages/filters/section_filters',
[
'isTemplateEdit' => false,
'template' => null,
]
);
$tplMng->render('parts/packages/filters/section_installer');
?>
<div class="dup-button-footer">
<input
type="button"
value="<?php esc_attr_e("Reset", 'duplicator-pro') ?>"
class="button hollow secondary small" <?php echo ($requirements['Success']) ? '' : 'disabled="disabled"'; ?>
onClick="DupliJs.Pack.ResetSettings()">&nbsp;
<input
id="button-next"
type="submit"
value="<?php esc_attr_e("Next", 'duplicator-pro') ?> &#9654;"
class="button primary small" <?php echo ($requirements['Success']) ? '' : 'disabled="disabled"'; ?>>
</div>
</form>
<!-- CACHE PROTECTION: If the back-button is used from the scanner page then we need to
refresh page in-case any filters where set while on the scanner page -->
<form id="cache_detection">
<input type="hidden" id="cache_state" name="cache_state" value="" />
</form>
<?php
$confirm1 = new UiDialog();
$confirm1->title = __('Would you like to continue', 'duplicator-pro');
$confirm1->message = __('This will clear all of the current backup settings.', 'duplicator-pro');
$confirm1->progressText = __('Please Wait...', 'duplicator-pro');
$confirm1->jsCallback = 'DupliJs.Pack.ResetSettingsRun()';
$confirm1->initConfirm();
?>
<script>
jQuery(function($) {
var packageTemplates = <?php TemplateEntity::getTemplatesFrontendListData(); ?>
DupliJs.Pack.BeforeSubmit = function(e) {
$('#mu-exclude option').each(function() {
$(this).prop('selected', true);
});
DupliJs.Pack.FillExcludeTablesList();
return true;
};
$('#dup-form-opts').submit(function() {
return DupliJs.Pack.BeforeSubmit();
})
// Template-specific Functions
DupliJs.Pack.GetTemplateById = function(templateId) {
for (var i = 0; i < packageTemplates.length; i++) {
var currentTemplate = packageTemplates[i];
if (currentTemplate.id == templateId) {
return currentTemplate;
}
}
return null;
};
$.fn.selectOption = function(val) {
this.val(val)
.find('option')
.prop('selected', false)
.parent()
.find('option[value="' + val + '"]')
.prop('selected', true)
.parent()
.trigger('change');
return this;
};
DupliJs.Pack.PopulateCurrentTemplate = function() {
var selectedId = $('#template_id').val();
var selectedTemplate = DupliJs.Pack.GetTemplateById(selectedId);
if (selectedTemplate != null) {
let formatInput = $('#package-name-format');
formatInput.val(selectedTemplate.package_name_format)
if (selectedTemplate.is_manual) {
name = '<?php echo esc_js(PackageUtils::getDefaultPackageName()); ?>';
}
$("#package-notes").val(selectedTemplate.notes);
$("#files-filter-on").prop("checked", selectedTemplate.archive_filter_on);
$("#filter-names").prop("checked", selectedTemplate.archive_filter_names);
//Add trailing slash to directories to differentiate between files and directories
let filterDirs = selectedTemplate.archive_filter_dirs.split(';').join(";\n");
let filterFiles = selectedTemplate.archive_filter_files.split(';').join(";\n")
let separator = filterDirs.length > 0 && filterFiles.length > 0 ? ";\n" : '';
$("#filter-paths").val(filterDirs + separator + filterFiles);
$("#filter-exts").val(selectedTemplate.archive_filter_exts);
$("#dbfilter-on").prop("checked", selectedTemplate.database_filter_on);
$("#db-prefix-filter").prop("checked", selectedTemplate.databasePrefixFilter);
$("#db-prefix-sub-filter").prop("checked", selectedTemplate.databasePrefixSubFilter);
$(".dup-components-checkbox").each(function(i, component) {
$(component).prop("checked", false);
});
selectedTemplate.components.forEach(function(component) {
$("#" + component).prop("checked", true);
});
DupliJs.Pack.ToggleDBOnly()
DupliJs.Pack.SetComponentsSelect();
if (typeof selectedTemplate.filter_sites != 'undefined' && selectedTemplate.filter_sites.length > 0) {
for (var i = 0; i < selectedTemplate.filter_sites.length; i++) {
var site_id = selectedTemplate.filter_sites[i];
var exclude_option = $('#mu-include').find("option[value=" + site_id + "]").first();
console.log(exclude_option.html());
$("#mu-exclude").append(exclude_option.clone());
exclude_option.remove();
}
}
//-- cPanel
$("#cpnl-enable").prop("checked", selectedTemplate.installer_opts_cpnl_enable);
$("#cpnl-host").val(selectedTemplate.installer_opts_cpnl_host);
$("#cpnl-user").val(selectedTemplate.installer_opts_cpnl_user);
$('.secure-on-input-wrapper input').prop("checked", false);
$('.secure-on-input-wrapper input[value=' + selectedTemplate.installer_opts_secure_on + ']:enabled').prop("checked", true);
$("#skipscan").prop("checked", selectedTemplate.installer_opts_skip_scan);
$("#secure-pass").val(selectedTemplate.installerPassowrd);
$("#cpnl-dbaction").selectOption(selectedTemplate.installer_opts_cpnl_db_action);
$("#cpnl-dbhost").val(selectedTemplate.installer_opts_cpnl_db_host);
$("#cpnl-dbname").val(selectedTemplate.installer_opts_cpnl_db_name);
$("#cpnl-dbuser").val(selectedTemplate.installer_opts_cpnl_db_user);
//-- Brand
let installer_opts_brand = selectedTemplate.installer_opts_brand;
installer_opts_brand_id = [];
x = 0;
// most tricky thing - setup proper brand on emplate change
if (typeof selectedTemplate.installer_opts_brand != 'undefined') {
if (selectedTemplate.installer_opts_brand <= 0) {
installer_opts_brand = -1;
} else if (selectedTemplate.installer_opts_brand > 0) {
installer_opts_brand = Number(selectedTemplate.installer_opts_brand);
}
}
// find, fix deleted brands and setup default
for (var i = 0; i < packageTemplates.length; i++) {
if (
typeof packageTemplates[i].installer_opts_brand != 'undefined' &&
null != packageTemplates[i].installer_opts_brand &&
packageTemplates[i].installer_opts_brand != 0
) {
installer_opts_brand_id[x] = Number(packageTemplates[i].installer_opts_brand);
x++;
}
}
$("#brand").selectOption(installer_opts_brand);
//-- Database
if (selectedTemplate.database_filter_tables.length) {
let databaseFilterTables = selectedTemplate.database_filter_tables.split(",");
let tablesToExclude = $("#dup-db-tables-exclude");
tablesToExclude.find(".dup-pseudo-checkbox").each(function() {
let node = $(this);
if (databaseFilterTables.includes(node.data('value'))) {
node.addClass('checked');
} else {
node.removeClass('checked');
}
});
}
$("#dbhost").val(selectedTemplate.installer_opts_db_host);
$("#dbname").val(selectedTemplate.installer_opts_db_name);
$("#dbuser").val(selectedTemplate.installer_opts_db_user);
} else {
console.log("Template ID doesn't exist?? " + selectedId);
}
//Default to Installer cPanel tab if used
$('#cpnl-enable').is(":checked") ? $('#dupli-cpnl-tab-lbl').trigger("click") : $('#dupli-bsc-tab-lbl').trigger("click");
};
DupliJs.Pack.ResetSettings = function() {
<?php $confirm1->showConfirm(); ?>
};
DupliJs.Pack.ResetSettingsRun = function() {
$('#dup-form-opts')[0].reset();
setTimeout(function() {
tb_remove();
}, 800);
}
DupliJs.Pack.EditTemplate = function() {
var manualTemplateID = <?php echo (int) $manual_template->getId(); ?>;
var templateID = $('#template_id').val();
var url;
if (templateID <= 0 || templateID == manualTemplateID) {
url = <?php echo json_encode($templatesUrl); ?>;
} else {
url = <?php echo json_encode($templateEditBaseUrl); ?> + '&package_template_id=' + templateID;
}
window.open(url, 'edit-template');
};
});
//INIT
jQuery(document).ready(function($) {
DupliJs.Pack.checkPageCache = function() {
var $state = $('#cache_state');
if ($state.val() == "") {
$state.val("fresh-load");
} else {
$state.val("cached");
<?php $redirect = PackagesPageController::getInstance()->getPackageBuildS1Url(); ?>
window.location.href = '<?php echo esc_js($redirect); ?>';
}
}
DupliJs.Pack.EnableTemplate = function() {
$('#dupli-template-specific-area').show(0);
DupliJs.Pack.PopulateCurrentTemplate();
//DupliJs.Pack.ToggleInstallerPassword();
DupliJs.EnableInstallerPassword();
DupliJs.Pack.ToggleFileFilters();
DupliJs.Pack.ToggleDBFilters();
DupliJs.Pack.ToggleActiveThemes();
DupliJs.Pack.ToggleActivePlugins();
DupliJs.Pack.ToggleDBExcluded();
DupliJs.Pack.ToggleNoPrefixTables(false);
DupliJs.Pack.ToggleNoSubsiteExistsTables(false);
}
DupliJs.Pack.checkPageCache();
DupliJs.Pack.EnableTemplate();
});
</script>

View File

@@ -0,0 +1,92 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\ImportPageController;
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\CapMng;
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
*/
$settingsUrl = esc_url($ctrlMng->getMenuLink($ctrlMng::SETTINGS_SUBMENU_SLUG, SettingsPageController::L2_SLUG_PACKAGE));
$templateUrl = esc_url($ctrlMng->getMenuLink($ctrlMng::TOOLS_SUBMENU_SLUG, ToolsPageController::L2_SLUG_TEMPLATE));
$recoveryUrl = esc_url($ctrlMng->getMenuLink($ctrlMng::TOOLS_SUBMENU_SLUG, ToolsPageController::L2_SLUG_RECOVERY));
?>
<div class="dup-toolbar">
<label for="dup-pack-bulk-actions" class="screen-reader-text">Select bulk action</label>
<select id="dup-pack-bulk-actions" class="small" >
<option value="-1" selected="selected">
<?php esc_html_e("Bulk Actions", 'duplicator-pro') ?>
</option>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<option value="delete" title="<?php esc_attr_e("Delete selected Backup(s)", 'duplicator-pro') ?>">
<?php esc_html_e("Delete", 'duplicator-pro') ?>
</option>
<?php } ?>
</select>
<input
type="button"
id="dup-pack-bulk-apply"
class="button hollow secondary small"
value="<?php esc_attr_e("Apply", 'duplicator-pro') ?>"
onclick="DupliJs.Pack.ConfirmDelete()"
>
<span class="separator"></span>
<?php if (CapMng::can(CapMng::CAP_SETTINGS, false)) { ?>
<a href="<?php echo esc_url($settingsUrl); ?>"
class="button hollow secondary small dupli-toolbar-settings"
data-tooltip-title="<?php esc_attr_e("Backup Settings", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e("Advanced settings for backups.", 'duplicator-pro'); ?>"
>
<i class="fas fa-sliders-h fa-fw"></i>
</a>
<?php } ?>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) { ?>
<a href="<?php echo esc_url($templateUrl); ?>"
class="button hollow secondary small dupli-toolbar-templates"
data-tooltip-title="<?php esc_attr_e("Templates", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e("Create Backup Templates with Preset Configurations.", 'duplicator-pro'); ?>"
>
<i class="far fa-clone fa-fw"></i>
</a>
<?php } ?>
<?php if (CapMng::can(CapMng::CAP_IMPORT, false)) { ?>
<a href="<?php echo esc_url(ImportPageController::getImportPageLink()); ?>"
id="btn-logs-dialog"
class="button hollow secondary small dupli-toolbar-import"
data-tooltip-title="<?php esc_attr_e("Import", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e("Import a backups from a file or link.", 'duplicator-pro'); ?>"
>
<i class="fas fa-arrow-alt-circle-down fa-fw"></i>
</a>
<?php } ?>
<?php if (CapMng::can(CapMng::CAP_BACKUP_RESTORE, false)) { ?>
<span
class="dupli-toolbar-recovery-info
button hollow secondary small <?php echo (RecoveryPackage::getRecoverPackageId() === false ? 'dup-recovery-unset' : ''); ?>"
data-tooltip-title="<?php esc_attr_e("Disaster Recovery", 'duplicator-pro') ?>"
data-tooltip="<?php esc_attr_e("Quickly restore this site to a specific point in time.", 'duplicator-pro') ?>"
>
<?php ViewHelper::disasterIcon(); ?>
</span>
<?php } ?>
</div>

View File

@@ -0,0 +1,91 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SchedulePageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Models\ScheduleEntity;
use Duplicator\Models\Storages\AbstractStorageEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var AbstractStorageEntity $storage
*/
$blur = $tplData['blur'];
$schedule = $tplData['schedule'];
$copyScheduleList = ScheduleEntity::getAll(
0,
0,
null,
fn(ScheduleEntity $s): bool => $s->getId() != $schedule->getId()
);
$schedulesListURL = ControllersManager::getMenuLink(
ControllersManager::SCHEDULES_SUBMENU_SLUG
);
$scheduleCopyBaseURL = SchedulePageController::getInstance()->getCopyActionUrl($schedule->getId());
$countList = count($copyScheduleList);
?>
<div class="dup-toolbar <?php echo ($blur ? 'dup-mock-blur' : ''); ?>">
<label for="dup-copy-source-id-select" class="screen-reader-text">Copy storage action</label>
<select
id="dup-schedule-copy-select"
name="dupli-source-schedule-id"
class="small"
<?php disabled($countList, 0); ?>>
<option value="-1" selected="selected" disabled="true">
<?php esc_html_e('Copy From', 'duplicator-pro'); ?>
</option>
<?php foreach ($copyScheduleList as $copy_schedule) { ?>
<option value="<?php echo (int) $copy_schedule->getId(); ?>">
<?php echo esc_html($copy_schedule->name); ?>
</option>
<?php } ?>
</select>
<input
id="dup-schedule-copy-btn"
type="button"
class="button hollow secondary small action"
value="<?php esc_html_e("Apply", 'duplicator-pro') ?>"
disabled>
<span class="separator"></span>
<a
href="<?php echo esc_url($schedulesListURL); ?>"
class="button hollow secondary small "
title="<?php esc_attr_e('Back to Schedules list.', 'duplicator-pro'); ?>">
<i class="far fa-clock fa-sm"></i> <?php esc_html_e('Schedules', 'duplicator-pro'); ?>
</a>
</div>
<script>
jQuery(document).ready(function($) {
$('#dup-schedule-copy-select').on('change', function(e) {
let copyId = parseInt($(this).val());
$('#dup-schedule-copy-btn').prop('disabled', (copyId <= 0));
});
/*$('#dup-schedule-copy-select').change(function (evente) {
event.preventDefault();
alert('changed val ' + $(this).val());
$('#dup-schedule-copy-btn').prop('disabled', ($(this).val() > 0));
});*/
$('#dup-schedule-copy-btn').click(function(event) {
event.preventDefault();
let copyId = $('#dup-schedule-copy-select').val();
document.location.href = <?php echo json_encode($scheduleCopyBaseURL); ?> + '&dupli-source-schedule-id=' + copyId;
});
});
</script>
<hr class="dup-toolbar-divider" />

View File

@@ -0,0 +1,38 @@
<?php
/**
* Duplicator Daily repeat template
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$runEvery = $tplMng->getDataValueIntRequired('run_every');
$frequency_note = $tplMng->getDataValueString('frequency_note', '');
?>
<label class="lbl-larger">
<?php esc_html_e('Every', 'duplicator-pro'); ?>
</label>
<div>
<select name="_run_every_days" class="width-tiny inline-block margin-0" data-parsley-ui-enabled="false">
<?php for ($i = 1; $i < 30; $i++) { ?>
<option <?php selected($i, $runEvery); ?> value="<?php echo (int) $i; ?>">
<?php echo (int) $i; ?>
</option>
<?php } ?>
</select>
<?php esc_html_e('days', 'duplicator-pro'); ?>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Frequency Note", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($frequency_note) ?>">
</i>
</div>

View File

@@ -0,0 +1,49 @@
<?php
/**
* Duplicator Hourly repeat template
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$runEvery = $tplMng->getDataValueIntRequired('run_every');
$frequency_note = $tplMng->getDataValueString('frequency_note', '');
$hour_intervals = [
1,
2,
4,
6,
12,
];
$tipContent = __('Backup will build every x hours starting at 00:00.', 'duplicator-pro') . '<br/><br/>' . $frequency_note;
?>
<label class="lbl-larger">
<?php esc_html_e('Every', 'duplicator-pro'); ?>
</label>
<div>
<select name="_run_every_hours" class="width-tiny inline-block margin-0" data-parsley-ui-enabled="false">
<?php foreach ($hour_intervals as $hour_interval) { ?>
<option <?php selected($hour_interval, $runEvery); ?> value="<?php echo (int) $hour_interval; ?>">
<?php echo (int) $hour_interval; ?>
</option>
<?php } ?>
</select>
<?php
esc_html_e('hours', 'duplicator-pro');
?>
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Frequency Note", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tipContent); ?>">
</i>
</div>

View File

@@ -0,0 +1,42 @@
<?php
/**
* Duplicator Monthly repeat template
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$runEvery = $tplMng->getDataValueIntRequired('run_every');
$dayOfMonth = $tplMng->getDataValueIntRequired('day_of_month');
?>
<label class="lbl-larger">
<?php esc_html_e('Day', 'duplicator-pro'); ?>
</label>
<div>
<select name="day_of_month" class="width-tiny inline-block margin-0">
<?php for ($i = 1; $i <= 31; $i++) { ?>
<option <?php selected($i, $dayOfMonth); ?> value="<?php echo (int) $i; ?>">
<?php echo (int) $i; ?>
</option>
<?php } ?>
</select>&nbsp;
<?php esc_html_e('of every', 'duplicator-pro'); ?>&nbsp;
<select name="_run_every_months" data-parsley-ui-enabled="false" class="width-tiny inline-block margin-0">
<?php for ($i = 1; $i <= 12; $i++) { ?>
<option <?php selected($i, $runEvery); ?> value="<?php echo (int) $i; ?>">
<?php echo (int) $i; ?>
</option>
<?php } ?>
</select>&nbsp;
<?php esc_html_e('month(s)', 'duplicator-pro'); ?>
</div>

View File

@@ -0,0 +1,86 @@
<?php
/**
* Duplicator Weekly repeat template
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$weekdays = $tplMng->getDataValueArrayRequired('weekdays');
?>
<label class="lbl-larger">
<?php esc_html_e('Every', 'duplicator-pro'); ?>
</label>
<div>
<!-- RSR Cron does not support counting by week - just days and months so removing (for now?)-->
<div class="weekday-div">
<input
<?php checked($weekdays['mon']); ?>
value="mon" name="weekday[]"
type="checkbox"
id="repeat-weekly-mon"
data-parsley-group="weekly" required data-parsley-class-handler="#repeat-weekly-area"
data-parsley-error-message="<?php esc_attr_e('At least one day must be checked.', 'duplicator-pro'); ?>"
data-parsley-no-focus data-parsley-errors-container="#weekday-errors">
<label for="repeat-weekly-mon"><?php esc_html_e('Monday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div">
<input
<?php checked($weekdays['tue']); ?>
value="tue" name="weekday[]"
type="checkbox"
id="repeat-weekly-tue">
<label for="repeat-weekly-tue"><?php esc_html_e('Tuesday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div">
<input
<?php checked($weekdays['wed']); ?>
value="wed" name="weekday[]"
type="checkbox"
id="repeat-weekly-wed">
<label for="repeat-weekly-wed"><?php esc_html_e('Wednesday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div">
<input
<?php checked($weekdays['thu']); ?>
value="thu" name="weekday[]"
type="checkbox"
id="repeat-weekly-thu">
<label for="repeat-weekly-thu"><?php esc_html_e('Thursday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div" style="clear:both">
<input
<?php checked($weekdays['fri']); ?>
value="fri" name="weekday[]"
type="checkbox"
id="repeat-weekly-fri">
<label for="repeat-weekly-fri"><?php esc_html_e('Friday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div">
<input
<?php checked($weekdays['sat']); ?>
value="sat" name="weekday[]"
type="checkbox"
id="repeat-weekly-sat">
<label for="repeat-weekly-sat"><?php esc_html_e('Saturday', 'duplicator-pro'); ?></label>
</div>
<div class="weekday-div">
<input
<?php checked($weekdays['sun']); ?>
value="sun" name="weekday[]"
type="checkbox"
id="repeat-weekly-sun">
<label for="repeat-weekly-sun"><?php esc_html_e('Sunday', 'duplicator-pro'); ?></label>
</div>
<div style="padding-top:3px; clear:both;" id="weekday-errors"></div>
</div>

View File

@@ -0,0 +1,148 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Addons\ProBase\License\License;
use Duplicator\Models\ScheduleEntity;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$repeatType = $tplMng->getDataValueIntRequired('repeat_type');
$min_frequency = 0;
$max_frequency = (
License::can(License::CAPABILITY_SHEDULE_HOURLY) ?
ScheduleEntity::REPEAT_HOURLY :
ScheduleEntity::REPEAT_MONTHLY
);
$frequencyUpgradMsg = sprintf(
__(
'Hourly frequency isn\'t available at the <b>%1$s</b> license level.',
'duplicator-pro'
),
License::getLicenseToString()
) .
' <b>' .
sprintf(
_x(
'To enable this option %1$supgrade%2$s the License.',
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
'duplicator-pro'
),
'<a href="' . esc_url(License::getUpsellURL()) . '" target="_blank">',
'</a>'
) .
'</b>';
$frequency_note = __(
'If you have a large site, it\'s recommended you schedule backups during lower traffic periods.
If you\'re on a shared host then be aware that running multiple schedules too close together
(i.e. every 10 minutes) may alert your host to a spike in system resource usage.
Be sure that your schedules do not overlap and give them plenty of time to run.',
'duplicator-pro'
);
?>
<div class="dup-settings-wrapper margin-bottom-1">
<label class="lbl-larger"><?php esc_html_e("Repeats", 'duplicator-pro'); ?></label>
<div class="margin-bottom-1">
<select
id="change-mode"
name="repeat_type"
class="width-small margin-0"
onchange="DupliJs.Schedule.ChangeMode()"
data-parsley-range='<?php printf('[%1$s, %2$s]', (int) $min_frequency, (int) $max_frequency); ?>'
data-parsley-error-message="<?php echo esc_attr($frequencyUpgradMsg); ?>">
<option
value="<?php echo (int) ScheduleEntity::REPEAT_HOURLY; ?>"
<?php selected($repeatType, ScheduleEntity::REPEAT_HOURLY) ?>>
<?php esc_html_e("Hourly", 'duplicator-pro'); ?>
</option>
<option
value="<?php echo (int) ScheduleEntity::REPEAT_DAILY; ?>"
<?php selected($repeatType, ScheduleEntity::REPEAT_DAILY) ?>>
<?php esc_html_e("Daily", 'duplicator-pro'); ?>
</option>
<option
value="<?php echo (int) ScheduleEntity::REPEAT_WEEKLY; ?>"
<?php selected($repeatType, ScheduleEntity::REPEAT_WEEKLY) ?>>
<?php esc_html_e("Weekly", 'duplicator-pro'); ?>
</option>
<option
value="<?php echo (int) ScheduleEntity::REPEAT_MONTHLY; ?>"
<?php selected($repeatType, ScheduleEntity::REPEAT_MONTHLY) ?>>
<?php esc_html_e("Monthly", 'duplicator-pro'); ?>
</option>
</select>
</div>
<!-- Repeat Options -->
<div id="repeat-hourly-area" class="repeater-area margin-bottom-1">
<?php $tplMng->render('admin_pages/schedules/parts/repeat_hourly', ['frequency_note' => $frequency_note]); ?>
</div>
<div id="repeat-daily-area" class="repeater-area margin-bottom-1">
<?php $tplMng->render('admin_pages/schedules/parts/repeat_daily', ['frequency_note' => $frequency_note]); ?>
</div>
<div id="repeat-weekly-area" class="repeater-area margin-bottom-1">
<?php $tplMng->render('admin_pages/schedules/parts/repeat_weekly'); ?>
</div>
<div id="repeat-monthly-area" class="repeater-area margin-bottom-1">
<?php $tplMng->render('admin_pages/schedules/parts/repeat_monthly'); ?>
</div>
<!-- Start Time -->
<?php $tplMng->render('admin_pages/schedules/parts/start_time'); ?>
</div>
<script>
jQuery(document).ready(function($) {
DupliJs.Schedule.ChangeMode = function() {
var mode = $("#change-mode option:selected").val();
var animate = 400;
$('#repeat-hourly-area, #repeat-daily-area, #repeat-weekly-area, #repeat-monthly-area').hide();
n = $("#repeat-weekly-area input:checked").length;
if (n == 0) {
// Hack so parsely will ignore weekly if it isnt selected
$('#repeat-weekly-mon').prop("checked", true);
}
switch (mode) {
case "0":
$('#repeat-daily-area').show(animate);
$('#start-time-label, #start-time-content').show(animate);
break;
case "1":
$('#repeat-weekly-area').show(animate);
$('#start-time-label, #start-time-content').show(animate);
break;
case "2":
$('#repeat-monthly-area').show(animate);
$('#start-time-label, #start-time-content').show(animate);
break;
case "3":
$('#repeat-hourly-area').show(animate);
$('#start-time-label, #start-time-content').hide(animate);
break;
}
}
DupliJs.Schedule.ChangeMode();
});
</script>

View File

@@ -0,0 +1,60 @@
<?php
/**
* Duplicator Start Time template
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
*/
$start_hour = $tplMng->getDataValueIntRequired('start_hour');
$start_minute = $tplMng->getDataValueIntRequired('start_minute');
$mins = 0;
?>
<label class="lbl-larger" id="start-time-label">
<?php esc_html_e('Start Time', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1" id="start-time-content">
<select name="_start_time" class="width-small inline-display margin-0">
<?php
// Add setting to use 24 hour vs AM/PM the interval for hours is '1'
for ($hours = 0; $hours < 24; $hours++) {
?>
<option <?php selected($hours, $start_hour); ?> value="<?php echo (int) $hours; ?>">
<?php echo esc_html(sprintf('%02d:%02d', $hours, $mins)); ?>
</option>
<?php } ?>
</select>
<i class="dupli-edit-info">
<?php esc_html_e("Current Server Time Stamp is", 'duplicator-pro'); ?>&nbsp;
<?php echo esc_html(date_i18n('Y-m-d H:i:s')); ?>
</i>
</div>
<div class="margin-bottom-1">
<p class="description width-xlarge">
<?php
printf(
esc_html_x(
'%1$sNote:%2$s Schedules require web site traffic in order to start a build.
If you set a start time of 06:00 daily but do not get any traffic till 10:00 then the build will not start until 10:00.
If you have low traffic consider setting up a cron job to periodically hit your site.',
'%1$s and %2$s represent opening and closing bold tags',
'duplicator-pro'
),
'<b>',
'</b>'
);
?>
</p>
</div>

View File

@@ -0,0 +1,45 @@
<?php
/**
* Duplicator Backup row in table Backups list
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\SchedulePageController;
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 bool $blur
*/
$blur = $tplData['blur'];
if (CapMng::can(CapMng::CAP_SCHEDULE, false) && !$blur) {
$scheduleEditBaseURL = SchedulePageController::getInstance()->getEditBaseUrl();
$tipContent = __(
'Create a new Scheduled Backup.',
'duplicator-pro'
);
?>
<span
class="dup-new-package-wrapper"
data-tooltip="<?php echo esc_attr($tipContent); ?>"
>
<a
href="<?php echo esc_url($scheduleEditBaseURL); ?>"
id="dupli-create-new"
class="button primary tiny font-bold margin-bottom-0"
>
<?php esc_html_e('Add New', 'duplicator-pro'); ?>
</a>
</span>
<?php
}

View File

@@ -0,0 +1,240 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\SchedulePageController;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Models\ScheduleEntity;
use Duplicator\Models\TemplateEntity;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
*/
$blur = $tplMng->getDataValueBool('blur');
$schedule = $tplMng->getDataValueObjRequired('schedule', ScheduleEntity::class);
$templatesPageUrl = ToolsPageController::getInstance()->getMenuLink(ToolsPageController::L2_SLUG_TEMPLATE);
$editTemplateUrl = ControllersManager::getMenuLink(
ControllersManager::TOOLS_SUBMENU_SLUG,
ToolsPageController::L2_SLUG_TEMPLATE,
null,
[ControllersManager::QUERY_STRING_INNER_PAGE => 'edit']
);
?>
<form
id="dup-schedule-form"
class="dup-monitored-form <?php echo ($blur ? 'dup-mock-blur' : ''); ?>"
action="<?php echo esc_url(ControllersManager::getCurrentLink()); ?>"
method="post"
data-parsley-ui-enabled="true">
<?php $tplMng->render('admin_pages/schedules/parts/edit_toolbar'); ?>
<?php $tplMng->getAction(SchedulePageController::ACTION_EDIT_SAVE)->getActionNonceFileds(); ?>
<input type="hidden" name="schedule_id" value="<?php echo (int) $schedule->getId(); ?>">
<!-- ===============================
SETTINGS -->
<table class="form-table">
<tr valign="top">
<th scope="row"><label><?php esc_html_e('Schedule Name', 'duplicator-pro'); ?></label></th>
<td>
<input
type="text"
id="schedule-name"
class="width-medium"
name="name"
value="<?php echo esc_attr($schedule->name); ?>"
required data-parsley-group="standard"
autocomplete="off">
</td>
</tr>
<tr valign="top">
<th scope="row">
<label><?php esc_html_e('Backup Template', 'duplicator-pro'); ?></label>
</th>
<td>
<div class="schedule-template display-flex">
<div>
<select id="schedule-template-selector" name="template_id" class="width-medium margin-bottom-0" required>
<?php
$templates = TemplateEntity::getAllWithoutManualMode();
if (count($templates) == 0) {
$no_templates = __('No Templates Found', 'duplicator-pro');
printf('<option value="">%1$s</option>', esc_html($no_templates));
} else {
echo "<option value='' selected='true'>" . esc_html__("&lt;Choose A Template&gt;", 'duplicator-pro') . "</option>";
foreach ($templates as $template) {
?>
<option
<?php selected($schedule->template_id, $template->getId()); ?>
value="<?php echo (int) $template->getId(); ?>">
<?php echo esc_html($template->name); ?>
</option>
<?php
}
}
?>
</select>
<div class="margin-bottom-1">
<small>
<a href="<?php echo esc_url($templatesPageUrl); ?>" target="edit-template">
[<?php esc_attr_e("Show All Templates", 'duplicator-pro') ?>]
</a>
</small>
</div>
</div>
<div>
<a
id="schedule-template-edit-btn"
href="javascript:void(0)"
onclick="DupliJs.Schedule.EditTemplate()"
style="display:none"
class="pack-temp-btns button hollow secondary small margin-bottom-0"
title="<?php esc_attr_e("Edit Selected Template", 'duplicator-pro') ?>">
<i class="far fa-edit"></i>
</a>
<a
id="schedule-template-add-btn"
href="<?php echo esc_url($editTemplateUrl); ?>"
class="pack-temp-btns button hollow secondary small margin-bottom-0"
title="<?php esc_attr_e("Add New Template", 'duplicator-pro') ?>"
target="edit-template">
<i class="far fa-plus-square"></i>
</a>
<a
id="schedule-template-sync-btn"
href="javascript:window.location.reload()"
class="pack-temp-btns button hollow secondary small margin-bottom-0"
title="<?php esc_attr_e("Refresh Template List", 'duplicator-pro') ?>">
<i class="fas fa-sync-alt"></i>
</a>
&nbsp;
<i
class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Template Details", 'duplicator-pro'); ?>"
data-tooltip="<?php
esc_attr_e(
'The template specifies which files and database tables should be included in the archive.<br/><br/>
Choose from an existing template or create a new one by clicking the "Add New Template" button.
To edit a template, select it and then click the "Edit Selected Template" button.',
'duplicator-pro'
);
?>">
</i>
</div>
</div>
</td>
</tr>
<tr>
<th scope="row"><label><?php esc_html_e('Storage', 'duplicator-pro'); ?></label></th>
<td>
<!-- ===============================
STORAGE -->
<?php $tplMng->render(
'parts/storage/select_list',
[
'selectedStorageIds' => $schedule->storage_ids,
'showAddNew' => false,
'recoveryPointMsg' => true,
]
); ?>
</td>
</tr>
<tr valign="top">
<td colspan="2">
<?php
$tplMng->render(
'admin_pages/schedules/parts/repeats_options',
[
'repeat_type' => $schedule->repeat_type,
'run_every' => $schedule->run_every,
'day_of_month' => $schedule->day_of_month,
'weekdays' => [
'mon' => $schedule->isDaySet('mon'),
'tue' => $schedule->isDaySet('tue'),
'wed' => $schedule->isDaySet('wed'),
'thu' => $schedule->isDaySet('thu'),
'fri' => $schedule->isDaySet('fri'),
'sat' => $schedule->isDaySet('sat'),
'sun' => $schedule->isDaySet('sun'),
],
'start_hour' => $schedule->getStartTimePiece(0),
'start_minute' => $schedule->getStartTimePiece(1),
]
);
?>
</td>
</tr>
<tr valign="top">
<th scope="row"><label><?php esc_html_e('Recovery Status', 'duplicator-pro'); ?></label></th>
<td class="dup-recovery-template">
<div class="margin-bottom-1">
<?php
if (($template = $schedule->getTemplate()) !== false) {
$schedule->recoveableHtmlInfo();
} else {
esc_html_e('Unavailable', 'duplicator-pro');
?>
<i class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Recovery Status", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e('Status is unavailable. Please save the schedule to view recovery status', 'duplicator-pro');
?>"></i>
<?php } ?>
</div>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="schedule-active"><?php esc_html_e('Activated', 'duplicator-pro'); ?></label></th>
<td>
<input name="_active" id="schedule-active" type="checkbox" <?php checked($schedule->isActive()); ?> class="margin-0">
<label for="schedule-active"><?php esc_html_e('Enable This Schedule', 'duplicator-pro'); ?></label><br />
<i class="dupli-edit-info"> <?php esc_html_e('When checked this schedule will run', 'duplicator-pro'); ?></i>
</td>
</tr>
</table><br />
<button
id="dupli-save-schedule"
class="button primary small"
type="submit">
<?php esc_html_e('Save Schedule', 'duplicator-pro'); ?>
</button>
</form>
<script>
jQuery(document).ready(function($) {
DupliJs.Schedule.EditTemplate = function() {
var templateID = $('#schedule-template-selector').val();
var url = <?php echo wp_json_encode($editTemplateUrl); ?> + '&package_template_id=' + templateID;
window.open(url, 'edit-template');
};
DupliJs.Schedule.ToggleTemplateEditBtn = function() {
$('#schedule-template-edit-btn, #schedule-template-add-btn, #schedule-template-sync-btn').hide();
if ($("#schedule-template-selector").val() > 0) {
$('#schedule-template-edit-btn').show();
} else {
$('#schedule-template-add-btn, #schedule-template-sync-btn').show();
}
}
$('#dup-schedule-form').parsley({
excluded: ':disabled'
});
jQuery('#schedule-name').focus().select();
DupliJs.Schedule.ToggleTemplateEditBtn();
$("#schedule-template-selector").change(function() {
DupliJs.Schedule.ToggleTemplateEditBtn()
});
});
</script>

View File

@@ -0,0 +1,619 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Ajax\ServicesSchedule;
use Duplicator\Controllers\PackagesPageController;
use Duplicator\Controllers\SchedulePageController;
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Controllers\ToolsPageController;
use Duplicator\Core\CapMng;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Models\ScheduleEntity;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Models\TemplateEntity;
use Duplicator\Package\DupPackage;
use Duplicator\Views\UI\UiDialog;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var bool $blur
*/
$blur = $tplData['blur'];
$active_schedules = ScheduleEntity::getActive();
$active_count = count($active_schedules);
$schedules = ScheduleEntity::getAll();
$schedule_count = ScheduleEntity::count();
$active_package = DupPackage::getNextActive();
$active_schedule_id = -1;
if ($active_package != null) {
$active_schedule_id = $active_package->getScheduleId();
}
$packagesPageUrl = PackagesPageController::getInstance()->getMenuLink();
$scheduleEditBaseURL = SchedulePageController::getInstance()->getEditBaseUrl();
$scheduleCopyBaseURL = SchedulePageController::getInstance()->getCopyActionUrl();
$settingsScheudleUrl = ControllersManager::getMenuLink(
ControllersManager::SETTINGS_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_SCHEDULE
);
$templatesPageUrl = ToolsPageController::getInstance()->getMenuLink(ToolsPageController::L2_SLUG_TEMPLATE);
$tooltopCreatedContent = __(
'Backup date and time expressed in UTC (Coordinated Universal Time).
The displayed date corresponds to the server\'s international time, independent of local time zones.',
'duplicator-pro'
);
?>
<div class="dup-toolbar <?php echo ($blur ? 'dup-mock-blur' : ''); ?>">
<label for="bulk_action" class="screen-reader-text">Select bulk action</label>
<select id="bulk_action" class="small">
<option value="-1" selected="selected">
<?php esc_html_e("Bulk Actions", 'duplicator-pro'); ?>
</option>
<option value="<?php echo (int) ServicesSchedule::SCHEDULE_BULK_ACTIVATE; ?>" title="Activate selected schedules(s)">
<?php esc_html_e("Activate", 'duplicator-pro'); ?>
</option>
<option value="<?php echo (int) ServicesSchedule::SCHEDULE_BULK_DEACTIVATE; ?>" title="Deactivate selected schedules(s)">
<?php esc_html_e("Deactivate", 'duplicator-pro'); ?>
</option>
<option value="<?php echo (int) ServicesSchedule::SCHEDULE_BULK_DELETE; ?>" title="Delete selected schedules(s)">
<?php esc_html_e("Delete", 'duplicator-pro'); ?>
</option>
</select>
<input
type="button"
id="dup-schedule-bulk-apply"
class="button hollow secondary small action"
value="<?php esc_attr_e("Apply", 'duplicator-pro') ?>"
onclick="DupliJs.Schedule.BulkAction()">
<span class="separator"></span>
<?php if (CapMng::can(CapMng::CAP_SETTINGS, false)) { ?>
<a
href="<?php echo esc_url($settingsScheudleUrl); ?>"
class="button hollow secondary small dup-schedule-settings"
title="<?php esc_attr_e("Settings", 'duplicator-pro') ?>">
<i class="fas fa-sliders-h fa-fw"></i>
</a>
<?php } ?>
<a
href="<?php echo esc_url($templatesPageUrl); ?>"
id="btn-logs-dialog"
class="button hollow secondary small dup-schedule-templates"
title="<?php esc_attr_e("Templates", 'duplicator-pro') ?>">
<i class="far fa-clone"></i>
</a>
</div>
<form
id="dup-schedule-form"
class="<?php echo ($blur ? 'dup-mock-blur' : ''); ?>"
action="<?php echo esc_url(ControllersManager::getCurrentLink()); ?>"
method="post">
<input type="hidden" id="dup-schedule-form-action" name="action" value="" />
<input type="hidden" id="dup-schedule-selected-schedule" name="schedule_id" value="-1" />
<!-- ====================
LIST ALL SCHEDULES -->
<table class="widefat storage-tbl dup-table-list valign-top schedule-tbl">
<thead>
<tr>
<th style='width:10px;'><input type="checkbox" id="dupli-chk-all" title="Select all Backups" onclick="DupliJs.Schedule.SetDeleteAll(this)"></th>
<th style='width:275px;'><?php esc_html_e('Name', 'duplicator-pro'); ?></th>
<th><?php esc_html_e('Storage', 'duplicator-pro'); ?></th>
<th>
<?php esc_html_e('Runs Next', 'duplicator-pro'); ?>&nbsp;
<i
class="fa-solid fa-circle-info"
data-tooltip-title="<?php esc_attr_e('Runs Next Date/Time', 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltopCreatedContent); ?>"></i>
</th>
<th>
<?php esc_html_e('Last Ran', 'duplicator-pro'); ?>&nbsp;
<i
class="fa-solid fa-circle-info"
data-tooltip-title="<?php esc_attr_e('Last Ran Date/Time', 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tooltopCreatedContent); ?>"></i>
</th>
<th><?php esc_html_e('Active', 'duplicator-pro'); ?></th>
<th class="dup-col-recovery"><?php esc_html_e('Recovery', 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody>
<?php if ($schedule_count <= 0) : ?>
<tr>
<td colspan="7" class="dup-schedules-no-schedule">
<div class="margin-top-1 margin-bottom-1">
<h3 class="margin-bottom-0">
<b><i class="far fa-clock fa-sm"></i> <?php esc_html_e('No Schedules Found', 'duplicator-pro') ?></b>
</h3>
<a href="<?php echo esc_url($scheduleEditBaseURL); ?>">
[<?php esc_html_e('Add New Schedule', 'duplicator-pro') ?>]
</a>
</div>
</td>
</tr>
<?php endif; ?>
<?php
$i = 0;
foreach ($schedules as $schedule) :
$i++;
$icon_display = (($schedule->getId() == $active_schedule_id) ? 'inline' : 'none');
?>
<tr class="schedule-row <?php echo ($i % 2) ? 'alternate' : ''; ?>">
<td>
<input name="selected_id[]" type="checkbox" value="<?php echo (int) $schedule->getId() ?>" class="item-chk" />
</td>
<td>
<i
id="<?php echo "icon-{" . (int) $schedule->getId() . "}-status"; ?>"
class="fas fa-cog fa-spin schedule-status-icon"
style="display:<?php echo esc_attr($icon_display); ?>; margin-right:4px;"
data-tooltip="<?php esc_attr_e('This scheduled backup is currently in progress', 'duplicator-pro'); ?>">
</i>
<a
id="<?php echo "text-{" . (int) $schedule->getId() . "}"; ?>"
href="javascript:void(0);"
onclick="DupliJs.Schedule.Edit('<?php echo (int) $schedule->getId() ?>');"
class="name">
<?php echo esc_html($schedule->name); ?>
</a>
<div class="sub-menu">
<span class="link-style dup-schedule-quick-view" onclick="DupliJs.Schedule.QuickView('<?php echo (int) $schedule->getId() ?>');">
<?php esc_html_e('Quick View', 'duplicator-pro'); ?>
</span> |
<span class="link-style dup-schedule-edit" onclick="DupliJs.Schedule.Edit('<?php echo (int) $schedule->getId() ?>');">
<?php esc_html_e('Edit', 'duplicator-pro'); ?>
</span> |
<span class="link-style dup-schedule-copy" onclick="DupliJs.Schedule.Copy('<?php echo (int) $schedule->getId(); ?>');">
<?php esc_html_e('Copy', 'duplicator-pro'); ?>
</span> |
<span class="link-style dup-schedule-delete" onclick="DupliJs.Schedule.Delete('<?php echo (int) $schedule->getId(); ?>');">
<?php esc_html_e('Delete', 'duplicator-pro'); ?>
</span>
<?php if (CapMng::can(CapMng::CAP_CREATE, false)) : ?>
| <span class="link-style dup-schedule-run-now" onclick="DupliJs.Schedule.RunNow('<?php echo (int) $schedule->getId(); ?>');">
<?php esc_html_e('Run Now', 'duplicator-pro'); ?>
</span>
<?php endif; ?>
</div>
</td>
<td>
<?php
if (count($schedule->storage_ids) > 0 && strlen(implode('', $schedule->storage_ids)) != 0) {
foreach ($schedule->storage_ids as $storage_id) {
if (($storage = AbstractStorageEntity::getById($storage_id)) === false) {
continue;
}
// Check storage validity
$isValid = $storage->isValid();
$isSupported = $storage::isSupported();
if (!$isSupported) {
echo '<span style="opacity: 0.5;" data-tooltip="' . esc_attr($storage::getNotSupportedNotice()) . '">';
echo esc_html($storage->getName());
echo '</span><br/>';
} elseif (!$isValid) {
$tooltipMsg = __('This storage has invalid configuration and cannot be used.', 'duplicator-pro');
echo '<span style="opacity: 0.5;" data-tooltip="' . esc_attr($tooltipMsg) . '">';
echo esc_html($storage->getName());
echo '</span><br/>';
} else {
// Valid storage - display normally
echo esc_html($storage->getName()) . '<br/>';
}
}
} else {
$txt_DeleteStorage = __('No Storage', 'duplicator-pro');
echo "<a href='javascript:void(0)' onclick='DupliJs.Schedule.showDeleteStorageMessage()'>"
. "<i class='fa fa-info-circle fa-fw fa-sm'></i>"
. "<u>" . esc_html($txt_DeleteStorage) . "</u></a>";
}
?>
</td>
<td>
<?php echo esc_html($schedule->getNextRunTimeString()); ?>
</td>
<td id="schedule-<?php echo (int) $schedule->getId() ?>-last-ran-string">
<?php echo esc_html($schedule->getLastRanString()); ?>
</td>
<td>
<b>
<?php if ($schedule->isActive()) { ?>
<span class="green"><?php esc_html_e('Yes', 'duplicator-pro'); ?></span>
<?php } else { ?>
<span class="maroon"><?php esc_html_e('No', 'duplicator-pro'); ?></span>
<?php } ?>
</b>
</td>
<td class="dup-col-recovery">
<?php $schedule->recoveableHtmlInfo(true); ?>
</td>
</tr>
<tr id='detail-<?php echo (int) $schedule->getId() ?>' class='<?php echo ($i % 2) ? 'alternate' : ''; ?> schedule-detail'>
<td colspan="7">
<?php
$template = TemplateEntity::getById($schedule->template_id);
?>
<ul class="no-bullet">
<li>
<b><?php esc_html_e('Backup Template:', 'duplicator-pro'); ?></b>
<?php echo esc_html($template->name); ?>
</li>
<li>
<b><?php esc_html_e('Summary:', 'duplicator-pro'); ?></b>
<?php echo sprintf(esc_html__('Runs %1$s', 'duplicator-pro'), esc_html($schedule->getRepeatText())); ?>
</li>
<li>
<b><?php esc_html_e('Last Ran:', 'duplicator-pro') ?></b>
<?php echo esc_html($schedule->getLastRanString()); ?>
</li>
<li>
<b><?php esc_html_e('Times Run:', 'duplicator-pro') ?></b>
<?php echo (int) $schedule->times_run; ?>
</li>
</ul>
</td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<th colspan="7" style="text-align:right; white-space: nowrap; font-size:12px">
<?php
printf(
esc_html_x(
'Total: %1$s | Active: %2$s | Time: %3$s',
'%1$s represents total schedules, %2$s represents active schedules, %3$s represents current time',
'duplicator-pro'
),
(int) $schedule_count,
(int) $active_count,
'<span id="dupli-clock-container"></span>'
);
?>
</th>
</tr>
</tfoot>
</table>
</form>
<?php
$alert1 = new UiDialog();
$alert1->title = __('Bulk Action Required', 'duplicator-pro');
$alert1->message = __('Please select an action from the "Bulk Actions" drop down menu!', 'duplicator-pro');
$alert1->initAlert();
$alert2 = new UiDialog();
$alert2->title = __('Selection Required', 'duplicator-pro');
$alert2->wrapperClassButtons = 'dupli-dlg-noschedule-sel-bulk-action-btns';
$alert2->message = __('Please select at least one schedule to perform the action on!', 'duplicator-pro');
$alert2->initAlert();
$alert3 = new UiDialog();
$alert3->title = __('No Storage', 'duplicator-pro');
$alert3->message = __('All storage types associated with this schedule have been deleted.&nbsp;', 'duplicator-pro');
$alert3->message .= __('To enable this schedule please assign a valid storage type.', 'duplicator-pro');
$alert3->message .= '<br/><br/>';
$alert3->initAlert();
$confirm1 = new UiDialog();
$confirm1->title = __('Delete Schedule?', 'duplicator-pro');
$confirm1->wrapperClassButtons = 'dupli-dlg-delete-schedules-btns';
$confirm1->message = __('Are you sure you want to delete the selected schedule(s)?', 'duplicator-pro');
$confirm1->message .= '<br/>';
$confirm1->message .= '<small><i>' . __('Note: This action removes all schedules.', 'duplicator-pro') . '</i></small>';
$confirm1->progressText = __('Removing Schedules, Please Wait...', 'duplicator-pro');
$confirm1->jsCallback = 'DupliJs.Schedule.BulkDelete()';
$confirm1->initConfirm();
$confirm4 = new UiDialog();
$confirm4->title = __('Activate Schedule?', 'duplicator-pro');
$confirm4->wrapperClassButtons = 'dupli-dlg-activate-schedules-btns';
$confirm4->message = __('Are you sure you want to activate the selected schedule(s)?', 'duplicator-pro');
$confirm4->message .= '<br/>';
$confirm4->message .= '<small><i>' . __('Note: This action activates all schedules.', 'duplicator-pro') . '</i></small>';
$confirm4->progressText = __('Activating Schedules, Please Wait...', 'duplicator-pro');
$confirm4->jsCallback = 'DupliJs.Schedule.BulkActivate()';
$confirm4->initConfirm();
$confirm5 = new UiDialog();
$confirm5->title = __('Deactivate Schedule?', 'duplicator-pro');
$confirm5->wrapperClassButtons = 'dupli-dlg-deactivate-schedules-btns';
$confirm5->message = __('Are you sure you want to deactivate the selected schedule(s)?', 'duplicator-pro');
$confirm5->message .= '<br/>';
$confirm5->message .= '<small><i>' . __('Note: This action deactivates all schedules.', 'duplicator-pro') . '</i></small>';
$confirm5->progressText = __('Deactivating Schedules, Please Wait...', 'duplicator-pro');
$confirm5->jsCallback = 'DupliJs.Schedule.BulkDeactivate()';
$confirm5->initConfirm();
$confirm2 = new UiDialog();
$confirm2->title = __('RUN SCHEDULE?', 'duplicator-pro');
$confirm2->message = __('Are you sure you want to run schedule now?', 'duplicator-pro');
$confirm2->progressText = __('Running Schedule, Please Wait...', 'duplicator-pro');
$confirm2->jsCallback = 'DupliJs.Schedule.Run(this)';
$confirm2->initConfirm();
$confirm3 = new UiDialog();
$confirm3->title = $confirm1->title;
$confirm3->message = __('Are you sure you want to delete this schedule?', 'duplicator-pro');
$confirm3->progressText = $confirm1->progressText;
$confirm3->jsCallback = 'DupliJs.Schedule.DeleteThis(this)';
$confirm3->initConfirm();
$schedule_bulk_action_nonce = wp_create_nonce('duplicator_schedule_bulk_action');
?>
<script>
jQuery(document).ready(function($) {
/*METHOD: Shows quick view summary */
DupliJs.Schedule.QuickView = function(id) {
$('#detail-' + id).toggle();
};
/*METHOD: Run the schedule now and redirect to backups page */
DupliJs.Schedule.RunNow = function(schedule_id) {
<?php $confirm2->showConfirm(); ?>
$("#<?php echo esc_js($confirm2->getID()); ?>-confirm").attr('data-id', schedule_id);
};
DupliJs.Schedule.Run = function(e) {
var schedule_id = $(e).attr('data-id');
$('#icon-' + schedule_id + '-status').show();
$('#text-' + schedule_id).html("<?php esc_html_e('Queueing Now - Please Wait...', 'duplicator-pro') ?>");
var data = {
action: 'duplicator_run_schedule_now',
schedule_id: schedule_id,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_run_schedule_now')); ?>'
}
$.ajax({
type: "POST",
url: ajaxurl,
timeout: 10000000,
data: data
}).done(function(respData) {
try {
var data = DupliJs.parseJSON(respData);
} catch (err) {
console.error(err);
console.error('JSON parse failed for response data: ' + respData);
return false;
}
window.location.href = <?php echo wp_json_encode($packagesPageUrl) ?>;
});
};
/*METHOD: Deletes a single schedule */
DupliJs.Schedule.Delete = function(id) {
<?php $confirm3->showConfirm(); ?>
$("#<?php echo esc_js($confirm3->getID()); ?>-confirm").attr('data-id', id);
};
DupliJs.Schedule.DeleteThis = function(e) {
var id = $(e).attr('data-id');
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_schedule_bulk_action',
perform: <?php echo (int) ServicesSchedule::SCHEDULE_BULK_DELETE; ?>,
schedule_ids: [id],
nonce: '<?php echo esc_js($schedule_bulk_action_nonce); ?>'
},
}).done(function(data) {
$('#dup-schedule-form').submit();
});
};
// Creats a comma seperate list of all selected Backup ids
DupliJs.Schedule.SelectedList = function() {
var arr = [];
$("input[name^='selected_id[]']").each(function() {
if ($(this).is(':checked')) {
arr.push($(this).val());
}
});
return arr;
};
// Bulk delete
DupliJs.Schedule.BulkDelete = function() {
var list = DupliJs.Schedule.SelectedList();
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_schedule_bulk_action',
perform: <?php echo (int) ServicesSchedule::SCHEDULE_BULK_DELETE; ?>,
schedule_ids: list,
nonce: '<?php echo esc_js($schedule_bulk_action_nonce); ?>'
},
}).done(function(data) {
$('#dup-schedule-form').submit();
});
};
// Bulk activate
DupliJs.Schedule.BulkActivate = function() {
var list = DupliJs.Schedule.SelectedList();
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_schedule_bulk_action',
perform: <?php echo (int) ServicesSchedule::SCHEDULE_BULK_ACTIVATE; ?>,
schedule_ids: list,
nonce: '<?php echo esc_js($schedule_bulk_action_nonce); ?>'
},
}).done(function(data) {
if (data.success) {
$('#dup-schedule-form').submit();
} else {
if (data.message.length > 0) {
$('#<?php echo esc_js($confirm4->getID()); ?>-progress').hide();
$('#<?php echo esc_js($confirm4->getMessageID()); ?>').html(data.message);
}
}
});
};
// Bulk deactivate
DupliJs.Schedule.BulkDeactivate = function() {
var list = DupliJs.Schedule.SelectedList();
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_schedule_bulk_action',
perform: <?php echo (int) ServicesSchedule::SCHEDULE_BULK_DEACTIVATE; ?>,
schedule_ids: list,
nonce: '<?php echo esc_js($schedule_bulk_action_nonce); ?>'
},
}).done(function(data) {
$('#dup-schedule-form').submit();
});
};
/*METHOD: Bulk action response */
DupliJs.Schedule.BulkAction = function() {
var list = DupliJs.Schedule.SelectedList();
if (list.length == 0) {
<?php $alert2->showAlert(); ?>
return;
}
var action = $('#bulk_action').val(),
checked = ($('.item-chk:checked').length > 0);
if (action == -1) {
<?php $alert1->showAlert(); ?>
return;
}
if (checked) {
switch (action) {
case '<?php echo (int) ServicesSchedule::SCHEDULE_BULK_DELETE; ?>':
<?php $confirm1->showConfirm(); ?>
break;
case '<?php echo (int) ServicesSchedule::SCHEDULE_BULK_ACTIVATE; ?>':
<?php $confirm4->showConfirm(); ?>
break;
case '<?php echo (int) ServicesSchedule::SCHEDULE_BULK_DEACTIVATE; ?>':
<?php $confirm5->showConfirm(); ?>
break;
default:
<?php $alert2->showAlert(); ?>
break;
}
}
};
/*METHOD: Edit a single schedule */
DupliJs.Schedule.Edit = function(id) {
document.location.href = <?php echo json_encode($scheduleEditBaseURL); ?> + '&schedule_id=' + id;
};
/*METHOD: Copy a schedule */
DupliJs.Schedule.Copy = function(id) {
document.location.href = <?php echo json_encode($scheduleCopyBaseURL); ?> + '&dupli-source-schedule-id=' + id;
};
/*METHOD: Set delete all */
DupliJs.Schedule.SetDeleteAll = function(chkbox) {
$('.item-chk').each(function() {
this.checked = chkbox.checked;
});
};
/*METHOD: Shows the delete storage message*/
DupliJs.Schedule.showDeleteStorageMessage = function() {
<?php $alert3->showAlert(); ?>
};
/*METHOD: Enableds the update flag to track proccessing */
DupliJs.Schedule.SetUpdateInterval = function(period) {
console.log('setting interval to ' + period);
if (DupliJs.Schedule.setIntervalID != -1) {
clearInterval(DupliJs.Schedule.setIntervalID);
DupliJs.Schedule.setIntervalID = -1
}
DupliJs.Schedule.setIntervalID = setInterval(DupliJs.Schedule.UpdateSchedules, period * 1000);
};
/*METHOD: Checks the schedule status */
DupliJs.Schedule.UpdateSchedules = function() {
var data = {
action: 'duplicator_get_schedule_infos',
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_get_schedule_infos')); ?>'
};
$.ajax({
type: "POST",
url: ajaxurl,
data: data,
success: function(schedule_infos) {
activeSchedulePresent = false;
for (schedule_info_key in schedule_infos) {
var schedule_info = schedule_infos[schedule_info_key];
var is_running_selector = "#icon-" + schedule_info.schedule_id + "-status";
var last_ran_selector = "#schedule-" + schedule_info.schedule_id + "-last-ran-string";
if (schedule_info.is_running) {
$(is_running_selector).show();
activeSchedulePresent = true;
} else {
$(is_running_selector).hide();
}
$(last_ran_selector).text(schedule_info.last_ran_string);
}
if (activeSchedulePresent) {
DupliJs.Schedule.SetUpdateInterval(10);
} else {
DupliJs.Schedule.SetUpdateInterval(60);
}
},
error: function(data) {
console.log("error");
console.log(data);
$(".schedule-status-icon").css('display', 'none');
DupliJs.Schedule.SetUpdateInterval(60);
}
});
};
DupliJs.UI.Clock(DupliJs._WordPressInitTime);
DupliJs.Schedule.setIntervalID = -1;
DupliJs.Schedule.UpdateSchedules();
});
</script>

View File

@@ -0,0 +1,413 @@
<?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
*/
use Duplicator\Models\GlobalEntity;
use Duplicator\Libs\Snap\SnapIO;
use Duplicator\Libs\Snap\SnapUtil;
use Duplicator\Models\DynamicGlobalEntity;
use Duplicator\Utils\LockUtil;
use Duplicator\Libs\WpUtils\WpArchiveUtils;
$global = GlobalEntity::getInstance();
$dGlobal = DynamicGlobalEntity::getInstance();
$max_execution_time = (int) SnapUtil::phpIniGet("max_execution_time", 0);
$max_execution_time = $max_execution_time < 0 ? PHP_INT_MAX : $max_execution_time;
$max_execution_time = empty($max_execution_time) ? 30 : $max_execution_time;
$workerTimeCapRange = [
10,
min(180, max(30, (int) (0.7 * (float) $max_execution_time))),
];
$workerTimeValue = (int) max($workerTimeCapRange[0], min((int) $global->php_max_worker_time_in_sec, $workerTimeCapRange[1]));
?>
<div class="dup-accordion-wrapper display-separators close">
<div class="accordion-header">
<h3 class="title">
<?php esc_html_e("Advanced", 'duplicator-pro'); ?>
</h3>
</div>
<div class="accordion-content">
<label class="lbl-larger">
<?php esc_html_e("Thread Lock", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="radio"
name="lock_mode"
id="lock_mode_flock"
class="margin-0"
value="<?php echo (int) LockUtil::LOCK_MODE_FILE; ?>"
<?php checked($global->lock_mode, LockUtil::LOCK_MODE_FILE); ?>>
<label for="lock_mode_flock">
<?php esc_html_e("File", 'duplicator-pro'); ?>
</label>&nbsp;
<input
type="radio"
name="lock_mode"
id="lock_mode_sql"
class="margin-0"
value="<?php echo (int) LockUtil::LOCK_MODE_SQL; ?>"
<?php checked($global->lock_mode, LockUtil::LOCK_MODE_SQL); ?>>
<label for="lock_mode_sql">
<?php esc_html_e("SQL", 'duplicator-pro'); ?>
</label>&nbsp;
</div>
<label class="lbl-larger">
<?php esc_html_e("Max Worker Time", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
data-parsley-required
data-parsley-errors-container="#php_max_worker_time_in_sec_error_container"
data-parsley-range="<?php echo esc_attr(wp_json_encode($workerTimeCapRange)); ?>"
data-parsley-type="number"
class="width-small inline-display margin-0"
type="text"
name="php_max_worker_time_in_sec"
id="php_max_worker_time_in_sec"
value="<?php echo (int) $workerTimeValue; ?>">&nbsp;
<span>
<?php esc_html_e('Seconds', 'duplicator-pro'); ?>
</span>
<div id="php_max_worker_time_in_sec_error_container" class="duplicator-error-container"></div>
<p class="description">
<?php
esc_html_e(
'This setting controls how long each processing chunk can run. A lower value makes the process more reliable but slower.',
'duplicator-pro'
);
?><br />
<?php
esc_html_e(
"Try a low value (30 seconds or lower) if the build fails with the recommended setting.",
'duplicator-pro'
); ?>
</p>
</div>
<label class="lbl-larger">
<?php esc_html_e("Ajax", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="radio"
id="ajax_protocol_1"
name="ajax_protocol"
class="ajax_protocol margin-0"
value="admin"
<?php checked($global->ajax_protocol, 'admin'); ?>>
<label for="ajax_protocol_1">
<?php esc_html_e("Auto", 'duplicator-pro'); ?>
</label> &nbsp;
<input
type="radio"
id="ajax_protocol_2"
name="ajax_protocol"
class="ajax_protocol margin-0"
value="http"
<?php checked($global->ajax_protocol == 'http'); ?>>
<label for="ajax_protocol_2">
<?php esc_html_e("HTTP", 'duplicator-pro'); ?>
</label> &nbsp;
<input
type="radio"
id="ajax_protocol_3"
name="ajax_protocol"
class="ajax_protocol margin-0"
value="https"
<?php checked($global->ajax_protocol == 'https'); ?>>
<label for="ajax_protocol_3">
<?php esc_html_e("HTTPS", 'duplicator-pro'); ?>
</label> &nbsp;
<input
type="radio"
id="ajax_protocol_4"
name="ajax_protocol"
class="ajax_protocol margin-0"
value="custom"
<?php checked($global->ajax_protocol, 'custom'); ?>>
<label for="ajax_protocol_4">
<?php esc_html_e("Custom URL", 'duplicator-pro'); ?>
</label> <br />
<input
type="<?php echo ($global->ajax_protocol == 'custom' ? 'text' : 'hidden'); ?>"
id="custom_ajax_url"
name="custom_ajax_url"
class="width-xlarge"
placeholder="<?php esc_attr_e('Consult support before changing.', 'duplicator-pro'); ?>"
value="<?php echo esc_url($global->custom_ajax_url); ?>">
<span id="custom_ajax_url_error" class="alert-color">
<?php esc_html_e("Bad URL!", 'duplicator-pro'); ?>
</span>
<p class="description">
<?php esc_html_e("Used to kick off build worker. Only change if Backups get stuck at the start of a build.", 'duplicator-pro'); ?>
</p>
</div>
<label class="lbl-larger">
<?php esc_html_e('Root path', 'duplicator-pro') ?>
</label>
<div class="margin-bottom-1">
<input
type="checkbox"
name="homepath_as_abspath"
id="homepath_as_abspath"
class="margin-0"
<?php disabled(WpArchiveUtils::isAbspathHomepathEquivalent()); ?>
<?php checked($global->homepath_as_abspath); ?>
value="1">
<label for="homepath_as_abspath">
<?php
printf(
esc_html_x(
'Use ABSPATH %s as root path.',
'%s represents the ABSPATH surrounded with bold (<b>) tags',
'duplicator-pro'
),
'<b>' . esc_html(WpArchiveUtils::getArchiveListPaths('abs')) . '</b>'
);
?>
<br>
</label>
<p class="description">
<?php
if (WpArchiveUtils::isAbspathHomepathEquivalent()) {
esc_html_e('Abspath and home path are equivalent so this option is disabled', 'duplicator-pro');
} else {
?>
<?php
printf(
esc_html_x(
'In this installation the default root path is %s.',
'%s represents the root path surrounded with bold (<b>) tags',
'duplicator-pro'
),
'<b>' . esc_html(SnapIO::safePathUntrailingslashit(get_home_path(), true)) . '</b>'
); ?><br>
<?php
esc_html_e(
'The path of the WordPress core is different. Activate this option if you want to consider ABSPATH as root path.',
'duplicator-pro'
);
}
?>
</p>
</div>
<label class="lbl-larger">
<?php esc_html_e('Scan File Checks', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="checkbox"
name="_skip_archive_scan"
id="_skip_archive_scan"
class="margin-0"
<?php checked($global->skip_archive_scan); ?>>
<label for="_skip_archive_scan">
<?php esc_html_e("Skip", 'duplicator-pro') ?>
</label><br />
<p class="description">
<?php
esc_html_e(
'If enabled all files check on scan will be skipped before Backup creation.
In some cases, this option can be beneficial if the scan process is having issues running or returning errors.',
'duplicator-pro'
);
?>
</p>
</div>
<label class="lbl-larger">
<?php esc_html_e('Client-side Kickoff', 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="checkbox"
name="_clientside_kickoff"
id="_clientside_kickoff"
class="margin-0"
<?php checked($global->clientside_kickoff); ?> />
<label for="_clientside_kickoff">
<?php esc_html_e("Enabled", 'duplicator-pro') ?>
</label><br />
<p class="description">
<?php esc_html_e('Initiate Backup build from client. Only check this if instructed to by Duplicator support.', 'duplicator-pro'); ?>
</p>
</div>
<label class="lbl-larger">
<?php esc_html_e("Password-Protected Access", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="checkbox"
name="_basic_auth_enabled"
id="_basic_auth_enabled"
value="1"
class="margin-0"
<?php checked($dGlobal->getValBool('basic_auth_enabled')); ?>>
<label for="_basic_auth_enabled">
<?php esc_html_e("Enabled", 'duplicator-pro') ?>
</label>
<i class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("HTTP Basic authentication", 'duplicator-pro'); ?>"
data-tooltip="<?php esc_attr_e(
"When HTTP Basic authentication is applied Duplicator needs to attach the login credentials to each request to the server.
This is required for the build process to work properly. If you see a browser popup login window when accessing the admin area,
then basic authentication should be enabled. If you are not sure, please consult your hosting provider.",
'duplicator-pro'
); ?>"></i>
<div id="dup-basic-auth-login-wrapper">
<input
autocomplete="off"
placeholder="<?php esc_attr_e('User', 'duplicator-pro'); ?>"
type="text"
name="basic_auth_user"
id="basic_auth_user"
class="margin-0"
value="<?php echo esc_attr($dGlobal->getValString('basic_auth_user')); ?>"
<?php disabled(!$dGlobal->getValBool('basic_auth_enabled')); ?>>
<span class="dup-password-toggle">
<input
id="auth_password"
autocomplete="off"
placeholder="<?php esc_attr_e('Password', 'duplicator-pro'); ?>"
type="password"
name="basic_auth_password"
id="basic_auth_password"
class="margin-0"
value="<?php echo esc_attr($dGlobal->getValString('basic_auth_password')); ?>"
<?php disabled(!$dGlobal->getValBool('basic_auth_enabled')); ?>>
<button type="button">
<i class="fas fa-eye fa-sm"></i>
</button>
</span>
</div>
<p class="description">
<?php esc_html_e(
'Enable this function and provide username and password in case Backup creation error.
Essential for making authorized HTTP requests in a server protected folder.',
'duplicator-pro'
); ?>
</p>
</div>
</div>
</div>
<script>
(function($) {
$('#_basic_auth_enabled').on('change', function() {
if ($(this).is(':checked')) {
$('#dup-basic-auth-login-wrapper input').prop('disabled', false);
} else {
$('#dup-basic-auth-login-wrapper input').prop('disabled', true);
}
});
var url_error = $('#custom_ajax_url_error');
// Check URL is valid
$.urlExists = function(url) {
var http = new XMLHttpRequest();
try {
http.open('HEAD', url, false);
http.send();
} catch (err) {
$('#custom_ajax_url_error').html(err.message);
return false;
}
return http.status != 404;
};
var debounce;
$('#custom_ajax_url').on('input keyup keydown change paste focus', function(e) {
clearTimeout(debounce);
var $this = $(this);
debounce = setTimeout(function() {
$this.css({
'border': ''
});
url_error.hide();
if (!$.urlExists($this.val())) {
$this.css({
'border': 'maroon 1px solid'
});
url_error.show();
}
}, 500);
});
(function($this) {
$this.css({
'border': ''
});
url_error.hide();
setTimeout(function() {
var isCustomAjaxUrl = $('#ajax_protocol_4').is(':checked');
if (isCustomAjaxUrl && !$.urlExists($this.val())) {
$this.css({
'border': 'maroon 1px solid'
});
url_error.show();
}
if (isCustomAjaxUrl) {
$('#custom_ajax_url').attr('data-parsley-required', 'true');
} else {
$('#custom_ajax_url').removeAttr('data-parsley-required');
}
}, 0);
}($('#custom_ajax_url')))
/*
* DISPLAY OR HIDE CUSTOM_AJAX_URL
*/
$('.ajax_protocol').on('input click change select touchstart', function(e) {
// Setup and collect value
var $this = $(this),
value = $this.val(),
hideField = $('#custom_ajax_url'),
hideFieldState = hideField.attr('type'),
offset = 200;
url_error.hide();
if (value == 'custom') {
// Display hidden field
if (hideFieldState == 'hidden') {
hideField.hide().attr('type', 'text').fadeIn(offset).attr('data-parsley-required', 'true');
hideField.css({
'border': ''
});
url_error.hide();
if (!$.urlExists(hideField.val())) {
hideField.css({
'border': 'maroon 1px solid'
});
url_error.show();
}
}
} else {
// Hide field but keep it active for POST reading
if (hideFieldState == 'text') {
var parsleyId = $('#custom_ajax_url').data('parsley-id');
var errorUlId = '#parsley-id-' + parsleyId;
if ($(errorUlId).length)
$(errorUlId).remove();
hideField.fadeOut(Math.round(offset / 2), function() {
$(this).attr('type', 'hidden').show();
}).removeAttr('data-parsley-required');;
}
}
});
}(window.jQuery || jQuery))
</script>

View File

@@ -0,0 +1,191 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Libs\Shell\ShellZipUtils;
use Duplicator\Models\GlobalEntity;
use Duplicator\Package\Archive\PackageArchive;
use Duplicator\Utils\ZipArchiveExtended;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
$global = GlobalEntity::getInstance();
$isZipArchiveAvailable = ZipArchiveExtended::isPhpZipAvailable();
$isShellZipAvailable = (ShellZipUtils::getShellExecZipPath() != null);
?>
<h3 class="title">
<?php esc_html_e("Archive", 'duplicator-pro') ?>
</h3>
<hr size="1" />
<label class="lbl-larger">
<?php esc_html_e("Compression", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<input
type="radio"
name="archive_compression"
id="archive_compression_off"
value="0"
class="margin-0"
<?php checked($global->archive_compression, false); ?>>
<label for="archive_compression_off">
<?php esc_html_e("Off", 'duplicator-pro'); ?>
</label> &nbsp;
<input
type="radio"
name="archive_compression"
id="archive_compression_on"
value="1"
class="margin-0"
<?php checked($global->archive_compression); ?>>
<label for="archive_compression_on">
<?php esc_html_e("On", 'duplicator-pro'); ?>
</label>
<?php $tipContent = __(
'This setting controls archive compression. The setting apply to all Archive Engine formats.
For ZipArchive this setting only works on PHP 7.0 or higher.',
'duplicator-pro'
); ?>&nbsp;
<i style="margin-right:7px;" class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("Archive Compression", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tipContent); ?>">
</i>
</div>
<label class="lbl-larger">
<?php esc_html_e("Archive Engine", 'duplicator-pro'); ?>
</label>
<div class="margin-bottom-1">
<div class="engine-radio">
<input
onclick="DupliJs.UI.SetArchiveOptionStates();"
type="radio"
name="archive_build_mode" id="archive_build_mode3"
class="margin-0"
value="<?php echo (int) PackageArchive::BUILD_MODE_DUP_ARCHIVE; ?>"
<?php checked($global->getBuildMode() == PackageArchive::BUILD_MODE_DUP_ARCHIVE); ?>
<?php disabled(!$global->isBuildModeAvailable(PackageArchive::BUILD_MODE_DUP_ARCHIVE)) ?>>
<label for="archive_build_mode3"><?php esc_html_e("DupArchive", 'duplicator-pro'); ?></label> &nbsp; &nbsp;
</div>
<div class="engine-radio <?php echo ($isShellZipAvailable) ? '' : 'engine-radio-disabled'; ?>">
<input
onclick="DupliJs.UI.SetArchiveOptionStates();"
type="radio"
name="archive_build_mode"
id="archive_build_mode1"
class="margin-0"
value="<?php echo (int) PackageArchive::BUILD_MODE_SHELL_EXEC; ?>"
<?php checked($global->getBuildMode() == PackageArchive::BUILD_MODE_SHELL_EXEC); ?>
<?php disabled(!$global->isBuildModeAvailable(PackageArchive::BUILD_MODE_SHELL_EXEC)) ?>>
<label for="archive_build_mode1"><?php esc_html_e("Shell Zip", 'duplicator-pro'); ?></label>
</div>
<div class="engine-radio">
<input
onclick="DupliJs.UI.SetArchiveOptionStates();"
type="radio"
name="archive_build_mode"
id="archive_build_mode2"
class="margin-0"
value="<?php echo (int) PackageArchive::BUILD_MODE_ZIP_ARCHIVE; ?>"
<?php checked($global->getBuildMode() == PackageArchive::BUILD_MODE_ZIP_ARCHIVE); ?>
<?php disabled(!$global->isBuildModeAvailable(PackageArchive::BUILD_MODE_ZIP_ARCHIVE)) ?>>
<label for="archive_build_mode2"><?php esc_html_e("ZipArchive", 'duplicator-pro'); ?></label>
</div>
<br style="clear:both" />
<!-- DUPARCHIVE -->
<div class="engine-sub-opts" id="engine-details-3" style="display:none">
<?php
esc_html_e('This option creates a custom Duplicator Archive Format (.daf) archive file.', 'duplicator-pro');
echo '<br/> ';
esc_html_e('This option is fully multi-threaded and recommended for large sites or throttled servers.', 'duplicator-pro');
echo '<br/> ';
printf(
'%s <a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-work-with-daf-files-and-the-duparchive-extraction-tool')
. '" target="_blank">%s</a> ',
esc_html__('For details on how to use and manually extract the DAF format please see the ', 'duplicator-pro'),
esc_html__('online documentation.', 'duplicator-pro')
);
?>
</div>
<!-- SHELL EXEC -->
<div class="engine-sub-opts" id="engine-details-1" style="display:none">
<?php
$tplMng->render(
'parts/settings/shellZipMessage',
['hasShellZip' => $isShellZipAvailable]
);
?>
</div>
<!-- ZIP ARCHIVE -->
<div class="engine-sub-opts" id="engine-details-2" style="display:none;">
<div class="margin-bottom-1">
<span><?php esc_html_e("Process Mode", 'duplicator-pro'); ?></span>&nbsp;
<select name="ziparchive_mode" id="ziparchive_mode" onchange="DupliJs.UI.setZipArchiveMode();" class="inline-display width-medium margin-0">
<option <?php selected($global->ziparchive_mode, PackageArchive::ZIP_MODE_MULTI_THREAD); ?>
value="<?php echo (int) PackageArchive::ZIP_MODE_MULTI_THREAD ?>">
<?php esc_html_e("Multi-Threaded", 'duplicator-pro'); ?>
</option>
<option <?php selected($global->ziparchive_mode == PackageArchive::ZIP_MODE_SINGLE_THREAD); ?>
value="<?php echo (int) PackageArchive::ZIP_MODE_SINGLE_THREAD ?>">
<?php esc_html_e("Single-Threaded", 'duplicator-pro'); ?>
</option>
</select>&nbsp;
<i style="margin-right:7px;" class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("PHP ZipArchive Mode", 'duplicator-pro'); ?>"
data-tooltip="<?php
esc_attr_e(
'Single-Threaded mode attempts to create the entire archive in one request.
Multi-Threaded mode allows the archive to be chunked over multiple requests.
Multi-Threaded mode is typically slower but much more reliable especially for larger sites.',
'duplicator-pro'
);
?>"></i>
</div>
<div id="dupli-ziparchive-mode-st">
<input type="checkbox" id="ziparchive_validation" name="ziparchive_validation" class="margin-0"
<?php checked($global->ziparchive_validation); ?>>
<label for="ziparchive_validation">Enable file validation</label>
</div>
<div id="dupli-ziparchive-mode-mt">
<span><?php esc_html_e("Buffer Size", 'duplicator-pro'); ?></span>&nbsp;
<input
maxlength="4"
class="inline-display width-small margin-0"
data-parsley-required data-parsley-errors-container="#ziparchive_chunk_size_error_container"
data-parsley-min="5" data-parsley-type="number"
type="text" name="ziparchive_chunk_size_in_mb" id="ziparchive_chunk_size_in_mb"
value="<?php echo (int) $global->ziparchive_chunk_size_in_mb; ?>">
<?php esc_html_e('MB', 'duplicator-pro'); ?>
<?php
$toolTipContent = __(
'Buffer size only applies to multi-threaded requests and indicates how large an archive will get before a close is registered.
Higher values are faster but can be more unstable based on the hosts max_execution_time.',
'duplicator-pro'
);
?>
<i style="margin-right:7px" class="fa-solid fa-question-circle fa-sm dark-gray-color"
data-tooltip-title="<?php esc_attr_e("PHP ZipArchive Buffer", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($toolTipContent); ?>">
</i>
<div id="ziparchive_chunk_size_error_container" class="duplicator-error-container"></div>
</div>
</div>
</div>

View File

@@ -0,0 +1,137 @@
<?php
/**
* @package Duplicator
*/
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\Controllers\ControllersManager;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
*/
?>
<form
id="dup-settings-form" class="dup-settings-pack-basic"
action="<?php echo esc_url(ControllersManager::getCurrentLink()); ?>"
method="post" data-parsley-validate
>
<?php $tplData['actions'][SettingsPageController::ACTION_PACKAGE_BASIC_SAVE]->getActionNonceFileds(); ?>
<div class="dup-settings-wrapper margin-bottom-1">
<?php $tplMng->render('admin_pages/settings/backup/database_settings'); ?>
<?php $tplMng->render('admin_pages/settings/backup/archive_settings'); ?>
<?php $tplMng->render('admin_pages/settings/backup/processing_settings'); ?>
<?php $tplMng->render('admin_pages/settings/backup/installer_settings'); ?>
<?php $tplMng->render('admin_pages/settings/backup/advanced_settings'); ?>
</div>
<p class="submit dupli-save-submit">
<input
type="submit"
name="submit"
id="submit"
class="button primary small"
value="<?php esc_attr_e('Save Settings', 'duplicator-pro') ?>" style="display: inline-block;"
>
</p>
</form>
<script>
jQuery(document).ready(function ($)
{
DupliJs.UI.SetDBEngineMode = function ()
{
var isMysqlDump = $('#package_mysqldump').is(':checked');
var isPHPMode = $('#package_phpdump').is(':checked');
var isPHPChunkMode = $('#package_phpchunkingdump').is(':checked');
$('#dbengine-details-1, #dbengine-details-2').hide();
switch (true) {
case isMysqlDump :
$('#dbengine-details-1').show();
break;
case isPHPMode :
case isPHPChunkMode :
$('#dbengine-details-2').show();
break;
}
}
DupliJs.UI.setZipArchiveMode = function ()
{
$('#dupli-ziparchive-mode-st, #dupli-ziparchive-mode-mt').hide();
if ($('#ziparchive_mode').val() == 0) {
$('#dupli-ziparchive-mode-mt').show();
} else {
$('#dupli-ziparchive-mode-st').show();
}
}
DupliJs.UI.SetArchiveOptionStates = function ()
{
var php70 = <?php echo (version_compare(PHP_VERSION, '7', '>=') ? 'true' : 'false'); ?>;
var isShellZipSelected = $('#archive_build_mode1').is(':checked');
var isZipArchiveSelected = $('#archive_build_mode2').is(':checked');
var isDupArchiveSelected = $('#archive_build_mode3').is(':checked');
if (isShellZipSelected || isDupArchiveSelected) {
$("[name='archive_compression']").prop('disabled', false);
$("[name='ziparchive_mode']").prop('disabled', true);
} else {
$("[name='ziparchive_mode']").prop('disabled', false);
if (php70) {
$("[name='archive_compression']").prop('disabled', false);
} else {
$('#archive_compression_on').prop('checked', true);
$("[name='archive_compression']").prop('disabled', true);
}
}
$('#engine-details-1, #engine-details-2, #engine-details-3').hide();
switch (true) {
case isShellZipSelected :
$('#engine-details-1').show();
break;
case isZipArchiveSelected :
$('#engine-details-2').show();
break;
case isDupArchiveSelected :
$('#engine-details-3').show();
break;
}
DupliJs.UI.setZipArchiveMode();
}
//INIT
DupliJs.UI.SetArchiveOptionStates();
DupliJs.UI.SetDBEngineMode();
DupliJs.UI.cleanupModeRadioSwitched = function() {
if ($('#cleanup_mode_Cleanup_Off').is(":checked")){
$('#auto_cleanup_hours').attr('readonly','readonly');
$('#cleanup_email').attr('readonly','readonly');
} else if ($('#cleanup_mode_Email_Notice').is(":checked")) {
$('#auto_cleanup_hours').attr('readonly','readonly');
$("#cleanup_email").removeAttr('readonly');
} else if ($('#cleanup_mode_Auto_Cleanup').is(":checked")) {
$("#auto_cleanup_hours").removeAttr('readonly');
$("#cleanup_email").removeAttr('readonly');
}
}
$('input[type=radio][name=cleanup_mode]').change(function () {
DupliJs.UI.cleanupModeRadioSwitched();
});
// We must call this also once in the beginning, after UI is loaded
DupliJs.UI.cleanupModeRadioSwitched();
});
</script>

Some files were not shown because too many files have changed in this diff Show More