sessionId = session_id(); $this->uploadDir = __DIR__ . '/uploads/sessions'; $this->sessionDir = $this->uploadDir . '/' . $this->sessionId; // Create session directory if it doesn't exist if (!is_dir($this->sessionDir)) { mkdir($this->sessionDir, 0755, true); mkdir($this->sessionDir . '/images', 0755, true); } // Initialize session data $this->initializeSessionData(); } private function initializeSessionData() { if (!isset($_SESSION['conversation_history'])) { $_SESSION['conversation_history'] = []; } if (!isset($_SESSION['image_history'])) { $_SESSION['image_history'] = []; } if (!isset($_SESSION['current_image_path'])) { $_SESSION['current_image_path'] = null; } } public function getSessionId() { return $this->sessionId; } public function getSessionDir() { return $this->sessionDir; } public function getImagesDir() { return $this->sessionDir . '/images'; } /** * Save image to disk and return file path */ public function saveImage($imageData, $mimeType = 'image/png') { $extension = $this->getExtensionFromMime($mimeType); $timestamp = time(); $filename = 'image_' . $timestamp . '_' . uniqid() . '.' . $extension; $filepath = $this->getImagesDir() . '/' . $filename; // Decode base64 if needed if (base64_decode($imageData, true) !== false) { $imageData = base64_decode($imageData); } // Save image if (file_put_contents($filepath, $imageData) === false) { throw new Exception('Failed to save image to disk'); } // Save metadata $metadataFile = $filepath . '.meta'; $metadata = [ 'created_at' => $timestamp, 'mime_type' => $mimeType, 'session_id' => $this->sessionId, 'expires_at' => $timestamp + 86400 // 24 hours ]; file_put_contents($metadataFile, json_encode($metadata)); return $filename; } /** * Get image data from disk */ public function getImage($filename) { $filepath = $this->getImagesDir() . '/' . $filename; if (!file_exists($filepath)) { return null; } // Check if image has expired $metadataFile = $filepath . '.meta'; if (file_exists($metadataFile)) { $metadata = json_decode(file_get_contents($metadataFile), true); if ($metadata && $metadata['expires_at'] < time()) { // Image expired, delete it $this->deleteImage($filename); return null; } } return [ 'data' => base64_encode(file_get_contents($filepath)), 'mime_type' => $this->getMimeTypeFromFile($filepath) ]; } /** * Delete image from disk */ public function deleteImage($filename) { $filepath = $this->getImagesDir() . '/' . $filename; $metadataFile = $filepath . '.meta'; if (file_exists($filepath)) { unlink($filepath); } if (file_exists($metadataFile)) { unlink($metadataFile); } } /** * Set current image */ public function setCurrentImage($filename, $mimeType = 'image/png') { $_SESSION['current_image_path'] = $filename; $_SESSION['current_image_mime'] = $mimeType; } /** * Get current image */ public function getCurrentImage() { if (!isset($_SESSION['current_image_path']) || !$_SESSION['current_image_path']) { return null; } return $this->getImage($_SESSION['current_image_path']); } /** * Clear current image */ public function clearCurrentImage() { if (isset($_SESSION['current_image_path']) && $_SESSION['current_image_path']) { $this->deleteImage($_SESSION['current_image_path']); } $_SESSION['current_image_path'] = null; $_SESSION['current_image_mime'] = 'image/png'; } /** * Add to conversation history */ public function addToHistory($prompt, $type = 'edit') { $_SESSION['conversation_history'][] = [ 'prompt' => $prompt, 'type' => $type, 'timestamp' => time() ]; // Keep only last 50 items if (count($_SESSION['conversation_history']) > 50) { $_SESSION['conversation_history'] = array_slice($_SESSION['conversation_history'], -50); } } /** * Get conversation history */ public function getHistory() { return $_SESSION['conversation_history'] ?? []; } /** * Clear all session data and images */ public function reset() { // Delete all images in session directory $imagesDir = $this->getImagesDir(); if (is_dir($imagesDir)) { $files = glob($imagesDir . '/*'); foreach ($files as $file) { if (is_file($file)) { unlink($file); } } } // Clear session data $_SESSION['conversation_history'] = []; $_SESSION['image_history'] = []; $_SESSION['current_image_path'] = null; $_SESSION['current_image_mime'] = 'image/png'; } /** * Get file extension from MIME type */ private function getExtensionFromMime($mimeType) { $mimeMap = [ 'image/jpeg' => 'jpg', 'image/jpg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', 'image/gif' => 'gif' ]; return $mimeMap[$mimeType] ?? 'png'; } /** * Get MIME type from file */ private function getMimeTypeFromFile($filepath) { $extension = strtolower(pathinfo($filepath, PATHINFO_EXTENSION)); $extMap = [ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'webp' => 'image/webp', 'gif' => 'image/gif' ]; return $extMap[$extension] ?? 'image/png'; } /** * Static method to clean up expired images across all sessions */ public static function cleanupExpiredImages($uploadDir = null) { if ($uploadDir === null) { $uploadDir = __DIR__ . '/uploads/sessions'; } if (!is_dir($uploadDir)) { return ['cleaned' => 0, 'errors' => []]; } $cleaned = 0; $errors = []; $currentTime = time(); // Scan all session directories $sessionDirs = glob($uploadDir . '/*', GLOB_ONLYDIR); foreach ($sessionDirs as $sessionDir) { $imagesDir = $sessionDir . '/images'; if (!is_dir($imagesDir)) { continue; } // Find all metadata files $metadataFiles = glob($imagesDir . '/*.meta'); foreach ($metadataFiles as $metadataFile) { try { $metadata = json_decode(file_get_contents($metadataFile), true); // Check if expired if ($metadata && isset($metadata['expires_at']) && $metadata['expires_at'] < $currentTime) { // Delete image and metadata $imageFile = str_replace('.meta', '', $metadataFile); if (file_exists($imageFile)) { unlink($imageFile); } unlink($metadataFile); $cleaned++; } } catch (Exception $e) { $errors[] = $e->getMessage(); } } // Remove empty session directories $remainingFiles = glob($imagesDir . '/*'); if (empty($remainingFiles)) { rmdir($imagesDir); rmdir($sessionDir); } } return [ 'cleaned' => $cleaned, 'errors' => $errors, 'timestamp' => date('Y-m-d H:i:s') ]; } }