first commit

This commit is contained in:
Roman Pyrih
2026-04-28 09:27:26 +02:00
commit 968c7e1248
4942 changed files with 1507729 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\Storages\Local\LocalStorage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var LocalStorage $storage
*/
$storage = $tplData["storage"];
/** @var int */
$maxPackages = $tplData["maxPackages"];
/** @var int */
$isFilderProtection = $tplData["isFilderProtection"];
/** @var string */
$storageFolder = $tplData["storageFolder"];
$tplMng->render('admin_pages/storages/parts/provider_head');
?>
<tr valign="top">
<th scope="row">
<?php $home_path = duplicator_pro_get_home_path(); ?>
<label onclick="jQuery('#_local_storage_folder').val('<?php echo esc_js($home_path); ?>')">
<?php esc_html_e("Storage Folder", 'duplicator-pro'); ?>
</label>
</th>
<td>
<input
data-parsley-errors-container="#_local_storage_folder_error_container"
data-parsley-required="true"
type="text"
id="_local_storage_folder"
class="dup-empty-field-on-submit"
name="_local_storage_folder"
data-parsley-pattern=".*"
data-parsley-not-core-paths="true"
value="<?php echo esc_attr($storageFolder); ?>"
>&nbsp;
<i class="fas fa-question-circle fa-sm"
data-tooltip-title="<?php esc_attr_e('Server storage folder', 'duplicator-pro'); ?>"
data-tooltip="<?php $tplMng->renderEscAttr('admin_pages/storages/configs/local_storage_folder_tooltip'); ?>">
</i>
<div id="_local_storage_folder_error_container" class="duplicator-error-container"></div>
</td>
</tr>
<tr>
<th scope="row"><label for="local_filter_protection"><?php esc_html_e("Filter Protection", 'duplicator-pro'); ?></label></th>
<td>
<input
id="_local_filter_protection"
name="_local_filter_protection"
type="checkbox" <?php checked($isFilderProtection); ?>
onchange="DupPro.Storage.LocalFilterToggle()"
>&nbsp;
<label for="_local_filter_protection">
<?php esc_html_e("Filter the Storage Folder (recommended)", 'duplicator-pro'); ?>
</label>
<div style="padding-top:6px">
<i>
<?php
esc_html_e(
"When checked this will exclude the 'Storage Folder' and all of its content and sub-folders from package builds.",
'duplicator-pro'
); ?>
</i>
<div id="_local_filter_protection_message" style="display:none; color:maroon">
<i>
<?php
esc_html_e(
"Unchecking filter protection is not recommended. This setting helps to prevents packages from getting bundled in other packages.",
'duplicator-pro'
); ?>
</i>
</div>
</div>
</td>
</tr>
<tr>
<th scope="row"><label for=""><?php esc_html_e("Max Packages", 'duplicator-pro'); ?></label></th>
<td>
<label for="local_max_files">
<input
id="local_max_files"
name="local_max_files"
type="number"
value="<?php echo (int) $maxPackages; ?>"
min="0"
maxlength="4"
data-parsley-errors-container="#local_max_files_error_container"
data-parsley-required="true"
data-parsley-type="number"
data-parsley-min="0"
>
&nbsp;
<?php esc_html_e("Number of packages to keep in folder.", 'duplicator-pro'); ?><br/>
<i><?php esc_html_e("When this limit is exceeded, the oldest package will be deleted. Set to 0 for no limit.", 'duplicator-pro'); ?></i>
</label>
<div id="local_max_files_error_container" class="duplicator-error-container"></div>
</td>
</tr>
<?php $tplMng->render('admin_pages/storages/parts/provider_foot'); ?>
<script>
jQuery(document).ready(function ($) {
let validatorMsg = <?php
echo json_encode(
__(
'Storage Folder should not be root directory path, content directory path and upload directory path',
'duplicator-pro'
)
); ?>;
window.Parsley.addValidator('notCorePaths', {
requirementType: 'string',
validateString: function(value) {
<?php
$home_path = duplicator_pro_get_home_path();
$wp_upload_dir = wp_upload_dir();
$wp_upload_dir_basedir = str_replace('\\', '/', $wp_upload_dir['basedir']);
?>
var corePaths = [
'<?php echo esc_js($home_path);?>',
'<?php echo esc_js(untrailingslashit($home_path));?>',
'<?php echo esc_js($home_path . 'wp-content');?>',
'<?php echo esc_js($home_path . 'wp-content/');?>',
'<?php echo esc_js($home_path . 'wp-admin');?>',
'<?php echo esc_js($home_path . 'wp-admin/');?>',
'<?php echo esc_js($home_path . 'wp-includes');?>',
'<?php echo esc_js($home_path . 'wp-includes/');?>',
'<?php echo esc_js($wp_upload_dir_basedir);?>',
'<?php echo esc_js(trailingslashit($wp_upload_dir_basedir));?>'
];
// console.log(value);
for (var i = 0; i < corePaths.length; i++) {
if (value === corePaths[i]) {
return false;
}
}
return true;
},
messages: {
en: validatorMsg
}
});
DupPro.Storage.LocalFilterToggle = function ()
{
$("#_local_filter_protection").is(":checked")
? $("#_local_filter_protection_message").hide(400)
: $("#_local_filter_protection_message").show(400);
};
//Init
DupPro.Storage.LocalFilterToggle();
});
</script>

View File

@@ -0,0 +1,74 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\Storages\Local\LocalStorage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var LocalStorage $storage
*/
$storage = $tplData["storage"];
/** @var int */
$maxPackages = $tplData["maxPackages"];
/** @var bool */
$purgePackages = $tplData["purgePackages"];
/** @var string */
$storageFolder = $tplData["storageFolder"];
$tplMng->render('admin_pages/storages/parts/provider_head');
?>
<tr valign="top">
<th scope="row"><label><?php esc_html_e("Location", 'duplicator-pro'); ?></label></th>
<td><?php echo esc_html($storageFolder); ?></td>
</tr>
<tr>
<th scope="row"><label for=""><?php esc_html_e("Max Packages", 'duplicator-pro'); ?></label></th>
<td>
<label for="max_default_store_files">
<input
data-parsley-errors-container="#max_default_store_files_error_container"
id="max_default_store_files"
name="max_default_store_files"
type="text"
data-parsley-type="number"
data-parsley-min="0"
data-parsley-required="true"
value="<?php echo intval($maxPackages); ?>"
maxlength="4"
>
&nbsp;<?php esc_html_e("Number of packages to keep in folder. ", 'duplicator-pro'); ?><br/>
<i><?php esc_html_e("When this limit is exceeded, the oldest package will be deleted. Set to 0 for no limit.", 'duplicator-pro'); ?></i>
</label>
<div id="max_default_store_files_error_container" class="duplicator-error-container"></div>
</td>
</tr>
<tr>
<th scope="row"><label for=""></label></th>
<td>
<label for="purge_default_package_record">
<input
name="purge_default_package_record"
<?php checked($purgePackages); ?>
class="checkbox"
value="1"
type="checkbox"
id="purge_default_package_record"
>
<i>
<?php esc_html_e("Delete associated package record when Max Packages limit is exceeded.", 'duplicator-pro'); ?></i>
</label>
</td>
</tr>
<?php $tplMng->render('admin_pages/storages/parts/provider_foot'); ?>

View File

@@ -0,0 +1,47 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\Storages\Local\LocalStorage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var LocalStorage $storage
*/
$storage = $tplData["storage"];
/** @var int */
$maxPackages = $tplData["maxPackages"];
/** @var int */
$isFilderProtection = $tplData["isFilderProtection"];
/** @var string */
$storageFolder = $tplData["storageFolder"];
$tplMng->render('admin_pages/storages/parts/provider_head');
?>
<?php esc_html_e("Where to store on the server hosting this site.", 'duplicator-pro'); ?><br>
<?php
printf(
esc_html_x(
'The folder can be either a child of the home directory (%1$s) or be outside it as well..',
'%1$s represents the home directory path',
'duplicator-pro'
),
'<b>' . esc_html(duplicator_pro_get_home_path()) . '</b>'
); ?><br>
<?php esc_html_e("On Linux servers start with '/' (e.g. /mypath). On Windows use drive letters (e.g. E:/mypath).", 'duplicator-pro'); ?><br>
<?php esc_html_e("If you are unsure of the path, contact your hosting provider.", 'duplicator-pro'); ?><br>
<br>
<b><?php esc_html_e('Note: This will not store to your local computer unless that is where this web-site is hosted.', 'duplicator-pro'); ?></b><br>

View File

@@ -0,0 +1,36 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\Storages\UnknownStorage;
defined("ABSPATH") or die("");
/**
* Variables
*
* @var \Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var \Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var UnknownStorage $storage
*/
$storage = $tplData["storage"];
$tplMng->render('admin_pages/storages/parts/provider_head');
?>
<tr valign="top">
<th scope="row">
<label>
<?php esc_html_e("Unknown Storage Type", 'duplicator-pro'); ?>
</label>
</th>
<td>
</td>
</tr>
<?php $tplMng->render('admin_pages/storages/parts/provider_foot');

View File

@@ -0,0 +1,119 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Models\Storages\Local\DefaultLocalStorage;
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
* @var AbstractStorageEntity $storage
*/
$storage = $tplData["storage"];
/** @var int */
$storage_id = $tplData["storage_id"];
$storage_tab_url = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG
);
$baseCopyUrl = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
null,
null,
array(
ControllersManager::QUERY_STRING_INNER_PAGE => 'edit',
'action' => $tplData['actions']['copy-storage']->getKey(),
'_wpnonce' => $tplData['actions']['copy-storage']->getNonce(),
'storage_id' => $storage_id,
)
);
$newStorageUrl = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
null,
null,
array(ControllersManager::QUERY_STRING_INNER_PAGE => 'edit')
);
if ($storage->getId() > 0) {
$storages = AbstractStorageEntity::getAllBySType($storage->getSType());
} else {
$storages = AbstractStorageEntity::getAll(0, 0, [StoragesUtil::class, 'sortByPriority']);
}
$storages = array_filter($storages, function (AbstractStorageEntity $s) use ($storage) {
if ($s->getId() == $storage->getId()) {
return false;
}
if ($s->getSType() == DefaultLocalStorage::getSType()) {
return false;
}
return true;
});
$storage_count = count($storages);
?>
<table class="dpro-edit-toolbar">
<tr>
<td>
<select
id="dup-copy-source-id-select"
name="duppro-source-storage-id"
<?php disabled($storage_count, 0); ?>
>
<option value="-1" selected="selected" disabled="true">
<?php esc_html_e('Copy From', 'duplicator-pro'); ?>
</option>
<?php foreach ($storages as $copy_storage) { ?>
<option value="<?php echo (int) $copy_storage->getId(); ?>">
<?php echo esc_html($copy_storage->getName()); ?> [<?php echo esc_html($copy_storage->getStypeName()); ?>]
</option>
<?php } ?>
</select>
<input
type="button"
class="button action"
value="<?php esc_attr_e("Apply", 'duplicator-pro') ?>"
onclick="DupPro.Storage.Copy()"
<?php disabled($storage_count, 0); ?>
>
</td>
<td>
<div class="btnnav">
<a href="<?php echo esc_url($storage_tab_url); ?>" class="button">
<i class="fas fa-server fa-sm"></i> <?php esc_html_e('Providers', 'duplicator-pro'); ?>
</a>
<?php if ($storage_id != -1) : ?>
<a href="<?php echo esc_attr($newStorageUrl); ?>" class="button">
<?php esc_html_e("Add New", 'duplicator-pro'); ?>
</a>
<?php endif; ?>
</div>
</td>
</tr>
</table>
<hr class="dpro-edit-toolbar-divider"/>
<script>
jQuery(document).ready(function ($) {
// COMMON STORAGE RELATED METHODS
DupPro.Storage.Copy = function ()
{
document.location.href = <?php echo json_encode($baseCopyUrl); ?> +
'&duppro-source-storage-id=' + $("#dup-copy-source-id-select option:selected").val();
};
});
</script>

View File

@@ -0,0 +1,25 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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
*/
$storage = $tplData["storage"];
?>
</table>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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
*/
$storage = $tplData["storage"];
?>
<table id="provider-<?php echo (int) $storage->getSType() ?>" class="provider form-table dup-remove-on-submit-if-hidden">

View File

@@ -0,0 +1,59 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Controllers\StoragePageController;
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
*/
$storage = $tplData["storage"];
/** @var bool */
$failed = $tplData["failed"];
/** @var bool */
$cancelled = $tplData["cancelled"];
$containerClasses = ['dup-dlg-store-endpoint'];
if ($failed) {
$containerClasses[] = 'dup-dlg-store-endpoint-failed';
}
if ($cancelled) {
$containerClasses[] = 'dup-dlg-store-endpoint-cancelled';
}
?>
<div class="<?php echo esc_attr(implode(' ', $containerClasses)); ?>" >
<h4 class="dup-dlg-store-names">
<?php echo $storage->getStypeIcon(); ?>&nbsp;
<?php echo esc_html($storage->getStypeName()) ?>:&nbsp;
<span>
<?php echo esc_html($storage->getName()); ?>
<?php if ($failed) { ?>
&nbsp;<i>(<?php esc_html_e('failed', 'duplicator-pro'); ?>)</i>
<?php } ?>
<?php if ($cancelled) { ?>
&nbsp;<i>(<?php esc_html_e('cancelled', 'duplicator-pro'); ?>)</i>
<?php } ?>
</span>
</h4>
<div class="dup-dlg-store-links">
<?php echo $storage->getHtmlLocationLink(); ?>
</div>
<div class="dup-dlg-store-test">
<a href="<?php echo esc_url(StoragePageController::getEditUrl($storage)); ?>" target='_blank'>
[ <?php esc_html_e('Test Storage', 'duplicator-pro'); ?> ]
</a>
</div>
</div>

View File

@@ -0,0 +1,175 @@
<?php
/**
* Duplicator messages sections
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Core\Addons\AddonsManager;
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
*/
$storage = $tplData["storage"];
$sTypeSelected = ($storage->isSelectable() ? $storage->getSType() : -1);
$types = AbstractStorageEntity::getResisteredTypesByPriority();
if ($storage->getId() < 0) {
$supportedNotices = [];
?>
<select id="change-mode" name="storage_type" onchange="DupPro.Storage.ChangeMode()">
<?php foreach ($types as $type) {
$class = AbstractStorageEntity::getSTypePHPClass($type);
call_user_func([$class, 'isSelectable']);
if (!call_user_func([$class, 'isSelectable'])) {
continue;
}
if (!call_user_func([$class, 'isSupported'])) {
$supportedNotices[] = call_user_func([$class, 'getNotSupportedNotice']);
continue;
}
$name = call_user_func([$class, 'getStypeName']);
?>
<option value="<?php echo (int) $type; ?>" <?php selected($sTypeSelected, $type); ?>>
<?php echo esc_html($name) ?>
</option>
<?php } ?>
</select>
<?php
if (count($supportedNotices) > 0) { ?>
<div class="margin-top-1" >
<small class="dpro-store-type-notice"><b><?php esc_html_e('Unsupported storages: ', 'duplicator-pro'); ?></b></small><br>
<?php foreach ($supportedNotices as $notice) { ?>
<small class="dpro-store-type-notice">
<?php
echo '- ',
wp_kses(
$notice,
[
'a' => [
'href' => [],
'target' => [],
],
]
);
?>
</small>
<br>
<?php } ?>
</div>
<?php
}
} else {
?>
<span id="dup-storage-mode-fixed" data-storage-type="<?php echo (int) $storage->getSType(); ?>">
<?php echo $storage->getStypeIcon(); ?>&nbsp;<b><?php echo esc_html($storage->getStypeName()); ?></b>
</span>
<?php
} ?>
<script>
jQuery(document).ready(function ($) {
DupPro.Storage.BindParsley = function (node)
{
$('#dup-storage-form').parsley().destroy();
$('#dup-storage-form .provider input').attr('data-parsley-excluded', 'true');
$('#dup-storage-form .provider input').prop('disabled', true);
node.find('input').removeAttr('data-parsley-excluded');
node.find('input').prop('disabled', false);
$('#dup-storage-form').parsley();
};
DupPro.Storage.Autofill = function (mode) {
<?php if (AddonsManager::getInstance()->isAddonEnabled('AmazonS3Addon')) : ?>
switch (parseInt(mode)) {
case <?php echo (int) \Duplicator\Addons\AmazonS3Addon\Models\BackblazeStorage::getSType(); ?>:
autoFillRegion(mode, 1);
break;
case <?php echo (int) \Duplicator\Addons\AmazonS3Addon\Models\DreamStorage::getSType(); ?>:
case <?php echo (int) \Duplicator\Addons\AmazonS3Addon\Models\VultrStorage::getSType(); ?>:
case <?php echo (int) \Duplicator\Addons\AmazonS3Addon\Models\DigitalOceanStorage::getSType(); ?>:
autoFillRegion(mode, 0);
break;
case <?php echo (int) \Duplicator\Addons\AmazonS3Addon\Models\WasabiStorage::getSType(); ?>:
let wasabiRegion = $("#s3_region_" + mode);
let wasabiEndpoint = $("#s3_endpoint_" + mode);
if (wasabiRegion.val().length > 0) {
wasabiEndpoint.val("s3." + wasabiRegion.val() + ".wasabisys.com");
}
wasabiRegion.change(function(e) {
let regionVal = $(this).val();
if (regionVal.length > 0) {
wasabiEndpoint.val("s3." + regionVal + ".wasabisys.com");
} else {
wasabiEndpoint.val("");
}
});
break;
}
function autoFillRegion(type, regionPos) {
let region = $("#s3_region_" + type);
let endpoint = $("#s3_endpoint_" + type);
bindEndpointToRegion(region, endpoint, regionPos);
endpoint.change(function(e) {
bindEndpointToRegion(region, endpoint, regionPos);
});
}
function bindEndpointToRegion(region, endpoint, pos) {
if (endpoint.val().length > 0) {
let regionStr = endpoint.val().replace(/.*:\/\//g,'').split(".")[pos];
region.val(regionStr);
} else {
region.val("");
}
}
<?php else : ?>
return;
<?php endif; ?>
}
// GENERAL STORAGE LOGIC
DupPro.Storage.ChangeMode = function (animateOverride) {
let mode = 0;
if ($('#dup-storage-mode-fixed').length > 0) {
mode = $('#dup-storage-mode-fixed').data('storage-type');
} else {
let optionSelected = $("#change-mode option:selected");
mode = optionSelected.val();
}
let animate = 400;
let providerConfigNode = $('#provider-' + mode);
if (arguments.length == 1) {
animate = animateOverride;
}
$('.provider').hide();
providerConfigNode.show(animate);
DupPro.Storage.BindParsley(providerConfigNode);
DupPro.Storage.Autofill(mode);
}
$('#dup-storage-form').parsley();
DupPro.Storage.ChangeMode(0);
});
</script>

View File

@@ -0,0 +1,120 @@
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
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
*/
$storage = $tplData["storage"];
$buttonDisabled = ($storage->getId() < 0 || $storage->isValid() == false);
?>
<table class="form-table">
<tr>
<th scope="row">
<label for=""><?php esc_html_e("Validation", 'duplicator-pro'); ?></label>
</th>
<td>
<button
id="button_file_test"
class="button button-large button_file_test"
type="button"
onclick="DupPro.Storage.Test(); return false;"
<?php disabled($buttonDisabled); ?>
>
<i class="fas fa-cloud-upload-alt fa-sm"></i> <?php esc_html_e('Test Storage', 'duplicator-pro'); ?>
</button>
<p>
<i><?php esc_html_e("Test creating and deleting a small file on storage.", 'duplicator-pro'); ?></i>
</p>
</td>
</tr>
</table>
<?php
$alertStorageStatus = new DUP_PRO_UI_Dialog();
$alertStorageStatus->title = __('Storage Status', 'duplicator-pro');
$alertStorageStatus->height = 185;
$alertStorageStatus->message = 'testings'; // javascript inserted message
$alertStorageStatus->initAlert();
$alertStorageStatusLong = new DUP_PRO_UI_Dialog();
$alertStorageStatusLong->title = __('Storage Status', 'duplicator-pro');
$alertStorageStatusLong->width = 800;
$alertStorageStatusLong->height = 520;
$alertStorageStatusLong->showTextArea = true;
$alertStorageStatusLong->textAreaRows = 15;
$alertStorageStatusLong->textAreaCols = 100;
$alertStorageStatusLong->message = ''; // javascript inserted message
$alertStorageStatusLong->initAlert();
?>
<script>
jQuery(document).ready(function ($) {
DupPro.Storage.Test = function ()
{
var $test_button = $('#button_file_test');
$test_button.html('<i class="fas fa-circle-notch fa-spin"></i> <?php esc_html_e('Attempting to test storage', 'duplicator-pro'); ?>');
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_storage_test',
storage_id: <?php echo (int) $storage->getId(); ?>,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_pro_storage_test')); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
console.log('Func data',funcData);
if (funcData.success) {
if (funcData.status_msgs.length==0) {
<?php $alertStorageStatus->showAlert(); ?>
let alertMsg = "<span style='color:green'><b><input type='checkbox' class='checkbox' checked disabled='disabled'>" +
funcData.message+"</b></span>";
<?php $alertStorageStatus->updateMessage("alertMsg"); ?>
} else {
<?php $alertStorageStatusLong->showAlert(); ?>
<?php $alertStorageStatusLong->updateTextareaMessage("funcData.status_msgs"); ?>
let alertMsg = "<span style='color:green'><b><input type='checkbox' class='checkbox' checked disabled='disabled'>" +
funcData.message+"</b></span>";
<?php $alertStorageStatusLong->updateMessage("alertMsg"); ?>
}
} else {
if (funcData.status_msgs.length==0) {
<?php $alertStorageStatus->showAlert(); ?>
let alertMsg = "<i class='fas fa-exclamation-triangle'></i> "+funcData.message;
<?php $alertStorageStatus->updateMessage("alertMsg"); ?>
} else {
<?php $alertStorageStatusLong->showAlert(); ?>
<?php $alertStorageStatusLong->updateTextareaMessage("funcData.status_msgs"); ?>
let alertMsg = "<i class='fas fa-exclamation-triangle'></i> "+funcData.message;
<?php $alertStorageStatusLong->updateMessage("alertMsg"); ?>
}
}
$test_button.html('<i class="fas fa-cloud-upload-alt fa-sm"></i> <?php esc_html_e('Test Storage', 'duplicator-pro'); ?>');
return '';
},
function (result, data, funcData, textStatus, jqXHR) {
$test_button.html('<i class="fas fa-cloud-upload-alt fa-sm"></i> <?php esc_html_e('Test Storage', 'duplicator-pro'); ?>');
<?php $alertStorageStatus->showAlert(); ?>
let alertMsg = "<i class='fas fa-exclamation-triangle'></i> <?php esc_html_e('AJAX error while testing storage', 'duplicator-pro'); ?>";
<?php $alertStorageStatus->updateMessage("alertMsg"); ?>
console.log(parsedData);
return '';
}
);
}
});
</script>

View File

@@ -0,0 +1,246 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Core\Views\TplMng;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Views\AdminNotices;
/**
* 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 int */
$storage_id = $tplData["storage_id"];
/** @var Duplicator\Models\Storages\AbstractStorageEntity */
$storage = $tplData["storage"];
/** @var ?string */
$error_message = $tplData["error_message"];
/** @var ?string */
$success_message = $tplData["success_message"];
$relativeEditUrl = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_STORAGE,
null,
array(ControllersManager::QUERY_STRING_INNER_PAGE => 'edit')
);
$fullEditUrl = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_STORAGE,
null,
array(ControllersManager::QUERY_STRING_INNER_PAGE => 'edit'),
false
);
?>
<form
id="dup-storage-form"
class="dup-monitored-form <?php echo ($blur ? 'dup-mock-blur' : ''); ?>"
action="<?php echo esc_url($relativeEditUrl); ?>"
method="post"
data-parsley-ui-enabled="true"
target="_self"
>
<?php $tplData['actions']['save']->getActionNonceFileds(); ?>
<input type="hidden" name="storage_id" id="storage_id" value="<?php echo (int) $storage->getId(); ?>">
<?php
$tplMng->render('admin_pages/storages/parts/edit_toolbar');
if (!is_null($error_message)) {
AdminNotices::displayGeneralAdminNotice($error_message, AdminNotices::GEN_ERROR_NOTICE, true);
} elseif (!is_null($success_message)) {
AdminNotices::displayGeneralAdminNotice($success_message, AdminNotices::GEN_SUCCESS_NOTICE, true);
}
?>
<table class="form-table top-entry">
<tr valign="top">
<th scope="row">
<label><?php esc_html_e("Name", 'duplicator-pro'); ?></label>
</th>
<td>
<?php if ($storage->isDefault()) {
esc_html_e('Default', 'duplicator-pro');
$tCont = __('The "Default" storage type is a built in type that cannot be removed.', 'duplicator-pro') . ' ' .
__(' This storage type is used by default should no other storage types be available.', 'duplicator-pro') . ' ' .
__('This storage type is always stored to the local server.', 'duplicator-pro');
?>
<i
class="fas fa-question-circle fa-sm"
data-tooltip-title="<?php esc_attr_e("Default Storage Type", 'duplicator-pro'); ?>"
data-tooltip="<?php echo esc_attr($tCont); ?>"
>
</i>
<?php } else { ?>
<input
data-parsley-errors-container="#name_error_container"
type="text"
id="name"
name="name"
value="<?php echo esc_attr($storage->getName()); ?>" autocomplete="off"
>
<?php } ?>
<div id="name_error_container" class="duplicator-error-container"></div>
</td>
</tr>
<tr valign="top">
<th scope="row"><label><?php esc_html_e("Notes", 'duplicator-pro'); ?></label></th>
<td>
<textarea id="notes" name="notes" style="width:100%; max-width: 500px"><?php echo esc_html($storage->getNotes()); ?></textarea>
</td>
</tr>
<tr valign="top">
<th scope="row"><label><?php esc_html_e("Type", 'duplicator-pro'); ?></label></th>
<td>
<?php $tplMng->render('admin_pages/storages/parts/storage_type_select'); ?>
</td>
</tr>
</table>
<hr size="1" />
<?php
if ($storage->getId() > 0) {
$storage->renderConfigFields();
} else {
$types = AbstractStorageEntity::getResisteredTypes();
foreach ($types as $type) {
AbstractStorageEntity::renderSTypeConfigFields($type);
}
}
$tplMng->render('admin_pages/storages/parts/test_button');
?>
<br style="clear:both" />
<button
id="button_save_provider"
class="button button-primary"
type="submit"
>
<?php esc_html_e('Save Provider', 'duplicator-pro'); ?>
</button>
</form>
<script>
jQuery(document).ready(function ($) {
let storageEditBaseUrl = <?php echo json_encode($fullEditUrl); ?>;
// Quick fix for submint/enter error
$(window).on('keyup keydown', function (e) {
if (!$(e.target).is('textarea'))
{
var keycode = (typeof e.keyCode != 'undefined' && e.keyCode > -1 ? e.keyCode : e.which);
if ((keycode === 13)) {
e.preventDefault();
return false;
}
}
});
// Removes the values of hidden input fields marked with class dup-empty-field-on-submit
DupPro.Storage.EmptyValues = function () {
$(':hidden .dup-empty-field-on-submit').val('');
}
// Removes tags marked with class dup-remove-on-submit-if-hidden, if they are hidden
DupPro.Storage.RemoveMarkedHiddenTags = function () {
$('.dup-remove-on-submit-if-hidden:hidden').each(function() {
$(this).remove();
});
}
DupPro.Storage.PrepareForSubmit = function () {
DupPro.Storage.EmptyValues();
if ($('#dup-storage-form').parsley().isValid()) {
// The form is about to be submitted.
DupPro.Storage.RemoveMarkedHiddenTags();
}
}
$('#dup-storage-form').submit(DupPro.Storage.PrepareForSubmit);
DupPro.Storage.AuthMessages = function () {
let reloadUrl = new URL(window.location.href);
let authMessage = reloadUrl.searchParams.get('dup-auth-message');
if (authMessage) {
DupPro.addAdminMessage(authMessage, 'notice');
}
let revokeMessage = reloadUrl.searchParams.get('dup-revoke-message');
if (revokeMessage) {
DupPro.addAdminMessage(revokeMessage, 'notice');
}
}
DupPro.Storage.RevokeAuth = function (storageId)
{
Duplicator.Util.ajaxWrapper(
{
action: 'duplicator_pro_revoke_storage',
storage_id: storageId,
nonce: '<?php echo esc_js(wp_create_nonce('duplicator_pro_revoke_storage')); ?>'
},
function (result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
let reloadUrl = new URL(storageEditBaseUrl);
reloadUrl.searchParams.set('storage_id', storageId);
reloadUrl.searchParams.set('dup-revoke-message', funcData.message);
window.location.href = reloadUrl.href;
//location.reload();
} else {
DupPro.addAdminMessage(funcData.message, 'error');
}
return '';
}
);
}
DupPro.Storage.Authorize = function (storageId, storageType, extraData)
{
extraData.action = 'duplicator_pro_auth_storage';
extraData.storage_id = storageId;
extraData.storage_type = storageType;
extraData.nonce = '<?php echo esc_js(wp_create_nonce('duplicator_pro_auth_storage')); ?>';
Duplicator.Util.ajaxWrapper(
extraData,
function (result, data, funcData, textStatus, jqXHR) {
if (funcData.success) {
let reloadUrl = new URL(storageEditBaseUrl);
reloadUrl.searchParams.set('storage_id', funcData.storage_id);
reloadUrl.searchParams.set('dup-auth-message', funcData.message);
// set unsaved changes to false, not to trigger alert during finalization
DupPro.UI.hasUnsavedChanges = false;
window.location.href = reloadUrl.href;
} else {
DupPro.addAdminMessage(funcData.message, 'error');
}
return '';
}
);
return false;
}
// Toggles Save Provider button for existing Storages only
DupPro.UI.formOnChangeValues($('#dup-storage-form'), function() {
$('#button_file_test').prop('disabled', true);
});
//Init
DupPro.Storage.AuthMessages();
jQuery('#name').focus().select();
});
</script>

View File

@@ -0,0 +1,443 @@
<?php
/**
* @package Duplicator
*/
defined("ABSPATH") or die("");
use Duplicator\Ajax\ServicesStorage;
use Duplicator\Controllers\SettingsPageController;
use Duplicator\Controllers\StoragePageController;
use Duplicator\Core\CapMng;
use Duplicator\Core\Controllers\ControllersManager;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Models\Storages\StoragesUtil;
/**
* Variables
*
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
* @var Duplicator\Core\Views\TplMng $tplMng
* @var array<string, mixed> $tplData
* @var DUP_PRO_Schedule_Entity $schedule
* @var bool $blur
*/
$blur = $tplData['blur'];
if (($storages = AbstractStorageEntity::getAll(0, 0, [StoragesUtil::class, 'sortDefaultFirst'])) === false) {
$storages = [];
}
$storage_count = count($storages);
$edit_storage_url = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
null,
null,
array(
ControllersManager::QUERY_STRING_INNER_PAGE => StoragePageController::INNER_PAGE_EDIT,
)
);
$storage_tab_url = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_STORAGE
);
$settingsStorageUrl = ControllersManager::getMenuLink(
ControllersManager::SETTINGS_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_STORAGE
);
$baseCopyUrl = ControllersManager::getMenuLink(
ControllersManager::STORAGE_SUBMENU_SLUG,
SettingsPageController::L2_SLUG_STORAGE,
null,
array(
ControllersManager::QUERY_STRING_INNER_PAGE => 'edit',
'action' => $tplData['actions']['copy-storage']->getKey(),
'_wpnonce' => $tplData['actions']['copy-storage']->getNonce(),
)
);
?>
<!-- ====================
TOOL-BAR -->
<table class="dpro-edit-toolbar <?php echo ($blur ? 'dup-mock-blur' : ''); ?>">
<tr>
<td>
<select id="bulk_action">
<option value="-1" ><?php esc_html_e('Bulk Actions', 'duplicator-pro'); ?></option>
<option value="<?php echo (int) ServicesStorage::STORAGE_BULK_DELETE; ?>" title="Delete selected storage endpoint(s)">
<?php esc_html_e('Delete', 'duplicator-pro'); ?>
</option>
</select>
<input type="button" class="button action" value="<?php esc_attr_e("Apply", 'duplicator-pro') ?>" onclick="DupPro.Storage.BulkAction()">
<?php if (CapMng::can(CapMng::CAP_SETTINGS, false)) { ?>
<span class="btn-separator"></span>
<a href="<?php echo esc_attr($settingsStorageUrl); ?>" class="button grey-icon" title="<?php esc_attr_e("Settings", 'duplicator-pro') ?>">
<i class="fas fa-sliders-h fa-fw"></i>
</a>
<?php } ?>
</td>
<td>
<div class="btnnav">
<a href="<?php echo esc_url($edit_storage_url); ?>" id="duplicator-pro-add-new-storage" class="button">
<?php esc_html_e('Add New', 'duplicator-pro'); ?>
</a>
</div>
</td>
</tr>
</table>
<form
id="dup-storage-form"
action="<?php echo esc_url($storage_tab_url); ?>"
method="post"
class="<?php echo ($blur ? 'dup-mock-blur' : ''); ?>"
>
<input type="hidden" id="dup-selected-storage" name="storage_id" value="null"/>
<!-- ====================
LIST ALL STORAGE -->
<table class="widefat storage-tbl">
<thead>
<tr>
<th style='width:10px;'>
<input type="checkbox" id="dpro-chk-all" title="Select all storage endpoints" onclick="DupPro.Storage.SetAll(this)">
</th>
<th style='width:275px;'>Name</th>
<th><?php esc_html_e('Type', 'duplicator-pro'); ?></th>
</tr>
</thead>
<tbody>
<?php
$i = 0;
foreach ($storages as $storage) :
$i++;
$type_name = $storage->getStypeName();
$type_id = $storage->getSType();
?>
<tr id="main-view-<?php echo (int) $storage->getId() ?>"
class="storage-row <?php echo ($i % 2) ? 'alternate' : ''; ?>"
data-delete-view="<?php echo esc_attr($storage->getDeleteView(false)); ?>"
>
<td>
<?php if ($storage->isDefault()) : ?>
<input type="checkbox" disabled="disabled" />
<?php else : ?>
<input name="selected_id[]" type="checkbox" value="<?php echo (int) $storage->getId(); ?>" class="item-chk" />
<?php endif; ?>
</td>
<td>
<a href="javascript:void(0);" onclick="DupPro.Storage.Edit('<?php echo (int) $storage->getId(); ?>')">
<b><?php echo esc_html($storage->getName()); ?></b>
</a>
<div class="sub-menu">
<a href="javascript:void(0);" onclick="DupPro.Storage.Edit('<?php echo (int) $storage->getId(); ?>')">
<?php esc_html_e('Edit', 'duplicator-pro'); ?>
</a>
|
<a href="javascript:void(0);" onclick="DupPro.Storage.View('<?php echo (int) $storage->getId(); ?>');">
<?php esc_html_e('Quick View', 'duplicator-pro'); ?>
</a>
<?php if (!$storage->isDefault()) : ?>
|
<a href="javascript:void(0);" onclick="DupPro.Storage.CopyEdit('<?php echo (int) $storage->getId(); ?>');">
<?php esc_html_e('Copy', 'duplicator-pro'); ?>
</a>
|
<a href="javascript:void(0);" onclick="DupPro.Storage.deleteSingle('<?php echo (int) $storage->getId(); ?>');">
<?php esc_html_e('Delete', 'duplicator-pro'); ?>
</a>
<?php endif; ?>
</div>
</td>
<td>
<?php echo $storage->getStypeIcon() . '&nbsp;' . esc_html($storage->getStypeName()); ?>
</td>
</tr>
<?php
ob_start();
try { ?>
<tr id='quick-view-<?php echo (int) $storage->getId(); ?>' class='<?php echo ($i % 2) ? 'alternate' : ''; ?> storage-detail'>
<td colspan="3">
<b><?php esc_html_e('QUICK VIEW', 'duplicator-pro') ?></b> <br/>
<div>
<label><?php esc_html_e('Name', 'duplicator-pro') ?>:</label>
<?php echo esc_html($storage->getName()); ?>
</div>
<div>
<label><?php esc_html_e('Notes', 'duplicator-pro') ?>:</label>
<?php echo (strlen($storage->getNotes())) ? esc_html($storage->getNotes()) : esc_html__('(no notes)', 'duplicator-pro'); ?>
</div>
<div>
<label><?php esc_html_e('Type', 'duplicator-pro') ?>:</label>
<?php echo esc_html($storage->getStypeName()); ?>
</div>
<?php $storage->getListQuickView(); ?>
<button type="button" class="button" onclick="DupPro.Storage.View('<?php echo (int) $storage->getId(); ?>');">
<?php esc_html_e('Close', 'duplicator-pro') ?>
</button>
</td>
</tr>
<?php
} catch (Exception $e) {
ob_clean(); ?>
<tr id='quick-view-<?php echo intval($storage->getId()); ?>' class='<?php echo ($i % 2) ? 'alternate' : ''; ?>'>
<td colspan="3">
<?php
StoragePageController::getErrorMsg($e, true);
?>
<br><br>
<button type="button" class="button" onclick="DupPro.Storage.View('<?php echo intval($storage->getId()); ?>');">
<?php esc_html_e('Close', 'duplicator-pro') ?>
</button>
</td>
</tr>
<?php
}
$rowStr = ob_get_clean();
echo $rowStr;
endforeach; ?>
</tbody>
<tfoot>
<tr>
<th colspan="8" style="text-align:right; font-size:12px">
<?php echo esc_html__('Total', 'duplicator-pro') . ': ' . (int) $storage_count; ?>
</th>
</tr>
</tfoot>
</table>
</form>
<?php
//Select Action Alert
$alert1 = new DUP_PRO_UI_Dialog();
$alert1->title = __('Bulk Action Required', 'duplicator-pro');
$alert1->message = __('Please select an action from the "Bulk Actions" drop down menu!', 'duplicator-pro');
$alert1->initAlert();
//Select Storage Alert
$alert2 = new DUP_PRO_UI_Dialog();
$alert2->title = __('Selection Required', 'duplicator-pro');
$alert2->message = __('Please select at least one storage to delete!', 'duplicator-pro');
$alert2->initAlert();
//Delete Dialog
$dlgDelete = new DUP_PRO_UI_Dialog();
$dlgDelete->height = 525;
$dlgDelete->title = __('Delete Storage(s)?', 'duplicator-pro');
$dlgDelete->progressText = __('Removing Storages, Please Wait...', 'duplicator-pro');
$dlgDelete->jsCallback = 'DupPro.Storage.deleteAjax()';
$dlgDelete->initConfirm();
$storage_bulk_action_nonce = wp_create_nonce("duplicator_pro_storage_bulk_actions");
?>
<script>
jQuery(document).ready(function($) {
//Shows detail view
DupPro.Storage.Edit = function (id) {
document.location.href = '<?php echo "$edit_storage_url&storage_id="; ?>' + id;
};
//Copy and edit
DupPro.Storage.CopyEdit = function (id) {
document.location.href = <?php echo json_encode($baseCopyUrl); ?> + '&duppro-source-storage-id=' + id;
};
//Shows detail view
DupPro.Storage.View = function (id) {
$('#quick-view-' + id).toggle();
$('#main-view-' + id).toggle();
};
//Select all checked items
DupPro.Storage.SelectedList = function () {
var arr = [];
$("input[name^='selected_id[]']").each(function () {
if ($(this).is(':checked')) {
arr.push($(this).val());
}
});
return arr;
};
//Sets all for deletion
DupPro.Storage.SetAll = function (chkbox) {
$('.item-chk').each(function () {
this.checked = chkbox.checked;
});
};
// Bulk action
DupPro.Storage.BulkAction = function () {
var list = DupPro.Storage.SelectedList();
var action = $('#bulk_action').val();
if (list.length === 0) {
<?php $alert2->showAlert(); ?>
return;
}
switch (action) {
case '<?php echo (int) ServicesStorage::STORAGE_BULK_DELETE; ?>':
DupPro.Storage.deleteConfirm(list);
break;
default:
<?php $alert1->showAlert(); ?>
break;
}
};
//Delete via the delete link
DupPro.Storage.deleteSingle = function(id) {
$('#dup-selected-storage').val(id);
DupPro.Storage.deleteConfirm([id]);
};
//Load the delete confirm dialog
DupPro.Storage.deleteConfirm = function(idList) {
var $rowData;
var name, id, typeName, html;
var storeCount = idList.length;
var isSingle = (storeCount == 1) ? true : false;
var dlgID = "<?php echo esc_js($dlgDelete->getID()); ?>";
var $content = $(`#${dlgID}_message`);
html = (isSingle)
? "<i><?php esc_html_e('Are you sure you want to delete this storage item?', 'duplicator-pro')?></i>"
: `<i><?php esc_html_e('Are you sure you want to delete these ${storeCount} storage items?', 'duplicator-pro')?></i>`;
// Build storage item html
html += '<div class="store-items">';
idList.forEach(v => {
html += $('#main-view-' + v).data('delete-view');
});
html += '</div>';
$content.html(html);
<?php $dlgDelete->showConfirm(); ?>
html = `<div class="schedule-area">
<b><?php esc_html_e('Linked Schedules', 'duplicator-pro')?>:</b><br/>
<small><?php esc_html_e("Schedules linked to the storage items above", 'duplicator-pro'); ?>:</small>
<div class="schedule-progress" id="${dlgID}-schedule-progress">
<i class="fas fa-circle-notch fa-spin"></i>
<?php esc_html_e('Finding Schedule Links... Please wait', 'duplicator-pro')?>
</div>
<small>
<?php
esc_html_e("To remove storage items and unlink schedules click OK. ", 'duplicator-pro');
printf(
esc_html_x(
'Schedules with asterisk%1$s will be deactivated if storage is removed.',
'%1$s is an asterisk symbol',
'duplicator-pro'
),
'<span class="maroon">*</span>'
);
?>
</small>
</div>`;
$content.append(html);
function loadSchedules(idList, dlgID){
let result = DupPro.Storage.getScheduleData(idList);
(result != null)
? $(`#${dlgID}-schedule-progress`).html(result)
: $(`#${dlgID}-schedule-progress`).html("<?php esc_html_e('- No linked schedules found -', 'duplicator-pro')?>");
}
setTimeout(loadSchedules, 100, idList, dlgID);
};
//Get the linked schedule data
DupPro.Storage.getScheduleData = function(storageIDs) {
var result = null;
var html;
$.ajax({
type: "POST",
url: ajaxurl,
async: false,
dataType: "json",
data: {
action: 'duplicator_pro_storage_bulk_actions',
perform: <?php echo (int) ServicesStorage::STORAGE_GET_SCHEDULES; ?>,
storage_ids: storageIDs,
nonce: '<?php echo esc_js($storage_bulk_action_nonce); ?>'
}
})
.done(function (data) {
//__sleepFor(1000); //Test delays
if (data.schedules !== undefined && data.schedules.length > 0) {
html = '';
data.schedules.forEach(function (schedule) {
let name = $("<div/>").text(schedule.name).html();
let asterisk = schedule.hasOneStorage ? "*" : "";
html += `<div class="schedule-item">
<i class="far fa-clock"></i> <a href="${schedule.editURL}">${name}</a> <span class="maroon">${asterisk}</span>
</div>`;
});
result = html;
}
})
.fail(function() {
result = '<i class="fas fa-exclamation-triangle"></i> <?php esc_html_e('Unable to get schedule data.', 'duplicator-pro')?>';
});
return result;
};
//Perform the delete via ajax
DupPro.Storage.deleteAjax = function () {
var dlgID = "<?php echo esc_js($dlgDelete->getID()); ?>";
var list = DupPro.Storage.SelectedList();
//Delete from the quick link
if (list.length == 0) {
var singleID = $('#dup-selected-storage').val();
list = (singleID > 0) ? [singleID] : null;
}
$(`#${dlgID}_message`).hide();
$.ajax({
type: "POST",
url: ajaxurl,
dataType: "json",
data: {
action: 'duplicator_pro_storage_bulk_actions',
perform: <?php echo (int) ServicesStorage::STORAGE_BULK_DELETE; ?>,
storage_ids: list,
nonce: '<?php echo esc_js($storage_bulk_action_nonce); ?>'
}
})
.done(function() {$('#dup-storage-form').submit()})
.always(function() {$('#dup-selected-storage').val(null)});
};
//--------------------------
//INIT
//Name hover show menu
$("tr.storage-row").hover(
function () {
$(this).find(".sub-menu").show();
},
function () {
$(this).find(".sub-menu").hide();
}
);
});
//Used to test ajax delays
function __sleepFor(sleepDuration){
var now = new Date().getTime();
while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}
</script>