Файловый менеджер - Редактировать - /home/gqdcvggs/.trash/profile.php
Назад
<?php require_once 'config.php'; $profile_id = isset($_GET['id']) ? (int)$_GET['id'] : ($_SESSION['user_id'] ?? null); if(!$profile_id) { header('Location: login.php'); exit; } // Récupération de l'utilisateur avec ses stats $stmt = $pdo->prepare(" SELECT u.*, COUNT(DISTINCT c.id) as total_videos, COUNT(DISTINCT CASE WHEN i.type = 'view' THEN i.id END) as total_views, COUNT(DISTINCT CASE WHEN i.type = 'like' THEN i.id END) as total_likes, COUNT(DISTINCT CASE WHEN i.type = 'comment' THEN i.id END) as total_comments, COUNT(DISTINCT p.id) as total_photos FROM users u LEFT JOIN content c ON u.id = c.author_id LEFT JOIN interactions i ON c.id = i.content_id LEFT JOIN photos p ON u.id = p.user_id WHERE u.id = ? GROUP BY u.id "); $stmt->execute([$profile_id]); $user = $stmt->fetch(); if(!$user) { header('Location: index.php'); exit; } $isOwnProfile = isset($_SESSION['user_id']) && $_SESSION['user_id'] == $profile_id; // Gestion des uploads et mises à jour if($isOwnProfile) { // Update profil (bio et réseaux sociaux) if(isset($_POST['update_profile'])) { $bio = trim($_POST['bio'] ?? ''); $twitter = trim($_POST['twitter_url'] ?? ''); $instagram = trim($_POST['instagram_url'] ?? ''); $stmt = $pdo->prepare("UPDATE users SET bio = ?, twitter_url = ?, instagram_url = ? WHERE id = ?"); $stmt->execute([$bio, $twitter, $instagram, $profile_id]); $user['bio'] = $bio; $user['twitter_url'] = $twitter; $user['instagram_url'] = $instagram; } // Upload avatar if(isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) { $uploadDir = 'uploads/avatars/'; if (!file_exists($uploadDir)) mkdir($uploadDir, 0777, true); $fileName = uniqid() . '_' . basename($_FILES['avatar']['name']); $uploadPath = $uploadDir . $fileName; if(move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadPath)) { if($user['avatar_url'] && file_exists($user['avatar_url'])) unlink($user['avatar_url']); $stmt = $pdo->prepare("UPDATE users SET avatar_url = ? WHERE id = ?"); $stmt->execute([$uploadPath, $profile_id]); $user['avatar_url'] = $uploadPath; } } // Upload photo if(isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) { $uploadDir = 'uploads/photos/'; if (!file_exists($uploadDir)) mkdir($uploadDir, 0777, true); $photoName = uniqid() . '_' . basename($_FILES['photo']['name']); $uploadPath = $uploadDir . $photoName; if(move_uploaded_file($_FILES['photo']['tmp_name'], $uploadPath)) { $caption = isset($_POST['caption']) ? trim($_POST['caption']) : ''; $stmt = $pdo->prepare("INSERT INTO photos (user_id, image_url, caption) VALUES (?, ?, ?)"); $stmt->execute([$profile_id, $uploadPath, $caption]); } } // Suppression vidéo if(isset($_POST['delete_video'])) { $video_id = (int)$_POST['video_id']; // Supprimer les interactions $stmt = $pdo->prepare("DELETE FROM interactions WHERE content_id = ?"); $stmt->execute([$video_id]); // Supprimer la vidéo $stmt = $pdo->prepare("SELECT url_video, picture_cover FROM content WHERE id = ? AND author_id = ?"); $stmt->execute([$video_id, $profile_id]); $video = $stmt->fetch(); if($video) { if(file_exists($video['url_video'])) unlink($video['url_video']); if(file_exists($video['picture_cover'])) unlink($video['picture_cover']); $stmt = $pdo->prepare("DELETE FROM content WHERE id = ?"); $stmt->execute([$video_id]); } } // Suppression photo if(isset($_POST['delete_photo'])) { $photo_id = (int)$_POST['photo_id']; $stmt = $pdo->prepare("SELECT image_url FROM photos WHERE id = ? AND user_id = ?"); $stmt->execute([$photo_id, $profile_id]); $photo = $stmt->fetch(); if($photo && file_exists($photo['image_url'])) { unlink($photo['image_url']); $stmt = $pdo->prepare("DELETE FROM photos WHERE id = ?"); $stmt->execute([$photo_id]); } } } // Récupérer les vidéos avec stats $videoQuery = $pdo->prepare(" SELECT c.*, COUNT(DISTINCT CASE WHEN i.type = 'view' THEN i.id END) as views, COUNT(DISTINCT CASE WHEN i.type = 'like' THEN i.id END) as likes, COUNT(DISTINCT CASE WHEN i.type = 'comment' THEN i.id END) as comments, MAX(CASE WHEN i.user_id = ? AND i.type IN ('like', 'dislike') THEN i.type END) as user_interaction FROM content c LEFT JOIN interactions i ON c.id = i.content_id WHERE c.author_id = ? GROUP BY c.id ORDER BY c.created_at DESC "); $videoQuery->execute([$_SESSION['user_id'] ?? null, $profile_id]); $videos = $videoQuery->fetchAll(); // Récupérer les photos $photoQuery = $pdo->prepare(" SELECT p.*, DATE_FORMAT(p.created_at, '%M %d, %Y') as formatted_date FROM photos p WHERE p.user_id = ? ORDER BY p.created_at DESC "); $photoQuery->execute([$profile_id]); $photos = $photoQuery->fetchAll(); // Stats mensuelles pour les graphiques $monthlyStatsQuery = $pdo->prepare(" SELECT DATE_FORMAT(i.created_at, '%Y-%m') as month, COUNT(DISTINCT CASE WHEN i.type = 'view' THEN i.id END) as views, COUNT(DISTINCT CASE WHEN i.type = 'like' THEN i.id END) as likes, COUNT(DISTINCT CASE WHEN i.type = 'comment' THEN i.id END) as comments FROM content c LEFT JOIN interactions i ON c.id = i.content_id WHERE c.author_id = ? GROUP BY DATE_FORMAT(i.created_at, '%Y-%m') ORDER BY month DESC LIMIT 12 "); $monthlyStatsQuery->execute([$profile_id]); $monthlyStats = array_reverse($monthlyStatsQuery->fetchAll()); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= htmlspecialchars($user['username']) ?> - ForMore</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Titillium+Web:wght@200;300;400;600;700;900&display=swap" rel="stylesheet"> <style> body { font-family: 'Titillium Web', sans-serif; } .formore { font-weight: 900; background: linear-gradient(to right, #3b82f6, #1d4ed8); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .hover-scale { transition: all 0.3s ease; } .hover-scale:hover { transform: scale(1.02); } .modal-animation { animation: modalIn 0.3s ease-out; } @keyframes modalIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } </style> </head> <body class="bg-gradient-to-br from-black to-blue-900 min-h-screen text-white"> <nav class="fixed top-0 left-0 right-0 bg-black/50 backdrop-blur-sm z-50"> <div class="max-w-7xl mx-auto px-4 py-4"> <div class="flex justify-between items-center"> <a href="index.php" class="text-4xl formore">ForMore</a> <div class="flex items-center gap-6"> <?php if(isset($_SESSION['user_id'])): ?> <?php if(!$isOwnProfile): ?> <a href="profile.php" class="text-gray-300 hover:text-white transition-colors">My Profile</a> <?php endif; ?> <a href="upload.php" class="bg-blue-600 hover:bg-blue-700 px-6 py-2 rounded-xl transition-all">Upload</a> <a href="logout.php" class="text-red-400 hover:text-red-300">Logout</a> <?php else: ?> <a href="login.php" class="text-blue-400 hover:text-blue-300">Login</a> <a href="signup.php" class="bg-blue-600 hover:bg-blue-700 px-6 py-2 rounded-xl transition-all">Sign Up</a> <?php endif; ?> </div> </div> </div> </nav> <main class="max-w-7xl mx-auto px-4 pt-24 pb-8"> <!-- Profile Header --> <div class="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-8 mb-8"> <div class="flex flex-col lg:flex-row items-center gap-8"> <!-- Avatar --> <div class="relative group"> <?php if($user['avatar_url']): ?> <img src="<?= htmlspecialchars($user['avatar_url']) ?>" class="w-32 h-32 rounded-full object-cover"> <?php else: ?> <div class="w-32 h-32 rounded-full bg-gray-700 flex items-center justify-center text-4xl font-bold"> <?= strtoupper(substr($user['username'], 0, 1)) ?> </div> <?php endif; ?> <?php if($isOwnProfile): ?> <form id="avatarForm" class="hidden"> <input type="file" name="avatar" id="avatarInput" accept="image/*"> </form> <button onclick="document.getElementById('avatarInput').click()" class="absolute inset-0 bg-black/50 rounded-full opacity-0 group-hover:opacity-100 transition-all flex items-center justify-center"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"/> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"/> </svg> </button> <?php endif; ?> </div> <div class="flex-grow text-center lg:text-left"> <div class="flex items-center justify-center lg:justify-start gap-4"> <h1 class="text-3xl font-bold"><?= htmlspecialchars($user['username']) ?></h1> <?php if($isOwnProfile): ?> <button onclick="toggleEditMode()" class="text-blue-400 hover:text-blue-300"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/> </svg> </button> <?php endif; ?> </div> <!-- Bio --> <div id="bioView" class="mt-4"> <p class="text-gray-300"><?= $user['bio'] ? nl2br(htmlspecialchars($user['bio'])) : 'No bio yet.' ?></p> <?php if($user['twitter_url'] || $user['instagram_url']): ?> <div class="flex gap-4 mt-4 justify-center lg:justify-start"> <?php if($user['twitter_url']): ?> <a href="<?= htmlspecialchars($user['twitter_url']) ?>" target="_blank" class="text-blue-400 hover:text-blue-300 flex items-center gap-2"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z"/> </svg> Twitter </a> <?php endif; ?> <?php if($user['instagram_url']): ?> <a href="<?= htmlspecialchars($user['instagram_url']) ?>" target="_blank" class="text-pink-400 hover:text-pink-300 flex items-center gap-2"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/> </svg> Instagram </a> <?php endif; ?> </div> <?php endif; ?> </div> <!-- Stats --> <div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mt-6"> <div class="bg-gray-900/50 rounded-xl p-4 text-center hover-scale"> <div class="text-2xl font-bold"><?= number_format($user['total_videos']) ?></div> <div class="text-gray-400">Videos</div> </div> <div class="bg-gray-900/50 rounded-xl p-4 text-center hover-scale"> <div class="text-2xl font-bold"><?= number_format($user['total_views']) ?></div> <div class="text-gray-400">Views</div> </div> <div class="bg-gray-900/50 rounded-xl p-4 text-center hover-scale"> <div class="text-2xl font-bold"><?= number_format($user['total_likes']) ?></div> <div class="text-gray-400">Likes</div> </div> <div class="bg-gray-900/50 rounded-xl p-4 text-center hover-scale"> <div class="text-2xl font-bold"><?= number_format($user['total_photos']) ?></div> <div class="text-gray-400">Photos</div> </div> </div> </div> </div> </div> <!-- Content Tabs --> <div class="flex gap-6 mb-8"> <button onclick="switchTab('videos')" id="videosTab" class="text-xl font-bold pb-2 border-b-2 border-blue-500">Videos</button> <button onclick="switchTab('photos')" id="photosTab" class="text-xl font-bold pb-2 border-b-2 border-transparent">Photos</button> </div> <!-- Videos Grid --> <div id="videosContent" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"> <?php foreach($videos as $video): ?> <div class="bg-gray-800/50 backdrop-blur-sm rounded-xl overflow-hidden hover-scale"> <div class="relative aspect-video cursor-pointer" onclick="window.location.href='index.php?v=<?= $video['id'] ?>'"> <img src="<?= htmlspecialchars($video['picture_cover']) ?>" class="w-full h-full object-cover"> <div class="absolute inset-0 bg-black/50 opacity-0 hover:opacity-100 transition-opacity flex items-center justify-center"> <svg class="w-16 h-16" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"/> </svg> </div> <div class="absolute bottom-2 right-2 bg-black/70 backdrop-blur-sm px-3 py-1 rounded-lg text-sm"> <?= htmlspecialchars($video['time']) ?> </div> </div> <div class="p-4"> <h3 class="font-bold text-lg truncate"><?= htmlspecialchars($video['name']) ?></h3> <p class="text-gray-400 text-sm mt-2 line-clamp-2"><?= htmlspecialchars($video['description']) ?></p> <div class="flex justify-between mt-4"> <div class="flex items-center gap-4 text-sm text-gray-400"> <span><?= number_format($video['views']) ?> views</span> <span><?= number_format($video['likes']) ?> likes</span> </div> <?php if($isOwnProfile): ?> <div class="flex gap-2"> <a href="edit_video.php?id=<?= $video['id'] ?>" class="p-2 bg-blue-600 hover:bg-blue-700 rounded-lg">Edit</a> <button onclick="confirmDelete(<?= $video['id'] ?>)" class="p-2 bg-red-600 hover:bg-red-700 rounded-lg">Delete</button> </div> <?php endif; ?> </div> </div> </div> <?php endforeach; ?> </div> <!-- Photos Grid --> <div id="photosContent" class="hidden"> <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> <?php foreach($photos as $photo): ?> <div class="relative aspect-square rounded-xl overflow-hidden group hover-scale cursor-pointer" onclick="showPhoto('<?= htmlspecialchars($photo['image_url']) ?>', '<?= htmlspecialchars($photo['caption']) ?>')"> <img src="<?= htmlspecialchars($photo['image_url']) ?>" class="w-full h-full object-cover"> <div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity"> <?php if($photo['caption']): ?> <div class="absolute bottom-0 p-4"> <p class="text-sm"><?= htmlspecialchars($photo['caption']) ?></p> </div> <?php endif; ?> <?php if($isOwnProfile): ?> <form method="POST" class="absolute top-2 right-2" onclick="event.stopPropagation()"> <input type="hidden" name="photo_id" value="<?= $photo['id'] ?>"> <button type="submit" name="delete_photo" class="p-2 bg-red-600 hover:bg-red-700 rounded-lg"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/> </svg> </button> </form> <?php endif; ?> </div> </div> <?php endforeach; ?> </div> <?php if($isOwnProfile): ?> <button onclick="document.getElementById('uploadPhotoModal').classList.remove('hidden')" class="fixed bottom-8 right-8 bg-blue-600 hover:bg-blue-700 p-4 rounded-full shadow-lg"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/> </svg> </button> <?php endif; ?> </div> </main> <!-- Modals --> <?php if($isOwnProfile): ?> <!-- Upload Photo Modal --> <div id="uploadPhotoModal" class="fixed inset-0 bg-black/90 backdrop-blur-sm hidden items-center justify-center p-4 z-50"> <div class="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-6 max-w-lg w-full modal-animation"> <form method="POST" enctype="multipart/form-data" class="space-y-4"> <div class="flex justify-between items-center"> <h3 class="text-xl font-bold">Upload Photo</h3> <button type="button" onclick="this.closest('#uploadPhotoModal').classList.add('hidden')" class="text-gray-400">×</button> </div> <input type="file" name="photo" accept="image/*" required> <input type="text" name="caption" placeholder="Add a caption..." class="w-full bg-gray-900/50 rounded-xl p-4"> <button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 p-4 rounded-xl">Upload</button> </form> </div> </div> <!-- Delete Confirmation Modal --> <div id="deleteModal" class="fixed inset-0 bg-black/90 backdrop-blur-sm hidden items-center justify-center p-4 z-50"> <div class="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-6 max-w-md w-full modal-animation"> <h3 class="text-xl font-bold mb-4">Delete Video</h3> <p class="text-gray-300 mb-6">Are you sure? This action cannot be undone.</p> <div class="flex gap-4"> <form method="POST" class="flex-1"> <input type="hidden" name="video_id" id="deleteVideoId"> <button type="submit" name="delete_video" class="w-full bg-red-600 hover:bg-red-700 p-4 rounded-xl"> Delete </button> </form> <button onclick="closeDeleteModal()" class="flex-1 bg-gray-700 hover:bg-gray-600 p-4 rounded-xl"> Cancel </button> </div> </div> </div> <?php endif; ?> <!-- Photo Viewer Modal --> <div id="photoModal" class="fixed inset-0 bg-black/90 backdrop-blur-sm hidden items-center justify-center p-4 z-50"> <img id="modalImage" src="" alt="" class="max-h-[90vh] max-w-[90vw] rounded-xl"> <p id="modalCaption" class="absolute bottom-8 left-1/2 -translate-x-1/2 text-center bg-black/70 backdrop-blur-sm px-4 py-2 rounded-xl"></p> <button onclick="closePhotoModal()" class="absolute top-4 right-4 text-gray-400 hover:text-white"> <svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> </button> </div> <script> // Avatar Upload document.getElementById('avatarInput')?.addEventListener('change', function() { const formData = new FormData(document.getElementById('avatarForm')); fetch(window.location.href, { method: 'POST', body: formData }).then(() => location.reload()); }); // Content Tabs function switchTab(tab) { document.getElementById('videosContent').classList.toggle('hidden', tab !== 'videos'); document.getElementById('photosContent').classList.toggle('hidden', tab !== 'photos'); document.getElementById('videosTab').classList.toggle('border-blue-500', tab === 'videos'); document.getElementById('photosTab').classList.toggle('border-blue-500', tab === 'photos'); } // Photo Modal function showPhoto(url, caption) { document.getElementById('modalImage').src = url; document.getElementById('modalCaption').textContent = caption; document.getElementById('photoModal').classList.remove('hidden'); document.getElementById('photoModal').classList.add('flex'); document.body.style.overflow = 'hidden'; } function closePhotoModal() { document.getElementById('photoModal').classList.add('hidden'); document.getElementById('photoModal').classList.remove('flex'); document.body.style.overflow = 'auto'; } // Delete Modal function confirmDelete(videoId) { document.getElementById('deleteVideoId').value = videoId; document.getElementById('deleteModal').classList.remove('hidden'); document.getElementById('deleteModal').classList.add('flex'); document.body.style.overflow = 'hidden'; } function closeDeleteModal() { document.getElementById('deleteModal').classList.add('hidden'); document.getElementById('deleteModal').classList.remove('flex'); document.body.style.overflow = 'auto'; } // Close modals on escape document.addEventListener('keydown', e => { if (e.key === 'Escape') { document.querySelectorAll('.modal').forEach(modal => { modal.classList.add('hidden'); modal.classList.remove('flex'); }); document.body.style.overflow = 'auto'; } }); </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка