![]() 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/api/ |
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
header('Content-Type: application/json; charset=utf-8');
try {
$pdo = getDBConnection();
// Get popular genres from all possible sources (metadata.genre, metadata.style, mt.genre)
$stmt = $pdo->prepare("
SELECT
COALESCE(
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))), ''),
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))), ''),
NULLIF(TRIM(mt.genre), ''),
'Unknown'
) as genre,
COUNT(DISTINCT mt.id) as track_count,
COALESCE(SUM(play_stats.play_count), 0) as total_plays
FROM music_tracks mt
LEFT JOIN (
SELECT track_id, COUNT(*) as play_count
FROM track_plays
GROUP BY track_id
) play_stats ON mt.id = play_stats.track_id
WHERE mt.status = 'complete'
AND mt.is_public = 1
AND mt.audio_url IS NOT NULL
AND mt.audio_url != ''
AND (
JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre')) IS NOT NULL
OR JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style')) IS NOT NULL
OR mt.genre IS NOT NULL
)
AND COALESCE(
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))), ''),
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))), ''),
NULLIF(TRIM(mt.genre), ''),
''
) != ''
AND COALESCE(
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))), ''),
NULLIF(TRIM(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))), ''),
NULLIF(TRIM(mt.genre), ''),
''
) != 'Unknown'
GROUP BY genre
HAVING track_count >= 1
ORDER BY total_plays DESC, track_count DESC
LIMIT 24
");
$stmt->execute();
$genres = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Also get genres from user_profiles if available
try {
$profile_genres_stmt = $pdo->prepare("
SELECT DISTINCT
JSON_UNQUOTE(JSON_EXTRACT(genres, CONCAT('$[', idx, ']'))) as genre
FROM user_profiles,
(SELECT 0 as idx UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) as indices
WHERE genres IS NOT NULL
AND JSON_UNQUOTE(JSON_EXTRACT(genres, CONCAT('$[', idx, ']'))) IS NOT NULL
AND JSON_UNQUOTE(JSON_EXTRACT(genres, CONCAT('$[', idx, ']'))) != ''
");
$profile_genres_stmt->execute();
$profile_genres = $profile_genres_stmt->fetchAll(PDO::FETCH_COLUMN);
// Merge profile genres with track genres
$existing_genres = array_column($genres, 'genre');
foreach ($profile_genres as $profile_genre) {
$profile_genre = trim($profile_genre);
if (!empty($profile_genre) && !in_array($profile_genre, $existing_genres)) {
// Add genre with 0 tracks if not already in list
$genres[] = [
'genre' => $profile_genre,
'track_count' => 0,
'total_plays' => 0
];
}
}
} catch (Exception $e) {
// If user_profiles.genres doesn't exist or has issues, continue without it
error_log("Could not fetch profile genres: " . $e->getMessage());
}
// Helper function to normalize genre names (handles "Hip Hop" vs "Hip-Hop" etc.)
function normalizeGenreName($name) {
// Normalize spaces and hyphens - treat "Hip Hop", "Hip-Hop", "HipHop" as the same
$normalized = preg_replace('/[\s\-_]+/', ' ', $name);
$normalized = trim($normalized);
return $normalized;
}
// Helper function to properly capitalize genre names
function capitalizeGenreName($name) {
// Handle special cases like "R&B", "EDM", etc.
$specialCases = ['R&B', 'EDM', 'IDM', 'UKG', 'UK Garage'];
$nameUpper = strtoupper($name);
foreach ($specialCases as $special) {
if (strtoupper($special) === $nameUpper) {
return $special;
}
}
// Handle compound genres like "Deep House", "Hip Hop", etc.
$words = explode(' ', $name);
$capitalized = array_map(function($word) {
// Don't capitalize if it's all caps (like "EDM" in "Deep EDM House")
if (strtoupper($word) === $word && strlen($word) > 1) {
return $word;
}
return ucfirst(strtolower($word));
}, $words);
return implode(' ', $capitalized);
}
// Remove duplicates and format - normalize variations like "Hip Hop" vs "Hip-Hop"
// BUT keep the version that has the most tracks (not just normalize to space version)
$unique_genres = [];
foreach ($genres as $genre) {
$genre_name = trim($genre['genre']);
if (empty($genre_name) || $genre_name === 'Unknown') continue;
// Normalize the genre name for comparison (handles spaces, hyphens, underscores)
$genre_normalized = normalizeGenreName($genre_name);
// Use normalized lowercase as key to merge duplicates
$genre_key = strtolower($genre_normalized);
$track_count = (int)($genre['track_count'] ?? 0);
$total_plays = (int)($genre['total_plays'] ?? 0);
if (!isset($unique_genres[$genre_key])) {
// First time seeing this genre - keep the original format
$unique_genres[$genre_key] = [
'name' => capitalizeGenreName($genre_name), // Keep original format
'track_count' => $track_count,
'total_plays' => $total_plays,
'original_name' => $genre_name // Store original for comparison
];
} else {
// Merge if duplicate found - KEEP THE VERSION WITH MORE TRACKS
$existing_count = $unique_genres[$genre_key]['track_count'];
$existing_plays = $unique_genres[$genre_key]['total_plays'];
// If this version has more tracks, use it instead
if ($track_count > $existing_count ||
($track_count === $existing_count && $total_plays > $existing_plays)) {
$unique_genres[$genre_key]['name'] = capitalizeGenreName($genre_name);
$unique_genres[$genre_key]['original_name'] = $genre_name;
}
// Always merge counts (add them together since they're the same genre)
$unique_genres[$genre_key]['track_count'] = max($existing_count, $track_count);
$unique_genres[$genre_key]['total_plays'] = max($existing_plays, $total_plays);
}
}
// Convert to array first
$formatted_genres = array_values($unique_genres);
// Only add default genres that actually have tracks in the database
// Check database for these genres before adding them
$default_genres_to_check = [
'Hip-Hop', 'Hip Hop', 'Rap',
'Electronic', 'House', 'Techno', 'Pop', 'Rock', 'Jazz',
'Classical', 'Ambient', 'Trance', 'Dubstep', 'R&B',
'Reggae', 'Country', 'Folk', 'Blues', 'Funk', 'Disco',
'Drum & Bass', 'Progressive', 'Chillout', 'Lofi', 'EDM',
'Trap', 'Indie', 'Alternative', 'Metal', 'Punk', 'Soul'
];
$existing_genre_keys = array_map(function($g) {
return strtolower(normalizeGenreName($g['name']));
}, $formatted_genres);
// Check which default genres actually have tracks in database
foreach ($default_genres_to_check as $default_genre) {
$default_normalized = normalizeGenreName($default_genre);
$default_key = strtolower($default_normalized);
$found = false;
// Check if genre already exists in our list
foreach ($existing_genre_keys as $existing_key) {
if ($existing_key === $default_key) {
$found = true;
break;
}
}
// If not found, check if it exists in database with tracks
if (!$found) {
try {
$check_stmt = $pdo->prepare("
SELECT COUNT(*) as track_count
FROM music_tracks mt
WHERE mt.status = 'complete'
AND mt.is_public = 1
AND mt.audio_url IS NOT NULL
AND mt.audio_url != ''
AND (
LOWER(mt.genre) LIKE ?
OR LOWER(mt.tags) LIKE ?
OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.genre'))) LIKE ?
OR LOWER(JSON_UNQUOTE(JSON_EXTRACT(mt.metadata, '$.style'))) LIKE ?
OR LOWER(mt.title) LIKE ?
)
LIMIT 1
");
$genre_like = '%' . strtolower($default_genre) . '%';
$check_stmt->execute([
$genre_like, $genre_like, $genre_like, $genre_like, $genre_like
]);
$result = $check_stmt->fetch(PDO::FETCH_ASSOC);
$has_tracks = ($result && $result['track_count'] > 0);
// Only add if it has tracks in database
if ($has_tracks) {
$formatted_genres[] = [
'name' => capitalizeGenreName($default_genre),
'track_count' => (int)$result['track_count'],
'total_plays' => 0
];
}
} catch (Exception $e) {
// If check fails, don't add the genre
error_log("Error checking default genre '$default_genre': " . $e->getMessage());
}
}
}
// Sort genres
usort($formatted_genres, function($a, $b) {
// Prioritize genres with tracks, then by plays
if ($a['track_count'] > 0 && $b['track_count'] === 0) return -1;
if ($a['track_count'] === 0 && $b['track_count'] > 0) return 1;
if ($b['total_plays'] !== $a['total_plays']) {
return $b['total_plays'] - $a['total_plays'];
}
return $b['track_count'] - $a['track_count'];
});
// Limit to top 30 (increased to show more genres including defaults)
$formatted_genres = array_slice($formatted_genres, 0, 30);
// Convert 'name' to 'genre' for frontend compatibility
$response_genres = array_map(function($g) {
return [
'name' => $g['name'],
'genre' => $g['name'], // Also include as 'genre' for compatibility
'track_count' => $g['track_count'],
'total_plays' => $g['total_plays']
];
}, $formatted_genres);
echo json_encode([
'success' => true,
'genres' => $response_genres
], JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
error_log("Error fetching popular genres: " . $e->getMessage());
echo json_encode([
'success' => false,
'error' => 'Failed to fetch popular genres'
], JSON_UNESCAPED_UNICODE);
}
?>