soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} //default whereclause list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,''); //BUILD UP PARTNERHIERARCHY FROM USER $partner_hierarchy = $condition; //QUERY AND VERIFY ALLOWED if (isAllowed('marketing',$profile,$permission,'C') === 1){ if (!isset($_FILES['file'])) { echo json_encode(['success' => false, 'error' => 'No file uploaded']); exit; } $file = $_FILES['file']; $folder_id = $_POST['folder_id'] ?? ''; $tags = isset($_POST['tags']) ? json_decode($_POST['tags'], true) : []; $title = $_POST['title'] ?? pathinfo($file['name'], PATHINFO_FILENAME); // Validate file type $allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'mp4', 'mov', 'avi']; $filename = $file['name']; $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); if (!in_array($ext, $allowedTypes)) { echo json_encode(['success' => false, 'error' => 'Invalid file type. Allowed: ' . implode(', ', $allowedTypes)]); exit; } $imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp']; $isImage = in_array($ext, $imageTypes); // For images over 10MB, automatically compress if ($isImage && $file['size'] > 10000000) { $compressed = compressImage($file['tmp_name'], $ext, 10000000); if ($compressed === false) { echo json_encode(['success' => false, 'error' => 'Failed to compress large image. Please reduce file size manually.']); exit; } // Update file size after compression $file['size'] = filesize($file['tmp_name']); } // Non-images must be under 10MB if (!$isImage && $file['size'] > 10000000) { echo json_encode(['success' => false, 'error' => 'File too large. Maximum size is 10MB.']); exit; } // Create unique filename $unique_filename = uniqid() . '_' . time() . '.' . $ext; $target_dir = dirname(__FILE__, 4) . "/marketing/uploads/"; $target_file = $target_dir . $unique_filename; $logical_path = "marketing/uploads/" . $unique_filename; // Ensure upload directory exists if (!file_exists($target_dir)) { mkdir($target_dir, 0755, true); } if (move_uploaded_file($file['tmp_name'], $target_file)) { // Generate thumbnail for images $thumbnail_path = null; if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) { $thumb_dir = $target_dir . "thumbs/"; if (!file_exists($thumb_dir)) { mkdir($thumb_dir, 0755, true); } $thumbnail_file = $thumb_dir . $unique_filename; if (generateThumbnail($target_file, $thumbnail_file, 200, 200)) { $thumbnail_path = "marketing/uploads/thumbs/" . $unique_filename; } } // Insert into database $insert_sql = 'INSERT INTO `marketing_files` (`title`, `original_filename`, `file_path`, `thumbnail_path`, `file_type`, `file_size`, `folder_id`, `tags`, `createdby`, `accounthierarchy`) VALUES (?,?,?,?,?,?,?,?,?,?)'; $stmt = $pdo->prepare($insert_sql); $stmt->execute([ $title, $filename, $logical_path, $thumbnail_path, $ext, $file['size'], $folder_id, json_encode($tags), $username, $partner_hierarchy ]); $file_id = $pdo->lastInsertId(); // Insert tags into separate table if (!empty($tags)) { $tag_sql = 'INSERT IGNORE INTO `marketing_tags` (`tag_name`) VALUES (?)'; $tag_stmt = $pdo->prepare($tag_sql); $file_tag_sql = 'INSERT INTO `marketing_file_tags` (`file_id`, `tag_id`) SELECT ?, id FROM marketing_tags WHERE tag_name = ?'; $file_tag_stmt = $pdo->prepare($file_tag_sql); foreach ($tags as $tag) { $tag_stmt->execute([trim($tag)]); $file_tag_stmt->execute([$file_id, trim($tag)]); } } echo json_encode([ 'success' => true, 'file_id' => $file_id, 'path' => $logical_path, 'thumbnail' => $thumbnail_path, 'message' => 'File uploaded successfully' ]); } else { echo json_encode(['success' => false, 'error' => 'Failed to move uploaded file']); } } else { echo json_encode(['success' => false, 'error' => 'Insufficient permissions']); } // Function to compress large images function compressImage($source, $ext, $maxSize) { $info = @getimagesize($source); if ($info === false) return false; $mime = $info['mime']; // Load image switch ($mime) { case 'image/jpeg': $image = @imagecreatefromjpeg($source); break; case 'image/png': $image = @imagecreatefrompng($source); break; case 'image/gif': $image = @imagecreatefromgif($source); break; case 'image/webp': $image = @imagecreatefromwebp($source); break; default: return false; } if ($image === false) return false; $width = imagesx($image); $height = imagesy($image); // Start with 90% quality and reduce dimensions if needed $quality = 90; $scale = 1.0; $tempFile = $source . '.tmp'; // Try progressive compression while (true) { // Calculate new dimensions $newWidth = (int)($width * $scale); $newHeight = (int)($height * $scale); // Create resized image $resized = imagecreatetruecolor($newWidth, $newHeight); // Preserve transparency for PNG/GIF if ($mime === 'image/png' || $mime === 'image/gif') { imagealphablending($resized, false); imagesavealpha($resized, true); $transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127); imagefilledrectangle($resized, 0, 0, $newWidth, $newHeight, $transparent); } imagecopyresampled($resized, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height); // Save with current quality if ($ext === 'jpg' || $ext === 'jpeg') { imagejpeg($resized, $tempFile, $quality); } elseif ($ext === 'png') { // PNG compression level (0-9, where 9 is best compression) $pngQuality = (int)((100 - $quality) / 11); imagepng($resized, $tempFile, $pngQuality); } elseif ($ext === 'webp') { imagewebp($resized, $tempFile, $quality); } else { imagegif($resized, $tempFile); } imagedestroy($resized); $fileSize = filesize($tempFile); // If file is small enough, use it if ($fileSize <= $maxSize) { imagedestroy($image); rename($tempFile, $source); return true; } // If we've reduced too much, give up if ($quality < 50 && $scale < 0.5) { imagedestroy($image); @unlink($tempFile); return false; } // Reduce quality or scale if ($quality > 50) { $quality -= 10; } else { $scale -= 0.1; } } } // Function to generate thumbnail function generateThumbnail($source, $destination, $width, $height) { $info = getimagesize($source); if ($info === false) return false; $mime = $info['mime']; switch ($mime) { case 'image/jpeg': $image = imagecreatefromjpeg($source); break; case 'image/png': $image = imagecreatefrompng($source); break; case 'image/gif': $image = imagecreatefromgif($source); break; case 'image/webp': $image = imagecreatefromwebp($source); break; default: return false; } if ($image === false) return false; $original_width = imagesx($image); $original_height = imagesy($image); // Calculate aspect ratio $aspect_ratio = $original_width / $original_height; if ($width / $height > $aspect_ratio) { $new_width = $height * $aspect_ratio; $new_height = $height; } else { $new_height = $width / $aspect_ratio; $new_width = $width; } $thumbnail = imagecreatetruecolor($new_width, $new_height); // Preserve transparency imagealphablending($thumbnail, false); imagesavealpha($thumbnail, true); $transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127); imagefilledrectangle($thumbnail, 0, 0, $new_width, $new_height, $transparent); imagecopyresampled($thumbnail, $image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height); // Save thumbnail switch ($mime) { case 'image/jpeg': $result = imagejpeg($thumbnail, $destination, 85); break; case 'image/png': $result = imagepng($thumbnail, $destination, 8); break; case 'image/gif': $result = imagegif($thumbnail, $destination); break; case 'image/webp': $result = imagewebp($thumbnail, $destination, 85); break; default: $result = false; } imagedestroy($image); imagedestroy($thumbnail); return $result; } ?>