From e7ab0379715f5aca232bdc6a1db9f2bb6ba39124 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 15 Feb 2026 06:25:40 +0000 Subject: [PATCH] add a card --- admin/generate_card.php | 86 ++++++++++++++++++ admin/settings.php | 25 ++++- assets/images/card_templates/default.png | Bin 0 -> 2809 bytes ...260215_add_whatsapp_send_cards_setting.sql | 1 + mail/WablasService.php | 67 ++++++++++++-- 5 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 admin/generate_card.php create mode 100644 assets/images/card_templates/default.png create mode 100644 db/migrations/20260215_add_whatsapp_send_cards_setting.sql diff --git a/admin/generate_card.php b/admin/generate_card.php new file mode 100644 index 0000000..e8553ea --- /dev/null +++ b/admin/generate_card.php @@ -0,0 +1,86 @@ +utf8Glyphs($text); +} + +// --- Image Generation --- +header('Content-Type: image/jpeg'); +$image = imagecreatefrompng($template_image); + +// Colors +$text_color = imagecolorallocate($image, 0, 0, 0); // Black + +// --- Text Wrapping and Positioning --- +$lines = []; +if ($lang === 'ar') { + // Simple reverse for RTL line wrapping (basic) + $words = explode(' ', $text); + $line = ''; + foreach ($words as $word) { + $new_line = $line . ' ' . $word; + $bbox = imagettfbbox($font_size, 0, $font_file, $new_line); + $line_width = abs($bbox[2] - $bbox[0]); + if ($line_width > ($width - 80)) { // 40px margin + $lines[] = $line; + $line = $word; + } else { + $line = $new_line; + } + } + $lines[] = $line; +} else { + $words = explode(' ', $text); + $line = ''; + foreach ($words as $word) { + $new_line = $line . ($line ? ' ' : '') . $word; + $bbox = imagettfbbox($font_size, 0, $font_file, $new_line); + $line_width = abs($bbox[2] - $bbox[0]); + if ($line_width > ($width - 80)) { // 40px margin + $lines[] = $line; + $line = $word; + } else { + $line = $new_line; + } + } + $lines[] = $line; +} + + +// Calculate total text height +$total_text_height = count($lines) * ($font_size * 1.5); +$y_start = ($height - $total_text_height) / 2; + +// Draw text line by line +foreach ($lines as $i => $line) { + $line = trim($line); + $bbox = imagettfbbox($font_size, 0, $font_file, $line); + $line_width = abs($bbox[2] - $bbox[0]); + $x = ($width - $line_width) / 2; + $y = $y_start + ($i * $font_size * 1.5); + imagettftext($image, $font_size, 0, $x, $y, $text_color, $font_file, $line); +} + + +// --- Output --- +imagejpeg($image); +imagedestroy($image); diff --git a/admin/settings.php b/admin/settings.php index 8f51d3b..2ed8880 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -11,10 +11,16 @@ if (!is_super_admin()) { $pdo = db(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Handle checkbox separately + if (!isset($_POST['settings']['whatsapp_send_cards'])) { + $_POST['settings']['whatsapp_send_cards'] = '0'; + } + foreach ($_POST['settings'] as $key => $value) { $stmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)"); $stmt->execute([$key, $value]); } + header('Location: settings.php?success=1'); exit; } @@ -194,16 +200,25 @@ $is_rtl = (get_current_lang() === 'ar'); -
- - -
-
+
+ +
+
+
+
+
+
+ > + +
+
+
+
diff --git a/assets/images/card_templates/default.png b/assets/images/card_templates/default.png new file mode 100644 index 0000000000000000000000000000000000000000..1e0f8d5d11a68411188b08c94566cd07479dd1d7 GIT binary patch literal 2809 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i0*Z)=h^hlA&H|6fVg?4jBOuH;Rhv(m zfq`qar;B4q#hka-0y!BJL=HG?t=}DfLWtS%ozR=&>NGJ1hPj`u7#JRyvvD&hq-|he zNE&5~2Eu4c7|jKvxnMLGjOK#TTripoMsopua)J21&+M90Ipr1t+p-Lvu6{1-oD!M< DL2C|# literal 0 HcmV?d00001 diff --git a/db/migrations/20260215_add_whatsapp_send_cards_setting.sql b/db/migrations/20260215_add_whatsapp_send_cards_setting.sql new file mode 100644 index 0000000..89772a9 --- /dev/null +++ b/db/migrations/20260215_add_whatsapp_send_cards_setting.sql @@ -0,0 +1 @@ +INSERT INTO settings (setting_key, setting_value) VALUES ('whatsapp_send_cards', '0'); \ No newline at end of file diff --git a/mail/WablasService.php b/mail/WablasService.php index 9d98fb2..6612bc6 100644 --- a/mail/WablasService.php +++ b/mail/WablasService.php @@ -8,7 +8,6 @@ class WablasService { $token = $settings['wablas_api_token'] ?? ''; $serverUrl = $settings['wablas_server_url'] ?? ''; - $securityKey = $settings['wablas_security_key'] ?? ''; if (empty($token) || empty($serverUrl)) { error_log("Wablas settings missing."); @@ -18,10 +17,6 @@ class WablasService { $to = prefix_phone($to); $data = ['phone' => $to, 'message' => $message]; - if (!empty($securityKey)) { - $data['security_key'] = $securityKey; - $data['secret_key'] = $securityKey; - } $curl = curl_init(); curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: $token"]); @@ -50,13 +45,60 @@ class WablasService { return ['success' => false, 'error' => $result]; } + public static function sendImageAndCaption($to, $imageUrl, $caption) { + $pdo = db(); + $settings = $pdo->query("SELECT setting_key, setting_value FROM settings WHERE setting_key LIKE 'wablas_%'")->fetchAll(PDO::FETCH_KEY_PAIR); + + $token = $settings['wablas_api_token'] ?? ''; + $serverUrl = $settings['wablas_server_url'] ?? ''; + + if (empty($token) || empty($serverUrl)) { + error_log("Wablas settings missing."); + return ['success' => false, 'error' => 'Settings missing']; + } + + $to = prefix_phone($to); + + $data = [ + 'phone' => $to, + 'image' => $imageUrl, + 'caption' => $caption + ]; + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: $token"]); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data)); + curl_setopt($curl, CURLOPT_URL, rtrim($serverUrl, '/') . "/api/send-image"); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); + + $result = curl_exec($curl); + $error = curl_error($curl); + curl_close($curl); + + if ($error) { + error_log("Wablas CURL error: " . $error); + return ['success' => false, 'error' => $error]; + } + + $response = json_decode($result, true); + if (isset($response['status']) && $response['status'] == true) { + return ['success' => true, 'data' => $response]; + } + + error_log("Wablas API error: " . $result); + return ['success' => false, 'error' => $result]; + } + public static function getOrgName($lang = 'en') { $pdo = db(); $org = $pdo->query("SELECT name_en, name_ar FROM org_profile LIMIT 1")->fetch(); return ($lang === 'ar') ? ($org['name_ar'] ?? 'المنظمة') : ($org['name_en'] ?? 'Organization'); } - private static function sendTemplatedMessage($to, $templateName, $vars, $lang = 'en') { + private static function sendTemplatedMessage($to, $templateName, $vars, $lang = 'en', $useImage = true) { if (empty($to)) { return ['success' => false, 'error' => 'Recipient phone number is missing.']; } @@ -77,7 +119,18 @@ class WablasService { $messageBody = str_replace('{'.$key.'}', $value, $messageBody); } - return self::sendMessage($to, $messageBody); + if ($useImage) { + // ToDo: Find a way to get the base URL + $siteUrl = 'http://' . $_SERVER['HTTP_HOST']; + $imageUrl = $siteUrl . '/admin/generate_card.php?' . http_build_query([ + 'text' => $messageBody, + 'lang' => $lang, + 'template' => $templateName + ]); + return self::sendImageAndCaption($to, $imageUrl, $messageBody); + } else { + return self::sendMessage($to, $messageBody); + } } public static function sendThankYou($donation, $lang = 'en') {