- Implemented PayPal webhook for handling payment notifications, including signature verification and transaction updates. - Created invoice generation and license management for software upgrades upon successful payment. - Added comprehensive logging for debugging purposes. - Introduced new CSS styles for the marketing file management system, including layout, toolbar, breadcrumb navigation, search filters, and file management UI components.
302 lines
9.8 KiB
PHP
302 lines
9.8 KiB
PHP
<?php
|
|
defined($security_key) or exit;
|
|
|
|
//------------------------------------------
|
|
// Marketing Upload
|
|
//------------------------------------------
|
|
//Connect to DB
|
|
$pdo = dbConnect($dbname);
|
|
|
|
//SoldTo is empty
|
|
if (empty($partner->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;
|
|
}
|
|
|
|
?>
|