Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 5m27s
311 lines
16 KiB
PHP
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'; ?>
|