first commit
This commit is contained in:
170
wp-content/plugins/duplicator-pro/addons/probase/ProBase.php
Normal file
170
wp-content/plugins/duplicator-pro/addons/probase/ProBase.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Version Pro Base addon class
|
||||
*
|
||||
* Name: Duplicator PRO base
|
||||
* Version: 1
|
||||
* Author: Duplicator
|
||||
* Author URI: http://snapcreek.com
|
||||
*
|
||||
* PHP version 7.4
|
||||
*
|
||||
* @category Duplicator
|
||||
* @package Plugin
|
||||
* @author Duplicator
|
||||
* @copyright 2011-2021 Snapcreek LLC
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
|
||||
* @version GIT: $Id$
|
||||
* @link https://duplicator.com/
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase;
|
||||
|
||||
// phpcs:disable
|
||||
require_once __DIR__ . '/vendor/edd/EDD_SL_Plugin_Updater.php';
|
||||
// phpcs:enable
|
||||
|
||||
use Duplicator\Controllers\SchedulePageController;
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\License\LicenseNotices;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
use Duplicator\Core\Controllers\AbstractMenuPageController;
|
||||
use Duplicator\Core\MigrationMng;
|
||||
use Duplicator\Installer\Models\MigrateData;
|
||||
|
||||
/**
|
||||
* Version Pro Base addon class
|
||||
*
|
||||
* @category Duplicator
|
||||
* @package Plugin
|
||||
* @author Snapcreek <admin@snapcreek.com>
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
|
||||
* @link http://snapcreek.com
|
||||
*/
|
||||
class ProBase extends \Duplicator\Core\Addons\AbstractAddonCore
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function init(): void
|
||||
{
|
||||
add_action('init', [$this, 'hookInit']);
|
||||
|
||||
add_filter('duplicator_main_menu_label', fn(): string => 'Duplicator Pro');
|
||||
|
||||
add_filter('duplicator_menu_pages', [$this, 'addScheduleMenuField']);
|
||||
|
||||
add_action(MigrationMng::HOOK_FIRST_LOGIN_AFTER_INSTALL, function (MigrateData $migrationData): void {
|
||||
License::clearVersionCache(true);
|
||||
$licenseData = LicenseData::getInstance();
|
||||
if ($licenseData->getStatus() !== LicenseData::STATUS_VALID) {
|
||||
$licenseData->activate();
|
||||
}
|
||||
});
|
||||
|
||||
add_action('duplicator_after_activation', [$this, 'onUpgradePlugin'], 10, 2);
|
||||
|
||||
add_action('duplicator_before_update_crypt_setting', [self::class, 'beforeCryptUpdateSettings']);
|
||||
add_action('duplicator_after_update_crypt_setting', [self::class, 'afterCryptUpdateSettings']);
|
||||
|
||||
add_filter('duplicator_dynamic_data_skip_reset', function (array $skipResetData): array {
|
||||
$skipResetData[] = 'license_key_visible';
|
||||
$skipResetData[] = 'license_key_visible_pwd';
|
||||
return $skipResetData;
|
||||
});
|
||||
|
||||
add_filter('duplicator_dynamic_skip_data_export', function (array $skipExportData): array {
|
||||
$skipExportData[] = 'license_key_visible';
|
||||
$skipExportData[] = 'license_key_visible_pwd';
|
||||
return $skipExportData;
|
||||
});
|
||||
|
||||
LicenseNotices::init();
|
||||
LicensingController::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add schedule menu page
|
||||
*
|
||||
* @param array<string, AbstractMenuPageController> $basicMenuPages menu pages
|
||||
*
|
||||
* @return array<string, AbstractMenuPageController>
|
||||
*/
|
||||
public function addScheduleMenuField($basicMenuPages)
|
||||
{
|
||||
$page = SchedulePageController::getInstance();
|
||||
|
||||
$basicMenuPages[$page->getSlug()] = $page;
|
||||
return $basicMenuPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function calle on duplicator_addons_loaded hook
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hookInit(): void
|
||||
{
|
||||
License::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called on plugin upgrade
|
||||
*
|
||||
* @param false|string $currentVersion current version
|
||||
* @param string $newVersion new version
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onUpgradePlugin($currentVersion, $newVersion): void
|
||||
{
|
||||
if ($currentVersion !== false && version_compare($currentVersion, '4.5.16-beta1', '<')) {
|
||||
$legacyKey = get_option(LicenseData::LICENSE_OLD_KEY_OPTION_NAME, '');
|
||||
if (!empty($legacyKey)) {
|
||||
LicenseData::getInstance()->setKey($legacyKey);
|
||||
}
|
||||
delete_option(LicenseData::LICENSE_OLD_KEY_OPTION_NAME);
|
||||
}
|
||||
License::clearVersionCache(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Before crypt update settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function beforeCryptUpdateSettings(): void
|
||||
{
|
||||
// make sure the license date si reade before the settings are updated
|
||||
LicenseData::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* After crypt update settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function afterCryptUpdateSettings(): void
|
||||
{
|
||||
LicenseData::getInstance()->save();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getAddonPath(): string
|
||||
{
|
||||
return __DIR__;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getAddonFile(): string
|
||||
{
|
||||
return __FILE__;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Version Pro Base Installer addon class
|
||||
*
|
||||
* Name: Duplicator PRO base
|
||||
* Version: 1
|
||||
* Author: Snap Creek
|
||||
* Author URI: http://snapcreek.com
|
||||
*
|
||||
* @category Duplicator
|
||||
* @package Installer
|
||||
* @author Snapcreek <admin@snapcreek.com>
|
||||
* @copyright 2011-2021 Snapcreek LLC
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
|
||||
* @version GIT: $Id$
|
||||
* @link http://snapcreek.com
|
||||
*/
|
||||
|
||||
namespace Duplicator\Installer\Addons\ProBase;
|
||||
|
||||
use Duplicator\Installer\Core\Hooks\HooksMng;
|
||||
use Duplicator\Installer\Core\Params\Items\ParamItem;
|
||||
|
||||
/**
|
||||
* Version Pro Base Installer addon class
|
||||
*
|
||||
* @category Duplicator
|
||||
* @package Installer
|
||||
* @author Snapcreek <admin@snapcreek.com>
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
|
||||
* @link http://snapcreek.com
|
||||
*/
|
||||
class ProBase extends \Duplicator\Installer\Core\Addons\InstAbstractAddonCore
|
||||
{
|
||||
/**
|
||||
* Main init addon
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init(): void
|
||||
{
|
||||
HooksMng::getInstance()->addFilter(
|
||||
'dupx_main_header',
|
||||
fn($value): string => 'Duplicator PRO'
|
||||
);
|
||||
|
||||
HooksMng::getInstance()->addFilter('installer_get_init_params', [self::class, 'getInitParams']);
|
||||
HooksMng::getInstance()->addAction(
|
||||
'after_params_overwrite',
|
||||
[
|
||||
AdvancedParams::class,
|
||||
'updateParamsAfterOverwrite',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getInitParams
|
||||
*
|
||||
* @param ParamItem[] $params params list
|
||||
*
|
||||
* @return ParamItem[]
|
||||
*/
|
||||
public static function getInitParams($params): array
|
||||
{
|
||||
$advParams = [];
|
||||
AdvancedParams::init($advParams);
|
||||
return array_merge($params, $advParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get addon main folder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getAddonPath(): string
|
||||
{
|
||||
return __DIR__;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get addon main file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getAddonFile(): string
|
||||
{
|
||||
return __FILE__;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Installer\Addons\ProBase;
|
||||
|
||||
use Exception;
|
||||
|
||||
abstract class AbstractLicense
|
||||
{
|
||||
const TYPE_UNKNOWN = -1;
|
||||
const TYPE_UNLICENSED = 0;
|
||||
const TYPE_PERSONAL = 1;
|
||||
const TYPE_FREELANCER = 2;
|
||||
const TYPE_BUSINESS = 3;
|
||||
const TYPE_PERSONAL_AUTO = 4;
|
||||
const TYPE_FREELANCER_AUTO = 5;
|
||||
const TYPE_BUSINESS_AUTO = 6;
|
||||
const TYPE_GOLD = 7;
|
||||
const TYPE_BASIC = 8;
|
||||
const TYPE_PLUS = 9;
|
||||
const TYPE_PRO = 10;
|
||||
const TYPE_ELITE = 11;
|
||||
|
||||
const CAPABILITY_BRAND = 1000;
|
||||
const CAPABILITY_IMPORT_SETTINGS = 1001;
|
||||
const CAPABILITY_SHEDULE_HOURLY = 1002;
|
||||
const CAPABILITY_MULTISITE = 1003;
|
||||
const CAPABILITY_MULTISITE_PLUS = 1004;
|
||||
const CAPABILITY_POWER_TOOLS = 1005;
|
||||
const CAPABILITY_CHANGE_TABLE_PREFIX = 1006;
|
||||
const CAPABILITY_UPDATE_AUTH = 1007;
|
||||
const CAPABILITY_CAPABILITIES_MNG = 1008;
|
||||
const CAPABILITY_CAPABILITIES_MNG_PLUS = 1009;
|
||||
const CAPABILITY_BASE_ADVANCED = 1010;
|
||||
const CAPABILITY_PACKAGE_COMPONENTS_PLUS = 1011;
|
||||
const CAPABILITY_IMPORT = 1012;
|
||||
const CAPABILITY_SCHEDULE = 1013;
|
||||
const CAPABILITY_STORAGE = 1014;
|
||||
const CAPABILITY_TEMPLATE = 1015;
|
||||
const CAPABILITY_STAGING = 1016;
|
||||
|
||||
/**
|
||||
* Return true if multisite is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isMultisite()
|
||||
{
|
||||
// This is to avoid warnings in PHP 5.6 because isn't possibile declare an abstract static method.
|
||||
throw new Exception('This method must be extended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the license type this installer file is made of.
|
||||
*
|
||||
* @return int Returns an enum type of License
|
||||
*/
|
||||
public static function getType()
|
||||
{
|
||||
// This is to avoid warnings in PHP 5.6 because isn't possibile declare an abstract static method.
|
||||
throw new Exception('This method must be extended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license limit
|
||||
*
|
||||
* @return int<0, max>
|
||||
*/
|
||||
public static function getLimit()
|
||||
{
|
||||
// This is to avoid warnings in PHP 5.6 because isn't possibile declare an abstract static method.
|
||||
throw new Exception('This method must be extended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return upsell URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getUpsellURL()
|
||||
{
|
||||
// This is to avoid warnings in PHP 5.6 because isn't possibile declare an abstract static method.
|
||||
throw new Exception('This method must be extended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if license is unlimited
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUnlimited()
|
||||
{
|
||||
return in_array(
|
||||
static::getType(),
|
||||
[
|
||||
self::TYPE_BUSINESS,
|
||||
self::TYPE_BUSINESS_AUTO,
|
||||
self::TYPE_GOLD,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if license have the capability
|
||||
*
|
||||
* @param int $capability capability key
|
||||
* @param ?int $license ENUM license type, if null Get currnt licnse type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function can($capability, $license = null)
|
||||
{
|
||||
if (is_null($license)) {
|
||||
$license = static::getType();
|
||||
}
|
||||
|
||||
$basicMultisite = in_array(
|
||||
$license,
|
||||
[
|
||||
self::TYPE_PERSONAL,
|
||||
self::TYPE_FREELANCER,
|
||||
self::TYPE_FREELANCER_AUTO,
|
||||
self::TYPE_BUSINESS,
|
||||
self::TYPE_BUSINESS_AUTO,
|
||||
self::TYPE_GOLD,
|
||||
self::TYPE_PRO,
|
||||
self::TYPE_ELITE,
|
||||
]
|
||||
);
|
||||
|
||||
switch ($capability) {
|
||||
case self::CAPABILITY_BASE_ADVANCED:
|
||||
return true;
|
||||
case self::CAPABILITY_MULTISITE:
|
||||
return $basicMultisite;
|
||||
case self::CAPABILITY_IMPORT:
|
||||
case self::CAPABILITY_SCHEDULE:
|
||||
case self::CAPABILITY_STORAGE:
|
||||
case self::CAPABILITY_TEMPLATE:
|
||||
if (static::isMultisite()) {
|
||||
return $basicMultisite;
|
||||
} else {
|
||||
return $license > 0;
|
||||
}
|
||||
case self::CAPABILITY_BRAND:
|
||||
case self::CAPABILITY_IMPORT_SETTINGS:
|
||||
case self::CAPABILITY_SHEDULE_HOURLY:
|
||||
case self::CAPABILITY_POWER_TOOLS:
|
||||
case self::CAPABILITY_UPDATE_AUTH:
|
||||
case self::CAPABILITY_CHANGE_TABLE_PREFIX:
|
||||
return in_array(
|
||||
$license,
|
||||
[
|
||||
self::TYPE_FREELANCER,
|
||||
self::TYPE_FREELANCER_AUTO,
|
||||
self::TYPE_BUSINESS,
|
||||
self::TYPE_BUSINESS_AUTO,
|
||||
self::TYPE_GOLD,
|
||||
self::TYPE_PLUS,
|
||||
self::TYPE_PRO,
|
||||
self::TYPE_ELITE,
|
||||
]
|
||||
);
|
||||
case self::CAPABILITY_MULTISITE_PLUS:
|
||||
case self::CAPABILITY_CAPABILITIES_MNG:
|
||||
case self::CAPABILITY_CAPABILITIES_MNG_PLUS:
|
||||
case self::CAPABILITY_PACKAGE_COMPONENTS_PLUS:
|
||||
return in_array(
|
||||
$license,
|
||||
[
|
||||
self::TYPE_BUSINESS,
|
||||
self::TYPE_BUSINESS_AUTO,
|
||||
self::TYPE_GOLD,
|
||||
self::TYPE_PRO,
|
||||
self::TYPE_ELITE,
|
||||
]
|
||||
);
|
||||
case self::CAPABILITY_STAGING:
|
||||
// Staging is available for Pro and Elite licenses
|
||||
return in_array(
|
||||
$license,
|
||||
[
|
||||
self::TYPE_PRO,
|
||||
self::TYPE_ELITE,
|
||||
]
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if license can be upgraded
|
||||
*
|
||||
* @param ?int $license ENUM license type, if null Get currnt licnse type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function canBeUpgraded($license = null)
|
||||
{
|
||||
if (is_null($license)) {
|
||||
$license = static::getType();
|
||||
}
|
||||
|
||||
return !in_array($license, [
|
||||
self::TYPE_BUSINESS,
|
||||
self::TYPE_BUSINESS_AUTO,
|
||||
self::TYPE_GOLD,
|
||||
self::TYPE_ELITE,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license description
|
||||
*
|
||||
* @param ?int $license ENUM license type, if null Get currnt licnse type
|
||||
* @param bool $article if true add article before description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLicenseToString($license = null, $article = false)
|
||||
{
|
||||
if (is_null($license)) {
|
||||
$license = static::getType();
|
||||
}
|
||||
|
||||
switch ($license) {
|
||||
case self::TYPE_UNLICENSED:
|
||||
return ($article ? 'an ' : '') . 'Unlicensed';
|
||||
case self::TYPE_PERSONAL:
|
||||
case self::TYPE_PERSONAL_AUTO:
|
||||
return ($article ? 'a ' : '') . 'Personal';
|
||||
case self::TYPE_FREELANCER:
|
||||
case self::TYPE_FREELANCER_AUTO:
|
||||
return ($article ? 'a ' : '') . 'Freelancer';
|
||||
case self::TYPE_BUSINESS:
|
||||
case self::TYPE_BUSINESS_AUTO:
|
||||
return ($article ? 'a ' : '') . 'Business';
|
||||
case self::TYPE_GOLD:
|
||||
return ($article ? 'a ' : '') . 'Gold';
|
||||
case self::TYPE_BASIC:
|
||||
return ($article ? 'a ' : '') . 'Basic';
|
||||
case self::TYPE_PLUS:
|
||||
return ($article ? 'a ' : '') . 'Plus';
|
||||
case self::TYPE_PRO:
|
||||
return ($article ? 'a ' : '') . 'Pro';
|
||||
case self::TYPE_ELITE:
|
||||
return ($article ? 'a ' : '') . 'Elite';
|
||||
default:
|
||||
return ($article ? 'an ' : '') . 'Unknown Type';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get best license from two given
|
||||
*
|
||||
* @param int $l1 ENUM license
|
||||
* @param int $l2 ENUM license
|
||||
*
|
||||
* @return int ENUM license
|
||||
*/
|
||||
protected static function getBestLicense($l1, $l2)
|
||||
{
|
||||
$l1Weight = 0;
|
||||
$l2Weight = 0;
|
||||
|
||||
$wheigts = [
|
||||
self::TYPE_UNLICENSED => -1,
|
||||
self::TYPE_BASIC => 0,
|
||||
self::TYPE_PERSONAL => 1,
|
||||
self::TYPE_PERSONAL_AUTO => 1,
|
||||
self::TYPE_PLUS => 2,
|
||||
self::TYPE_FREELANCER => 3,
|
||||
self::TYPE_FREELANCER_AUTO => 3,
|
||||
self::TYPE_PRO => 4,
|
||||
self::TYPE_ELITE => 5,
|
||||
self::TYPE_BUSINESS => 6,
|
||||
self::TYPE_BUSINESS_AUTO => 6,
|
||||
self::TYPE_GOLD => 7,
|
||||
];
|
||||
|
||||
$l1Weight = ($wheigts[$l1] ?? -1);
|
||||
$l2Weight = ($wheigts[$l2] ?? -1);
|
||||
|
||||
return ($l1Weight >= $l2Weight ? $l1 : $l2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* License class
|
||||
*
|
||||
* @category Duplicator
|
||||
* @package Installer
|
||||
* @author Snapcreek <admin@snapcreek.com>
|
||||
* @copyright 2011-2021 Snapcreek LLC
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
|
||||
*/
|
||||
|
||||
namespace Duplicator\Installer\Addons\ProBase;
|
||||
|
||||
use Duplicator\Installer\Core\Params\Descriptors\DescriptorInterface;
|
||||
use Duplicator\Installer\Core\Params\Items\ParamForm;
|
||||
use Duplicator\Installer\Core\Params\PrmMng;
|
||||
use DUPX_U;
|
||||
|
||||
class AdvancedParams implements DescriptorInterface
|
||||
{
|
||||
/**
|
||||
* Init advanced params
|
||||
*
|
||||
* @param \Duplicator\Installer\Core\Params\Items\ParamItem[] $params params list
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init(&$params): void
|
||||
{
|
||||
$params[PrmMng::PARAM_GEN_WP_AUTH_KEY] = new ParamForm(
|
||||
PrmMng::PARAM_GEN_WP_AUTH_KEY,
|
||||
ParamForm::TYPE_BOOL,
|
||||
ParamForm::FORM_TYPE_CHECKBOX,
|
||||
['default' => false],
|
||||
[
|
||||
'label' => 'Auth Keys:',
|
||||
'checkboxLabel' => 'Generate New Unique Authentication Keys and Salts',
|
||||
'status' => (License::can(License::CAPABILITY_UPDATE_AUTH) ? ParamForm::STATUS_ENABLED : ParamForm::STATUS_DISABLED),
|
||||
'subNote' => (License::can(License::CAPABILITY_UPDATE_AUTH) ? '' : License::getLicenseUpdateText()),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update params after overwrite
|
||||
*
|
||||
* @param \Duplicator\Installer\Core\Params\Items\ParamItem[] $params params list
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function updateParamsAfterOverwrite($params)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Installer\Addons\ProBase;
|
||||
|
||||
use Duplicator\Installer\Core\Params\PrmMng;
|
||||
use DUPX_ArchiveConfig;
|
||||
use DUPX_U;
|
||||
|
||||
class License extends AbstractLicense
|
||||
{
|
||||
/**
|
||||
* Returns the license type this installer file is made of.
|
||||
*
|
||||
* @return int Returns an enum type of License
|
||||
*/
|
||||
public static function getType()
|
||||
{
|
||||
return self::getBestLicense(self::getImporterLicense(), self::getInstallerLicense());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license limit
|
||||
*
|
||||
* @return int<0, max>
|
||||
*/
|
||||
public static function getLimit(): int
|
||||
{
|
||||
return (int) max(0, (int) \DUPX_ArchiveConfig::getInstance()->license_limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return upsell URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getUpsellURL(): string
|
||||
{
|
||||
return 'https://duplicator.com/my-account/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if multisite is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isMultisite(): bool
|
||||
{
|
||||
return DUPX_ArchiveConfig::getInstance()->isNetwork();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license on installer from package data
|
||||
*
|
||||
* @return int Returns an enum type of License
|
||||
*/
|
||||
protected static function getInstallerLicense()
|
||||
{
|
||||
return DUPX_ArchiveConfig::getInstance()->license_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get importer license from params data
|
||||
*
|
||||
* @return int Returns an enum type of License
|
||||
*/
|
||||
protected static function getImporterLicense()
|
||||
{
|
||||
$overwriteData = PrmMng::getInstance()->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA);
|
||||
return $overwriteData['dupLicense'] ?? self::TYPE_UNLICENSED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license required note
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLicenseUpdateText(): string
|
||||
{
|
||||
return 'This option isn\'t available at the <b>' . static::getLicenseToString() . '</b> license level.' .
|
||||
'To enable this option ' .
|
||||
'<a href="' . DUPX_U::esc_url(static::getUpsellURL()) . '" target="_blank">' . 'upgrade' . '</a>' .
|
||||
' the License.';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase;
|
||||
|
||||
use Duplicator\Models\ScheduleEntity;
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
|
||||
class DrmHandler
|
||||
{
|
||||
const SCHEDULE_DRM_DELAY_DAYS = 14;
|
||||
|
||||
/**
|
||||
* Check if the license has a schedule delay to DRM.
|
||||
*
|
||||
* This method determines if the current license type allows for a schedule delay
|
||||
* to DRM (Digital Rights Management). It returns true if the license type is not
|
||||
* one of the restricted types that do not allow for a schedule delay.
|
||||
*
|
||||
* @return bool True if there is a schedule delay, false otherwise.
|
||||
*/
|
||||
protected static function haveLicenseScheduleDelayToDRM(): bool
|
||||
{
|
||||
$licenseType = LicenseData::getInstance()->getLicenseType();
|
||||
if (is_multisite()) {
|
||||
$noScheduleDRMTypes = [
|
||||
License::TYPE_UNKNOWN,
|
||||
License::TYPE_UNLICENSED,
|
||||
License::TYPE_BASIC,
|
||||
License::TYPE_PLUS,
|
||||
];
|
||||
} else {
|
||||
$noScheduleDRMTypes = [
|
||||
License::TYPE_UNKNOWN,
|
||||
License::TYPE_UNLICENSED,
|
||||
];
|
||||
}
|
||||
return !in_array($licenseType, $noScheduleDRMTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of days until the scheduled DRM activation.
|
||||
*
|
||||
* @return int Returns the number of days left until the scheduled DRM activation, or -1 if there are no days left.
|
||||
*/
|
||||
public static function getDaysTillScheduleDRM()
|
||||
{
|
||||
if (count(ScheduleEntity::getActive()) == 0) {
|
||||
// No active schedules, no need to check DRM
|
||||
return -1;
|
||||
}
|
||||
$status = LicenseData::getInstance()->getStatus();
|
||||
if (!in_array($status, [LicenseData::STATUS_VALID, LicenseData::STATUS_EXPIRED])) {
|
||||
return -1;
|
||||
}
|
||||
if (!self::haveLicenseScheduleDelayToDRM()) {
|
||||
return -1;
|
||||
}
|
||||
if (($expiresDays = LicenseData::getInstance()->getExpirationDays()) === false) {
|
||||
return -1;
|
||||
}
|
||||
return self::SCHEDULE_DRM_DELAY_DAYS + $expiresDays;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase\License;
|
||||
|
||||
use Duplicator\Utils\Logging\DupLog;
|
||||
use Duplicator\Addons\ProBase\Vendor\EDD\EDD_SL_Plugin_Updater;
|
||||
use Duplicator\Addons\ProBase\DrmHandler;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
use Duplicator\Core\CapMng;
|
||||
use Duplicator\Installer\Addons\ProBase\AbstractLicense;
|
||||
use Duplicator\Utils\ExpireOptions;
|
||||
|
||||
final class License extends AbstractLicense
|
||||
{
|
||||
/**
|
||||
* GENERAL SETTINGS
|
||||
*/
|
||||
const EDD_DUP_ITEM_NAME = 'Duplicator Pro';
|
||||
const FRONTEND_CHECK_DELAY = 61; // Seconds, different fromgeneral frontend check to unsync
|
||||
const FRONTEND_CHECK_DELAY_OPTION_KEY = 'license_check';
|
||||
|
||||
const VISIBILITY_INFO = 0;
|
||||
const VISIBILITY_ALL = 1;
|
||||
const VISIBILITY_NONE = 2;
|
||||
|
||||
|
||||
/** @var ?EDD_SL_Plugin_Updater */
|
||||
private static $edd_updater;
|
||||
|
||||
/**
|
||||
* License check
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function check(): void
|
||||
{
|
||||
if (
|
||||
!is_admin() &&
|
||||
!(defined('WP_CLI') && WP_CLI) &&
|
||||
ExpireOptions::getUpdate(
|
||||
self::FRONTEND_CHECK_DELAY_OPTION_KEY,
|
||||
true,
|
||||
self::FRONTEND_CHECK_DELAY
|
||||
) !== false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
in_array(
|
||||
LicenseData::getInstance()->getStatus(),
|
||||
[
|
||||
LicenseData::STATUS_INVALID,
|
||||
LicenseData::STATUS_UNKNOWN,
|
||||
]
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::initEddUpdater();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if multisite is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isMultisite()
|
||||
{
|
||||
return is_multisite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if license have the capability
|
||||
*
|
||||
* @param int $capability capability key
|
||||
* @param ?int $license ENUM license type, if null Get currnt licnse type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function can($capability, $license = null)
|
||||
{
|
||||
if (is_null($license)) {
|
||||
$license = static::getType();
|
||||
}
|
||||
|
||||
switch ($capability) {
|
||||
case self::CAPABILITY_SCHEDULE:
|
||||
if (parent::can($capability, $license)) {
|
||||
return true;
|
||||
}
|
||||
if (DrmHandler::getDaysTillScheduleDRM() >= 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return parent::can($capability, $license);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force upgrade check
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function forceUpgradeCheck(): void
|
||||
{
|
||||
if (
|
||||
in_array(
|
||||
LicenseData::getInstance()->getStatus(),
|
||||
[
|
||||
LicenseData::STATUS_INVALID,
|
||||
LicenseData::STATUS_UNKNOWN,
|
||||
]
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::clearVersionCache(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return latest version of the plugin
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public static function getLatestVersion()
|
||||
{
|
||||
$version_info = null;
|
||||
$edd_updater = self::getEddUpdater();
|
||||
|
||||
/** @var false|object */
|
||||
$version_info = $edd_updater->get_cached_version_info();
|
||||
|
||||
if (is_object($version_info) && isset($version_info->new_version)) {
|
||||
return $version_info->new_version;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear version cache
|
||||
*
|
||||
* @param bool $clearLicenseData Clear license data cache
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clearVersionCache(bool $clearLicenseData): void
|
||||
{
|
||||
DupLog::trace("CLEAR EDD VERSION CACHE");
|
||||
if ($clearLicenseData) {
|
||||
LicenseData::getInstance()->clearCache();
|
||||
}
|
||||
self::getEddUpdater()->set_version_info_cache(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLicenseKey()
|
||||
{
|
||||
return LicenseData::getInstance()->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license status
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getLicenseStatus()
|
||||
{
|
||||
return LicenseData::getInstance()->getStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license type
|
||||
*
|
||||
* @return int ENUM AbstractLicense::TYPE_*
|
||||
*/
|
||||
public static function getType()
|
||||
{
|
||||
return (
|
||||
LicenseData::getInstance()->getStatus() == LicenseData::STATUS_VALID ?
|
||||
LicenseData::getInstance()->getLicenseType() :
|
||||
self::TYPE_UNLICENSED
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the EDD Updater
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function initEddUpdater(): void
|
||||
{
|
||||
if (self::$edd_updater !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eddOpts = [
|
||||
'version' => DUPLICATOR_VERSION,
|
||||
'license' => self::getLicenseKey(),
|
||||
'item_name' => self::EDD_DUP_ITEM_NAME,
|
||||
'author' => 'Snap Creek Software',
|
||||
'wp_override' => true,
|
||||
];
|
||||
|
||||
self::$edd_updater = new EDD_SL_Plugin_Updater(
|
||||
DUPLICATOR_STORE_URL,
|
||||
DUPLICATOR____FILE,
|
||||
$eddOpts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor that returns the EDD Updater singleton
|
||||
*
|
||||
* @return EDD_SL_Plugin_Updater
|
||||
*/
|
||||
private static function getEddUpdater()
|
||||
{
|
||||
if (self::$edd_updater === null) {
|
||||
self::initEddUpdater();
|
||||
}
|
||||
|
||||
return self::$edd_updater;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return upsell URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getUpsellURL(): string
|
||||
{
|
||||
return DUPLICATOR_BLOG_URL . 'my-account/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EDD license upgrade checkout page URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLicenseCheckoutURL(): string
|
||||
{
|
||||
if (
|
||||
!CapMng::can(CapMng::CAP_LICENSE, false) ||
|
||||
empty(self::getLicenseKey())
|
||||
) {
|
||||
return DUPLICATOR_BLOG_URL . 'my-account/';
|
||||
} else {
|
||||
return DUPLICATOR_BLOG_URL . 'checkout?edd_license_key=' . self::getLicenseKey();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return no activation left message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getNoActivationLeftMessage()
|
||||
{
|
||||
if (self::isUnlimited()) {
|
||||
$result = sprintf(__('%1$s site licenses are granted in batches of 500.', 'duplicator-pro'), License::getLicenseToString());
|
||||
$result .= ' ';
|
||||
$result .= sprintf(
|
||||
_x(
|
||||
'Please submit a %1$sticket request%2$s and we will grant you another batch.',
|
||||
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a href="' . DUPLICATOR_BLOG_URL . 'my-account/support/" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
$result .= '<br>';
|
||||
return $result . __('This process helps to ensure that licenses are not stolen or abused for users.', 'duplicator-pro');
|
||||
} else {
|
||||
return __(
|
||||
'Use the link above to login to your duplicator.com dashboard to manage your licenses or upgrade to a higher license.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase\License;
|
||||
|
||||
use Duplicator\Addons\ProBase\DrmHandler;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
use Duplicator\Controllers\SettingsPageController;
|
||||
use Duplicator\Core\CapMng;
|
||||
use Duplicator\Core\Controllers\ControllersManager;
|
||||
use Duplicator\Core\Views\TplMng;
|
||||
use Duplicator\Views\AdminNotices;
|
||||
|
||||
class LicenseNotices
|
||||
{
|
||||
/**
|
||||
* Init notice actions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init(): void
|
||||
{
|
||||
add_action('admin_init', [self::class, 'adminInit']);
|
||||
|
||||
$path = plugin_basename(DUPLICATOR____FILE);
|
||||
|
||||
// Important to make this priority 11 or greater to ensure the version cache is up to date by EDD
|
||||
add_action("after_plugin_row_{$path}", [self::class, 'noLicenseDisplay'], 11, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called on hook admin_init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function adminInit(): void
|
||||
{
|
||||
$action = is_multisite() ? 'network_admin_notices' : 'admin_notices';
|
||||
add_action($action, [self::class, 'licenseAlertCheck']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called on hook admin_init
|
||||
*
|
||||
* @param string $file Path to the plugin file relative to the plugins directory
|
||||
* @param array<string, mixed> $plugin An array of plugin data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function noLicenseDisplay($file, $plugin): void
|
||||
{
|
||||
$latest_version = License::getLatestVersion();
|
||||
|
||||
// Only display this message when there is no update message
|
||||
if (($latest_version === false) || version_compare(DUPLICATOR_VERSION, $latest_version, '>=')) {
|
||||
$error_string = null;
|
||||
|
||||
$licenseSettingsUrl = SettingsPageController::getInstance()->getMenuLink(
|
||||
SettingsPageController::L2_SLUG_GENERAL
|
||||
);
|
||||
|
||||
switch (LicenseData::getInstance()->getStatus()) {
|
||||
case LicenseData::STATUS_INVALID:
|
||||
case LicenseData::STATUS_SITE_INACTIVE:
|
||||
$error_string = sprintf(
|
||||
esc_html_x(
|
||||
'Your Duplicator Pro license key is invalid so you aren\'t getting important updates!
|
||||
%1$sActivate your license%2$s or %3$spurchase a license%4$s.',
|
||||
'1,3: <a> tag, 2,4: </a> tag',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a href="' . esc_url($licenseSettingsUrl) . '">',
|
||||
'</a>',
|
||||
'<a target="_blank" href="' . esc_url(DUPLICATOR_BLOG_URL . 'pricing/') . '">',
|
||||
'</a>'
|
||||
);
|
||||
break;
|
||||
case LicenseData::STATUS_EXPIRED:
|
||||
$error_string = sprintf(
|
||||
__(
|
||||
'Your Duplicator Pro license key has expired so you aren\'t getting important updates! %1$sRenew your license now%2$s',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a target="_blank" href="' . esc_url(License::getLicenseCheckoutURL()) . '">',
|
||||
'</a>'
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ($error_string == null) {
|
||||
return;
|
||||
} elseif (!CapMng::can(CapMng::CAP_LICENSE, false)) {
|
||||
// Overwrite error message if the user does not have the license capability
|
||||
$error_string = esc_html__(
|
||||
'Duplicator Pro license key is not activated. Please contact the Duplicator license manager to activate it.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<script>
|
||||
jQuery("[data-slug=\'duplicator-pro\']").addClass("update");
|
||||
</script>
|
||||
<tr style="border-top-color:black" class="plugin-update-tr active">
|
||||
<td colspan="4" class="plugin-update colspanchange">
|
||||
<div class="update-message notice inline notice-error notice-alt">
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
$error_string,
|
||||
[
|
||||
'a' => [
|
||||
'href' => [],
|
||||
'target' => [],
|
||||
],
|
||||
]
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
ob_end_flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the WP action hook to detect the state of the endpoint license
|
||||
* which calls the various show* methods for which alert to display
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function licenseAlertCheck(): void
|
||||
{
|
||||
if (
|
||||
!CapMng::can(CapMng::CAP_BASIC, false) ||
|
||||
ControllersManager::isCurrentPage(
|
||||
ControllersManager::SETTINGS_SUBMENU_SLUG,
|
||||
SettingsPageController::L2_SLUG_GENERAL
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_exists(DUPLICATOR_SSDIR_PATH . "/ovr.dup")) {
|
||||
return;
|
||||
}
|
||||
|
||||
$licenseData = LicenseData::getInstance();
|
||||
|
||||
switch ($licenseData->getStatus()) {
|
||||
case LicenseData::STATUS_VALID:
|
||||
if (is_multisite() && !License::can(License::CAPABILITY_MULTISITE)) {
|
||||
self::showMultisiteDRMAlert();
|
||||
}
|
||||
break;
|
||||
case LicenseData::STATUS_EXPIRED:
|
||||
self::showExpired();
|
||||
break;
|
||||
case LicenseData::STATUS_UNKNOWN:
|
||||
case LicenseData::STATUS_INVALID:
|
||||
case LicenseData::STATUS_INACTIVE:
|
||||
case LicenseData::STATUS_DISABLED:
|
||||
case LicenseData::STATUS_SITE_INACTIVE:
|
||||
default:
|
||||
if ($licenseData->haveNoActivationsLeft()) {
|
||||
self::showNoActivationsLeft();
|
||||
} else {
|
||||
self::showInvalidStandardNag();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the smaller standard nag screen
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function showInvalidStandardNag(): void
|
||||
{
|
||||
$problem_text = esc_html__('missing', 'duplicator-pro');
|
||||
|
||||
$htmlMsg = TplMng::getInstance()->render(
|
||||
'licensing/notices/inactive_message',
|
||||
['problem' => $problem_text],
|
||||
false
|
||||
);
|
||||
|
||||
AdminNotices::displayGeneralAdminNotice(
|
||||
$htmlMsg,
|
||||
AdminNotices::GEN_ERROR_NOTICE,
|
||||
false,
|
||||
['dup-license-message'],
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the license count used up alert
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function showNoActivationsLeft(): void
|
||||
{
|
||||
$htmlMsg = TplMng::getInstance()->render(
|
||||
'licensing/notices/no_activation_left',
|
||||
[],
|
||||
false
|
||||
);
|
||||
AdminNotices::displayGeneralAdminNotice(
|
||||
$htmlMsg,
|
||||
AdminNotices::GEN_ERROR_NOTICE,
|
||||
false,
|
||||
['dup-license-message'],
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the expired message alert
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function showExpired(): void
|
||||
{
|
||||
$renewal_url = License::getLicenseCheckoutURL();
|
||||
$htmlMsg = TplMng::getInstance()->render(
|
||||
'licensing/notices/expired',
|
||||
[
|
||||
'renewal_url' => $renewal_url,
|
||||
'schedule_disalbe_days_left' => DrmHandler::getDaysTillScheduleDRM(),
|
||||
],
|
||||
false
|
||||
);
|
||||
AdminNotices::displayGeneralAdminNotice(
|
||||
$htmlMsg,
|
||||
AdminNotices::GEN_ERROR_NOTICE,
|
||||
false,
|
||||
['dup-license-message'],
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the multisite DRM alert
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function showMultisiteDRMAlert(): void
|
||||
{
|
||||
$problem_text = esc_html__('missing', 'duplicator-pro');
|
||||
|
||||
$htmlMsg = TplMng::getInstance()->render(
|
||||
'licensing/notices/drm_multisite_msg',
|
||||
[],
|
||||
false
|
||||
);
|
||||
|
||||
AdminNotices::displayGeneralAdminNotice(
|
||||
$htmlMsg,
|
||||
AdminNotices::GEN_ERROR_NOTICE,
|
||||
false,
|
||||
['dup-license-message'],
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upgrade link
|
||||
*
|
||||
* @param string $label The label of the link
|
||||
* @param bool $echo Whether to echo the link or return it
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getUpsellLinkHTML($label = 'Upgrade', $echo = true)
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<a class="dup-upgrade-license-link primary-color" href="<?php echo esc_url(License::getUpsellURL()); ?>" target="_blank">
|
||||
<?php echo esc_html($label); ?>
|
||||
</a>
|
||||
<?php
|
||||
if ($echo) {
|
||||
ob_end_flush();
|
||||
return '';
|
||||
} else {
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase\License;
|
||||
|
||||
class LicenseUtils
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Version Pro Base functionalities
|
||||
*
|
||||
* Name: Duplicator PRO base
|
||||
* Version: 1
|
||||
* Author: Snap Creek
|
||||
* Author URI: http://snapcreek.com
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase;
|
||||
|
||||
use Duplicator\Utils\Logging\DupLog;
|
||||
use Duplicator\Core\Controllers\ControllersManager;
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
use Duplicator\Controllers\SettingsPageController;
|
||||
use Duplicator\Core\CapMng;
|
||||
use Duplicator\Core\Controllers\PageAction;
|
||||
use Duplicator\Core\Views\TplMng;
|
||||
use Duplicator\Libs\Snap\SnapUtil;
|
||||
use Duplicator\Libs\Snap\SnapWP;
|
||||
use Duplicator\Models\ActivityLog\LogEventLicenseActivation;
|
||||
use Duplicator\Models\ActivityLog\LogEventLicenseDeactivation;
|
||||
use Duplicator\Models\ActivityLog\LogEventLicenseKeyCleared;
|
||||
use Duplicator\Models\ActivityLog\LogEventLicenseVisibilityChanged;
|
||||
use Duplicator\Models\ActivityLog\LogEventLicenseStatusChanged;
|
||||
use Duplicator\Models\DynamicGlobalEntity;
|
||||
use Duplicator\Views\AdminNotices;
|
||||
use Exception;
|
||||
|
||||
class LicensingController
|
||||
{
|
||||
//License actions
|
||||
const ACTION_ACTIVATE_LICENSE = 'activate_license';
|
||||
const ACTION_DEACTIVATE_LICENSE = 'deactivate_license';
|
||||
const ACTION_CHANGE_VISIBILITY = 'change_visibility';
|
||||
const ACTION_CLEAR_KEY = 'clear_key';
|
||||
const ACTION_FORCE_REFRESH = 'force_refresh';
|
||||
|
||||
// Legacy license key option
|
||||
const LEGACY_LICENSE_KEY_OPTION_AUTO_ACTIVE = 'duplicator_pro_license_auto_active';
|
||||
|
||||
// New license key option
|
||||
const LICENSE_KEY_OPTION_AUTO_ACTIVE = 'dupli_opt_auth_token_auto_active';
|
||||
|
||||
/**
|
||||
* License controller init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init(): void
|
||||
{
|
||||
add_action('admin_init', [self::class, 'licenseAutoActive']);
|
||||
add_action('admin_init', [self::class, 'forceUpgradeCheckAction']);
|
||||
add_action('duplicator_settings_general_before', [self::class, 'renderLicenseContent'], 10);
|
||||
add_action('duplicator_settings_general_before', [self::class, 'renderLicenseVisibility'], 100);
|
||||
add_filter('duplicator_page_actions_' . ControllersManager::SETTINGS_SUBMENU_SLUG, [self::class, 'pageActions']);
|
||||
add_filter('duplicator_template_file', [self::class, 'getTemplateFile'], 10, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method call on admin_init hook
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function licenseAutoActive(): void
|
||||
{
|
||||
// Get license key option
|
||||
$license_key_option = self::getLicenseKeyOption();
|
||||
|
||||
// Auto activation don't require capabilities check because is a background process
|
||||
if (($lKey = get_option($license_key_option, false)) === false) {
|
||||
return;
|
||||
}
|
||||
if (($action = SettingsPageController::getInstance()->getActionByKey(self::ACTION_ACTIVATE_LICENSE)) == false) {
|
||||
return;
|
||||
}
|
||||
delete_option($license_key_option);
|
||||
$redirect = $action->getUrl(['_license_key' => $lKey]);
|
||||
|
||||
DupLog::trace("CONTROLLER LICENSE AUTO ACTIVE: Redirecting to " . $action->getUrl());
|
||||
|
||||
if (wp_safe_redirect($redirect)) {
|
||||
exit;
|
||||
} else {
|
||||
throw new Exception(__('Error redirecting to license activation page', 'duplicator-pro'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license key option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLicenseKeyOption(): string
|
||||
{
|
||||
$license_key_option = self::LICENSE_KEY_OPTION_AUTO_ACTIVE;
|
||||
if (get_option(self::LEGACY_LICENSE_KEY_OPTION_AUTO_ACTIVE, false) !== false) {
|
||||
$license_key_option = self::LEGACY_LICENSE_KEY_OPTION_AUTO_ACTIVE;
|
||||
}
|
||||
return $license_key_option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return force upgrade check URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getForceUpgradeCheckURL(): string
|
||||
{
|
||||
return SnapWP::adminUrl('update-core.php', ['force-check' => 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Force upgrade check action
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function forceUpgradeCheckAction(): void
|
||||
{
|
||||
global $pagenow;
|
||||
|
||||
if ($pagenow !== 'update-core.php') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SnapUtil::sanitizeBoolInput(SnapUtil::INPUT_REQUEST, 'force-check')) {
|
||||
return;
|
||||
}
|
||||
|
||||
License::forceUpgradeCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define actions related to the license
|
||||
*
|
||||
* @param PageAction[] $actions Page actions array from filter
|
||||
*
|
||||
* @return PageAction[] Updated page actions array
|
||||
*/
|
||||
public static function pageActions($actions)
|
||||
{
|
||||
$actions[] = new PageAction(
|
||||
self::ACTION_ACTIVATE_LICENSE,
|
||||
[
|
||||
self::class,
|
||||
'activateLicense',
|
||||
],
|
||||
[ControllersManager::SETTINGS_SUBMENU_SLUG]
|
||||
);
|
||||
$actions[] = new PageAction(
|
||||
self::ACTION_DEACTIVATE_LICENSE,
|
||||
[
|
||||
self::class,
|
||||
'deactivateLicense',
|
||||
],
|
||||
[ControllersManager::SETTINGS_SUBMENU_SLUG]
|
||||
);
|
||||
$actions[] = new PageAction(
|
||||
self::ACTION_CLEAR_KEY,
|
||||
[
|
||||
self::class,
|
||||
'clearLicenseKeyAction',
|
||||
],
|
||||
[ControllersManager::SETTINGS_SUBMENU_SLUG]
|
||||
);
|
||||
$actions[] = new PageAction(
|
||||
self::ACTION_CHANGE_VISIBILITY,
|
||||
[
|
||||
self::class,
|
||||
'changeLicenseVisibility',
|
||||
],
|
||||
[ControllersManager::SETTINGS_SUBMENU_SLUG]
|
||||
);
|
||||
$actions[] = new PageAction(
|
||||
self::ACTION_FORCE_REFRESH,
|
||||
[
|
||||
self::class,
|
||||
'forceRefresh',
|
||||
],
|
||||
[ControllersManager::SETTINGS_SUBMENU_SLUG]
|
||||
);
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that changes the license visibility
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function changeLicenseVisibility(): array
|
||||
{
|
||||
DupLog::trace("CONTROLLER CHANGE LICENSE VISIBILITY ACTION: Changing license visibility");
|
||||
|
||||
$result = [
|
||||
'license_success' => false,
|
||||
'license_message' => '',
|
||||
];
|
||||
$dGlobal = DynamicGlobalEntity::getInstance();
|
||||
|
||||
$oldVisibility = $dGlobal->getValInt('license_key_visible', LIcense::VISIBILITY_ALL);
|
||||
$newVisibility = filter_input(INPUT_POST, 'license_key_visible', FILTER_VALIDATE_INT);
|
||||
$newPassword = SnapUtil::sanitizeInput(INPUT_POST, '_key_password', '');
|
||||
|
||||
if ($oldVisibility === $newVisibility) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
switch ($newVisibility) {
|
||||
case License::VISIBILITY_ALL:
|
||||
if ($dGlobal->getValString('license_key_visible_pwd') !== $newPassword) {
|
||||
$result['license_message'] = __("Wrong password entered. Please enter the correct password.", 'duplicator-pro');
|
||||
return $result;
|
||||
}
|
||||
$newPassword = ''; // reset password
|
||||
break;
|
||||
case License::VISIBILITY_NONE:
|
||||
case License::VISIBILITY_INFO:
|
||||
if ($oldVisibility == License::VISIBILITY_ALL) {
|
||||
$password_confirmation = SnapUtil::sanitizeInput(INPUT_POST, '_key_password_confirmation', '');
|
||||
|
||||
if (strlen($newPassword) === 0) {
|
||||
$result['license_message'] = __('Password cannot be empty.', 'duplicator-pro');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($newPassword !== $password_confirmation) {
|
||||
$result['license_message'] = __("Passwords don't match.", 'duplicator-pro');
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
if ($dGlobal->getValString('license_key_visible_pwd') !== $newPassword) {
|
||||
$result['license_message'] = __("Wrong password entered. Please enter the correct password.", 'duplicator-pro');
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception(__('Invalid license visibility value.', 'duplicator-pro'));
|
||||
}
|
||||
|
||||
$dGlobal->setValInt('license_key_visible', $newVisibility);
|
||||
$dGlobal->setValString('license_key_visible_pwd', $newPassword);
|
||||
|
||||
if ($dGlobal->save()) {
|
||||
LogEventLicenseVisibilityChanged::create($oldVisibility, $newVisibility);
|
||||
|
||||
return [
|
||||
'license_success' => true,
|
||||
'license_message' => __("License visibility changed", 'duplicator-pro'),
|
||||
];
|
||||
} else {
|
||||
LogEventLicenseVisibilityChanged::create($oldVisibility, $newVisibility, LogEventLicenseVisibilityChanged::SUB_TYPE_ERROR);
|
||||
|
||||
return [
|
||||
'license_success' => false,
|
||||
'license_message' => __("Couldn't change license visibility.", 'duplicator-pro'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that clears the license key
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function clearLicenseKeyAction()
|
||||
{
|
||||
DupLog::trace("CONTROLLER CLEAR LICENSE KEY ACTION: Clearing license key");
|
||||
|
||||
LicenseData::resetLastRequestFailure();
|
||||
$result = self::clearLicenseKey();
|
||||
LicenseData::resetLastRequestFailure();
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Action that clears the license key
|
||||
*
|
||||
* @param bool $logEvent Whether to log the event
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function clearLicenseKey($logEvent = true): array
|
||||
{
|
||||
$dGlobal = DynamicGlobalEntity::getInstance();
|
||||
|
||||
LicenseData::getInstance()->setKey('');
|
||||
License::clearVersionCache(true);
|
||||
|
||||
$dGlobal->setValInt('license_key_visible', License::VISIBILITY_ALL);
|
||||
$dGlobal->setValString('license_key_visible_pwd', '');
|
||||
|
||||
$result = [];
|
||||
|
||||
if ($dGlobal->save()) {
|
||||
$result['license_success'] = true;
|
||||
$result['license_message'] = __("License key cleared", 'duplicator-pro');
|
||||
} else {
|
||||
$result['license_success'] = false;
|
||||
$result['license_message'] = __("Couldn't save changes", 'duplicator-pro');
|
||||
}
|
||||
|
||||
if ($logEvent) {
|
||||
$eventSubType = $result['license_success'] ? LogEventLicenseKeyCleared::SUB_TYPE_SUCCESS : LogEventLicenseKeyCleared::SUB_TYPE_ERROR;
|
||||
LogEventLicenseKeyCleared::create($eventSubType);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that deactivates the license
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function deactivateLicense(): array
|
||||
{
|
||||
$result = [
|
||||
'license_success' => true,
|
||||
'license_message' => '',
|
||||
];
|
||||
|
||||
$lData = LicenseData::getInstance();
|
||||
|
||||
try {
|
||||
DupLog::trace("CONTROLLER DEACTIVATE LICENSE ACTION: Deactivating license");
|
||||
|
||||
if ($lData->getStatus() !== LicenseData::STATUS_VALID) {
|
||||
return [
|
||||
'license_success' => true,
|
||||
'license_message' => __('License already deactivated.', 'duplicator-pro'),
|
||||
];
|
||||
}
|
||||
|
||||
$licenseKey = $lData->getKey();
|
||||
|
||||
switch ($lData->deactivate()) {
|
||||
case LicenseData::ACTIVATION_RESPONSE_OK:
|
||||
$result['license_message'] = sprintf(
|
||||
_x(
|
||||
'License %1$s %2$sDeactivated%3$s',
|
||||
'%1$s is the license key, %2$s and %3$s are opening and closing HTML tags',
|
||||
'duplicator-pro'
|
||||
),
|
||||
LicenseData::maskLicenseKey($licenseKey),
|
||||
'<b class="alert-color">',
|
||||
'</b>'
|
||||
);
|
||||
|
||||
LogEventLicenseDeactivation::create(
|
||||
LogEventLicenseDeactivation::SUB_TYPE_SUCCESS,
|
||||
LicenseData::maskLicenseKey($licenseKey),
|
||||
$lData->getStatus(),
|
||||
);
|
||||
break;
|
||||
case LicenseData::ACTIVATION_RESPONSE_INVALID:
|
||||
throw new Exception(__('Invalid license key.', 'duplicator-pro'));
|
||||
case LicenseData::ACTIVATION_REQUEST_ERROR:
|
||||
$result['license_request_error'] = $lData->getLastRequestError();
|
||||
throw new Exception(self::getRequestErrorMessage());
|
||||
default:
|
||||
throw new Exception(__('Error deactivating license.', 'duplicator-pro'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
LogEventLicenseDeactivation::create(
|
||||
LogEventLicenseDeactivation::SUB_TYPE_ERROR,
|
||||
LicenseData::maskLicenseKey($lData->getKey()),
|
||||
$lData->getStatus(),
|
||||
$e->getMessage()
|
||||
);
|
||||
|
||||
$result['license_success'] = false;
|
||||
$result['license_message'] = $e->getMessage();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return template file path
|
||||
*
|
||||
* @param string $path path to the template file
|
||||
* @param string $slugTpl slug of the template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTemplateFile($path, $slugTpl)
|
||||
{
|
||||
if (strpos($slugTpl, 'licensing/') === 0) {
|
||||
return ProBase::getAddonPath() . '/template/' . $slugTpl . '.php';
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that activates the license
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function activateLicense(): array
|
||||
{
|
||||
$result = [
|
||||
'license_success' => true,
|
||||
'license_message' => '',
|
||||
];
|
||||
|
||||
$lData = LicenseData::getInstance();
|
||||
|
||||
try {
|
||||
if (($licenseKey = SnapUtil::sanitizeDefaultInput(SnapUtil::INPUT_REQUEST, '_license_key')) === false) {
|
||||
throw new Exception(__('Please enter a valid key. Key should be 32 characters long.', 'duplicator-pro'));
|
||||
}
|
||||
|
||||
if (!preg_match('/^[a-f0-9]{32}$/i', $licenseKey)) {
|
||||
throw new Exception(__('Please enter a valid key. Key should be 32 characters long.', 'duplicator-pro'));
|
||||
}
|
||||
|
||||
DupLog::trace("CONTROLLER ACTIVATE LICENSE ACTION: Setting license key to " . LicenseData::maskLicenseKey($licenseKey));
|
||||
|
||||
// make sure reset old license key if exists (without logging)
|
||||
self::clearLicenseKey(false);
|
||||
$lData->setKey($licenseKey);
|
||||
|
||||
switch ($lData->activate()) {
|
||||
case LicenseData::ACTIVATION_RESPONSE_OK:
|
||||
$result['license_message'] = sprintf(
|
||||
_x(
|
||||
'License %1$s %2$sActivated%3$s',
|
||||
'%1$s is the license key, %2$s and %3$s are opening and closing HTML tags',
|
||||
'duplicator-pro'
|
||||
),
|
||||
LicenseData::maskLicenseKey($licenseKey),
|
||||
'<b class="green-color">',
|
||||
'</b>'
|
||||
);
|
||||
|
||||
// Important to manage frontend license post activation actions
|
||||
$result['license_action_activation_success'] = true;
|
||||
|
||||
LogEventLicenseActivation::create(
|
||||
LogEventLicenseActivation::SUB_TYPE_SUCCESS,
|
||||
LicenseData::maskLicenseKey($licenseKey),
|
||||
$lData->getExpirationDate(),
|
||||
$lData->getExpirationDays(),
|
||||
$lData->getSiteCount(),
|
||||
$lData->getLicenseLimit(),
|
||||
$lData->getStatus(),
|
||||
);
|
||||
|
||||
|
||||
break;
|
||||
case LicenseData::ACTIVATION_RESPONSE_INVALID:
|
||||
throw new Exception(__('Invalid license key.', 'duplicator-pro'));
|
||||
case LicenseData::ACTIVATION_REQUEST_ERROR:
|
||||
$result['license_request_error'] = $lData->getLastRequestError();
|
||||
DupLog::traceObject('License request error', $result['license_request_error']);
|
||||
throw new Exception(self::getRequestErrorMessage());
|
||||
default:
|
||||
throw new Exception(__('Error activating license.', 'duplicator-pro'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$result['license_success'] = false;
|
||||
$result['license_message'] = $e->getMessage();
|
||||
|
||||
LogEventLicenseActivation::create(
|
||||
LogEventLicenseActivation::SUB_TYPE_ERROR,
|
||||
LicenseData::maskLicenseKey($lData->getKey()),
|
||||
$lData->getExpirationDate(),
|
||||
$lData->getExpirationDays(),
|
||||
$lData->getSiteCount(),
|
||||
$lData->getLicenseLimit(),
|
||||
$lData->getStatus(),
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a refresh of the license data action
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function forceRefresh(): array
|
||||
{
|
||||
DupLog::trace("CONTROLLER FORCE REFRESH ACTION: Force refreshing license data");
|
||||
|
||||
$result = [
|
||||
'license_success' => true,
|
||||
'license_message' => __("License data reloaded.", 'duplicator-pro'),
|
||||
];
|
||||
|
||||
$lData = LicenseData::getInstance();
|
||||
|
||||
try {
|
||||
$oldStatus = $lData->getStatus();
|
||||
$licenseKey = $lData->getKey();
|
||||
|
||||
$lData->resetLastRequestFailure();
|
||||
$lData->getLicenseData(true);
|
||||
|
||||
$newStatus = $lData->getStatus();
|
||||
|
||||
// Log the force refresh action and any status changes
|
||||
if ($oldStatus !== $newStatus) {
|
||||
// Status changed during refresh - determine the appropriate subtype
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_INVALID; // default
|
||||
switch ($newStatus) {
|
||||
case LicenseData::STATUS_EXPIRED:
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_EXPIRED;
|
||||
break;
|
||||
case LicenseData::STATUS_DISABLED:
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_DISABLED;
|
||||
break;
|
||||
case LicenseData::STATUS_INACTIVE:
|
||||
case LicenseData::STATUS_SITE_INACTIVE:
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_INACTIVE;
|
||||
break;
|
||||
case LicenseData::STATUS_INVALID:
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_INVALID;
|
||||
break;
|
||||
case LicenseData::STATUS_VALID:
|
||||
$subType = LogEventLicenseStatusChanged::SUB_TYPE_RESTORED;
|
||||
break;
|
||||
}
|
||||
|
||||
LogEventLicenseStatusChanged::create(
|
||||
$subType,
|
||||
LicenseData::maskLicenseKey($licenseKey),
|
||||
$lData->getStatus(),
|
||||
$lData->getExpirationDate(),
|
||||
$lData->getExpirationDays(),
|
||||
$lData->getSiteCount(),
|
||||
$lData->getLicenseLimit()
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$result['license_success'] = false;
|
||||
$result['license_message'] = $e->getMessage();
|
||||
|
||||
LogEventLicenseStatusChanged::create(
|
||||
LogEventLicenseStatusChanged::SUB_TYPE_ERROR,
|
||||
LicenseData::maskLicenseKey($lData->getKey()),
|
||||
$lData->getStatus(),
|
||||
$lData->getExpirationDate(),
|
||||
$lData->getExpirationDays(),
|
||||
$lData->getSiteCount(),
|
||||
$lData->getLicenseLimit(),
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render page content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function renderLicenseContent(): void
|
||||
{
|
||||
if (!CapMng::getInstance()->can(CapMng::CAP_LICENSE, false)) {
|
||||
return;
|
||||
}
|
||||
self::renderLicenseMessage();
|
||||
TplMng::getInstance()->render('licensing/main');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render page content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function renderLicenseVisibility(): void
|
||||
{
|
||||
if (!CapMng::getInstance()->can(CapMng::CAP_LICENSE, false)) {
|
||||
return;
|
||||
}
|
||||
TplMng::getInstance()->render('licensing/visibility');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true avter license activation action
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isActivationLicenseRender(): bool
|
||||
{
|
||||
return TplMng::getInstance()->getDataValueBool('license_action_activation_success', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render activation/deactivation license message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function renderLicenseMessage()
|
||||
{
|
||||
if (!CapMng::getInstance()->can(CapMng::CAP_LICENSE, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tplData = TplMng::getInstance()->getGlobalData();
|
||||
if (empty($tplData['license_message'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$success = (isset($tplData['license_success']) && $tplData['license_success'] === true);
|
||||
AdminNotices::displayGeneralAdminNotice(
|
||||
TplMng::getInstance()->render('licensing/notices/activation_message', [], false),
|
||||
($success ? AdminNotices::GEN_SUCCESS_NOTICE : AdminNotices::GEN_ERROR_NOTICE),
|
||||
false,
|
||||
[],
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the communication error message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getRequestErrorMessage(): string
|
||||
{
|
||||
$result = '<b>' . __('License data request failed.', 'duplicator-pro') . '</b>';
|
||||
$result .= '<br>';
|
||||
return $result . sprintf(
|
||||
_x(
|
||||
'Please see %1$sthis FAQ entry%2$s for possible causes and resolutions.',
|
||||
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a href="' . DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-resolve-license-activation-issues/" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,821 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Duplicator
|
||||
* @copyright (c) 2022, Snap Creek LLC
|
||||
*/
|
||||
|
||||
namespace Duplicator\Addons\ProBase\Models;
|
||||
|
||||
use DateTime;
|
||||
use Duplicator\Utils\Logging\DupLog;
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Models\StaticGlobal;
|
||||
use Duplicator\Core\Models\AbstractEntity;
|
||||
use Duplicator\Core\Models\TraitEntitySerializationEncryption;
|
||||
use Duplicator\Core\Models\TraitGenericModelSingleton;
|
||||
use Duplicator\Installer\Addons\ProBase\AbstractLicense;
|
||||
use Duplicator\Libs\Snap\SnapUtil;
|
||||
use Duplicator\Utils\Crypt\CryptBlowfish;
|
||||
use Duplicator\Utils\ExpireOptions;
|
||||
use Error;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use VendorDuplicator\Amk\JsonSerialize\JsonSerialize;
|
||||
use WP_Error;
|
||||
|
||||
class LicenseData extends AbstractEntity
|
||||
{
|
||||
use TraitGenericModelSingleton;
|
||||
use TraitEntitySerializationEncryption;
|
||||
|
||||
/**
|
||||
* Encrypted properties for license data
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected static array $encryptedProperties = [
|
||||
'licenseKey',
|
||||
'status',
|
||||
'type',
|
||||
'data',
|
||||
];
|
||||
|
||||
/**
|
||||
* GENERAL SETTINGS
|
||||
*/
|
||||
const LICENSE_CACHE_TIME = 7 * DAY_IN_SECONDS;
|
||||
const LICENSE_FAILURE_DELAY_TIME = 60 * MINUTE_IN_SECONDS;
|
||||
const LICENSE_FAILURE_OPT_KEY = 'license_failure_request';
|
||||
const FAILURE_SKIP_EXCEPTION_CODE = 100;
|
||||
const LICENSE_OLD_KEY_OPTION_NAME = 'duplicator_pro_license_key';
|
||||
|
||||
/**
|
||||
* LICENSE STATUS
|
||||
*/
|
||||
const STATUS_UNKNOWN = -1;
|
||||
const STATUS_VALID = 0;
|
||||
const STATUS_INVALID = 1;
|
||||
const STATUS_INACTIVE = 2;
|
||||
const STATUS_DISABLED = 3;
|
||||
const STATUS_SITE_INACTIVE = 4;
|
||||
const STATUS_EXPIRED = 5;
|
||||
|
||||
/**
|
||||
* ACTIVATION REPONSE
|
||||
*/
|
||||
const ACTIVATION_RESPONSE_OK = 0;
|
||||
const ACTIVATION_REQUEST_ERROR = -1;
|
||||
const ACTIVATION_RESPONSE_INVALID = -2;
|
||||
|
||||
const DEFAULT_LICENSE_DATA = [
|
||||
'success' => false,
|
||||
'license' => 'invalid',
|
||||
'item_id' => false,
|
||||
'item_name' => '',
|
||||
'checksum' => '',
|
||||
'expires' => '',
|
||||
'payment_id' => -1,
|
||||
'customer_name' => '',
|
||||
'customer_email' => '',
|
||||
'license_limit' => -1,
|
||||
'site_count' => -1,
|
||||
'activations_left' => -1,
|
||||
'price_id' => AbstractLicense::TYPE_UNLICENSED,
|
||||
'activeSubscription' => false,
|
||||
];
|
||||
|
||||
const VALID_RESPONSE_REQUIRED_KEYS = [
|
||||
'success',
|
||||
'license',
|
||||
'item_id',
|
||||
'item_name',
|
||||
'checksum',
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
protected $licenseKey = '';
|
||||
/** @var int */
|
||||
protected $status = self::STATUS_INVALID;
|
||||
/** @var int */
|
||||
protected $type = AbstractLicense::TYPE_UNKNOWN;
|
||||
/** @var array<string,scalar> License remote data */
|
||||
protected $data = self::DEFAULT_LICENSE_DATA;
|
||||
/** @var string timestamp YYYY-MM-DD HH:MM:SS UTC */
|
||||
protected $lastRemoteUpdate = '';
|
||||
/** @var string timestamp YYYY-MM-DD HH:MM:SS UTC */
|
||||
protected $lastFailureTime = '';
|
||||
|
||||
/**
|
||||
* Last error request
|
||||
*
|
||||
* @var array{code:int, message: string, details: string, requestDetails: string}
|
||||
*/
|
||||
protected $lastRequestError = [
|
||||
'code' => 0,
|
||||
'message' => '',
|
||||
'details' => '',
|
||||
'requestDetails' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* Return entity type identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getType(): string
|
||||
{
|
||||
return 'LicenseDataEntity';
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called, automatically, when Serialize
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = JsonSerialize::serializeToData($this, JsonSerialize::JSON_SKIP_MAGIC_METHODS | JsonSerialize::JSON_SKIP_CLASS_NAME);
|
||||
|
||||
// Encrypt properties using trait
|
||||
$data = $this->encryptSerializedProperties($data);
|
||||
|
||||
unset($data['lastRequestError']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize the entity from serialized data
|
||||
*
|
||||
* @param array<string,mixed> $data Serialized data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
try {
|
||||
// Decrypt properties
|
||||
$data = $this->decryptSerializedProperties($data);
|
||||
|
||||
// Verify that the data is an array
|
||||
if (!isset($data['data']) || !is_array($data['data'])) {
|
||||
throw new Exception('Unserialized license data is not an array');
|
||||
}
|
||||
|
||||
// Assign properties
|
||||
foreach ($data as $pName => $val) {
|
||||
if (!property_exists($this, $pName)) {
|
||||
continue;
|
||||
}
|
||||
$this->$pName = $val;
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
DupLog::trace('ERROR UNSERIALIZE LICENSE DATA: ' . $e->getMessage());
|
||||
// In case of any error during unserialization, reset to default values
|
||||
if (isset($data['licenseKey']) && !self::isValidLicenseFormat($data['licenseKey'])) {
|
||||
// Reset license only if is invalid format.
|
||||
$this->licenseKey = '';
|
||||
} elseif (isset($data['licenseKey'])) {
|
||||
$this->licenseKey = $data['licenseKey'];
|
||||
}
|
||||
// Reset cache and try to reload corrupted dat but don't reset last failure to avoid too many requests
|
||||
$this->clearCache(false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy decryption for old license data format
|
||||
*
|
||||
* @param array<string,mixed> $data Serialized data
|
||||
*
|
||||
* @return array<string,mixed> Data with legacy format decrypted
|
||||
*/
|
||||
protected function legacyDecryptProperties(array $data): array
|
||||
{
|
||||
// Old format detection: data is a string (encrypted JSON)
|
||||
if (isset($data['data']) && is_string($data['data'])) {
|
||||
// Data is encrypted in old format, decrypt all fields
|
||||
$data['licenseKey'] = (string) CryptBlowfish::decryptIfAvaiable((string) ($data['licenseKey'] ?? ''), null, true);
|
||||
$data['status'] = (int) CryptBlowfish::decryptIfAvaiable((string) ($data['status'] ?? 0), null, true);
|
||||
$data['type'] = (int) CryptBlowfish::decryptIfAvaiable((string) ($data['type'] ?? 0), null, true);
|
||||
|
||||
// Decrypt and unserialize the data property
|
||||
$decryptedData = CryptBlowfish::decryptIfAvaiable($data['data'], null, true);
|
||||
if (strlen($decryptedData)) {
|
||||
$data['data'] = JsonSerialize::unserialize($decryptedData);
|
||||
} else {
|
||||
// Decryption failed, set to empty array to avoid errors
|
||||
$data['data'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set license key
|
||||
*
|
||||
* @param string $licenseKey License key, if empty the license key will be removed
|
||||
*
|
||||
* @return bool return true if license key is valid and set
|
||||
*/
|
||||
public function setKey($licenseKey)
|
||||
{
|
||||
if ($this->licenseKey === $licenseKey) {
|
||||
return true;
|
||||
}
|
||||
DupLog::trace("UPDATE LICENSE KEY FROM " . self::maskLicenseKey($this->licenseKey) . " TO " . self::maskLicenseKey($licenseKey));
|
||||
|
||||
if ($this->getStatus() === self::STATUS_VALID) {
|
||||
// Deactivate old license
|
||||
$this->deactivate();
|
||||
}
|
||||
$this->licenseKey = self::isValidLicenseFormat($licenseKey) ? $licenseKey : '';
|
||||
return $this->clearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Chdeck is key is a valid licenze format
|
||||
*
|
||||
* @param string $key License Key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isValidLicenseFormat(string $key)
|
||||
{
|
||||
return preg_match('/^[a-f0-9]{32}$/i', $key) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->licenseKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset license data cache
|
||||
*
|
||||
* @param bool $save if true save the entity
|
||||
* @param bool $resetFailure if true reset last remote failure
|
||||
*
|
||||
* @return bool return true if license data cache is reset
|
||||
*/
|
||||
public function clearCache($save = true, $resetFailure = true): bool
|
||||
{
|
||||
DupLog::trace("LICENSE DATA CLEAR CACHE");
|
||||
$this->data = self::DEFAULT_LICENSE_DATA;
|
||||
$this->status = self::STATUS_INVALID;
|
||||
$this->type = AbstractLicense::TYPE_UNKNOWN;
|
||||
$this->lastRemoteUpdate = '';
|
||||
if ($resetFailure) {
|
||||
$this->lastFailureTime = '';
|
||||
}
|
||||
return ($save ? $this->save() : true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original home URL before filter it, prevent other plugins conflics (Like WPML).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getOriginalHomeURL(): string
|
||||
{
|
||||
$originalUrl = '';
|
||||
if (is_multisite()) {
|
||||
$callback = function ($url, $path, $orig_scheme) use (&$originalUrl) {
|
||||
$originalUrl = $url;
|
||||
return $url;
|
||||
};
|
||||
add_filter('network_home_url', $callback, PHP_INT_MIN, 3);
|
||||
network_home_url();
|
||||
remove_filter('network_home_url', $callback, PHP_INT_MIN);
|
||||
} else {
|
||||
$callback = function ($url, $path, $orig_scheme, $blog_id) use (&$originalUrl) {
|
||||
$originalUrl = $url;
|
||||
return $url;
|
||||
};
|
||||
add_filter('home_url', $callback, PHP_INT_MIN, 4);
|
||||
home_url();
|
||||
remove_filter('home_url', $callback, PHP_INT_MIN);
|
||||
}
|
||||
return $originalUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license data.
|
||||
* This function manage the license data cache.
|
||||
*
|
||||
* @param bool $force if true reset data cache and force a new request
|
||||
*
|
||||
* @return array<string,scalar> License data
|
||||
*/
|
||||
public function getLicenseData($force = false)
|
||||
{
|
||||
$this->data = [
|
||||
'success' => true,
|
||||
'license' => 'valid',
|
||||
'item_id' => 31,
|
||||
'item_name' => '',
|
||||
'checksum' => '',
|
||||
'expires' => 'lifetime',
|
||||
'payment_id' => -1,
|
||||
'customer_name' => '',
|
||||
'customer_email' => '',
|
||||
'license_limit' => 100,
|
||||
'site_count' => 1,
|
||||
'activations_left' => 99,
|
||||
'price_id' => AbstractLicense::TYPE_ELITE,
|
||||
'activeSubscription' => false,
|
||||
];
|
||||
|
||||
$this->status = self::STATUS_VALID;
|
||||
$this->type = AbstractLicense::TYPE_ELITE;
|
||||
$this->save();
|
||||
|
||||
return $this->data;
|
||||
|
||||
if ($this->licenseKey === '') {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
if ($force) {
|
||||
DupLog::trace("Force license data update resetting license data cache");
|
||||
$this->clearCache(false);
|
||||
}
|
||||
|
||||
$currentTime = (int) strtotime(gmdate("Y-m-d H:i:s"));
|
||||
|
||||
$lastFailureTime = (int) ($this->lastFailureTime === '' ? 0 : strtotime($this->lastFailureTime));
|
||||
if (($currentTime - $lastFailureTime) < self::LICENSE_FAILURE_DELAY_TIME) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$updatedTime = (int) ($this->lastRemoteUpdate === '' ? 0 : strtotime($this->lastRemoteUpdate));
|
||||
if ($this->data['license'] == 'valid') {
|
||||
if ($this->data['expires'] === 'lifetime') {
|
||||
$expireTime = PHP_INT_MAX;
|
||||
} elseif (empty($this->data['expires'])) {
|
||||
$expireTime = 0;
|
||||
} else {
|
||||
$expireTime = (int) strtotime($this->data['expires']);
|
||||
}
|
||||
// Recheck expired if the license is expired with more than 1 day to avoid unnecessary requests
|
||||
$recheckExpired = ($expireTime < ($currentTime - DAY_IN_SECONDS));
|
||||
} else {
|
||||
$recheckExpired = false;
|
||||
}
|
||||
|
||||
if (
|
||||
($currentTime - $updatedTime) > self::LICENSE_CACHE_TIME ||
|
||||
$recheckExpired
|
||||
) {
|
||||
try {
|
||||
$licenseEddStatus = $this->data['license'];
|
||||
$api_params = [
|
||||
'edd_action' => 'check_license',
|
||||
'license' => $this->licenseKey,
|
||||
'item_name' => urlencode(License::EDD_DUP_ITEM_NAME),
|
||||
'url' => self::getOriginalHomeURL(),
|
||||
];
|
||||
$api_params = apply_filters('duplicator_license_request_params', $api_params);
|
||||
$requestObj = $api_params;
|
||||
|
||||
$requestObj['license'] = self::maskLicenseKey($this->licenseKey);
|
||||
|
||||
if (($remoteData = $this->request($api_params, true)) === false) {
|
||||
DupLog::trace("LICENSE DATA GET: request error for " . self::maskLicenseKey($this->licenseKey) . " so leaving status alone");
|
||||
DupLog::traceObject("Request Data", $requestObj);
|
||||
$this->lastFailureTime = gmdate("Y-m-d H:i:s");
|
||||
} elseif (count(array_diff(self::VALID_RESPONSE_REQUIRED_KEYS, array_keys(get_object_vars($remoteData)))) > 0) {
|
||||
// If the response is not valid, do not update the license data
|
||||
DupLog::trace("LICENSE DATA GET: invalid response for " . self::maskLicenseKey($this->licenseKey) . " so leaving status alone");
|
||||
DupLog::traceObject("Request Data", $requestObj);
|
||||
DupLog::traceObject("Response Data", $remoteData);
|
||||
$this->lastFailureTime = gmdate("Y-m-d H:i:s");
|
||||
} else {
|
||||
// Update license data only if the request is successful
|
||||
if ($licenseEddStatus !== $remoteData->license) {
|
||||
DupLog::trace(
|
||||
"LICENSE DATA GET: License " .
|
||||
self::maskLicenseKey($this->licenseKey) .
|
||||
" status changed from $licenseEddStatus to $remoteData->license"
|
||||
);
|
||||
DupLog::traceObject("Request Data", $requestObj);
|
||||
DupLog::traceObject("Response Data", $remoteData);
|
||||
}
|
||||
$this->clearCache(false);
|
||||
foreach (self::DEFAULT_LICENSE_DATA as $key => $value) {
|
||||
if (isset($remoteData->{$key})) {
|
||||
$this->data[$key] = $remoteData->{$key};
|
||||
}
|
||||
}
|
||||
$this->status = self::getStatusFromEDDStatus($remoteData->license);
|
||||
$this->type = (int) (property_exists($remoteData, 'price_id') ? $remoteData->price_id : AbstractLicense::TYPE_UNLICENSED);
|
||||
$this->lastRemoteUpdate = gmdate("Y-m-d H:i:s");
|
||||
|
||||
DupLog::trace("NEW LICENSE DATA UPDATED STATUS: " . self::getStatusLabel($this->status));
|
||||
do_action('duplicator_license_check_remote_data_success', $this, $remoteData);
|
||||
}
|
||||
} finally {
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate license key
|
||||
*
|
||||
* @return int license status
|
||||
*/
|
||||
public function activate(): int
|
||||
{
|
||||
if (strlen($this->licenseKey) == 0) {
|
||||
return self::ACTIVATION_REQUEST_ERROR;
|
||||
}
|
||||
|
||||
$api_params = [
|
||||
'edd_action' => 'activate_license',
|
||||
'license' => $this->licenseKey,
|
||||
'item_name' => urlencode(License::EDD_DUP_ITEM_NAME), // the name of our product in EDD,
|
||||
'url' => self::getOriginalHomeURL(),
|
||||
];
|
||||
|
||||
$this->clearCache();
|
||||
if (($responseData = $this->request($api_params, true)) === false) {
|
||||
return self::ACTIVATION_REQUEST_ERROR;
|
||||
}
|
||||
|
||||
if ($responseData->license !== 'valid') {
|
||||
DupLog::traceObject("Problem activating license " . self::maskLicenseKey($this->licenseKey), $responseData);
|
||||
return self::ACTIVATION_RESPONSE_INVALID;
|
||||
}
|
||||
$this->getLicenseData(true);
|
||||
|
||||
DupLog::trace("License Activated " . self::maskLicenseKey($this->licenseKey));
|
||||
return self::ACTIVATION_RESPONSE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license status
|
||||
*
|
||||
* @return int ENUM self::STATUS_*
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
$this->getLicenseData();
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license type
|
||||
*
|
||||
* @return int ENUM AbstractLicense::TYPE_*
|
||||
*/
|
||||
public function getLicenseType()
|
||||
{
|
||||
$this->getLicenseData();
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license websites limit
|
||||
*
|
||||
* @return int<0, max>
|
||||
*/
|
||||
public function getLicenseLimit(): int
|
||||
{
|
||||
$this->getLicenseData();
|
||||
return (int) max(0, (int) $this->data['license_limit']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get site count
|
||||
*
|
||||
* @return int<-1, max>
|
||||
*/
|
||||
public function getSiteCount(): int
|
||||
{
|
||||
$this->getLicenseData();
|
||||
return (int) max(-1, (int) $this->data['site_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate license key
|
||||
*
|
||||
* @param string $url URL to deactivate for. If empty, uses current site URL and refreshes local license data.
|
||||
*
|
||||
* @return int license status
|
||||
*/
|
||||
public function deactivate(string $url = ''): int
|
||||
{
|
||||
if (strlen($this->licenseKey) == 0) {
|
||||
return self::ACTIVATION_RESPONSE_OK;
|
||||
}
|
||||
|
||||
$isRemoteDeactivation = !empty($url);
|
||||
if (empty($url)) {
|
||||
$url = self::getOriginalHomeURL();
|
||||
}
|
||||
|
||||
DupLog::trace("DEACTIVATE LICENSE: " . self::maskLicenseKey($this->licenseKey) . " for URL: " . $url);
|
||||
|
||||
$api_params = [
|
||||
'edd_action' => 'deactivate_license',
|
||||
'license' => $this->licenseKey,
|
||||
'item_name' => urlencode(License::EDD_DUP_ITEM_NAME), // the name of our product in EDD,
|
||||
'url' => $url,
|
||||
];
|
||||
|
||||
if (!$isRemoteDeactivation) {
|
||||
$this->clearCache();
|
||||
}
|
||||
if (($responseData = $this->request($api_params, true)) === false) {
|
||||
return self::ACTIVATION_REQUEST_ERROR;
|
||||
}
|
||||
|
||||
if ($responseData->license !== 'deactivated') {
|
||||
DupLog::traceObject("Problems deactivating license " . $this->licenseKey, $responseData);
|
||||
return self::ACTIVATION_RESPONSE_INVALID;
|
||||
}
|
||||
if (!$isRemoteDeactivation) {
|
||||
$this->getLicenseData(true);
|
||||
}
|
||||
|
||||
DupLog::trace("Deactivated license " . $this->licenseKey);
|
||||
return self::ACTIVATION_RESPONSE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expiration date format
|
||||
*
|
||||
* @param string $format date format
|
||||
*
|
||||
* @return string return expirtation date formatted, Unknown if license data is not available or Lifetime if license is lifetime
|
||||
*/
|
||||
public function getExpirationDate($format = 'Y-m-d')
|
||||
{
|
||||
$this->getLicenseData();
|
||||
if ($this->data['expires'] === 'lifetime') {
|
||||
return 'Lifetime';
|
||||
}
|
||||
if (empty($this->data['expires'])) {
|
||||
return 'Unknown';
|
||||
}
|
||||
$expirationDate = new DateTime($this->data['expires']);
|
||||
return date_i18n($format, $expirationDate->getTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return expiration license days, if is expired a negative number is returned
|
||||
*
|
||||
* @return false|int reutrn false on fail or number of days to expire, PHP_INT_MAX is filetime
|
||||
*/
|
||||
public function getExpirationDays()
|
||||
{
|
||||
$this->getLicenseData();
|
||||
if ($this->data['expires'] === 'lifetime') {
|
||||
return PHP_INT_MAX;
|
||||
}
|
||||
if (empty($this->data['expires'])) {
|
||||
return false;
|
||||
}
|
||||
$expirationDate = new DateTime($this->data['expires']);
|
||||
return (-1 * intval($expirationDate->diff(new DateTime())->format('%r%a')));
|
||||
}
|
||||
|
||||
/**
|
||||
* check is have no activations left
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function haveNoActivationsLeft(): bool
|
||||
{
|
||||
return ($this->getStatus() === self::STATUS_SITE_INACTIVE && $this->data['activations_left'] === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if have active subscription
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function haveActiveSubscription()
|
||||
{
|
||||
$this->getLicenseData();
|
||||
return $this->data['activeSubscription'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset last request failure delay time.
|
||||
* Important: Do not use this function indiscriminately if you are not sure what you are doing.
|
||||
* Using this function incorrectly overrides the logic that prevents too many requests to the server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resetLastRequestFailure(): void
|
||||
{
|
||||
// Reset request failure
|
||||
ExpireOptions::delete(self::LICENSE_FAILURE_OPT_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a license rquest
|
||||
*
|
||||
* @param mixed[] $params request params
|
||||
* @param bool $nocache if true add a dynamic parameter to avoid remote cache
|
||||
*
|
||||
* @return false|object
|
||||
*/
|
||||
public function request($params, $nocache = false)
|
||||
{
|
||||
DupLog::trace('LICENSE REMOTE REQUEST FUNCTION CMD: ' . $params['edd_action']);
|
||||
|
||||
if (!is_array($params)) {
|
||||
$params = [];
|
||||
}
|
||||
if ($nocache) {
|
||||
$params['cachetime'] = microtime(true); // To avoid remote cache
|
||||
}
|
||||
$requestParams = [
|
||||
'timeout' => 60,
|
||||
'sslverify' => false,
|
||||
'user-agent' => 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url'),
|
||||
'body' => $params,
|
||||
];
|
||||
|
||||
$requestDetails = JsonSerialize::serialize([
|
||||
'url' => DUPLICATOR_STORE_URL,
|
||||
'curlEnabled' => SnapUtil::isCurlEnabled(),
|
||||
'params' => $requestParams,
|
||||
], JSON_PRETTY_PRINT);
|
||||
|
||||
$this->lastRequestError['code'] = 0;
|
||||
$this->lastRequestError['message'] = '';
|
||||
$this->lastRequestError['details'] = '';
|
||||
$this->lastRequestError['requestDetails'] = '';
|
||||
|
||||
try {
|
||||
if (ExpireOptions::get(self::LICENSE_FAILURE_OPT_KEY, false)) {
|
||||
$endTime = human_time_diff(time(), ExpireOptions::getExpireTime(self::LICENSE_FAILURE_OPT_KEY));
|
||||
// Wait before try again
|
||||
$this->lastRequestError['code'] = 1;
|
||||
$this->lastRequestError['message'] = sprintf(__('License request failed recently. Wait %s and try again.', 'duplicator-pro'), $endTime);
|
||||
$this->lastRequestError['details'] = '';
|
||||
$this->lastRequestError['requestDetails'] = '';
|
||||
throw new Exception($this->lastRequestError['message'], self::FAILURE_SKIP_EXCEPTION_CODE);
|
||||
} else {
|
||||
DupLog::trace('LICENSE REMOTE GET CMD: ' . $params['edd_action']);
|
||||
$response = wp_remote_get(DUPLICATOR_STORE_URL, $requestParams);
|
||||
}
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
/** @var WP_Error $response */
|
||||
$this->lastRequestError['code'] = $response->get_error_code();
|
||||
$this->lastRequestError['message'] = $response->get_error_message();
|
||||
$this->lastRequestError['details'] = JsonSerialize::serialize($response->get_error_data(), JSON_PRETTY_PRINT);
|
||||
$this->lastRequestError['requestDetails'] = $requestDetails;
|
||||
throw new Exception($this->lastRequestError['message']);
|
||||
} elseif ($response['response']['code'] < 200 || $response['response']['code'] >= 300) {
|
||||
$this->lastRequestError['code'] = $response['response']['code'];
|
||||
$this->lastRequestError['message'] = $response['response']['message'];
|
||||
$this->lastRequestError['details'] = JsonSerialize::serialize($response, JSON_PRETTY_PRINT);
|
||||
$this->lastRequestError['requestDetails'] = $requestDetails;
|
||||
throw new Exception($this->lastRequestError['message']);
|
||||
}
|
||||
|
||||
$data = json_decode(wp_remote_retrieve_body($response));
|
||||
if (!is_object($data) || !property_exists($data, 'license')) {
|
||||
$this->lastRequestError['code'] = -1;
|
||||
$this->lastRequestError['message'] = __('Invalid license data.', 'duplicator-pro');
|
||||
$this->lastRequestError['details'] = 'Response: ' . wp_remote_retrieve_body($response);
|
||||
$this->lastRequestError['requestDetails'] = $requestDetails;
|
||||
throw new Exception($this->lastRequestError['message']);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
if ($e->getCode() !== self::FAILURE_SKIP_EXCEPTION_CODE) {
|
||||
ExpireOptions::set(self::LICENSE_FAILURE_OPT_KEY, true, self::LICENSE_FAILURE_DELAY_TIME);
|
||||
}
|
||||
DupLog::trace('LICENSE REQUEST FAILED: ' . $e->getMessage());
|
||||
DupLog::traceObject('** REQUEST DETAILS', $this->lastRequestError);
|
||||
return false;
|
||||
} catch (Error $e) {
|
||||
ExpireOptions::set(self::LICENSE_FAILURE_OPT_KEY, true, self::LICENSE_FAILURE_DELAY_TIME);
|
||||
DupLog::trace('LICENSE REQUEST FAILED: ' . $e->getMessage());
|
||||
DupLog::traceObject('** REQUEST DETAILS', $this->lastRequestError);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last error request
|
||||
*
|
||||
* @return array{code:int, message: string, details: string}
|
||||
*/
|
||||
public function getLastRequestError()
|
||||
{
|
||||
return $this->lastRequestError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license status from status by string
|
||||
*
|
||||
* @param string $eddStatus license status string
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function getStatusFromEDDStatus($eddStatus): int
|
||||
{
|
||||
switch ($eddStatus) {
|
||||
case 'valid':
|
||||
return self::STATUS_VALID;
|
||||
case 'invalid':
|
||||
return self::STATUS_INVALID;
|
||||
case 'expired':
|
||||
return self::STATUS_EXPIRED;
|
||||
case 'disabled':
|
||||
return self::STATUS_DISABLED;
|
||||
case 'site_inactive':
|
||||
return self::STATUS_SITE_INACTIVE;
|
||||
case 'inactive':
|
||||
return self::STATUS_INACTIVE;
|
||||
default:
|
||||
return self::STATUS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return license statu string by status
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLicenseStatusString()
|
||||
{
|
||||
switch ($this->getStatus()) {
|
||||
case self::STATUS_VALID:
|
||||
return __('Valid', 'duplicator-pro');
|
||||
case self::STATUS_INVALID:
|
||||
return __('Invalid', 'duplicator-pro');
|
||||
case self::STATUS_EXPIRED:
|
||||
return __('Expired', 'duplicator-pro');
|
||||
case self::STATUS_DISABLED:
|
||||
return __('Disabled', 'duplicator-pro');
|
||||
case self::STATUS_SITE_INACTIVE:
|
||||
return __('Site Inactive', 'duplicator-pro');
|
||||
case self::STATUS_EXPIRED:
|
||||
return __('Expired', 'duplicator-pro');
|
||||
default:
|
||||
return __('Unknown', 'duplicator-pro');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status label
|
||||
*
|
||||
* @param int $status status ENUM self::STATUS_*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getStatusLabel(int $status): string
|
||||
{
|
||||
switch ($status) {
|
||||
case self::STATUS_VALID:
|
||||
return __('Valid', 'duplicator-pro');
|
||||
case self::STATUS_INVALID:
|
||||
return __('Invalid', 'duplicator-pro');
|
||||
case self::STATUS_EXPIRED:
|
||||
return __('Expired', 'duplicator-pro');
|
||||
case self::STATUS_DISABLED:
|
||||
return __('Disabled', 'duplicator-pro');
|
||||
case self::STATUS_SITE_INACTIVE:
|
||||
return __('Site Inactive', 'duplicator-pro');
|
||||
case self::STATUS_INACTIVE:
|
||||
return __('Inactive', 'duplicator-pro');
|
||||
default:
|
||||
return __('Unknown', 'duplicator-pro');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask license key for security (show first 5 chars + ***)
|
||||
*
|
||||
* @param string $licenseKey License key to mask
|
||||
*
|
||||
* @return string Masked license key (e.g., ABCDE***)
|
||||
*/
|
||||
public static function maskLicenseKey(string $licenseKey): string
|
||||
{
|
||||
if (empty($licenseKey)) {
|
||||
return 'No License Key';
|
||||
}
|
||||
|
||||
return substr($licenseKey, 0, 5) . '***';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
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
|
||||
*/
|
||||
|
||||
$visibility = DynamicGlobalEntity::getInstance()->getValInt('license_key_visible', License::VISIBILITY_ALL);
|
||||
|
||||
?>
|
||||
<h3 class="title">
|
||||
<?php esc_html_e('License', 'duplicator-pro') ?>
|
||||
</h3>
|
||||
<hr size="1">
|
||||
<p>
|
||||
<?php esc_html_e('Your license key provides access to updates and addons.', 'duplicator-pro') ?>
|
||||
</p>
|
||||
|
||||
<label class="lbl-larger">
|
||||
<?php esc_html_e("License Key", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<div class="margin-bottom-1">
|
||||
<?php $tplMng->render('licensing/license_key_actions'); ?>
|
||||
<?php if ($visibility !== License::VISIBILITY_NONE) { ?>
|
||||
<div id="dup-tr-license-type" >
|
||||
<?php $tplMng->render('licensing/license_info'); ?>
|
||||
<?php $tplMng->render('licensing/activation_issue_message'); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\License\LicenseNotices;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
|
||||
defined("ABSPATH") or die("");
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
|
||||
* @var Duplicator\Core\Views\TplMng $tplMng
|
||||
* @var array<string, mixed> $tplData
|
||||
*/
|
||||
|
||||
switch (LicenseData::getInstance()->getStatus()) {
|
||||
case LicenseData::STATUS_VALID:
|
||||
case LicenseData::STATUS_INACTIVE:
|
||||
case LicenseData::STATUS_SITE_INACTIVE:
|
||||
case LicenseData::STATUS_EXPIRED:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
esc_html_e('If license activation fails please wait ~ one hour and retry.', 'duplicator-pro');
|
||||
?>
|
||||
<div class="dup-license-status-notes ">
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x(
|
||||
'- Failure to activate after several attempts please review %1$sfaq activation steps%2$s.',
|
||||
'1 and 2 represent opening and closing anchor tags (<a> and </a>)',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a target="_blank" href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-resolve-license-activation-issues/') . '">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x(
|
||||
'- To upgrade or renew your license visit %1$sduplicator.com%2$s.',
|
||||
'1 and 2 represent opening and closing anchor tags (<a> and </a>)',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a target="_blank" href="' . esc_url(DUPLICATOR_BLOG_URL) . '">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
<br/>
|
||||
<?php esc_html_e('- A valid key is needed for plugin updates but not for functionality.', 'duplicator-pro'); ?>
|
||||
</div>
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\LicensingController;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
use Duplicator\Core\Controllers\PageAction;
|
||||
|
||||
defined("ABSPATH") or die("");
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
|
||||
* @var Duplicator\Core\Views\TplMng $tplMng
|
||||
* @var array<string, mixed> $tplData
|
||||
* @var Duplicator\Core\Controllers\PageAction $refreshAction
|
||||
*/
|
||||
$refreshAction = $tplData['actions'][LicensingController::ACTION_FORCE_REFRESH];
|
||||
?>
|
||||
<p>
|
||||
<i>
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x(
|
||||
'If your license has been updated or is incorrect, then please %1$sForce a Refresh%2$s.',
|
||||
'1: <a> tag, 2: </a> tag',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a href="' . esc_url($refreshAction->getUrl()) . '">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
</i>
|
||||
</p>
|
||||
<div id="dup-license-info">
|
||||
<?php
|
||||
switch (LicenseData::getInstance()->getStatus()) {
|
||||
case LicenseData::STATUS_VALID:
|
||||
$statusClass = "";
|
||||
$statusText = '<b>' . License::getLicenseToString() . '</b> ' . __('License expires on', 'duplicator-pro') . ' ';
|
||||
$statusText .= '<b>' . LicenseData::getInstance()->getExpirationDate(get_option('date_format')) . '</b> ';
|
||||
|
||||
$expDays = LicenseData::getInstance()->getExpirationDays();
|
||||
$statusText .= ' (';
|
||||
if ($expDays === false) {
|
||||
$statusText .= __('no data', 'duplicator-pro');
|
||||
} elseif ($expDays <= 0) {
|
||||
$statusText .= __('expired', 'duplicator-pro');
|
||||
} elseif ($expDays == PHP_INT_MAX) {
|
||||
$statusText .= __('no expiration', 'duplicator-pro');
|
||||
} else {
|
||||
$statusText .= sprintf(__('%d days left', 'duplicator-pro'), $expDays);
|
||||
}
|
||||
$statusText .= ')';
|
||||
break;
|
||||
case LicenseData::STATUS_INACTIVE:
|
||||
$statusClass = "alert-color";
|
||||
$statusText = __('License Inactive', 'duplicator-pro');
|
||||
break;
|
||||
case LicenseData::STATUS_SITE_INACTIVE:
|
||||
$statusClass = "alert-color";
|
||||
if (LicenseData::getInstance()->haveNoActivationsLeft()) {
|
||||
$statusText = __('License Inactive (out of site licenses).', 'duplicator-pro') . '<br>' . License::getNoActivationLeftMessage();
|
||||
} else {
|
||||
$statusText = __('License Inactive', 'duplicator-pro');
|
||||
}
|
||||
break;
|
||||
case LicenseData::STATUS_EXPIRED:
|
||||
$statusClass = "alert-color";
|
||||
$statusText = sprintf(
|
||||
_x(
|
||||
'Your Duplicator Pro license key has expired so you aren\'t getting important updates! %1$sRenew your license now%2$s',
|
||||
'1: <a> tag, 2: </a> tag',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a target="_blank" href="' . esc_url(License::getLicenseCheckoutURL()) . '">',
|
||||
'</a>'
|
||||
);
|
||||
break;
|
||||
case LicenseData::STATUS_INVALID:
|
||||
case LicenseData::STATUS_UNKNOWN:
|
||||
default:
|
||||
// https://duplicator.com/knowledge-base/how-to-resolve-license-activation-issues/
|
||||
$statusClass = "alert-color";
|
||||
$statusText = sprintf(
|
||||
_x(
|
||||
'License %1$s',
|
||||
'1: License status (Invalid, Unknown)',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'</b>' . LicenseData::getStatusLabel(LicenseData::getInstance()->getStatus()) . '<br/>'
|
||||
);
|
||||
break;
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo esc_attr($statusClass); ?>">
|
||||
<?php
|
||||
echo wp_kses(
|
||||
$statusText,
|
||||
[
|
||||
'a' => [
|
||||
'href' => [],
|
||||
'target' => [],
|
||||
],
|
||||
'b' => [],
|
||||
'br' => [],
|
||||
]
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<ul class="dup-license-type-info no-bullet">
|
||||
<li>
|
||||
<?php
|
||||
$checkedClass = (LicenseData::getInstance()->getStatus() == LicenseData::STATUS_VALID ? 'far fa-check-circle' : 'far fa-circle');
|
||||
$sitesLimit = (License::isUnlimited() ? __('Unlimited', 'duplicator-pro') : LicenseData::getInstance()->getLicenseLimit());
|
||||
$sitesCount = (LicenseData::getInstance()->getSiteCount() < 0 ? '?' : LicenseData::getInstance()->getSiteCount());
|
||||
?>
|
||||
<i class="<?php echo esc_attr($checkedClass); ?>"></i>
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x(
|
||||
'Site Licenses: %1$s of %2$s',
|
||||
'1 = (string) Site Licenses, 2 = (number) Active sites, 3 = (number) License limit',
|
||||
'duplicator-pro'
|
||||
),
|
||||
esc_html($sitesCount),
|
||||
esc_html($sitesLimit)
|
||||
);
|
||||
$tipContent = __(
|
||||
'Indicates the number of sites the plugin can be active on at any one time.
|
||||
At any point you may deactivate/uninstall the plugin to free up the license and use the plugin elsewhere if needed.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
?>
|
||||
<i
|
||||
class='fa-solid fa-question-circle fa-sm dark-gray-color'
|
||||
data-tooltip-title='<?php esc_attr_e('Site Licenses', 'duplicator-pro') ?>'
|
||||
data-tooltip='<?php echo esc_attr($tipContent) ?>'>
|
||||
</i>
|
||||
</li>
|
||||
<li>
|
||||
<?php
|
||||
$checkedClass = License::can(License::CAPABILITY_POWER_TOOLS) ? 'far fa-check-circle' : 'far fa-circle';
|
||||
$tipContent = __(
|
||||
'Enhanced features that greatly improve the productivity of serious users. Include hourly schedules,
|
||||
installer branding, salt & key replacement, priority support and more.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
?>
|
||||
<i class="<?php echo esc_attr($checkedClass); ?>"></i>
|
||||
<?php esc_html_e('Powertools', 'duplicator-pro') ?>
|
||||
<i
|
||||
class='fa-solid fa-question-circle fa-sm dark-gray-color'
|
||||
data-tooltip-title='<?php echo esc_attr_e('Powertools', 'duplicator-pro') ?>'
|
||||
data-tooltip='<?php echo esc_attr($tipContent) ?>'>
|
||||
</i>
|
||||
</li>
|
||||
<li>
|
||||
<?php
|
||||
$checkedClass = License::can(License::CAPABILITY_MULTISITE_PLUS) ? 'far fa-check-circle' : 'far fa-circle';
|
||||
$tipContent = __(
|
||||
'Adds the ability to install a subsite as a standalone site,
|
||||
insert a standalone site into a multisite, or insert a subsite from the same/different multisite into a multisite.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
?>
|
||||
<i class="<?php echo esc_attr($checkedClass) ?>"></i>
|
||||
<?php esc_html_e('Multisite Plus+', 'duplicator-pro') ?>
|
||||
<i
|
||||
class='fa-solid fa-question-circle fa-sm dark-gray-color'
|
||||
data-tooltip-title='<?php echo esc_attr_e('Multisite Plus+', 'duplicator-pro') ?>'
|
||||
data-tooltip='<?php echo esc_attr($tipContent) ?>'>
|
||||
</i>
|
||||
</li>
|
||||
<?php if (License::canBeUpgraded()) { ?>
|
||||
<li>
|
||||
<div class="margin-top-1">
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x(
|
||||
'🔥 To unlock more features see our %1$sUpgrade Offers%2$s.',
|
||||
'1: <a> tag, 2: </a> tag',
|
||||
'duplicator-pro'
|
||||
),
|
||||
'<a class="dup-upgrade-license-link primary-color" href="' . esc_url(License::getUpsellURL()) . '" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\Models\LicenseData;
|
||||
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
|
||||
*/
|
||||
|
||||
$dGlobal = DynamicGlobalEntity::getInstance();
|
||||
$licenseVisibility = $dGlobal->getValInt('license_key_visible', License::VISIBILITY_ALL);
|
||||
|
||||
if ($licenseVisibility === License::VISIBILITY_ALL) {
|
||||
?>
|
||||
<div id="dup-tr-license-key-and-description" class="inline-display">
|
||||
<input
|
||||
type="text"
|
||||
class="dup-license-key-input width-large inline-display margin-0"
|
||||
name="_license_key"
|
||||
id="_license_key"
|
||||
value="<?php echo esc_attr(License::getLicenseKey()); ?>">
|
||||
<span class="dup-license-check-icon">
|
||||
<?php if (LicenseData::getInstance()->getStatus() === LicenseData::STATUS_VALID) { ?>
|
||||
<i class="fa-solid fa-circle-check fa-lg success-color"></i>
|
||||
<?php } else { ?>
|
||||
<i class="fa-solid fa-circle-xmark fa-lg alert-color"></i>
|
||||
<?php } ?>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="dup-license-key-btns inline-display">
|
||||
<?php
|
||||
if (LicenseData::getInstance()->getStatus() === LicenseData::STATUS_VALID) {
|
||||
$echostring = 'false';
|
||||
$buttonText = __('Deactivate', 'duplicator-pro');
|
||||
} else {
|
||||
$echostring = 'true';
|
||||
$buttonText = __('Activate', 'duplicator-pro');
|
||||
}
|
||||
?>
|
||||
<button
|
||||
id="dup-license-activation-btn"
|
||||
class="button secondary hollow small margin-0"
|
||||
onclick="DupliJs.Licensing.ChangeActivationStatus(<?php echo esc_js($echostring); ?>);return false;">
|
||||
<?php echo esc_html($buttonText); ?>
|
||||
</button>
|
||||
|
||||
<button
|
||||
id="dup-license-clear-btn"
|
||||
class="button secondary hollow small margin-0"
|
||||
onclick="DupliJs.Licensing.ClearActivationStatus();return false;">
|
||||
<?php esc_html_e('Clear Key', 'duplicator-pro') ?>
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\LicensingController;
|
||||
|
||||
defined("ABSPATH") or die("");
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
|
||||
* @var Duplicator\Core\Views\TplMng $tplMng
|
||||
* @var array<string, mixed> $tplData
|
||||
*/
|
||||
|
||||
?>
|
||||
<div class="dup-settings-wrapper" >
|
||||
<?php $tplMng->render('licensing/activation'); ?>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function($) {
|
||||
DupliJs.Licensing = new Object();
|
||||
DupliJs.Licensing.VISIBILITY_ALL = <?php echo (int) License::VISIBILITY_ALL;?>;
|
||||
DupliJs.Licensing.VISIBILITY_INFO = <?php echo (int) License::VISIBILITY_INFO;?>;
|
||||
DupliJs.Licensing.VISIBILITY_NONE = <?php echo (int) License::VISIBILITY_NONE;?>;
|
||||
|
||||
$("#_key_password, #_key_password_confirmation").keyup(function(event) {
|
||||
|
||||
if (event.keyCode == 13) {
|
||||
$("#show_hide").click();
|
||||
}
|
||||
});
|
||||
|
||||
DupliJs.Licensing.ChangeActivationStatus = function(activate) {
|
||||
if (activate) {
|
||||
let licenseKey = $('.dup-license-key-input').val();
|
||||
window.location.href =
|
||||
<?php echo json_encode($tplData['actions'][LicensingController::ACTION_ACTIVATE_LICENSE]->getUrl()); ?> +
|
||||
'&_license_key=' + encodeURIComponent(licenseKey);
|
||||
} else {
|
||||
window.location.href = <?php echo json_encode($tplData['actions'][LicensingController::ACTION_DEACTIVATE_LICENSE]->getUrl()); ?>;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DupliJs.Licensing.ClearActivationStatus = function() {
|
||||
window.location.href = <?php echo json_encode($tplData['actions'][LicensingController::ACTION_CLEAR_KEY]->getUrl()); ?>;
|
||||
}
|
||||
|
||||
DupliJs.Licensing.ChangeKeyVisibility = function(show) {
|
||||
$('#dup-license-visibility-form').submit();
|
||||
}
|
||||
|
||||
DupliJs.Licensing.VisibilityTemporary = function(visibility) {
|
||||
switch (visibility) {
|
||||
case DupliJs.Licensing.VISIBILITY_ALL:
|
||||
$("#dup-tr-license-dashboard").show();
|
||||
$("#dup-tr-license-type").show();
|
||||
$("#dup-tr-license-key-and-description").show();
|
||||
break;
|
||||
case DupliJs.Licensing.VISIBILITY_INFO:
|
||||
$("#dup-tr-license-dashboard").show();
|
||||
$("#dup-tr-license-type").show();
|
||||
$("#dup-tr-license-key-and-description").hide();
|
||||
break;
|
||||
case DupliJs.Licensing.VISIBILITY_NONE:
|
||||
$("#dup-tr-license-dashboard").hide();
|
||||
$("#dup-tr-license-type").hide();
|
||||
$("#dup-tr-license-key-and-description").hide();
|
||||
break;
|
||||
default:
|
||||
alert("Unexpected visibility value!");
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Libs\Snap\SnapUtil;
|
||||
|
||||
defined("ABSPATH") or die("");
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
|
||||
* @var Duplicator\Core\Views\TplMng $tplMng
|
||||
* @var array<string, mixed> $tplData
|
||||
*/
|
||||
|
||||
if (empty($tplData['license_message'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$details = "";
|
||||
if (isset($tplData['license_request_error'])) {
|
||||
$details = 'Message: ' . $tplData['license_request_error']['message'] . "\n" .
|
||||
'Error code: ' . $tplData['license_request_error']['code'];
|
||||
if (strlen($tplData['license_request_error']['requestDetails'])) {
|
||||
$details .= "\n\n" . 'Request Details' . "\n" . $tplData['license_request_error']['requestDetails'];
|
||||
}
|
||||
if (strlen($tplData['license_request_error']['details'])) {
|
||||
$details .= "\n" . 'Response Details' . "\n" . $tplData['license_request_error']['details'];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<p>
|
||||
<?php if (!$tplData['license_success']) { ?>
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
<?php
|
||||
}
|
||||
echo wp_kses(
|
||||
$tplData['license_message'],
|
||||
[
|
||||
'a' => [
|
||||
'href' => [],
|
||||
'target' => [],
|
||||
],
|
||||
'span' => [
|
||||
'class' => [],
|
||||
],
|
||||
'br' => [],
|
||||
'b' => [
|
||||
'class' => [],
|
||||
],
|
||||
]
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php if (isset($tplData['license_request_error'])) { ?>
|
||||
<p>
|
||||
<?php echo esc_html__('Error:', 'duplicator-pro') ?> <b><?php echo esc_html($tplData['license_request_error']['message']); ?></b>
|
||||
</p>
|
||||
<b>Details:</b>
|
||||
<textarea class="dup-error-message-textarea" disabled ><?php echo esc_textarea($details); ?></textarea>
|
||||
<button
|
||||
data-dup-copy-value="<?php echo esc_attr($details); ?>"
|
||||
data-dup-copy-title="<?php echo esc_attr("Copy Error Message to clipboard"); ?>"
|
||||
data-dup-copied-title="<?php echo esc_attr("Error Message copied to clipboard"); ?>"
|
||||
class="button dup-btn-copy-error-message">
|
||||
<?php esc_html_e('Copy error details', 'duplicator-pro'); ?>
|
||||
</button>
|
||||
<?php if (!SnapUtil::isCurlEnabled()) {
|
||||
$tplMng->render('licensing/notices/curl_message');
|
||||
} ?>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses(
|
||||
__("If the error persists please open a ticket <a href=\"%s\">here</a> and attach the errors details.", 'duplicator-pro'),
|
||||
[
|
||||
'a' => [
|
||||
'href' => [],
|
||||
],
|
||||
]
|
||||
),
|
||||
esc_url(DUPLICATOR_BLOG_URL . 'my-account/support/')
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php } ?>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
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
|
||||
echo wp_kses(
|
||||
__(
|
||||
'<b>CURL isn\'t enabled.</b> This module is far more reliable for remote communication.',
|
||||
'duplicator-pro'
|
||||
),
|
||||
ViewHelper::GEN_KSES_TAGS
|
||||
);
|
||||
?>
|
||||
</br>
|
||||
<?php esc_html_e('A possible solution to the problem could be to activate it.', 'duplicator-pro'); ?>
|
||||
</br>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses(
|
||||
_x(
|
||||
'For detailed steps on how to enable cURL please see <b>Solution 3, Issue A</b> in %1$sthis FAQ Entry%2$s.',
|
||||
'%1$s and %2$s represents the opening and closing HTML tags for an anchor or link',
|
||||
'duplicator-pro'
|
||||
),
|
||||
ViewHelper::GEN_KSES_TAGS
|
||||
),
|
||||
'<a href="' . esc_url(DUPLICATOR_DUPLICATOR_DOCS_URL . 'how-to-resolve-license-activation-issues/') . '" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
<br/>
|
||||
</p>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
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
|
||||
*/
|
||||
|
||||
$upgradeUrl = License::getUpsellURL();
|
||||
?>
|
||||
<span class='dashicons dashicons-warning'></span>
|
||||
<div class="dup-sub-content">
|
||||
<h3>
|
||||
<?php esc_html_e('Your license does not support multisite functionality', 'duplicator-pro'); ?>
|
||||
</h3>
|
||||
<p>
|
||||
<?php echo esc_html(
|
||||
sprintf(
|
||||
_x(
|
||||
'By upgrading to the %1$s or %2$s plans you will unlock the ability to create
|
||||
backups and do advanced migrations on multi-site installations!',
|
||||
'1: name of pro plan, 2: name of elite plan',
|
||||
'duplicator-pro'
|
||||
),
|
||||
License::getLicenseToString(License::TYPE_PRO),
|
||||
License::getLicenseToString(License::TYPE_ELITE)
|
||||
)
|
||||
); ?>
|
||||
</p>
|
||||
<br>
|
||||
<?php if (CapMng::can(CapMng::CAP_LICENSE, false)) { ?>
|
||||
<a class="button primary small margin-bottom-0" target="_blank" href="<?php echo esc_url($upgradeUrl); ?>">
|
||||
<?php esc_html_e('Upgrade Now!', 'duplicator-pro'); ?>
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<?php
|
||||
echo '<b>' . esc_html__(
|
||||
'Please contact the Duplicator license manager to update it.',
|
||||
'duplicator-pro'
|
||||
) . '</b>';
|
||||
?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
|
||||
defined("ABSPATH") or die("");
|
||||
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var Duplicator\Core\Controllers\ControllersManager $ctrlMng
|
||||
* @var Duplicator\Core\Views\TplMng $tplMng
|
||||
* @var array<string, mixed> $tplData
|
||||
*/
|
||||
$daysLeft = $tplData['schedule_disalbe_days_left'];
|
||||
|
||||
if ($daysLeft === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($daysLeft >= 0) {
|
||||
?>
|
||||
<u>
|
||||
<?php
|
||||
if (License::can(License::CAPABILITY_SCHEDULE)) {
|
||||
$message = sprintf(
|
||||
_n(
|
||||
'Scheduled Backups are going to be disabled <b><em>in %d day</em></b>.',
|
||||
'Scheduled Backups are going to be disabled <b><em>in %d days</em></b>.',
|
||||
$daysLeft,
|
||||
'duplicator-pro'
|
||||
),
|
||||
$daysLeft
|
||||
);
|
||||
$message .= __(' Please renew your license to assure your backups are not interrupted.', 'duplicator-pro');
|
||||
echo wp_kses(
|
||||
$message,
|
||||
[
|
||||
'b' => [],
|
||||
'em' => [],
|
||||
]
|
||||
);
|
||||
} else {
|
||||
esc_html_e(
|
||||
'All automatic backups have been disabeld. Please renew your license to re-enable them.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
}
|
||||
?>
|
||||
</u>
|
||||
<?php
|
||||
} else {
|
||||
esc_html_e(
|
||||
'Scheduled Backups.',
|
||||
'duplicator-pro'
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
$renewal_url = $tplData['renewal_url'];
|
||||
?>
|
||||
<span class='dashicons dashicons-warning'></span>
|
||||
<div class="dup-sub-content">
|
||||
<h3>
|
||||
<?php esc_html_e('Warning! Your Duplicator Pro license has expired...', 'duplicator-pro');?>
|
||||
</h3>
|
||||
<?php esc_html_e('You\'re currently missing:', 'duplicator-pro'); ?>
|
||||
<ul class="dupli-simple-style-disc" >
|
||||
<li><?php esc_html_e('Access to Advanced Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php $tplMng->render('licensing/notices/drm_schedules_msg'); ?></li>
|
||||
<li><?php esc_html_e('Storages Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Templates Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('New Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Important Updates for Security Patches', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Bug Fixes', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Support Requests', 'duplicator-pro'); ?></li>
|
||||
</ul>
|
||||
<?php if (CapMng::can(CapMng::CAP_LICENSE, false)) { ?>
|
||||
<a class="button primary small" target="_blank" href="<?php echo esc_url($renewal_url); ?>">
|
||||
<?php esc_html_e('Renew Now!', 'duplicator-pro'); ?>
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<?php
|
||||
echo '<b>' . esc_html__(
|
||||
'Please contact the Duplicator license manager to activate it.',
|
||||
'duplicator-pro'
|
||||
) . '</b>';
|
||||
?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Controllers\SettingsPageController;
|
||||
use Duplicator\Core\CapMng;
|
||||
use Duplicator\Core\Controllers\ControllersManager;
|
||||
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
|
||||
*/
|
||||
|
||||
$img_url = plugins_url('duplicator-pro/assets/img/warning.png');
|
||||
$problem_text = $tplData['problem'];
|
||||
$licensing_tab_url = ControllersManager::getMenuLink(
|
||||
ControllersManager::SETTINGS_SUBMENU_SLUG,
|
||||
SettingsPageController::L2_SLUG_GENERAL
|
||||
);
|
||||
?>
|
||||
<span class='dashicons dashicons-warning'></span>
|
||||
<div class="dup-sub-content">
|
||||
<h3>
|
||||
<?php
|
||||
printf(
|
||||
esc_html_x('Your Duplicator Pro license key is %1$s ...', '%1$s represent the license status', 'duplicator-pro'),
|
||||
esc_html($tplData['problem'])
|
||||
);
|
||||
?>
|
||||
</h3>
|
||||
<?php esc_html_e('You\'re currently missing:', 'duplicator-pro'); ?>
|
||||
<ul class="dupli-simple-style-disc" >
|
||||
<li><?php esc_html_e('Access to Advanced Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Scheduled Backups', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Storages Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Templates Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('New Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Important Updates for Security Patches', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Bug Fixes', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Support Requests', 'duplicator-pro'); ?></li>
|
||||
</ul>
|
||||
|
||||
<?php
|
||||
if (CapMng::can(CapMng::CAP_LICENSE, false)) {
|
||||
printf(
|
||||
wp_kses(
|
||||
_x(
|
||||
'<b>Please %1$sActivate Your License%2$s</b>. If you do not have a license key go to %3$sduplicator.com%4$s to get it.',
|
||||
'1 and 2 are opening and 3 and 4 are closing anchor tags (<a> and </a>)',
|
||||
'duplicator-pro'
|
||||
),
|
||||
ViewHelper::GEN_KSES_TAGS
|
||||
),
|
||||
'<a href="' . esc_url($licensing_tab_url) . '">',
|
||||
'</a>',
|
||||
'<a target="_blank" href="' . esc_url(DUPLICATOR_BLOG_URL . 'my-account') . '">',
|
||||
'</a>'
|
||||
);
|
||||
} else {
|
||||
echo '<b>' . esc_html__(
|
||||
'Please contact the Duplicator license manager to activate it.',
|
||||
'duplicator-pro'
|
||||
) . '</b>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\LicensingController;
|
||||
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
|
||||
*/
|
||||
|
||||
$licensing_tab_url = ControllersManager::getMenuLink(
|
||||
ControllersManager::SETTINGS_SUBMENU_SLUG,
|
||||
SettingsPageController::L2_SLUG_GENERAL
|
||||
);
|
||||
$dashboard_url = DUPLICATOR_BLOG_URL . 'my-account';
|
||||
$img_url = plugins_url('duplicator-pro/assets/img/warning.png');
|
||||
|
||||
?>
|
||||
<span class='dashicons dashicons-warning'></span>
|
||||
<div class="dup-sub-content">
|
||||
<h3>
|
||||
<?php esc_html_e('Duplicator Pro\'s license is deactivated because you\'re out of site activations.', 'duplicator-pro'); ?>
|
||||
</h3>
|
||||
<?php esc_html_e('You\'re currently missing:', 'duplicator-pro'); ?>
|
||||
<ul class="dupli-simple-style-disc" >
|
||||
<li><?php esc_html_e('Access to Advanced Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Scheduled Backups', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Storages Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Templates Management', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('New Features', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Important Updates for Security Patches', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Bug Fixes', 'duplicator-pro'); ?></li>
|
||||
<li><?php esc_html_e('Support Requests', 'duplicator-pro'); ?></li>
|
||||
</ul>
|
||||
<?php
|
||||
if (CapMng::can(CapMng::CAP_LICENSE, false)) {
|
||||
printf(
|
||||
wp_kses(
|
||||
_x(
|
||||
'Upgrade your license using the %1$sDuplicator Dashboard%2$s or deactivate plugin on old sites.<br/>
|
||||
After making necessary changes %3$srefresh the license status%4$s.',
|
||||
'1 and 2 are opening and 3 and 4 are closing anchor tags (<a> and </a>)',
|
||||
'duplicator-pro'
|
||||
),
|
||||
[
|
||||
'br' => [],
|
||||
]
|
||||
),
|
||||
'<a href="' . esc_url($dashboard_url) . '" target="_blank">',
|
||||
'</a>',
|
||||
'<a href="' . esc_url($licensing_tab_url) . '">',
|
||||
'</a>'
|
||||
);
|
||||
} else {
|
||||
echo '<b>' . esc_html__(
|
||||
'Please contact the Duplicator license manager to activate it.',
|
||||
'duplicator-pro'
|
||||
) . '</b>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Duplicator
|
||||
*/
|
||||
|
||||
use Duplicator\Addons\ProBase\License\License;
|
||||
use Duplicator\Addons\ProBase\LicensingController;
|
||||
use Duplicator\Core\Controllers\ControllersManager;
|
||||
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
|
||||
*/
|
||||
|
||||
$dGlobal = DynamicGlobalEntity::getInstance();
|
||||
$licenseVisibility = $dGlobal->getValInt('license_key_visible', License::VISIBILITY_ALL);
|
||||
?>
|
||||
<div class="dup-settings-wrapper" >
|
||||
<div class="dup-accordion-wrapper display-separators close">
|
||||
<div class="accordion-header">
|
||||
<h3 class="title">
|
||||
<?php esc_html_e("License Key Visibility", 'duplicator-pro') ?>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="accordion-content">
|
||||
<p>
|
||||
<?php
|
||||
esc_html_e(
|
||||
"This is an optional setting that prevents the 'License Key' from being copied.
|
||||
Select the desired visibility mode, enter a password and hit the 'Change Visibility' button.",
|
||||
'duplicator-pro'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
|
||||
<form
|
||||
id="dup-license-visibility-form"
|
||||
action="<?php echo esc_url(ControllersManager::getCurrentLink()); ?>"
|
||||
method="post"
|
||||
data-parsley-validate>
|
||||
<?php $tplData['actions'][LicensingController::ACTION_CHANGE_VISIBILITY]->getActionNonceFileds(); ?>
|
||||
|
||||
<label class="lbl-larger">
|
||||
<?php esc_html_e("Visibility", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<div class="margin-bottom-1">
|
||||
<label class="inline-display margin-right-1">
|
||||
<input
|
||||
type="radio"
|
||||
name="license_key_visible"
|
||||
value="<?php echo (int) License::VISIBILITY_ALL; ?>"
|
||||
class="margin-0"
|
||||
onclick="DupliJs.Licensing.VisibilityTemporary(<?php echo (int) License::VISIBILITY_ALL; ?>);"
|
||||
<?php checked($licenseVisibility, License::VISIBILITY_ALL); ?>>
|
||||
<?php esc_html_e("License Visible", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<label class="inline-display margin-right-1">
|
||||
<input
|
||||
type="radio"
|
||||
name="license_key_visible"
|
||||
value="<?php echo (int) License::VISIBILITY_INFO; ?>"
|
||||
class="margin-0"
|
||||
onclick="DupliJs.Licensing.VisibilityTemporary(<?php echo (int) License::VISIBILITY_INFO; ?>);"
|
||||
<?php checked($licenseVisibility, License::VISIBILITY_INFO); ?>>
|
||||
<?php esc_html_e("Info Only", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<label class="inline-display">
|
||||
<input
|
||||
type="radio"
|
||||
name="license_key_visible"
|
||||
value="<?php echo (int) License::VISIBILITY_NONE; ?>"
|
||||
class="margin-0"
|
||||
onclick="DupliJs.Licensing.VisibilityTemporary(<?php echo (int) License::VISIBILITY_NONE; ?>);"
|
||||
<?php checked($licenseVisibility, License::VISIBILITY_NONE); ?>>
|
||||
<?php esc_html_e("License Invisible", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="lbl-larger">
|
||||
<?php esc_html_e("Password", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<div class="margin-bottom-1">
|
||||
<input
|
||||
type="password"
|
||||
class="dup-wide-input"
|
||||
name="_key_password"
|
||||
id="_key_password" size="50">
|
||||
</div>
|
||||
<?php if ($licenseVisibility == License::VISIBILITY_ALL) { ?>
|
||||
<label class="lbl-larger">
|
||||
<?php esc_html_e("Retype Password", 'duplicator-pro'); ?>
|
||||
</label>
|
||||
<div class="margin-bottom-1">
|
||||
<input
|
||||
type="password"
|
||||
class="dup-wide-input"
|
||||
name="_key_password_confirmation"
|
||||
id="_key_password_confirmation"
|
||||
data-parsley-equalto="#_key_password"
|
||||
size="50">
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<label class="lbl-larger">
|
||||
|
||||
</label>
|
||||
<div class="margin-bottom-1">
|
||||
<button
|
||||
class="button secondary hollow small margin-0"
|
||||
id="show_hide"
|
||||
onclick="DupliJs.Licensing.ChangeKeyVisibility(); return false;">
|
||||
<?php esc_html_e('Change Visibility', 'duplicator-pro'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user