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/public_html/artist_includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/public_html/artist_includes/tracks_management.php
<?php
// Include translation system
require_once __DIR__ . '/../includes/translations.php';

// Include audio token system for signed URLs
require_once __DIR__ . '/../utils/audio_token.php';

// Pagination setup
$page = max(1, intval($_GET['page'] ?? 1));
$per_page = 20;
$offset = ($page - 1) * $per_page;

// Get user's tracks with detailed stats (with pagination)
$tracks_query = $pdo->prepare("
    SELECT 
        mt.*,
        COALESCE(like_count.count, 0) as likes,
        COALESCE(play_count.count, 0) as plays,
        COALESCE(comment_count.count, 0) as comments,
        COALESCE(sales_count.count, 0) as sales,
        COALESCE(sales_revenue.revenue, 0) as revenue
    FROM music_tracks mt
    LEFT JOIN (
        SELECT track_id, COUNT(*) as count
        FROM track_likes
        GROUP BY track_id
    ) like_count ON mt.id = like_count.track_id
    LEFT JOIN (
        SELECT track_id, COUNT(*) as count
        FROM track_plays
        GROUP BY track_id
    ) play_count ON mt.id = play_count.track_id
    LEFT JOIN (
        SELECT track_id, COUNT(*) as count
        FROM track_comments
        GROUP BY track_id
    ) comment_count ON mt.id = comment_count.track_id
    LEFT JOIN (
        SELECT track_id, COUNT(*) as count
        FROM sales
        GROUP BY track_id
    ) sales_count ON mt.id = sales_count.track_id
    LEFT JOIN (
        SELECT track_id, SUM(amount) as revenue
        FROM sales
        GROUP BY track_id
    ) sales_revenue ON mt.id = sales_revenue.track_id
    WHERE mt.user_id = ?
    ORDER BY mt.created_at DESC
    LIMIT ? OFFSET ?
");
$tracks_query->execute([$user_id, $per_page, $offset]);
$user_tracks = $tracks_query->fetchAll();

// Get total count for pagination
$count_query = $pdo->prepare("
    SELECT COUNT(*) as total
    FROM music_tracks mt
    WHERE mt.user_id = ?
");
$count_query->execute([$user_id]);
$total_tracks = $count_query->fetch()['total'];
$total_pages = ceil($total_tracks / $per_page);
?>

<div class="content-section">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
        <h2><i class="fas fa-music"></i> <?= t('tracks.my_tracks') ?> (<?= number_format($total_tracks) ?>)</h2>
        <a href="index.php" class="btn btn-primary">
            <i class="fas fa-plus"></i> <?= t('tracks.create_new_track') ?>
        </a>
    </div>

    <?php if (empty($user_tracks)): ?>
        <div style="text-align: center; padding: 3rem; color: #a0aec0;">
            <i class="fas fa-music" style="font-size: 4rem; margin-bottom: 1rem; opacity: 0.3;"></i>
            <h3><?= t('tracks.no_tracks_yet') ?></h3>
            <p><?= t('tracks.create_first_track') ?></p>
            <a href="index.php" class="btn btn-primary" style="margin-top: 1rem;">
                <i class="fas fa-plus"></i> <?= t('tracks.create_track') ?>
            </a>
        </div>
    <?php else: ?>
        <div class="tracks-grid">
            <?php foreach ($user_tracks as $track): ?>
                <div class="track-item">
                    <!-- Track Thumbnail -->
                    <div class="track-thumbnail">
                        <?php if (!empty($track['cover_image'])): ?>
                            <img src="<?= htmlspecialchars($track['cover_image']) ?>" alt="Cover" style="width: 100%; height: 100%; object-fit: cover; border-radius: 12px;">
                        <?php else: ?>
                            <i class="fas fa-music"></i>
                        <?php endif; ?>
                    </div>

                    <!-- Track Info -->
                    <div class="track-info">
                        <div class="track-title"><?= htmlspecialchars($track['title'] ?: t('tracks.untitled_track')) ?></div>
                        <div class="track-meta">
                            <div><?= t('tracks.status') ?>: 
                                <span style="color: <?= $track['status'] === 'complete' ? '#48bb78' : '#ed8936' ?>;">
                                    <?= t('tracks.status_' . $track['status']) ?>
                                </span>
                            </div>
                            <div><?= t('tracks.created') ?>: <?= date('M j, Y', strtotime($track['created_at'])) ?></div>
                            <?php if ($track['price'] > 0): ?>
                                <div><?= t('tracks.price') ?>: $<?= number_format($track['price'], 2) ?></div>
                            <?php else: ?>
                                <div style="color: #4299e1;"><?= t('tracks.free_track') ?></div>
                            <?php endif; ?>
                        </div>
                        <div class="track-stats">
                            <span><i class="fas fa-play"></i> <?= number_format($track['plays']) ?></span>
                            <span><i class="fas fa-heart"></i> <?= number_format($track['likes']) ?></span>
                            <span><i class="fas fa-comment"></i> <?= number_format($track['comments']) ?></span>
                            <span><i class="fas fa-shopping-cart"></i> <?= number_format($track['sales']) ?></span>
                        </div>
                    </div>

                    <!-- Track Revenue -->
                    <div style="text-align: center;">
                        <div style="font-size: 1.5rem; font-weight: bold; color: #48bb78;">
                            $<?= number_format($track['revenue'] * (1 - $commission_rate), 2) ?>
                        </div>
                        <div style="font-size: 0.9rem; color: #a0aec0;"><?= t('tracks.your_earnings') ?></div>
                        <?php if ($track['revenue'] > 0): ?>
                            <div style="font-size: 0.8rem; color: #cbd5e0; margin-top: 0.25rem;">
                                <?= t('tracks.total') ?>: $<?= number_format($track['revenue'], 2) ?>
                            </div>
                        <?php endif; ?>
                    </div>

                    <!-- Track Actions -->
                    <div class="track-actions">
                        <?php if ($track['status'] === 'complete' && !empty($track['audio_url'])): ?>
                            <button class="btn btn-success play-track-btn"
                                    data-audio-url="<?= htmlspecialchars(getSignedAudioUrl($track['id'])) ?>"
                                    data-title="<?= htmlspecialchars($track['title']) ?>"
                                    data-artist="<?= htmlspecialchars($user['name']) ?>">
                                <i class="fas fa-play"></i> <?= t('btn.play') ?>
                            </button>
                        <?php endif; ?>
                        
                        <button class="btn btn-primary edit-track-btn" 
                                data-track-id="<?= $track['id'] ?>"
                                data-track-title="<?= htmlspecialchars($track['title'] ?: t('tracks.untitled_track'), ENT_QUOTES) ?>"
                                data-track-description="<?= htmlspecialchars($track['prompt'] ?? '', ENT_QUOTES) ?>"
                                data-track-price="<?= $track['price'] ?? 0 ?>"
                                data-track-public="<?= $track['is_public'] ?? 0 ?>">
                            <i class="fas fa-edit"></i> <?= t('btn.edit') ?>
                        </button>
                        
                        <button class="btn btn-warning" onclick="duplicateTrack(<?= $track['id'] ?>)">
                            <i class="fas fa-copy"></i> <?= t('tracks.duplicate') ?>
                        </button>
                        
                        <?php if ($track['status'] === 'complete'): ?>
                            <button class="btn" onclick="toggleVisibility(<?= $track['id'] ?>, <?= $track['is_public'] ?? 0 ?>)">
                                <i class="fas fa-eye<?= ($track['is_public'] ?? 0) ? '' : '-slash' ?>"></i>
                                <?= ($track['is_public'] ?? 0) ? t('tracks.public') : t('tracks.private') ?>
                            </button>
                        <?php endif; ?>
                        
                        <?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
                            <button class="btn btn-danger" onclick="deleteTrack(<?= $track['id'] ?>, '<?= htmlspecialchars($track['title'], ENT_QUOTES) ?>')">
                                <i class="fas fa-trash"></i> <?= t('btn.delete') ?>
                            </button>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
        
        <!-- Pagination Controls -->
        <?php if ($total_pages > 1): ?>
        <div class="pagination-container" style="margin-top: 3rem; text-align: center;">
            <div class="pagination-info" style="margin-bottom: 1rem; color: #a0aec0;">
                <?= t('tracks.showing', ['start' => $offset + 1, 'end' => min($offset + $per_page, $total_tracks), 'total' => number_format($total_tracks)]) ?>
            </div>
            
            <div class="pagination-controls" style="display: flex; justify-content: center; gap: 0.5rem; flex-wrap: wrap;">
                <?php if ($page > 1): ?>
                    <a href="?tab=tracks&page=1" class="btn btn-secondary">
                        <i class="fas fa-angle-double-left"></i> <?= t('tracks.first') ?>
                    </a>
                    <a href="?tab=tracks&page=<?= $page - 1 ?>" class="btn btn-secondary">
                        <i class="fas fa-angle-left"></i> <?= t('tracks.previous') ?>
                    </a>
                <?php endif; ?>
                
                <?php
                $start_page = max(1, $page - 2);
                $end_page = min($total_pages, $page + 2);
                
                for ($i = $start_page; $i <= $end_page; $i++):
                ?>
                    <a href="?tab=tracks&page=<?= $i ?>" 
                       class="btn <?= $i == $page ? 'btn-primary' : 'btn-secondary' ?>">
                        <?= $i ?>
                    </a>
                <?php endfor; ?>
                
                <?php if ($page < $total_pages): ?>
                    <a href="?tab=tracks&page=<?= $page + 1 ?>" class="btn btn-secondary">
                        <?= t('tracks.next') ?> <i class="fas fa-angle-right"></i>
                    </a>
                    <a href="?tab=tracks&page=<?= $total_pages ?>" class="btn btn-secondary">
                        <?= t('tracks.last') ?> <i class="fas fa-angle-double-right"></i>
                    </a>
                <?php endif; ?>
            </div>
        </div>
        <?php endif; ?>
    <?php endif; ?>
</div>

<script>
// Enhanced track management functions
function duplicateTrack(trackId) {
    if (confirm(<?= json_encode(t('tracks.confirm_duplicate')) ?>)) {
        fetch('api_track_management.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ action: 'duplicate', track_id: trackId })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                location.reload();
            } else {
                alert(<?= json_encode(t('tracks.duplicate_failed')) ?> + ': ' + (data.message || <?= json_encode(t('tracks.unknown_error')) ?>));
            }
        })
        .catch(error => {
            console.error('Duplicate error:', error);
            alert(<?= json_encode(t('tracks.duplicate_failed')) ?>);
        });
    }
}

function toggleVisibility(trackId, currentVisibility) {
    const newVisibility = currentVisibility ? 0 : 1;
    const action = newVisibility ? <?= json_encode(t('tracks.make_public')) ?> : <?= json_encode(t('tracks.make_private')) ?>;
    
    if (confirm(<?= json_encode(t('tracks.confirm_visibility')) ?> + ' ' + action + '?')) {
        fetch('api_track_management.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                action: 'toggle_visibility', 
                track_id: trackId, 
                visibility: newVisibility 
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                location.reload();
            } else {
                alert(<?= json_encode(t('tracks.visibility_failed')) ?> + ': ' + (data.message || <?= json_encode(t('tracks.unknown_error')) ?>));
            }
        })
        .catch(error => {
            console.error('Visibility error:', error);
            alert(<?= json_encode(t('tracks.visibility_failed')) ?>);
        });
    }
}

function deleteTrack(trackId, trackTitle) {
    if (confirm(<?= json_encode(t('tracks.confirm_delete')) ?> + ' "' + trackTitle + '"?\n\n' + <?= json_encode(t('tracks.delete_warning')) ?>)) {
        fetch('api_track_management.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                action: 'delete', 
                track_id: trackId 
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // Show success message
                alert(<?= json_encode(t('tracks.delete_success')) ?>);
                location.reload();
            } else {
                alert(<?= json_encode(t('tracks.delete_failed')) ?> + ': ' + (data.message || <?= json_encode(t('tracks.unknown_error')) ?>));
            }
        })
        .catch(error => {
            console.error('Delete error:', error);
            alert(<?= json_encode(t('tracks.delete_failed')) ?>);
        });
    }
}

// Enhanced play button functionality for artist dashboard
function initPlayButtons() {
    // Play button handlers
    const playButtons = document.querySelectorAll('.play-track-btn');
    playButtons.forEach(button => {
        // Remove existing listeners to avoid duplicates
        const newButton = button.cloneNode(true);
        button.parentNode.replaceChild(newButton, button);
        
        newButton.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            
            const audioUrl = this.getAttribute('data-audio-url');
            const title = this.getAttribute('data-title');
            const artist = this.getAttribute('data-artist');
            
            if (!audioUrl || audioUrl === '' || audioUrl === 'NULL' || audioUrl === 'null') {
                alert(<?= json_encode(t('tracks.audio_not_available')) ?>);
                return;
            }
            
            // Ensure audio URL is absolute if it's relative
            let finalAudioUrl = audioUrl;
            if (audioUrl && !audioUrl.startsWith('http') && !audioUrl.startsWith('//')) {
                if (audioUrl.startsWith('/')) {
                    finalAudioUrl = window.location.origin + audioUrl;
                } else {
                    finalAudioUrl = window.location.origin + '/' + audioUrl;
                }
            }
            
            // Check if this track is currently playing (button has 'playing' class)
            const isCurrentlyPlaying = this.classList.contains('playing');
            const globalPlayer = window.enhancedGlobalPlayer;
            
            // If button shows playing state, pause it
            if (isCurrentlyPlaying && globalPlayer && typeof globalPlayer.togglePlayPause === 'function') {
                console.log('🎵 Dashboard: Button shows playing, pausing track');
                
                // Pause the track using togglePlayPause
                globalPlayer.togglePlayPause();
                
                // Update button state
                this.classList.remove('playing');
                this.innerHTML = '<i class="fas fa-play"></i> ' + <?= json_encode(t('btn.play')) ?>;
                
                // Clear playing state from all buttons
                document.querySelectorAll('.play-track-btn').forEach(btn => {
                    if (btn !== this) {
                        btn.classList.remove('playing');
                        const icon = btn.querySelector('i');
                        if (icon && icon.classList.contains('fa-pause')) {
                            btn.innerHTML = '<i class="fas fa-play"></i> ' + <?= json_encode(t('btn.play')) ?>;
                        }
                    }
                });
                
                return;
            }
            
            // Check if this is the same track that's already loaded but paused - resume it instead
            const audioElement = document.getElementById('globalAudioElement');
            if (audioElement && audioElement.src) {
                // Compare by track ID instead of URL (signed URLs have unique tokens)
                const getTrackIdFromUrl = (url) => {
                    if (!url) return null;
                    const match = url.match(/[?&]id=(\d+)/);
                    return match ? match[1] : null;
                };
                
                const currentTrackId = getTrackIdFromUrl(audioElement.src);
                const buttonTrackId = trackId || getTrackIdFromUrl(finalAudioUrl);
                const isSameTrack = currentTrackId && buttonTrackId && currentTrackId === buttonTrackId;
                const isPaused = audioElement.paused;
                
                if (isSameTrack && isPaused) {
                    console.log('🎵 Dashboard: Resuming paused track instead of restarting');
                    
                    // Resume playback using togglePlayPause (which will resume if paused)
                    if (globalPlayer && typeof globalPlayer.togglePlayPause === 'function') {
                        globalPlayer.togglePlayPause();
                    } else {
                        // Fallback: directly play the audio element
                        audioElement.play();
                    }
                    
                    // Update button state
                    document.querySelectorAll('.play-track-btn').forEach(btn => {
                        btn.classList.remove('playing');
                        const icon = btn.querySelector('i');
                        if (icon) {
                            btn.innerHTML = '<i class="fas fa-play"></i> ' + <?= json_encode(t('btn.play')) ?>;
                        }
                    });
                    
                    this.classList.add('playing');
                    this.innerHTML = '<i class="fas fa-pause"></i> ' + <?= json_encode(t('tracks.playing')) ?>;
                    
                    return;
                }
            }
            
            // Clear other playing states
            document.querySelectorAll('.play-track-btn').forEach(btn => {
                btn.classList.remove('playing');
                const icon = btn.querySelector('i');
                if (icon) {
                    btn.innerHTML = '<i class="fas fa-play"></i> ' + <?= json_encode(t('btn.play')) ?>;
                }
            });
            
            // Set this button as playing
            this.classList.add('playing');
            this.innerHTML = '<i class="fas fa-pause"></i> ' + <?= json_encode(t('tracks.playing')) ?>;
            
            // Function to try playing
            function tryPlay() {
                if (typeof window.enhancedGlobalPlayer !== 'undefined' && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
                    try {
                        const success = window.enhancedGlobalPlayer.playTrack(finalAudioUrl, title, artist);
                        if (!success) {
                            throw new Error('Play failed');
                        }
                        return true;
                    } catch (error) {
                        console.error('Play error:', error);
                        return false;
                    }
                } else if (typeof window.playTrack === 'function') {
                    try {
                        window.playTrack(null, finalAudioUrl, title, artist);
                        return true;
                    } catch (error) {
                        console.error('Play error:', error);
                        return false;
                    }
                }
                return false;
            }
            
            // Try to play immediately
            if (!tryPlay()) {
                // Wait for global player to load (retry up to 3 times)
                let retries = 0;
                const retryInterval = setInterval(() => {
                    retries++;
                    if (tryPlay() || retries >= 3) {
                        clearInterval(retryInterval);
                        if (retries >= 3 && !tryPlay()) {
                            alert(<?= json_encode(t('tracks.player_not_available')) ?>);
                            this.classList.remove('playing');
                            this.innerHTML = '<i class="fas fa-play"></i> ' + <?= json_encode(t('btn.play')) ?>;
                        }
                    }
                }, 300);
            }
        });
    });
}

// Initialize on DOM ready
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initPlayButtons);
} else {
    initPlayButtons();
}

// Re-initialize after AJAX loads (for pagination)
document.addEventListener('click', function(e) {
    if (e.target.closest('.pagination-controls a, .pagination-controls .btn')) {
        setTimeout(initPlayButtons, 500);
    }
});

// Initialize edit buttons on DOM ready
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function() {
        initEditButtons();
    });
} else {
    initEditButtons();
}

function initEditButtons() {
    // Edit button handlers
    const editButtons = document.querySelectorAll('.edit-track-btn');
    editButtons.forEach(button => {
        button.addEventListener('click', function(e) {
            e.preventDefault();
            
            const trackId = this.getAttribute('data-track-id');
            const title = this.getAttribute('data-track-title') || <?= json_encode(t('tracks.untitled_track')) ?>;
            const description = this.getAttribute('data-track-description') || '';
            const price = parseFloat(this.getAttribute('data-track-price')) || 0;
            const isPublic = parseInt(this.getAttribute('data-track-public')) || 0;
            
            // Call editTrack function if it exists
            if (typeof window.editTrack === 'function') {
                window.editTrack(trackId, title, description, price, isPublic);
            } else {
                console.error('editTrack function not found');
                alert(<?= json_encode(t('tracks.edit_not_available')) ?>);
            }
        });
    });
}

// Re-initialize edit buttons after pagination
document.addEventListener('click', function(e) {
    if (e.target.closest('.pagination-controls a, .pagination-controls .btn')) {
        setTimeout(initEditButtons, 500);
    }
});
</script> 

CasperSecurity Mini