Add PayPal webhook handler and marketing styles
- 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.
This commit is contained in:
302
api/v2/post/marketing_upload.php
Normal file
302
api/v2/post/marketing_upload.php
Normal file
@@ -0,0 +1,302 @@
|
||||
<?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;
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user