@artilingo/artiframe-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/assets/logo.png +0 -0
  2. package/assets/logo.svg +22 -0
  3. package/assets/logo.webp +0 -0
  4. package/assets/logo@0.5x.png +0 -0
  5. package/assets/logo@0.75x.png +0 -0
  6. package/assets/logo@1.5x.png +0 -0
  7. package/assets/logo@2x.png +0 -0
  8. package/assets/logo@3x.png +0 -0
  9. package/assets/logo@4x.png +0 -0
  10. package/bin/artiframe.js +57 -0
  11. package/bin/artiframe.php +45 -0
  12. package/core-stubs/app/ApiControl.php +81 -0
  13. package/core-stubs/app/Database.php +69 -0
  14. package/core-stubs/app/DotEnv.php +63 -0
  15. package/core-stubs/app/R2Manager.php +130 -0
  16. package/core-stubs/app/ViewControl.php +24 -0
  17. package/core-stubs/bin/SystemMethod.php +271 -0
  18. package/core-stubs/bin/ViewMethod.php +354 -0
  19. package/core-stubs/docs/de.html +951 -0
  20. package/core-stubs/docs/en.html +952 -0
  21. package/core-stubs/docs/es.html +947 -0
  22. package/core-stubs/docs/fr.html +850 -0
  23. package/core-stubs/docs/tr.html +951 -0
  24. package/core-stubs/public/assets/css/components/footer.css +0 -0
  25. package/core-stubs/public/assets/css/components/header.css +0 -0
  26. package/core-stubs/public/assets/css/components/mobilenav.css +0 -0
  27. package/core-stubs/public/assets/css/components/sidebar.css +0 -0
  28. package/core-stubs/public/assets/css/components/theme-modal.css +0 -0
  29. package/core-stubs/public/assets/css/root/app.css +61 -0
  30. package/core-stubs/public/assets/js/components/header.js +0 -0
  31. package/core-stubs/public/assets/js/components/mobilenav.js +0 -0
  32. package/core-stubs/public/assets/js/components/sidebar.js +0 -0
  33. package/core-stubs/public/assets/js/components/theme-modal.js +0 -0
  34. package/core-stubs/public/assets/js/root/app.js +30 -0
  35. package/core-stubs/public/includes/footer.php +5 -0
  36. package/core-stubs/public/includes/head.php +26 -0
  37. package/core-stubs/public/includes/header.php +5 -0
  38. package/core-stubs/public/includes/mobilenav.php +5 -0
  39. package/core-stubs/public/includes/sidebar.php +5 -0
  40. package/core-stubs/public/includes/theme-modal.php +5 -0
  41. package/core-stubs/readme/de.md +29 -0
  42. package/core-stubs/readme/en.md +29 -0
  43. package/core-stubs/readme/es.md +29 -0
  44. package/core-stubs/readme/fr.md +29 -0
  45. package/core-stubs/readme/tr.md +29 -0
  46. package/package.json +49 -0
  47. package/scripts/postinstall.js +21 -0
  48. package/src/App.php +266 -0
  49. package/src/Commands/MakeApiCommand.php +71 -0
  50. package/src/Commands/MakeClassCommand.php +88 -0
  51. package/src/Commands/MakeViewCommand.php +95 -0
  52. package/src/Commands/NewProjectCommand.php +633 -0
  53. package/src/Commands/VersionCommand.php +92 -0
  54. package/src/Lang/de.php +53 -0
  55. package/src/Lang/en.php +53 -0
  56. package/src/Lang/es.php +53 -0
  57. package/src/Lang/fr.php +53 -0
  58. package/src/Lang/tr.php +53 -0
  59. package/src/Services/Safeguard.php +48 -0
  60. package/src/Services/Translator.php +52 -0
@@ -0,0 +1,271 @@
1
+ <?php
2
+ /**
3
+ * ArtiFrame Core Engine
4
+ *
5
+ * @package ArtiFrame
6
+ * @author Artilingo
7
+ * @license AGPLv3 (Attribution-ShareAlike Required)
8
+ * @link https://artiframe.org
9
+ *
10
+ * NOTICE: This file is part of the ArtiFrame ecosystem.
11
+ * Any derivative works or patches MUST retain this original copyright notice
12
+ * and remain open-source under the AGPLv3 license.
13
+ */
14
+
15
+ namespace Bin;
16
+
17
+ class SystemMethod
18
+ {
19
+ /**
20
+ * E-posta adresinin format olarak geçerli olup olmadığını doğrular.
21
+ *
22
+ * @param string $email Doğrulanacak E-Posta
23
+ * @return bool
24
+ */
25
+ public static function verifyEmail(string $email): bool
26
+ {
27
+ return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
28
+ }
29
+
30
+ /**
31
+ * Gelen veriyi güvenli bir Integer (tam sayı) değerine dönüştürür.
32
+ * Harfleri siler ve sayısal karakter bırakır.
33
+ *
34
+ * @param mixed $value
35
+ * @return int
36
+ */
37
+ public static function sanitizeInt($value): int
38
+ {
39
+ return (int) filter_var($value, FILTER_SANITIZE_NUMBER_INT);
40
+ }
41
+
42
+ /**
43
+ * Gelen verideki HTML etiketlerini ve zararlı kodları temizler.
44
+ * Veritabanına String kaydetmeden önce mutlaka kullanılmalıdır.
45
+ *
46
+ * @param string $value
47
+ * @return string
48
+ */
49
+ public static function sanitizeString(string $value): string
50
+ {
51
+ return strip_tags(trim($value));
52
+ }
53
+
54
+ /**
55
+ * Sayfaya gelen isteğin bir form gönderimi (POST) olup olmadığını kontrol eder.
56
+ *
57
+ * @return bool
58
+ */
59
+ public static function isPost(): bool
60
+ {
61
+ return $_SERVER['REQUEST_METHOD'] === 'POST';
62
+ }
63
+
64
+ /**
65
+ * Oturum (Session) tabanlı CSRF (Cross-Site Request Forgery) güvenlik token'ı üretir.
66
+ */
67
+ public static function generateCsrf(): string
68
+ {
69
+ if (session_status() === PHP_SESSION_NONE) {
70
+ session_start();
71
+ }
72
+ if (empty($_SESSION['csrf_token'])) {
73
+ $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
74
+ }
75
+ return $_SESSION['csrf_token'];
76
+ }
77
+
78
+ /**
79
+ * Formdan gelen CSRF token'ın doğruluğunu onaylar. (Form güvenlik kalkanı)
80
+ */
81
+ public static function verifyCsrf(?string $token): bool
82
+ {
83
+ if (session_status() === PHP_SESSION_NONE) {
84
+ session_start();
85
+ }
86
+ if (empty($_SESSION['csrf_token']) || empty($token)) {
87
+ return false;
88
+ }
89
+ return hash_equals($_SESSION['csrf_token'], $token);
90
+ }
91
+
92
+ /**
93
+ * İsteğin AJAX üzerinden gelip gelmediğini kontrol eder. (Fetch / Axios destekli)
94
+ */
95
+ public static function isAjax(): bool
96
+ {
97
+ return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
98
+ }
99
+
100
+ /**
101
+ * API'ler için hızlı ve standart JSON yanıt (response) oluşturur.
102
+ * Kullanıldığı anda işlemi sonlandırır (exit).
103
+ *
104
+ * @param array $data JSON'a çevrilecek dizi (array)
105
+ * @param int $statusCode HTTP Durum Kodu (200 OK, 404 Not Found vb.)
106
+ */
107
+ public static function jsonResponse(array $data, int $statusCode = 200): void
108
+ {
109
+ http_response_code($statusCode);
110
+ header('Content-Type: application/json; charset=utf-8');
111
+ echo json_encode($data, JSON_UNESCAPED_UNICODE);
112
+ exit;
113
+ }
114
+ /**
115
+ * Sayfaya gelen isteğin GET olup olmadığını kontrol eder.
116
+ */
117
+ public static function isGet(): bool
118
+ {
119
+ return $_SERVER['REQUEST_METHOD'] === 'GET';
120
+ }
121
+
122
+ /**
123
+ * Sayfaya gelen isteğin PUT olup olmadığını kontrol eder.
124
+ */
125
+ public static function isPut(): bool
126
+ {
127
+ return $_SERVER['REQUEST_METHOD'] === 'PUT';
128
+ }
129
+
130
+ /**
131
+ * Sayfaya gelen isteğin DELETE olup olmadığını kontrol eder.
132
+ */
133
+ public static function isDelete(): bool
134
+ {
135
+ return $_SERVER['REQUEST_METHOD'] === 'DELETE';
136
+ }
137
+
138
+ /**
139
+ * Kullanıcının gerçek IP adresini tespit eder (Cloudflare ve Proxy destekli).
140
+ */
141
+ public static function getClientIp(): string
142
+ {
143
+ if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
144
+ return $_SERVER['HTTP_CF_CONNECTING_IP'];
145
+ }
146
+ if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
147
+ return $_SERVER['HTTP_CLIENT_IP'];
148
+ }
149
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
150
+ $ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
151
+ return trim($ipList[0]);
152
+ }
153
+ return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
154
+ }
155
+
156
+ /**
157
+ * İstenilen sayfaya yönlendirme yapar ve çalışmayı durdurur.
158
+ */
159
+ public static function redirect(string $url): void
160
+ {
161
+ header("Location: " . $url);
162
+ exit;
163
+ }
164
+
165
+ /**
166
+ * Kriptografik olarak güvenli, rastgele bir token üretir (Örn: Parola sıfırlama, API Key).
167
+ */
168
+ public static function generateToken(int $length = 32): string
169
+ {
170
+ return bin2hex(random_bytes($length));
171
+ }
172
+
173
+ /**
174
+ * E-posta adresini zararlı karakterlerden temizler.
175
+ */
176
+ public static function sanitizeEmail(string $email): string
177
+ {
178
+ return filter_var($email, FILTER_SANITIZE_EMAIL);
179
+ }
180
+ }
181
+
182
+ // Global helper functions for backend methods
183
+ if (!function_exists('verifyEmail')) {
184
+ function verifyEmail(string $email): bool {
185
+ return \Bin\SystemMethod::verifyEmail($email);
186
+ }
187
+ }
188
+
189
+ if (!function_exists('sanitizeInt')) {
190
+ function sanitizeInt($value): int {
191
+ return \Bin\SystemMethod::sanitizeInt($value);
192
+ }
193
+ }
194
+
195
+ if (!function_exists('sanitizeString')) {
196
+ function sanitizeString(string $value): string {
197
+ return \Bin\SystemMethod::sanitizeString($value);
198
+ }
199
+ }
200
+
201
+ if (!function_exists('isPost')) {
202
+ function isPost(): bool {
203
+ return \Bin\SystemMethod::isPost();
204
+ }
205
+ }
206
+
207
+ if (!function_exists('jsonResponse')) {
208
+ function jsonResponse(array $data, int $statusCode = 200): void {
209
+ \Bin\SystemMethod::jsonResponse($data, $statusCode);
210
+ }
211
+ }
212
+
213
+ if (!function_exists('generateCsrf')) {
214
+ function generateCsrf(): string {
215
+ return \Bin\SystemMethod::generateCsrf();
216
+ }
217
+ }
218
+
219
+ if (!function_exists('verifyCsrf')) {
220
+ function verifyCsrf(?string $token): bool {
221
+ return \Bin\SystemMethod::verifyCsrf($token);
222
+ }
223
+ }
224
+
225
+ if (!function_exists('isAjax')) {
226
+ function isAjax(): bool {
227
+ return \Bin\SystemMethod::isAjax();
228
+ }
229
+ }
230
+
231
+ if (!function_exists('isGet')) {
232
+ function isGet(): bool {
233
+ return \Bin\SystemMethod::isGet();
234
+ }
235
+ }
236
+
237
+ if (!function_exists('isPut')) {
238
+ function isPut(): bool {
239
+ return \Bin\SystemMethod::isPut();
240
+ }
241
+ }
242
+
243
+ if (!function_exists('isDelete')) {
244
+ function isDelete(): bool {
245
+ return \Bin\SystemMethod::isDelete();
246
+ }
247
+ }
248
+
249
+ if (!function_exists('getClientIp')) {
250
+ function getClientIp(): string {
251
+ return \Bin\SystemMethod::getClientIp();
252
+ }
253
+ }
254
+
255
+ if (!function_exists('redirect')) {
256
+ function redirect(string $url): void {
257
+ \Bin\SystemMethod::redirect($url);
258
+ }
259
+ }
260
+
261
+ if (!function_exists('generateToken')) {
262
+ function generateToken(int $length = 32): string {
263
+ return \Bin\SystemMethod::generateToken($length);
264
+ }
265
+ }
266
+
267
+ if (!function_exists('sanitizeEmail')) {
268
+ function sanitizeEmail(string $email): string {
269
+ return \Bin\SystemMethod::sanitizeEmail($email);
270
+ }
271
+ }
@@ -0,0 +1,354 @@
1
+ <?php
2
+ /**
3
+ * ArtiFrame Core Engine
4
+ *
5
+ * @package ArtiFrame
6
+ * @author Artilingo
7
+ * @license AGPLv3 (Attribution-ShareAlike Required)
8
+ * @link https://artiframe.org
9
+ *
10
+ * NOTICE: This file is part of the ArtiFrame ecosystem.
11
+ * Any derivative works or patches MUST retain this original copyright notice
12
+ * and remain open-source under the AGPLv3 license.
13
+ */
14
+
15
+ namespace Bin;
16
+
17
+ class ViewMethod
18
+ {
19
+ /**
20
+ * Veriyi ekrana yazdırırken XSS saldırılarına karşı temizler (Sanitize).
21
+ * Null değerlerde patlamamak için varsayılan değer döndürür.
22
+ *
23
+ * @param mixed $data Ekrana basılacak veri
24
+ * @param string $default Veri boşsa basılacak varsayılan değer (örn: '-')
25
+ * @return string Güvenli HTML string
26
+ */
27
+ public static function display($data, string $default = ''): string
28
+ {
29
+ if ($data === null || $data === '') {
30
+ return $default;
31
+ }
32
+ return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
33
+ }
34
+
35
+ /**
36
+ * URL'leri güvenli hale getirir, zararlı karakterleri temizler.
37
+ */
38
+ public static function escapeUrl(string $url): string
39
+ {
40
+ return filter_var($url, FILTER_SANITIZE_URL);
41
+ }
42
+
43
+ /**
44
+ * Tarih formatını (Veritabanındaki Y-m-d H:i:s formatını) kullanıcı dostu ve güvenli bir şekilde ekrana basar.
45
+ */
46
+ public static function formatDate(?string $date, string $format = 'd.m.Y H:i'): string
47
+ {
48
+ if (empty($date)) return '-';
49
+ $time = strtotime($date);
50
+ return $time ? date($format, $time) : '-';
51
+ }
52
+
53
+ /**
54
+ * Formlar için (XSS ve CSRF korumalı) gizli bir güvenlik token'ı (input) oluşturur.
55
+ */
56
+ public static function csrfField(): string
57
+ {
58
+ // Require SystemMethod implicitly if it exists in the same namespace context,
59
+ // or just call the global wrapper if it's available. We'll use the class method for purity.
60
+ $token = \Bin\SystemMethod::generateCsrf();
61
+ return '<input type="hidden" name="csrf_token" value="' . self::display($token) . '">';
62
+ }
63
+ // --- Tarih ve Zaman Fonksiyonları ---
64
+
65
+ /**
66
+ * Sadece Günü döndürür (Örn: 24)
67
+ */
68
+ public static function day($date): string
69
+ {
70
+ if (empty($date)) return '-';
71
+ return date('d', is_numeric($date) ? $date : strtotime($date));
72
+ }
73
+
74
+ /**
75
+ * Sadece Ayı rakamla döndürür (Örn: 07)
76
+ */
77
+ public static function month($date): string
78
+ {
79
+ if (empty($date)) return '-';
80
+ return date('m', is_numeric($date) ? $date : strtotime($date));
81
+ }
82
+
83
+ /**
84
+ * Yılı döndürür (Örn: 2026)
85
+ */
86
+ public static function year($date): string
87
+ {
88
+ if (empty($date)) return '-';
89
+ return date('Y', is_numeric($date) ? $date : strtotime($date));
90
+ }
91
+
92
+ /**
93
+ * Saati döndürür (Örn: 14:30)
94
+ */
95
+ public static function timeOnly($date): string
96
+ {
97
+ if (empty($date)) return '-';
98
+ return date('H:i', is_numeric($date) ? $date : strtotime($date));
99
+ }
100
+
101
+ /**
102
+ * Tarihi 24.07.2026 formatında döndürür
103
+ */
104
+ public static function fulldate($date): string
105
+ {
106
+ if (empty($date)) return '-';
107
+ return date('d.m.Y', is_numeric($date) ? $date : strtotime($date));
108
+ }
109
+
110
+ /**
111
+ * Ay isimlerini dile göre döndürür
112
+ */
113
+ public static function monthName($date, string $lang = 'tr'): string
114
+ {
115
+ if (empty($date)) return '-';
116
+ $m = (int)date('n', is_numeric($date) ? $date : strtotime($date));
117
+ $months = [
118
+ 'tr' => ['', 'Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
119
+ 'en' => ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
120
+ 'de' => ['', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
121
+ 'fr' => ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
122
+ 'es' => ['', 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
123
+ ];
124
+ $lang = strtolower($lang);
125
+ if (!isset($months[$lang])) $lang = 'en';
126
+ return $months[$lang][$m];
127
+ }
128
+
129
+ /**
130
+ * Tarihi yerelleştirilmiş ay ismiyle döndürür (Örn: 24 Temmuz 2026)
131
+ */
132
+ public static function fulldateName($date, string $lang = 'tr'): string
133
+ {
134
+ if (empty($date)) return '-';
135
+ $time = is_numeric($date) ? $date : strtotime($date);
136
+ $d = date('d', $time);
137
+ $y = date('Y', $time);
138
+ $mName = self::monthName($time, $lang);
139
+
140
+ // İngilizce'de ay öne gelebilir (July 24, 2026) ama basitlik açısından formatı koruyabiliriz veya dile göre değiştirebiliriz.
141
+ if (strtolower($lang) === 'en') {
142
+ return "{$mName} {$d}, {$y}";
143
+ }
144
+ return "{$d} {$mName} {$y}";
145
+ }
146
+
147
+ /**
148
+ * Sosyal medya tarzı zaman gösterimi (Örn: 5 dakika önce)
149
+ */
150
+ public static function timeAgo($date, string $lang = 'tr'): string
151
+ {
152
+ if (empty($date)) return '-';
153
+ $time = is_numeric($date) ? $date : strtotime($date);
154
+ $diff = time() - $time;
155
+ if ($diff < 1) return ($lang === 'tr') ? 'şimdi' : 'just now';
156
+
157
+ $tokens = [
158
+ 31536000 => 'year',
159
+ 2592000 => 'month',
160
+ 604800 => 'week',
161
+ 86400 => 'day',
162
+ 3600 => 'hour',
163
+ 60 => 'minute',
164
+ 1 => 'second'
165
+ ];
166
+
167
+ $lang = strtolower($lang);
168
+ $translations = [
169
+ 'tr' => ['year'=>'yıl', 'month'=>'ay', 'week'=>'hafta', 'day'=>'gün', 'hour'=>'saat', 'minute'=>'dakika', 'second'=>'saniye', 'ago'=>'önce', 'format'=>'{value} {unit} {ago}'],
170
+ 'en' => ['year'=>'year', 'month'=>'month', 'week'=>'week', 'day'=>'day', 'hour'=>'hour', 'minute'=>'minute', 'second'=>'second', 'ago'=>'ago', 'format'=>'{value} {unit}s {ago}'],
171
+ 'de' => ['year'=>'Jahr', 'month'=>'Monat', 'week'=>'Woche', 'day'=>'Tag', 'hour'=>'Stunde', 'minute'=>'Minute', 'second'=>'Sekunde', 'ago'=>'vor', 'format'=>'{ago} {value} {unit}en'], // simplified
172
+ 'fr' => ['year'=>'an', 'month'=>'mois', 'week'=>'semaine', 'day'=>'jour', 'hour'=>'heure', 'minute'=>'minute', 'second'=>'seconde', 'ago'=>'il y a', 'format'=>'{ago} {value} {unit}s'],
173
+ 'es' => ['year'=>'año', 'month'=>'mes', 'week'=>'semana', 'day'=>'día', 'hour'=>'hora', 'minute'=>'minuto', 'second'=>'segundo', 'ago'=>'hace', 'format'=>'{ago} {value} {unit}s']
174
+ ];
175
+ if (!isset($translations[$lang])) $lang = 'en';
176
+
177
+ foreach ($tokens as $unit => $text) {
178
+ if ($diff < $unit) continue;
179
+ $numberOfUnits = floor($diff / $unit);
180
+
181
+ // Pluralization logic is basic here, but functional for general use
182
+ $unitStr = $translations[$lang][$text];
183
+ if ($lang === 'en' && $numberOfUnits == 1) $translations['en']['format'] = '{value} {unit} {ago}';
184
+
185
+ $formatted = str_replace(
186
+ ['{value}', '{unit}', '{ago}'],
187
+ [$numberOfUnits, $unitStr, $translations[$lang]['ago']],
188
+ $translations[$lang]['format']
189
+ );
190
+
191
+ // Fix DE basic plurals roughly
192
+ if ($lang === 'de') {
193
+ $formatted = str_replace(['Jahren', 'Monaten', 'Wocheen', 'Tagen', 'Stundeen', 'Minuteen', 'Sekundeen'], ['Jahren', 'Monaten', 'Wochen', 'Tagen', 'Stunden', 'Minuten', 'Sekunden'], $formatted);
194
+ }
195
+ return $formatted;
196
+ }
197
+ return '-';
198
+ }
199
+
200
+ // --- Metin (String) İşleme Fonksiyonları ---
201
+
202
+ /**
203
+ * Uzun metinleri keser ve sonuna ... ekler
204
+ */
205
+ public static function truncate(string $text, int $length = 100, string $append = '...'): string
206
+ {
207
+ $text = strip_tags($text);
208
+ if (mb_strlen($text, 'UTF-8') <= $length) return $text;
209
+
210
+ $truncated = mb_substr($text, 0, $length, 'UTF-8');
211
+ // Son kelimeyi bölmemek için son boşluğa kadar al
212
+ if (strpos($text, ' ') !== false) {
213
+ $lastSpace = mb_strrpos($truncated, ' ', 0, 'UTF-8');
214
+ if ($lastSpace !== false) {
215
+ $truncated = mb_substr($truncated, 0, $lastSpace, 'UTF-8');
216
+ }
217
+ }
218
+ return $truncated . $append;
219
+ }
220
+
221
+ // --- Para Birimi Formatlama ---
222
+
223
+ /**
224
+ * Tutar ve para birimi sembolü formatlama
225
+ */
226
+ public static function money(float $amount, string $currency = 'usd'): string
227
+ {
228
+ $currencies = [
229
+ 'usd' => '$', // US Dollar
230
+ 'eur' => '€', // Euro
231
+ 'try' => '₺', // Turkish Lira
232
+ 'tl' => '₺', // Turkish Lira
233
+ 'gbp' => '£', // British Pound
234
+ 'jpy' => '¥', // Japanese Yen
235
+ 'cny' => '¥', // Chinese Yuan
236
+ 'rub' => '₽', // Russian Ruble
237
+ 'inr' => '₹', // Indian Rupee
238
+ 'aud' => 'A$', // Australian Dollar
239
+ 'cad' => 'C$', // Canadian Dollar
240
+ 'chf' => 'CHF', // Swiss Franc
241
+ 'krw' => '₩', // South Korean Won
242
+ 'brl' => 'R$', // Brazilian Real
243
+ 'zar' => 'R', // South African Rand
244
+ 'sek' => 'kr', // Swedish Krona
245
+ 'nok' => 'kr', // Norwegian Krone
246
+ 'mxn' => '$', // Mexican Peso
247
+ 'sgd' => 'S$', // Singapore Dollar
248
+ 'hkd' => 'HK$', // Hong Kong Dollar
249
+ 'nzd' => 'NZ$', // New Zealand Dollar
250
+ 'aed' => 'د.إ', // UAE Dirham
251
+ 'sar' => '﷼', // Saudi Riyal
252
+ 'pln' => 'zł' // Polish Zloty
253
+ ];
254
+
255
+ $currency = strtolower($currency);
256
+ $symbol = $currencies[$currency] ?? strtoupper($currency) . ' ';
257
+
258
+ // Sayıyı 1.250,50 veya 1,250.50 gibi formatlar. Genel standart olarak 1.250,50 (Avrupa/TR)
259
+ // İhtiyaca göre number_format değiştirilebilir. (TR formatı baz alındı)
260
+ $formattedAmount = number_format($amount, 2, ',', '.');
261
+
262
+ // USD ve GBP gibi birimlerde sembol genelde başa gelir, TL veya EUR'da sona.
263
+ if (in_array($currency, ['usd', 'gbp', 'aud', 'cad', 'sgd', 'hkd', 'nzd', 'mxn', 'brl'])) {
264
+ return $symbol . $formattedAmount;
265
+ }
266
+
267
+ return $formattedAmount . ' ' . $symbol;
268
+ }
269
+ }
270
+
271
+ // Geliştiriciler (Özellikle Juniorlar) için kullanımı en kolay global yardımcı fonksiyonlar
272
+ if (!function_exists('display')) {
273
+ function display($data, string $default = ''): string {
274
+ return \Bin\ViewMethod::display($data, $default);
275
+ }
276
+ }
277
+
278
+ if (!function_exists('escapeUrl')) {
279
+ function escapeUrl(string $url): string {
280
+ return \Bin\ViewMethod::escapeUrl($url);
281
+ }
282
+ }
283
+
284
+ if (!function_exists('formatDate')) {
285
+ function formatDate(?string $date, string $format = 'd.m.Y H:i'): string {
286
+ return \Bin\ViewMethod::formatDate($date, $format);
287
+ }
288
+ }
289
+
290
+ if (!function_exists('csrfField')) {
291
+ function csrfField(): string {
292
+ return \Bin\ViewMethod::csrfField();
293
+ }
294
+ }
295
+
296
+ if (!function_exists('day')) {
297
+ function day($date): string {
298
+ return \Bin\ViewMethod::day($date);
299
+ }
300
+ }
301
+
302
+ if (!function_exists('month')) {
303
+ function month($date): string {
304
+ return \Bin\ViewMethod::month($date);
305
+ }
306
+ }
307
+
308
+ if (!function_exists('year')) {
309
+ function year($date): string {
310
+ return \Bin\ViewMethod::year($date);
311
+ }
312
+ }
313
+
314
+ if (!function_exists('timeOnly')) {
315
+ function timeOnly($date): string {
316
+ return \Bin\ViewMethod::timeOnly($date);
317
+ }
318
+ }
319
+
320
+ if (!function_exists('fulldate')) {
321
+ function fulldate($date): string {
322
+ return \Bin\ViewMethod::fulldate($date);
323
+ }
324
+ }
325
+
326
+ if (!function_exists('monthName')) {
327
+ function monthName($date, string $lang = 'tr'): string {
328
+ return \Bin\ViewMethod::monthName($date, $lang);
329
+ }
330
+ }
331
+
332
+ if (!function_exists('fulldateName')) {
333
+ function fulldateName($date, string $lang = 'tr'): string {
334
+ return \Bin\ViewMethod::fulldateName($date, $lang);
335
+ }
336
+ }
337
+
338
+ if (!function_exists('timeAgo')) {
339
+ function timeAgo($date, string $lang = 'tr'): string {
340
+ return \Bin\ViewMethod::timeAgo($date, $lang);
341
+ }
342
+ }
343
+
344
+ if (!function_exists('truncate')) {
345
+ function truncate(string $text, int $length = 100, string $append = '...'): string {
346
+ return \Bin\ViewMethod::truncate($text, $length, $append);
347
+ }
348
+ }
349
+
350
+ if (!function_exists('money')) {
351
+ function money(float $amount, string $currency = 'usd'): string {
352
+ return \Bin\ViewMethod::money($amount, $currency);
353
+ }
354
+ }