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

605 lines
30 KiB
PHP

<?php
require_once 'includes/globals.php';
require_once 'vendor/autoload.php';
use DJMixHosting\Database;
use DJMixHosting\Genre;
use DJMixHosting\Mix;
use DJMixHosting\Mixshow;
use DJMixHosting\Playcount;
$db = new Database($config);
$mixFound = false;
if (isset($_GET['mix']) && $_GET['mix'] != "") {
$mix = new Mix($_GET['mix'], $db);
if ($mix->getName() != "") {
$mixFound = true;
$title = $mix->getName();
} else {
$title = $locale['notfound'];
}
} else {
$title = $locale['notfound'];
}
// if this is a playcount PUT request, update the playcount
if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
$data = json_decode(file_get_contents('php://input'), true);
if (isset($data['mix']) && $data['mix'] != "") {
$playcount = new Playcount($data['mix'], $db);
$playcount->updatePlaycount();
echo json_encode(['success' => true]);
} else {
echo json_encode(['error' => 'No mix provided']);
}
exit; // Stop further output
}
require_once 'includes/header.php'; ?>
<section>
<div class="container py-5">
<!-- breadcrumbs -->
<div class="row">
<div class="col">
<nav aria-label="breadcrumb" class="bg-body-tertiary rounded-3 p-3 mb-4">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="/"><?php echo $locale['home']; ?></a></li>
<li class="breadcrumb-item"><?php echo $locale['mixes']; ?></li>
<li class="breadcrumb-item active"
aria-current="page"><?php
if (isset($mix) && $mix->getName() != "") {
echo $mix->getName();
} else {
echo $locale['notfound'];
}
?></li>
</ol>
</nav>
</div>
</div>
<!-- end of breadcrumbs -->
<?php if ($mixFound) { ?>
<div class="row">
<!-- start column -->
<div class="col-lg-4">
<!-- cover card -->
<div class="card mb-4">
<div class="card-body bg-body-secondary text-center">
<?php
if ($mix->getCover() != "") {
echo "<img src='" . $mix->getCover() . "' alt='avatar' class='img-fluid' style='width: 150px;'>";
} ?>
<h1 class="my-3 fs-4"><?php echo $mix->getName();
?></h1>
<?php
if ($mix->getDescription() != "") {
echo "<h2 class='text-muted mb-4 fs-6'>" . $mix->getDescription() . "</h2>";
}
?>
</div>
</div>
<!-- end cover card -->
<!-- player card -->
<div class="card mb-4">
<div class="card-body bg-body-secondary text-center">
<?php
if ($mix->isDownloadOnly()) {
echo "<a href='/mix/" . $mix->getSlug() . "/download" . "' class='btn btn-primary w-100 mb-2'>" . $locale['download'] . "</a>";
} else {
?>
<div id="audio-player">
<audio id="audio" src="<?php echo $mix->getUrl(); ?>"></audio>
<div class="player-controls">
<button id="play-pause-btn">
<i class="fas fa-play" style="font-size: 12px;"></i>
</button>
<input type="range" id="seek-bar" value="0">
</div>
<div id="time-display">
<span id="current-time">0:00</span> / <span id="duration">0:00</span>
</div>
</div>
<?php } ?>
</div>
</div>
<!-- end player card -->
<!-- action card -->
<div class="card mb-4">
<div class="card-body bg-body-secondary text-center ">
<button type="button" id="shareBtn" class="w-100 mb-2 btn btn-secondary"
data-bs-toggle="modal" data-bs-target="#shareModal">
<?php echo $locale['share']; ?>
</button>
<?php if (!$mix->isDownloadOnly()) : ?>
<a href="<?php
echo "/mix/" . $mix->getSlug() . "/download";
?>"
class="btn btn-primary w-100 mb-2"><?php echo $locale['download']; ?></a>
<?php endif; ?>
</div>
</div>
<!-- end action card -->
</div>
<!-- end column -->
<!-- start info column -->
<div class="col-lg-8">
<!-- start info card -->
<div class="card mb-4">
<div class="card-body bg-body-secondary">
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['mixname'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0"><?php echo $mix->getName(); ?></p>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['djs'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php
// loop through the $mix['djs'] array and output them in comma separated format
$djs = $mix->getDJs();
$djCount = count($djs);
$i = 0;
foreach ($djs as $dj) {
echo "<a href='/dj/";
echo $dj->getSlug();
echo "'>" . $dj->getName() . "</a>";
if ($i < $djCount - 1) {
echo ", ";
}
$i++;
}
?>
</p>
</div>
</div>
<?php
$genres = $mix->getGenres();
$genreCount = count($genres);
if ($genreCount > 0) {
?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['genres'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php
$i = 0;
foreach ($genres as $genre) {
$genre = new Genre($genre, $db);
echo "<a href='/genre/";
echo $genre->get_slug();
echo "'>" . $genre->get_name() . "</a>";
if ($i < $genreCount - 1) {
echo ", ";
}
$i++;
}
?>
</div>
</div><?php } ?>
<?php
$mixshows = $mix->getMixshow();
$mixshowsCount = count($mixshows);
if ($mixshowsCount > 0) {
?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['mixshow'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php
$i = 0;
foreach ($mixshows as $mixshow) {
$mixshow = new Mixshow($mixshow, $db);
echo "<a href='/mixshow/";
echo $mixshow->get_slug();
echo "'>" . $mixshow->get_name() . "</a>";
if ($i < $mixshowsCount - 1) {
echo ", ";
}
$i++;
}
?>
</div>
</div><?php } ?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['duration'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php
$time = $mix->getDuration();
// Decide the correct singular or plural term
$hour_text = $time['h'] == 1 ? $locale['hour'] : $locale['hours'];
$minute_text = $time['m'] == 1 ? $locale['minute'] : $locale['minutes'];
$second_text = $time['s'] == 1 ? $locale['second'] : $locale['seconds'];
// Output the time, skipping hours if it is less than one hour
if ($time['h'] > 0) {
// If there are hours, always show hours.
echo $time['h'] . " " . $hour_text;
if ($time['m'] > 0) {
// Show minutes only if they are greater than 0.
echo ", " . $time['m'] . " " . $minute_text;
}
// Always show seconds, regardless of minutes.
echo ", " . $time['s'] . " " . $second_text;
} else {
// No hours, check minutes.
if ($time['m'] != 0) {
echo $time['m'] . " " . $minute_text . ", " . $time['s'] . " " . $second_text;
} else {
// Only seconds to show.
echo $time['s'] . " " . $second_text;
}
}
echo " (" . $time['t'] . ")";
?>
</div>
</div>
<?php if ($mix->getRecorded() != ""): ?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['recorded'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php echo $mix->getRecorded(); ?>
</div>
</div>
<?php endif; ?>
<?php if ($mix->getCreated() != ""): ?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['added'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php echo $mix->getCreated(); ?>
</div>
</div>
<?php endif; ?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['downloads'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php echo $mix->getDownloads(); ?>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['plays'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php echo $mix->getPlaycount(); ?>
</div>
</div>
<?php if ($mix->getUpdated() != "") { ?>
<hr>
<div class="row">
<div class="col-sm-3">
<p class="mb-0"><?php echo $locale['lastupdated'] ?></p>
</div>
<div class="col-sm-9">
<p class="text-muted mb-0">
<?php echo $mix->getUpdated(); ?>
</div>
</div>
<?php } ?>
</div>
</div>
<!-- end info card -->
<!-- start tracklist -->
<?php if ($mix->getTracklist() != []) { ?>
<div class='card mb-4 bg-body-secondary'>
<div class='card-body '>
<p class='mb-4'><span
class='text-primary font-italic me-1'><?php echo $locale['tracklist']; ?></span>
</p>
<ul class='list-group list-group-flush rounded-3 bg-body-secondary'>
<?php $tracklist = $mix->getTracklist();
foreach ($tracklist as $track) {
echo "<li class='list-group-item bg-body-secondary d-flex justify-content-between align-items-center'>";
echo $track;
echo "</li>";
}
?>
</ul>
</div>
</div>
<?php } ?>
<!-- end tracklist -->
</div>
<!-- end info column -->
<!-- modals -->
<div class="modal fade" id="shareModal" tabindex="-1" aria-labelledby="shareModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="shareModalLabel"><?php echo $locale['share']; ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<?php
$url = 'https://utahsdjs.com/mix/' . $_GET['mix'];
$utm_params = '?utm_source=website&utm_medium=share_modal&utm_campaign=sharing';
$share_url = urlencode($url . $utm_params);
?>
<a href="#" id="copyLinkBtn"
class="btn btn-secondary w-100 mb-2"><?php echo $locale['copyurl']; ?></a>
<a href="https://www.facebook.com/sharer/sharer.php?u=<?php echo $share_url; ?>"
target="_blank" class="btn btn-primary w-100 mb-2"
onclick="hideModal()"><?php echo $locale['sharetofb']; ?></a>
<a href="https://twitter.com/intent/tweet?url=<?php echo $share_url; ?>"
target="_blank" class="btn btn-dark w-100 mb-2"
onclick="hideModal()"><?php echo $locale['sharetotwitter']; ?></a>
</div>
</div>
</div>
</div>
<!-- end modals -->
<script>
document.addEventListener('DOMContentLoaded', function () {
const shareBtn = document.getElementById('shareBtn');
const shareModal = new bootstrap.Modal(document.getElementById('shareModal'));
const copyLinkBtn = document.getElementById("copyLinkBtn");
const urlToCopy = window.location.href + '?utm_source=website&utm_medium=share_modal&utm_campaign=sharing';
shareBtn.addEventListener('click', function () {
shareModal.show();
});
copyLinkBtn.onclick = function () {
navigator.clipboard.writeText(urlToCopy).then(function () {
alert('<?php echo $locale['urlcopiedtoclipboard'];?>');
shareModal.hide();
}, function (err) {
alert('<?php echo $locale['failedtocopyurl'];?>: ' + err);
});
}
window.hideModal = function () {
shareModal.hide();
}
});
// when the audio is played, send a PUT request to the page to update the playcount
document.addEventListener('DOMContentLoaded', function () {
const audioElement = document.querySelector('audio');
audioElement.addEventListener('play', function () {
fetch(window.location.href, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({mix: '<?php echo $mix->getId(); ?>'}),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
});
});
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "MusicRecording",
"name": "<?php echo $mix->getName(); ?>",
"byArtist": {
"@type": "MusicGroup",
"name": "<?php
$djs = $mix->getDJs();
echo $djs[0]->getName();
?>",
"image": "<?php echo $djs[0]->getImg(); ?>"
},
"inAlbum": {
"@type": "MusicAlbum",
"name": "<?php echo $mix->getName(); ?>"
},<?php
// genre could be blank so we need to check if it is empty
if (!empty($mix->getGenres())) {
?>
"genre": "<?php
$genre = new Genre($mix->getGenres()[0], $db);
echo $genre->get_name();
?>",<?php } ?>
"url": "<?php echo "https://utahsdjs.com/mix/" . $mix->getSlug(); ?>",
"image": "<?php echo $mix->getCover(); ?>",
"duration": "<?php echo $mix->getDuration()['S']; ?>",
<?php
// if recorded is empty, use created; if created is empty, use 2008-01-01;
if (empty($mix->getRecorded())) {
if (empty($mix->getCreated())) {
$recorded = '2008-01-01 00:00:00';
} else {
$recorded = $mix->getCreated();
}
} else {
$recorded = $mix->getRecorded();
} ?>
"datePublished": "<?php echo $recorded; ?>",
"description": "<?php
if (empty($mix->getDescription())) {
$description = 'Listen to ' . $mix->getName() . ' on Utah\'s DJs.';
}
echo $mix->getDescription(); ?>",
"interactionStatistic": {
"@type": "InteractionCounter",
"interactionType": "https://schema.org/ListenAction",
"userInteractionCount": "<?php echo $mix->getPlaycount() + $mix->getDownloads() ?>",
"url": "<?php echo "https://utahsdjs.com/mix/" . $mix->getSlug() . "/download"; ?>"
}
}
</script>
<script>
$(document).ready(function () {
const audio = $('#audio')[0];
const playPauseBtn = $('#play-pause-btn');
const playPauseIcon = playPauseBtn.find('i');
const seekBar = $('#seek-bar');
const currentTime = $('#current-time');
const duration = $('#duration');
function formatTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
seconds = Math.floor(seconds % 60);
if (hours > 0) {
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
} else {
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
}
function togglePlayPause() {
if (audio.paused) {
audio.play();
playPauseIcon.removeClass('fa-play').addClass('fa-pause');
} else {
audio.pause();
playPauseIcon.removeClass('fa-pause').addClass('fa-play');
}
}
audio.addEventListener('loadedmetadata', function () {
seekBar.attr('max', audio.duration);
duration.text(formatTime(audio.duration));
});
playPauseBtn.click(togglePlayPause);
seekBar.on('input', function () {
const time = seekBar.val();
audio.currentTime = time;
});
audio.addEventListener('timeupdate', function () {
seekBar.val(audio.currentTime);
currentTime.text(formatTime(audio.currentTime));
});
audio.addEventListener('ended', function () {
playPauseIcon.removeClass('fa-pause').addClass('fa-play');
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const audioElement = document.querySelector('audio');
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: '<?php echo addslashes($mix->getName()); ?>',
artist: '<?php
$djs = $mix->getDJs();
$djCount = count($djs);
$i = 0;
$djnamelist = [];
foreach ($djs as $dj) {
$djnamelist[] = $dj->getName();
$i++;
}
echo addslashes(implode(", ", $djnamelist));?>',
album: '<?php echo addslashes($mix->getName()); ?>',
artwork: [
{
src: '<?php echo $mix->getCover('small'); ?>',
sizes: '96x96',
type: 'image/jpeg'
},
{
src: '<?php echo $mix->getCover('large'); ?>',
sizes: '128x128',
type: 'image/jpeg'
}
]
});
// Define action handlers
navigator.mediaSession.setActionHandler('play', function () {
audioElement.play();
});
navigator.mediaSession.setActionHandler('pause', function () {
audioElement.pause();
});
audioElement.addEventListener('timeupdate', () => {
// Update the position state
navigator.mediaSession.setPositionState({
duration: audioElement.duration,
playbackRate: audioElement.playbackRate,
position: audioElement.currentTime
});
});
}
});
</script>
<?php }
else { ?>
<div class="row">
<div class="col">
<div class="alert alert-danger" role="alert">
<?php echo $locale['mixNotFound']; ?>
</div>
</div>
</div>
<?php }
?>
</div>
</section>
<?php require_once 'includes/footer.php';