Implement Software Upgrade Management API and Frontend Functionality
- Added software.php for managing software versions, including download and purchase actions. - Created upgrade_paths.php for handling upgrade paths management. - Developed user_licenses.php for managing user licenses. - Introduced version_access_rules.php for managing access rules for software versions. - Implemented frontend functions in functions.js for interacting with the software upgrade API. - Added version_access.php for user access validation and license management. - Created upgrades.php for displaying available upgrades and handling user interactions. - Enhanced UI with responsive design and progress indicators for downloads and purchases.
This commit is contained in:
282
includes/version_access.php
Normal file
282
includes/version_access.php
Normal file
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
function getUserOwnedVersions($userId) {
|
||||
global $pdo;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT sv.*, ul.license_key, ul.purchased_at
|
||||
FROM user_licenses ul
|
||||
JOIN software_versions sv ON ul.version_id = sv.id
|
||||
WHERE ul.user_id = ? AND ul.status = 'active'
|
||||
ORDER BY sv.major_version DESC, sv.minor_version DESC
|
||||
");
|
||||
$stmt->execute([$userId]);
|
||||
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function getLatestOwnedVersion($userId) {
|
||||
$versions = getUserOwnedVersions($userId);
|
||||
return !empty($versions) ? $versions[0] : null;
|
||||
}
|
||||
|
||||
function checkVersionAccess($userId, $versionId) {
|
||||
global $pdo;
|
||||
|
||||
// Get version and its access rules
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT sv.*, var.access_type, var.requires_base_version, var.price
|
||||
FROM software_versions sv
|
||||
JOIN version_access_rules var ON sv.id = var.version_id
|
||||
WHERE sv.id = ?
|
||||
");
|
||||
$stmt->execute([$versionId]);
|
||||
$version = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$version) {
|
||||
return ['accessible' => false, 'reason' => 'Version not found'];
|
||||
}
|
||||
|
||||
switch ($version['access_type']) {
|
||||
case 'free_all':
|
||||
// Free for everyone (like v0.99)
|
||||
return [
|
||||
'accessible' => true,
|
||||
'reason' => 'free_for_all',
|
||||
'price' => 0.00,
|
||||
'requires_payment' => false
|
||||
];
|
||||
|
||||
case 'free_for_owners':
|
||||
// Free for owners of required base version (like v1.1 for v1.0 owners)
|
||||
if ($version['requires_base_version']) {
|
||||
$hasBaseVersion = userOwnsVersion($userId, $version['requires_base_version']);
|
||||
|
||||
if ($hasBaseVersion) {
|
||||
return [
|
||||
'accessible' => true,
|
||||
'reason' => 'free_upgrade',
|
||||
'price' => 0.00,
|
||||
'requires_payment' => false
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'accessible' => false,
|
||||
'reason' => 'requires_base_version',
|
||||
'required_version' => $version['requires_base_version'],
|
||||
'price' => $version['price'],
|
||||
'requires_payment' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
return ['accessible' => false, 'reason' => 'invalid_access_rule'];
|
||||
|
||||
case 'paid':
|
||||
case 'paid_upgrade':
|
||||
// Check if user already owns this version
|
||||
if (userOwnsVersionById($userId, $versionId)) {
|
||||
return [
|
||||
'accessible' => true,
|
||||
'reason' => 'already_owned',
|
||||
'price' => 0.00,
|
||||
'requires_payment' => false
|
||||
];
|
||||
}
|
||||
|
||||
// Check for upgrade pricing
|
||||
$upgradeInfo = getUpgradePrice($userId, $versionId);
|
||||
|
||||
return [
|
||||
'accessible' => false,
|
||||
'reason' => 'requires_purchase',
|
||||
'price' => $upgradeInfo['price'],
|
||||
'original_price' => $version['price'],
|
||||
'is_upgrade' => $upgradeInfo['is_upgrade'],
|
||||
'requires_payment' => true
|
||||
];
|
||||
|
||||
default:
|
||||
return ['accessible' => false, 'reason' => 'unknown_access_type'];
|
||||
}
|
||||
}
|
||||
|
||||
function userOwnsVersion($userId, $version) {
|
||||
global $pdo;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM user_licenses ul
|
||||
JOIN software_versions sv ON ul.version_id = sv.id
|
||||
WHERE ul.user_id = ? AND sv.version = ? AND ul.status = 'active'
|
||||
");
|
||||
$stmt->execute([$userId, $version]);
|
||||
|
||||
return $stmt->fetchColumn() > 0;
|
||||
}
|
||||
|
||||
function userOwnsVersionById($userId, $versionId) {
|
||||
global $pdo;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM user_licenses
|
||||
WHERE user_id = ? AND version_id = ? AND status = 'active'
|
||||
");
|
||||
$stmt->execute([$userId, $versionId]);
|
||||
|
||||
return $stmt->fetchColumn() > 0;
|
||||
}
|
||||
|
||||
function getUpgradePrice($userId, $targetVersionId) {
|
||||
global $pdo;
|
||||
|
||||
// Get user's owned versions
|
||||
$ownedVersions = getUserOwnedVersions($userId);
|
||||
|
||||
if (empty($ownedVersions)) {
|
||||
// No owned versions, return full price
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT var.price
|
||||
FROM version_access_rules var
|
||||
WHERE var.version_id = ?
|
||||
");
|
||||
$stmt->execute([$targetVersionId]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return [
|
||||
'price' => $result['price'] ?? 0.00,
|
||||
'is_upgrade' => false
|
||||
];
|
||||
}
|
||||
|
||||
// Check for upgrade paths
|
||||
$bestUpgradePrice = null;
|
||||
$fromVersion = null;
|
||||
|
||||
foreach ($ownedVersions as $ownedVersion) {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT upgrade_price, is_free
|
||||
FROM upgrade_paths
|
||||
WHERE from_version_id = ? AND to_version_id = ?
|
||||
");
|
||||
$stmt->execute([$ownedVersion['id'], $targetVersionId]);
|
||||
$upgrade = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($upgrade) {
|
||||
if ($upgrade['is_free']) {
|
||||
return [
|
||||
'price' => 0.00,
|
||||
'is_upgrade' => true,
|
||||
'from_version' => $ownedVersion['version']
|
||||
];
|
||||
}
|
||||
|
||||
if ($bestUpgradePrice === null || $upgrade['upgrade_price'] < $bestUpgradePrice) {
|
||||
$bestUpgradePrice = $upgrade['upgrade_price'];
|
||||
$fromVersion = $ownedVersion['version'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($bestUpgradePrice !== null) {
|
||||
return [
|
||||
'price' => $bestUpgradePrice,
|
||||
'is_upgrade' => true,
|
||||
'from_version' => $fromVersion
|
||||
];
|
||||
}
|
||||
|
||||
// No upgrade path, return full price
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT var.price
|
||||
FROM version_access_rules var
|
||||
WHERE var.version_id = ?
|
||||
");
|
||||
$stmt->execute([$targetVersionId]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return [
|
||||
'price' => $result['price'] ?? 0.00,
|
||||
'is_upgrade' => false
|
||||
];
|
||||
}
|
||||
|
||||
function grantLicense($pdo, $userId, $versionId, $transactionId = null) {
|
||||
// Generate unique license key
|
||||
$licenseKey = generateLicenseKey($userId, $versionId);
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO user_licenses (user_id, version_id, license_key, transaction_id, status)
|
||||
VALUES (?, ?, ?, ?, 'active')
|
||||
ON DUPLICATE KEY UPDATE status = 'active', license_key = ?
|
||||
");
|
||||
|
||||
return $stmt->execute([$userId, $versionId, $licenseKey, $transactionId, $licenseKey]);
|
||||
}
|
||||
|
||||
function generateLicenseKey($userId, $versionId) {
|
||||
// Generate a unique license key
|
||||
$data = $userId . '-' . $versionId . '-' . time() . '-' . bin2hex(random_bytes(8));
|
||||
return strtoupper(substr(hash('sha256', $data), 0, 29)); // Format: XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
|
||||
}
|
||||
|
||||
function generateSecureDownloadToken($pdo, $userId, $versionId) {
|
||||
// Generate random token
|
||||
$token = bin2hex(random_bytes(32));
|
||||
|
||||
// Store token with expiration (5 minutes)
|
||||
$expiresAt = date('Y-m-d H:i:s', time() + 300);
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO download_tokens (token, user_id, version_id, expires_at, used)
|
||||
VALUES (?, ?, ?, ?, 0)"
|
||||
);
|
||||
$stmt->execute([$token, $userId, $versionId, $expiresAt]);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
function validateUserAccess($userId, $versionId) {
|
||||
global $pdo;
|
||||
|
||||
// Check if version requires payment
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT var.access_type
|
||||
FROM version_access_rules var
|
||||
WHERE var.version_id = ?
|
||||
");
|
||||
$stmt->execute([$versionId]);
|
||||
$accessRule = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$accessRule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($accessRule['access_type'] === 'free_all') {
|
||||
return true; // Free for everyone
|
||||
}
|
||||
|
||||
// Check if user has valid license
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT COUNT(*) FROM user_licenses
|
||||
WHERE user_id = ? AND version_id = ? AND status = 'active'"
|
||||
);
|
||||
$stmt->execute([$userId, $versionId]);
|
||||
|
||||
return $stmt->fetchColumn() > 0;
|
||||
}
|
||||
|
||||
function logDownload($pdo, $userId, $versionId) {
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO download_logs (user_id, version_id, ip_address, user_agent, downloaded_at)
|
||||
VALUES (?, ?, ?, ?, NOW())
|
||||
");
|
||||
$stmt->execute([
|
||||
$userId,
|
||||
$versionId,
|
||||
$_SERVER['REMOTE_ADDR'] ?? '',
|
||||
$_SERVER['HTTP_USER_AGENT'] ?? ''
|
||||
]);
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user