Cody Cook 635b3ddcbc
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 5m27s
Address changes.
2025-02-22 17:20:19 -08:00

311 lines
16 KiB
PHP

<?php
// upload.php - One Page Upload and Details Submission
require_once 'includes/globals.php';
require_once 'vendor/autoload.php';
use DJMixHosting\Upload;
use DJMixHosting\CDN;
use DJMixHosting\Database;
use DJMixHosting\Genres;
use DJMixHosting\DJs;
// Ensure user is authenticated
if (!isset($_SESSION['user'])) {
$_SESSION['error'] = $locale['loginToUploadMix'];
header("Location: /login");
exit;
}
// If the form was submitted, check which step we're processing via an "action" field.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Step 1: Handle file upload
if (isset($_POST['action']) && $_POST['action'] === 'upload_file') {
if (isset($_FILES['mix_file'])) {
$upload = new Upload($_FILES['mix_file'], $config);
// Validate the file
if (!$upload->validate()) {
$_SESSION['error'] = implode(", ", $upload->getErrors());
header("Location: /upload");
exit;
}
// Move the file to the temporary directory
if (!$upload->moveFile()) {
$_SESSION['error'] = implode(", ", $upload->getErrors());
header("Location: /upload");
exit;
}
// Process the file (extract metadata for MP3/ZIP)
$uploadTask = $upload->process();
$_SESSION['upload_task'] = $uploadTask;
// Reload the page so the details form can be shown
header("Location: /upload");
exit;
}
}
// Step 2: Handle mix details submission
elseif (isset($_POST['action']) && $_POST['action'] === 'submit_details') {
if (!isset($_SESSION['upload_task'])) {
$_SESSION['error'] = $locale['noUploadedFileFound'];
header("Location: /upload");
exit;
}
$uploadTask = $_SESSION['upload_task'];
$title = trim($_POST['title'] ?? '');
$description = trim($_POST['description'] ?? '');
$recorded = trim($_POST['recorded'] ?? '');
$selectedGenres = $_POST['genres'] ?? []; // array of genre IDs
$dj1 = $_POST['dj1'] ?? 0;
$dj2 = $_POST['dj2'] ?? 0;
$dj3 = $_POST['dj3'] ?? 0;
// Basic validation: title is required
if (empty($title)) {
$_SESSION['error'] = $locale['mixTitleRequired'];
header("Location: /upload");
exit;
}
// Simple slugify function
function slugify($text): string
{
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
$text = preg_replace('~[^-\w]+~', '', $text);
$text = trim($text, '-');
$text = preg_replace('~-+~', '-', $text);
$text = strtolower($text);
return empty($text) ? 'n-a' : $text;
}
$slug = slugify($title);
// Upload the file to the CDN
$cdn = new CDN($config);
$remotePath = "temp/mixes/" . uniqid() . "_" . basename($uploadTask['local_path']);
$mimeType = ($uploadTask['ext'] === 'mp3') ? 'audio/mpeg' : 'application/zip';
try {
$cdn->uploadFile($uploadTask['local_path'], $remotePath, $mimeType, 'private');
} catch (Exception $e) {
$_SESSION['error'] = $locale['errorUploadCDN'] . $e->getMessage();
header("Location: /upload");
exit;
}
// Insert the mix record into the database
$db = new Database($config);
$stmt = $db->prepare("INSERT INTO mix (title, slug, description, cover, url, seconds, mediaplayer, dj1, dj2, dj3, pending, recorded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)");
if ($uploadTask['file_type'] === 'mp3') {
$seconds = (int)$uploadTask['metadata']['duration'];
$mediaplayer = 0;
} elseif ($uploadTask['file_type'] === 'zip') {
$seconds = (int)$uploadTask['metadata']['total_duration'];
$mediaplayer = 1;
} else {
$seconds = 0;
$mediaplayer = 1;
}
$url = $remotePath;
$dj1 = (int)$dj1;
$dj2 = (int)$dj2;
$dj3 = (int)$dj3;
$cover = "";
$stmt->bind_param("sssssiiiiss", $title, $slug, $description, $cover, $url, $seconds, $mediaplayer, $dj1, $dj2, $dj3, $recorded);
if (!$stmt->execute()) {
$_SESSION['error'] = $locale['errorSavingMixDB'];
header("Location: /upload");
exit;
}
$mixId = $stmt->insert_id;
$stmt->close();
// Insert mix_meta entries for genres and tracklist
foreach ($selectedGenres as $genreId) {
$stmt = $db->prepare("INSERT INTO mix_meta (mix_id, attribute, value) VALUES (?, 'genre', ?)");
$stmt->bind_param("is", $mixId, $genreId);
$stmt->execute();
$stmt->close();
}
if ($uploadTask['file_type'] === 'mp3' && !empty($uploadTask['metadata']['title'])) {
$tracklist = $uploadTask['metadata']['title'];
$stmt = $db->prepare("INSERT INTO mix_meta (mix_id, attribute, value) VALUES (?, 'tracklist', ?)");
$stmt->bind_param("is", $mixId, $tracklist);
$stmt->execute();
$stmt->close();
} elseif ($uploadTask['file_type'] === 'zip' && !empty($uploadTask['metadata']['tracklist'])) {
$tracklist = implode("\n", $uploadTask['metadata']['tracklist']);
$stmt = $db->prepare("INSERT INTO mix_meta (mix_id, attribute, value) VALUES (?, 'tracklist', ?)");
$stmt->bind_param("is", $mixId, $tracklist);
$stmt->execute();
$stmt->close();
}
// Cleanup: delete the local temporary file and clear session upload task
unlink($uploadTask['local_path']);
unset($_SESSION['upload_task']);
$_SESSION['success'] = $locale['uploadedPendingApproval'];
header("Location: /profile");
exit;
}
}
require_once 'includes/header.php'; ?>
<section class="upload-section py-5">
<div class="container">
<?php
// Display any error messages
if (isset($_SESSION['error'])) {
echo '<div class="alert alert-danger">' . htmlspecialchars($_SESSION['error']) . '</div>';
unset($_SESSION['error']);
}
// If no file has been uploaded, show the file upload form.
if (!isset($_SESSION['upload_task'])):
?>
<div class="card">
<div class="card-body">
<h3 class="card-title mb-4"><?php echo $locale['uploadHeader1'];?></h3>
<!-- Info Alert -->
<div class="alert alert-info">
<h4 class="alert-heading"><?php echo $locale['uploadAlertHeader'];?></h4>
<p><?php echo $locale['uploadAlert1'];?></p>
</div>
<!-- Requirements -->
<h4 class="mb-3"><?php echo $locale['uploadHeader2'];?></h4>
<ul class="list-group list-group-flush mb-4">
<li class="list-group-item">
<i class="fas fa-check-circle text-success me-2"></i>
<?php echo $locale['uploadAlert2'];?>
</li>
<li class="list-group-item">
<i class="fas fa-check-circle text-success me-2"></i>
<?php echo $locale['uploadAlert3'];?>
</li>
<li class="list-group-item">
<i class="fas fa-info-circle text-primary me-2"></i>
<?php echo $locale['uploadAlert4'];?>
</li>
</ul>
<!-- Process Steps -->
<h4 class="mb-3"><?php echo $locale['uploadProcess'];?></h4>
<ol class="list-group list-group-numbered mb-4">
<li class="list-group-item"><?php echo $locale['uploadProcess1'];?></li>
<li class="list-group-item"><?php echo $locale['uploadProcess2'];?></li>
<li class="list-group-item"><?php echo $locale['uploadProcess3'];?></li>
<li class="list-group-item"><?php echo $locale['uploadProcess4'];?></li>
</ol>
<!-- Upload Form -->
<div class="card mt-4">
<div class="card-body">
<h4 class="card-title mb-4"><?php echo $locale['uploadAMix'];?></h4>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="upload_file">
<div class="mb-3">
<label for="mix_file" class="form-label"><?php echo $locale['uploadSelectMix'];?></label>
<?php
// we need to take the file extensions from config allowed_file_types and comma separate them with periods
$acceptedFileTypes = implode(",", array_map(function($ext) { return "." . $ext; }, $config['uploads']['allowed_file_types']));
?>
<input type="file" class="form-control" id="mix_file" name="mix_file" accept="<?php echo $acceptedFileTypes; ?>" required>
<div class="form-text"><?php echo $locale['uploadMaxFileSize'];?></div>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-upload me-2"></i><?php echo $locale['uploadFile'];?>
</button>
</form>
</div>
</div>
</div>
</div>
<?php
// If an upload task exists, show the mix details form.
else:
$uploadTask = $_SESSION['upload_task'];
// Load available genres and DJs for the form
$db = new Database($config);
$genresObj = new Genres($db);
$allGenres = $genresObj->get_all_genres();
$djsObj = new DJs($db);
$allDJs = $djsObj->get_all_djs();
?>
<div class="card">
<div class="card-body">
<h3 class="card-title mb-4">Enter Mix Details</h3>
<div class="card mb-4">
<div class="card-body">
<h5>File Summary</h5>
<p><strong>Original Name:</strong> <?php echo htmlspecialchars($uploadTask['original_name']); ?></p>
<p><strong>File Type:</strong> <?php echo htmlspecialchars(strtoupper($uploadTask['file_type'])); ?></p>
<p><strong>Size:</strong> <?php echo round($uploadTask['size'] / 1024, 2); ?> KB</p>
<?php if ($uploadTask['file_type'] === 'mp3'): ?>
<p><strong>Duration:</strong> <?php echo htmlspecialchars($uploadTask['metadata']['duration']); ?> seconds</p>
<?php elseif ($uploadTask['file_type'] === 'zip'): ?>
<p><strong>Total Duration:</strong> <?php echo htmlspecialchars($uploadTask['metadata']['total_duration']); ?> seconds</p>
<?php endif; ?>
</div>
</div>
<form action="/upload" method="post" class="needs-validation" novalidate>
<input type="hidden" name="action" value="submit_details">
<div class="mb-3">
<label for="title" class="form-label"><?php echo $locale['mixName'];?></label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label"><?php echo $locale['mixDescription'];?></label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
<div class="mb-3">
<label for="recorded" class="form-label"><?php echo $locale['recordedDate'];?></label>
<input type="date" class="form-control" id="recorded" name="recorded" required>
</div>
<div class="mb-3">
<label for="genres" class="form-label"><?php echo $locale['uploadSelectGenres'];?></label>
<select class="form-select" id="genres" name="genres[]" multiple required>
<?php foreach ($allGenres as $genre): ?>
<option value="<?php echo htmlspecialchars($genre['id']); ?>"><?php echo htmlspecialchars($genre['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label"><?php echo $locale['uploadSelectDJSMax3'];?></label>
<div class="row">
<div class="col">
<select class="form-select" name="dj1" required>
<option value=""><?php echo $locale['uploadSelectDJ1'];?></option>
<?php foreach ($allDJs as $dj): ?>
<option value="<?php echo htmlspecialchars($dj['id']); ?>"><?php echo htmlspecialchars($dj['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col">
<select class="form-select" name="dj2">
<option value=""><?php echo $locale['uploadSelectDJ2'];?></option>
<?php foreach ($allDJs as $dj): ?>
<option value="<?php echo htmlspecialchars($dj['id']); ?>"><?php echo htmlspecialchars($dj['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col">
<select class="form-select" name="dj3">
<option value=""><?php echo $locale['uploadSelectDJ3'];?></option>
<?php foreach ($allDJs as $dj): ?>
<option value="<?php echo htmlspecialchars($dj['id']); ?>"><?php echo htmlspecialchars($dj['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary"><?php echo $locale['uploadSubmitMix'];?></button>
</form>
</div>
</div>
<?php endif; ?>
</div>
</section>
<?php require_once 'includes/footer.php'; ?>