T.ME/BIBIL_0DAY
CasperSecurity


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/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/wishlist.php
<?php
session_start();
require_once 'includes/translations.php';
require_once 'config/database.php';

if (!isset($_SESSION['user_id'])) {
    header('Location: /auth/login.php');
    exit;
}

$current_page = 'wishlist';
$page_title = t('wishlist.page_title');
$page_description = t('wishlist.page_description');

$pdo = getDBConnection();

try {
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS user_wishlist (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            track_id INT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            UNIQUE KEY unique_wishlist (user_id, track_id),
            FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY (track_id) REFERENCES music_tracks(id) ON DELETE CASCADE
        )
    ");
} catch (Exception $e) {
    error_log('Wishlist table ensure error: ' . $e->getMessage());
}

// OPTIMIZED: Using JOINs instead of correlated subqueries for better performance
$stmt = $pdo->prepare("
    SELECT 
        mt.id,
        mt.title,
        mt.price,
        mt.image_url,
        mt.metadata,
        mt.duration,
        mt.audio_url,
        mt.prompt,
        mt.task_id,
        u.name as artist_name,
        u.id as artist_id,
        uw.created_at as saved_at,
        COALESCE(like_stats.like_count, 0) as like_count,
        COALESCE(play_stats.play_count, 0) as play_count,
        COALESCE(rating_stats.average_rating, 0) as average_rating,
        COALESCE(rating_stats.rating_count, 0) as rating_count
    FROM user_wishlist uw
    INNER JOIN music_tracks mt ON uw.track_id = mt.id
    INNER JOIN users u ON mt.user_id = u.id
    LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) like_stats ON mt.id = like_stats.track_id
    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
    LEFT JOIN (SELECT track_id, AVG(rating) as average_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) rating_stats ON mt.id = rating_stats.track_id
    WHERE uw.user_id = ?
    ORDER BY uw.created_at DESC
");
$stmt->execute([$_SESSION['user_id']]);
$wishlist_tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);

include 'includes/header.php';

function resolveTrackImage($track) {
    $imageUrl = $track['image_url'] ?? null;
    if ($imageUrl) {
        $imageUrl = trim($imageUrl);
        if ($imageUrl === '' || strtolower($imageUrl) === 'null') {
            $imageUrl = null;
        }
    }

    if ($imageUrl && !preg_match('/^https?:\/\//', $imageUrl)) {
        return '/' . ltrim($imageUrl, '/');
    }

    if (!empty($track['metadata'])) {
        $metadata = is_string($track['metadata']) ? json_decode($track['metadata'], true) : $track['metadata'];
        if (isset($metadata['image_url']) && $metadata['image_url']) {
            $metaUrl = $metadata['image_url'];
            if (!preg_match('/^https?:\/\//', $metaUrl)) {
                return '/' . ltrim($metaUrl, '/');
            }
        }
        if (isset($metadata['cover_url']) && $metadata['cover_url']) {
            $metaUrl = $metadata['cover_url'];
            if (!preg_match('/^https?:\/\//', $metaUrl)) {
                return '/' . ltrim($metaUrl, '/');
            }
        }
    }

    if (!empty($track['task_id'])) {
        $uploadsDir = $_SERVER['DOCUMENT_ROOT'] . '/uploads/track_covers/';
        if (is_dir($uploadsDir)) {
            $pattern = $uploadsDir . "track_{$track['task_id']}_*";
            $files = glob($pattern);
            if (!empty($files)) {
                $mostRecent = end($files);
                return '/uploads/track_covers/' . basename($mostRecent);
            }
        }
    }

    return '/assets/images/default-track.jpg';
}
?>

<div class="wishlist-page">
    <div class="container">
        <div class="wishlist-hero">
            <div>
                <p class="wishlist-badge"><i class="fas fa-heart"></i> <?= t('nav.wishlist') ?></p>
                <h1><?= htmlspecialchars(t('wishlist.page_title')) ?></h1>
                <p><?= htmlspecialchars(t('wishlist.page_description')) ?></p>
            </div>
        </div>

        <?php if (empty($wishlist_tracks)): ?>
            <div class="wishlist-empty" id="wishlistEmpty">
                <i class="fas fa-heart-broken"></i>
                <h2><?= t('wishlist.empty_title') ?></h2>
                <p><?= t('wishlist.empty_desc') ?></p>
                <a href="/community_fixed.php" class="btn-primary">
                    <i class="fas fa-compass"></i>
                    <?= t('community.hero_title') ?>
                </a>
            </div>
        <?php else: ?>
            <div class="wishlist-grid" id="wishlistItems">
                <?php foreach ($wishlist_tracks as $track): 
                    $imageUrl = resolveTrackImage($track);
                    $displayTitle = !empty($track['title']) ? $track['title'] : t('community.untitled_track');
                    $duration = $track['duration'] ? gmdate('i:s', $track['duration']) : '0:00';
                    $price = (!empty($track['price']) && floatval($track['price']) > 0) ? number_format(floatval($track['price']), 2) : '1.99';
                    $savedAt = date('M j, Y', strtotime($track['saved_at']));
                ?>
                <div class="wishlist-item" data-track-id="<?= $track['id'] ?>">
                    <div class="wishlist-cover">
                        <img src="<?= htmlspecialchars($imageUrl) ?>" alt="<?= htmlspecialchars($displayTitle) ?>" loading="lazy">
                    </div>
                    <div class="wishlist-info">
                        <div class="wishlist-top-row">
                            <div>
                                <h3><?= htmlspecialchars($displayTitle) ?></h3>
                                <a href="/artist_profile.php?id=<?= $track['artist_id'] ?>" class="wishlist-artist">
                                    <?= htmlspecialchars($track['artist_name']) ?>
                                </a>
                            </div>
                            <div class="wishlist-price">$<?= $price ?></div>
                        </div>
                        <div class="wishlist-meta">
                            <span><i class="fas fa-clock"></i> <?= $duration ?></span>
                            <span><i class="fas fa-play"></i> <?= number_format($track['play_count']) ?></span>
                            <span><i class="fas fa-heart"></i> <?= number_format($track['like_count']) ?></span>
                            <span><i class="fas fa-star"></i> <?= number_format($track['average_rating'], 1) ?>/10</span>
                        </div>
                        <div class="wishlist-actions">
                            <button class="btn-secondary" onclick="toggleWishlist(<?= $track['id'] ?>, this)" aria-pressed="true">
                                <i class="fas fa-times"></i>
                                <?= t('wishlist.remove') ?>
                            </button>
                            <a href="/track.php?id=<?= $track['id'] ?>" class="btn-ghost">
                                <i class="fas fa-external-link-alt"></i>
                                <?= t('wishlist.view_track') ?>
                            </a>
                            <button class="btn-primary" onclick="wishlistAddToCart(<?= $track['id'] ?>, '<?= htmlspecialchars($displayTitle, ENT_QUOTES) ?>', <?= $price ?>, this)">
                                <i class="fas fa-shopping-cart"></i>
                                <?= t('artist_profile.add_to_cart') ?>
                            </button>
                        </div>
                        <div class="wishlist-footer">
                            <span><i class="fas fa-bookmark"></i> <?= t('wishlist.added_on') ?> <?= $savedAt ?></span>
                        </div>
                    </div>
                </div>
                <?php endforeach; ?>
            </div>

            <div class="wishlist-empty" id="wishlistEmpty" style="display:none;">
                <i class="fas fa-heart-broken"></i>
                <h2><?= t('wishlist.empty_title') ?></h2>
                <p><?= t('wishlist.empty_desc') ?></p>
                <a href="/community_fixed.php" class="btn-primary">
                    <i class="fas fa-compass"></i>
                    <?= t('community.hero_title') ?>
                </a>
            </div>
        <?php endif; ?>
    </div>
</div>

<style>
.wishlist-page {
    background: linear-gradient(180deg, #05050b, #0f0f21 35%, #13132b);
    min-height: 100vh;
    padding: 80px 0 140px;
}

.wishlist-page .container {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 24px;
}

.wishlist-hero {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 40px;
    color: white;
    gap: 24px;
}

.wishlist-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.15);
    padding: 0.6rem 1.2rem;
    border-radius: 999px;
    font-size: 1.2rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.wishlist-hero h1 {
    font-size: 3rem;
    margin: 1rem 0 0.5rem;
}

.wishlist-hero p {
    color: #cbd5ff;
    max-width: 540px;
}

.wishlist-empty {
    margin-top: 60px;
    text-align: center;
    color: white;
    padding: 80px 20px;
    border-radius: 24px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
}

.wishlist-empty i {
    font-size: 4rem;
    margin-bottom: 20px;
}

.wishlist-grid {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.wishlist-item {
    display: grid;
    grid-template-columns: minmax(180px, 240px) 1fr;
    gap: 24px;
    background: rgba(15, 15, 32, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 24px;
    padding: 24px;
    align-items: center;
}

.wishlist-cover {
    position: relative;
    border-radius: 20px;
    overflow: hidden;
}

.wishlist-cover img {
    width: 100%;
    height: clamp(200px, 26vw, 260px);
    object-fit: cover;
    display: block;
}

.wishlist-info h3 {
    color: white;
    margin: 0;
}

.wishlist-artist {
    color: #a8b4ff;
    text-decoration: none;
    font-weight: 600;
}

.wishlist-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin: 1rem 0;
    color: #a0a0c0;
}

.wishlist-meta span {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.wishlist-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.wishlist-top-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
}

.wishlist-top-row > div:first-child {
    flex: 1;
    min-width: 0;
}

.wishlist-price {
    font-size: 1.8rem;
    font-weight: 700;
    color: white;
    white-space: nowrap;
}

.btn-secondary, .btn-ghost, .btn-primary {
    border-radius: 12px;
    padding: 0.9rem 1.6rem;
    border: none;
    cursor: pointer;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    text-decoration: none;
    transition: all 0.3s ease;
}

.btn-secondary {
    background: rgba(255, 255, 255, 0.08);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.15);
}

.btn-ghost {
    background: transparent;
    color: #cbd5ff;
    border: 1px solid rgba(203, 213, 255, 0.3);
}

.btn-primary {
    background: linear-gradient(135deg, #667eea, #764ba2);
    color: white;
    border: none;
}

.wishlist-footer {
    margin-top: 1rem;
    color: #a0a0c0;
    font-size: 0.95rem;
}

@media (max-width: 1024px) {
    .wishlist-hero {
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
    }

    .wishlist-item {
        grid-template-columns: 200px 1fr;
        padding: 20px;
    }
}

@media (max-width: 768px) {
    .wishlist-page {
        padding: 60px 0 100px;
    }

    .wishlist-hero h1 {
        font-size: 2.4rem;
    }

    .wishlist-item {
        grid-template-columns: 1fr;
    }
    
    .wishlist-cover img {
        height: clamp(180px, 55vw, 240px);
    }

    .wishlist-top-row {
        flex-direction: column;
        align-items: flex-start;
    }

    .wishlist-price {
        font-size: 1.5rem;
    }
}

@media (max-width: 540px) {
    .wishlist-page .container {
        padding: 0 16px;
    }

    .wishlist-hero {
        text-align: center;
        align-items: center;
    }

    .wishlist-hero h1 {
        font-size: 2rem;
    }

    .wishlist-meta {
        flex-direction: column;
        gap: 0.5rem;
    }

    .wishlist-actions {
        flex-direction: column;
    }

    .wishlist-actions .btn-secondary,
    .wishlist-actions .btn-ghost,
    .wishlist-actions .btn-primary {
        width: 100%;
        justify-content: center;
    }
}
</style>

<script>
function wishlistAddToCart(trackId, title, price, button) {
    if (!trackId) return;
    const originalHTML = button ? button.innerHTML : null;
    if (button) {
        button.disabled = true;
        button.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
    }
    const formData = new FormData();
    formData.append('action', 'add');
    formData.append('track_id', trackId);
    formData.append('artist_plan', 'free');

    fetch('/cart.php', { method: 'POST', body: formData })
        .then(response => response.json())
        .then(data => {
            if (!data.success) throw new Error(data.message || 'Failed to add track to cart');
            notifyWishlist(`"${title}" added to cart!`);
        })
        .catch(error => {
            notifyWishlist(error.message || 'Unable to add to cart', 'error');
        })
        .finally(() => {
            if (button && originalHTML) {
                button.disabled = false;
                button.innerHTML = originalHTML;
            }
        });
}

function notifyWishlist(message, type) {
    if (typeof window.showNotification === 'function') {
        window.showNotification(message, type || 'success');
    } else {
        alert(message);
    }
}

function updateWishlistEmptyState() {
    const container = document.getElementById('wishlistItems');
    const emptyState = document.getElementById('wishlistEmpty');
    if (!container || !emptyState) return;
    const hasItems = container.querySelector('.wishlist-item') !== null;
    emptyState.style.display = hasItems ? 'none' : 'flex';
}

window.addEventListener('wishlist:toggled', function(event) {
    if (!event.detail || event.detail.added) return;
    const item = document.querySelector(`.wishlist-item[data-track-id="${event.detail.trackId}"]`);
    if (item) {
        item.style.opacity = '0';
        setTimeout(() => {
            item.remove();
            updateWishlistEmptyState();
        }, 200);
    }
});

document.addEventListener('DOMContentLoaded', updateWishlistEmptyState);
</script>

<?php include 'includes/footer.php'; ?>


CasperSecurity Mini