![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/private_html/includes/ |
<?php
/**
* Grace Period Helper Functions for SoundStudioPro
*
* Handles the 30-day upgrade grace period for new users.
* When a user upgrades within 30 days of account creation,
* their starter gift tracks (up to 5) and any promotional credits
* receive full commercial rights.
*/
require_once __DIR__ . '/../config/database.php';
// Grace period constants
define('GRACE_PERIOD_DAYS', 30);
define('GRACE_PERIOD_MAX_TRACKS', 5); // Base starter gift tracks
// Promotional tracks have no limit - all are included if within grace period
/**
* Check if a user is currently within their 30-day grace period
*
* @param int $user_id The user ID to check
* @return array ['eligible' => bool, 'days_remaining' => int, 'expires_at' => string]
*/
function isUserInGracePeriod($user_id) {
$pdo = getDBConnection();
if (!$pdo) {
return ['eligible' => false, 'days_remaining' => 0, 'expires_at' => null, 'error' => 'Database connection failed'];
}
try {
$stmt = $pdo->prepare("SELECT created_at, plan FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
return ['eligible' => false, 'days_remaining' => 0, 'expires_at' => null, 'error' => 'User not found'];
}
// User must be on free plan to be in grace period consideration
// (if already paid, they don't need grace period)
$account_created = new DateTime($user['created_at']);
$grace_expires = clone $account_created;
$grace_expires->modify('+' . GRACE_PERIOD_DAYS . ' days');
$now = new DateTime();
$is_eligible = $now <= $grace_expires;
$interval = $now->diff($grace_expires);
$days_remaining = $is_eligible ? $interval->days : 0;
return [
'eligible' => $is_eligible,
'days_remaining' => $days_remaining,
'expires_at' => $grace_expires->format('Y-m-d H:i:s'),
'account_created' => $user['created_at'],
'current_plan' => $user['plan']
];
} catch (PDOException $e) {
error_log("Grace period check failed: " . $e->getMessage());
return ['eligible' => false, 'days_remaining' => 0, 'expires_at' => null, 'error' => $e->getMessage()];
}
}
/**
* Get all grace period eligible tracks for a user
* These are tracks created within 30 days of account creation that don't have commercial rights yet
*
* @param int $user_id The user ID
* @return array List of eligible tracks
*/
function getGracePeriodEligibleTracks($user_id) {
$pdo = getDBConnection();
if (!$pdo) {
return [];
}
try {
// Get tracks that are:
// 1. Created within 30 days of user account creation
// 2. Don't already have commercial rights
// 3. Are marked as grace_period_eligible (or fall within the window)
$stmt = $pdo->prepare("
SELECT mt.*, u.created_at as user_created_at
FROM music_tracks mt
JOIN users u ON mt.user_id = u.id
WHERE mt.user_id = ?
AND mt.commercial_rights = 'none'
AND (
mt.grace_period_eligible = TRUE
OR mt.created_at <= DATE_ADD(u.created_at, INTERVAL ? DAY)
)
ORDER BY mt.created_at ASC
");
$stmt->execute([$user_id, GRACE_PERIOD_DAYS]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log("Get grace period tracks failed: " . $e->getMessage());
return [];
}
}
/**
* Convert grace period eligible tracks to full commercial rights
* Called when a user upgrades within their 30-day grace period
*
* @param int $user_id The user ID
* @return array ['success' => bool, 'converted_count' => int, 'tracks' => array]
*/
function convertGracePeriodTracks($user_id) {
$pdo = getDBConnection();
if (!$pdo) {
return ['success' => false, 'converted_count' => 0, 'error' => 'Database connection failed'];
}
try {
// First verify user is eligible for grace period conversion
$grace_status = isUserInGracePeriod($user_id);
if (!$grace_status['eligible']) {
return [
'success' => false,
'converted_count' => 0,
'error' => 'User is not within 30-day grace period',
'grace_expired_at' => $grace_status['expires_at']
];
}
// Get eligible tracks
$eligible_tracks = getGracePeriodEligibleTracks($user_id);
if (empty($eligible_tracks)) {
return [
'success' => true,
'converted_count' => 0,
'message' => 'No tracks eligible for grace period conversion'
];
}
// Begin transaction
$pdo->beginTransaction();
// Convert all eligible tracks (starter gift + any promotional)
// The limit is applied to base starter tracks (5), but promotional credits are unlimited
$converted_ids = [];
$conversion_time = date('Y-m-d H:i:s');
foreach ($eligible_tracks as $track) {
$stmt = $pdo->prepare("
UPDATE music_tracks
SET commercial_rights = 'grace',
grace_period_converted_at = ?
WHERE id = ?
");
$stmt->execute([$conversion_time, $track['id']]);
$converted_ids[] = $track['id'];
}
// Commit transaction
$pdo->commit();
// Log the conversion
error_log("Grace period conversion: User $user_id converted " . count($converted_ids) . " tracks to commercial rights");
return [
'success' => true,
'converted_count' => count($converted_ids),
'converted_track_ids' => $converted_ids,
'conversion_time' => $conversion_time
];
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log("Grace period conversion failed: " . $e->getMessage());
return ['success' => false, 'converted_count' => 0, 'error' => $e->getMessage()];
}
}
/**
* Mark a new track as grace period eligible if applicable
* Call this when creating a new track
*
* @param int $user_id The user ID
* @param int $track_id The new track ID
* @param string $user_plan The user's current plan at track creation
* @return bool Whether the track was marked as grace period eligible
*/
function markTrackGracePeriodEligible($user_id, $track_id, $user_plan = 'free') {
$pdo = getDBConnection();
if (!$pdo) {
return false;
}
try {
// Determine commercial rights based on user plan
$commercial_rights = ($user_plan !== 'free') ? 'full' : 'none';
// Check if user is in grace period (only matters for free users)
$grace_period_eligible = false;
if ($user_plan === 'free') {
$grace_status = isUserInGracePeriod($user_id);
$grace_period_eligible = $grace_status['eligible'];
}
// Update the track
$stmt = $pdo->prepare("
UPDATE music_tracks
SET commercial_rights = ?,
grace_period_eligible = ?,
user_plan_at_creation = ?
WHERE id = ?
");
$stmt->execute([$commercial_rights, $grace_period_eligible, $user_plan, $track_id]);
return true;
} catch (PDOException $e) {
error_log("Mark grace period eligible failed: " . $e->getMessage());
return false;
}
}
/**
* Get grace period status summary for a user
* Useful for displaying in the UI
*
* @param int $user_id The user ID
* @return array Comprehensive grace period status
*/
function getGracePeriodSummary($user_id) {
$grace_status = isUserInGracePeriod($user_id);
$eligible_tracks = getGracePeriodEligibleTracks($user_id);
return [
'in_grace_period' => $grace_status['eligible'],
'days_remaining' => $grace_status['days_remaining'],
'expires_at' => $grace_status['expires_at'],
'current_plan' => $grace_status['current_plan'] ?? 'unknown',
'eligible_track_count' => count($eligible_tracks),
'eligible_tracks' => array_map(function($track) {
return [
'id' => $track['id'],
'title' => $track['title'],
'created_at' => $track['created_at']
];
}, $eligible_tracks),
'message' => $grace_status['eligible']
? "Upgrade within {$grace_status['days_remaining']} days to unlock commercial rights for " . count($eligible_tracks) . " track(s)!"
: "Grace period expired. New tracks on free plan will not have commercial rights."
];
}