@artilingo/artiframe-cli 1.4.0 → 2.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 (38) hide show
  1. package/core-stubs/bin/SystemMethod.php +600 -521
  2. package/core-stubs/bin/ViewMethod.php +591 -393
  3. package/core-stubs/docs/de.html +4347 -4390
  4. package/core-stubs/docs/en.html +4347 -4389
  5. package/core-stubs/docs/es.html +4347 -4390
  6. package/core-stubs/docs/fr.html +4347 -4389
  7. package/core-stubs/docs/tr.html +138 -109
  8. package/package.json +1 -1
  9. package/src/App.php +8 -0
  10. package/src/Commands/AddCommand.php +1 -1
  11. package/src/Commands/ListCommand.php +2 -1
  12. package/src/Commands/MakeApiCommand.php +1 -1
  13. package/src/Commands/MakeClassCommand.php +1 -1
  14. package/src/Commands/MakeViewCommand.php +1 -1
  15. package/src/Commands/NewProjectCommand.php +37 -25
  16. package/src/Commands/RemoveCommand.php +21 -10
  17. package/src/Commands/ServeCommand.php +29 -9
  18. package/src/Commands/TableCommand.php +2 -1
  19. package/src/Commands/UpgradeCommand.php +209 -0
  20. package/src/Commands/VersionCommand.php +2 -1
  21. package/src/Lang/de.php +7 -1
  22. package/src/Lang/en.php +6 -0
  23. package/src/Lang/es.php +7 -1
  24. package/src/Lang/fr.php +6 -0
  25. package/src/Lang/tr.php +7 -1
  26. package/src/Services/Safeguard.php +25 -0
  27. package/stubs/service/image.stub +334 -334
  28. package/stubs/service/iyzico.stub +637 -637
  29. package/stubs/service/jwt.stub +312 -312
  30. package/stubs/service/phpmailer.stub +143 -143
  31. package/stubs/service/pusher.stub +232 -232
  32. package/stubs/service/qrcode.stub +169 -169
  33. package/stubs/service/redis.stub +361 -361
  34. package/stubs/service/s3.stub +377 -377
  35. package/stubs/service/sentry.stub +76 -106
  36. package/stubs/service/stripe.stub +526 -526
  37. package/stubs/service/twilio.stub +361 -361
  38. package/core-stubs/app/R2Manager.php +0 -130
@@ -1,4 +1,5 @@
1
1
  <?php
2
+
2
3
  /**
3
4
  * ArtiFrame Core Engine
4
5
  *
@@ -12,468 +13,665 @@
12
13
  * and remain open-source under the AGPLv3 license.
13
14
  */
14
15
 
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
16
+ namespace Bin {
17
+
18
+ \App\DotEnv::load($_SERVER['DOCUMENT_ROOT'] . '/../.env');
19
+
20
+ class ViewMethod
28
21
  {
29
- if ($data === null || $data === '') {
30
- return $default;
22
+ /**
23
+ * Veriyi ekrana yazdırırken XSS saldırılarına karşı temizler (Sanitize).
24
+ * Null değerlerde patlamamak için varsayılan değer döndürür.
25
+ *
26
+ * @param mixed $data Ekrana basılacak veri
27
+ * @param string $default Veri boşsa basılacak varsayılan değer (örn: '-')
28
+ * @return string Güvenli HTML string
29
+ */
30
+ public static function display($data, string $default = ''): string
31
+ {
32
+ if ($data === null || $data === '') {
33
+ return $default;
34
+ }
35
+ return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
31
36
  }
32
- return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
33
- }
34
37
 
35
- /**
36
- * URL'leri güvenli hale getirir, zararlı karakterleri temizler.
37
- */
38
- public static function escapeUrl(?string $url): string
39
- {
40
- if (empty($url)) return '#';
41
- return self::display(filter_var($url, FILTER_SANITIZE_URL));
42
- }
38
+ /**
39
+ * URL'leri güvenli hale getirir, zararlı karakterleri temizler.
40
+ */
41
+ public static function escapeUrl(?string $url): string
42
+ {
43
+ if (empty($url)) return '#';
44
+ return self::display(filter_var($url, FILTER_SANITIZE_URL));
45
+ }
43
46
 
44
- /**
45
- * Tarih formatını (Veritabanındaki Y-m-d H:i:s formatını) kullanıcı dostu ve güvenli bir şekilde ekrana basar.
46
- */
47
- public static function formatDate(?string $date, string $format = 'd.m.Y H:i'): string
48
- {
49
- if (empty($date)) return '-';
50
- $time = strtotime($date);
51
- return self::display($time ? date($format, $time) : '-');
52
- }
47
+ /**
48
+ * Tarih formatını (Veritabanındaki Y-m-d H:i:s formatını) kullanıcı dostu ve güvenli bir şekilde ekrana basar.
49
+ */
50
+ public static function formatDate(?string $date, string $format = 'd.m.Y H:i'): string
51
+ {
52
+ if (empty($date)) return '-';
53
+ $time = strtotime($date);
54
+ return self::display($time ? date($format, $time) : '-');
55
+ }
53
56
 
54
- /**
55
- * Formlar için (XSS ve CSRF korumalı) gizli bir güvenlik token'ı (input) oluşturur.
56
- */
57
- public static function csrfField(): string
58
- {
59
- // Require SystemMethod implicitly if it exists in the same namespace context,
60
- // or just call the global wrapper if it's available. We'll use the class method for purity.
61
- $token = \Bin\SystemMethod::generateCsrf();
62
- return '<input type="hidden" name="csrf_token" value="' . self::display($token) . '">';
63
- }
57
+ /**
58
+ * Formlar için (XSS ve CSRF korumalı) gizli bir güvenlik token'ı (input) oluşturur.
59
+ */
60
+ public static function csrfField(): string
61
+ {
62
+ // Require SystemMethod implicitly if it exists in the same namespace context,
63
+ // or just call the global wrapper if it's available. We'll use the class method for purity.
64
+ $token = \Bin\SystemMethod::generateCsrf();
65
+ return '<input type="hidden" name="csrf_token" value="' . self::display($token) . '">';
66
+ }
64
67
  // --- Tarih ve Zaman Fonksiyonları ---
65
68
 
66
- /**
67
- * Sadece Günü döndürür (Örn: 24)
68
- */
69
- public static function day($date): string
70
- {
71
- if (empty($date)) return '-';
72
- return self::display(date('d', is_numeric($date) ? $date : strtotime($date)));
73
- }
69
+ /**
70
+ * Sadece Günü döndürür (Örn: 24)
71
+ */
72
+ public static function day($date): string
73
+ {
74
+ if (empty($date)) return '-';
75
+ return self::display(date('d', is_numeric($date) ? $date : strtotime($date)));
76
+ }
74
77
 
75
- /**
76
- * Sadece Ayı rakamla döndürür (Örn: 07)
77
- */
78
- public static function month($date): string
79
- {
80
- if (empty($date)) return '-';
81
- return self::display(date('m', is_numeric($date) ? $date : strtotime($date)));
82
- }
78
+ /**
79
+ * Sadece Ayı rakamla döndürür (Örn: 07)
80
+ */
81
+ public static function month($date): string
82
+ {
83
+ if (empty($date)) return '-';
84
+ return self::display(date('m', is_numeric($date) ? $date : strtotime($date)));
85
+ }
83
86
 
84
- /**
85
- * Yılı döndürür (Örn: 2026)
86
- */
87
- public static function year($date): string
88
- {
89
- if (empty($date)) return '-';
90
- return self::display(date('Y', is_numeric($date) ? $date : strtotime($date)));
91
- }
87
+ /**
88
+ * Yılı döndürür (Örn: 2026)
89
+ */
90
+ public static function year($date): string
91
+ {
92
+ if (empty($date)) return '-';
93
+ return self::display(date('Y', is_numeric($date) ? $date : strtotime($date)));
94
+ }
92
95
 
93
- /**
94
- * Saati döndürür (Örn: 14:30)
95
- */
96
- public static function timeOnly($date): string
97
- {
98
- if (empty($date)) return '-';
99
- return self::display(date('H:i', is_numeric($date) ? $date : strtotime($date)));
100
- }
96
+ /**
97
+ * Saati döndürür (Örn: 14:30)
98
+ */
99
+ public static function timeOnly($date): string
100
+ {
101
+ if (empty($date)) return '-';
102
+ return self::display(date('H:i', is_numeric($date) ? $date : strtotime($date)));
103
+ }
101
104
 
102
- /**
103
- * Tarihi 24.07.2026 formatında döndürür
104
- */
105
- public static function fulldate($date): string
106
- {
107
- if (empty($date)) return '-';
108
- return self::display(date('d.m.Y', is_numeric($date) ? $date : strtotime($date)));
109
- }
105
+ /**
106
+ * Tarihi 24.07.2026 formatında döndürür
107
+ */
108
+ public static function fulldate($date): string
109
+ {
110
+ if (empty($date)) return '-';
111
+ return self::display(date('d.m.Y', is_numeric($date) ? $date : strtotime($date)));
112
+ }
110
113
 
111
- /**
112
- * Ay isimlerini dile göre döndürür
113
- */
114
- public static function monthName($date, string $lang = 'tr'): string
115
- {
116
- if (empty($date)) return '-';
117
- $m = (int)date('n', is_numeric($date) ? $date : strtotime($date));
118
- $months = [
119
- 'tr' => ['', 'Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
120
- 'en' => ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
121
- 'de' => ['', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
122
- 'fr' => ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
123
- 'es' => ['', 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
124
- ];
125
- $lang = strtolower($lang);
126
- if (!isset($months[$lang])) $lang = 'en';
127
- return self::display($months[$lang][$m]);
128
- }
114
+ /**
115
+ * Ay isimlerini dile göre döndürür
116
+ */
117
+ public static function monthName($date, string $lang = 'tr'): string
118
+ {
119
+ if (empty($date)) return '-';
120
+ $m = (int)date('n', is_numeric($date) ? $date : strtotime($date));
121
+ $months = [
122
+ 'tr' => ['', 'Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
123
+ 'en' => ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
124
+ 'de' => ['', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
125
+ 'fr' => ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
126
+ 'es' => ['', 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
127
+ ];
128
+ $lang = strtolower($lang);
129
+ if (!isset($months[$lang])) $lang = 'en';
130
+ return self::display($months[$lang][$m]);
131
+ }
129
132
 
130
- /**
131
- * Tarihi yerelleştirilmiş ay ismiyle döndürür (Örn: 24 Temmuz 2026)
132
- */
133
- public static function fulldateName($date, string $lang = 'tr'): string
134
- {
135
- if (empty($date)) return '-';
136
- $time = is_numeric($date) ? $date : strtotime($date);
137
- $d = date('d', $time);
138
- $y = date('Y', $time);
139
- $mName = self::monthName($time, $lang);
140
-
141
- // İngilizce'de ay öne gelebilir (July 24, 2026) ama basitlik açısından formatı koruyabiliriz veya dile göre değiştirebiliriz.
142
- if (strtolower($lang) === 'en') {
143
- return self::display("{$mName} {$d}, {$y}");
144
- }
145
- return self::display("{$d} {$mName} {$y}");
146
- }
133
+ /**
134
+ * Tarihi yerelleştirilmiş ay ismiyle döndürür (Örn: 24 Temmuz 2026)
135
+ */
136
+ public static function fulldateName($date, string $lang = 'tr'): string
137
+ {
138
+ if (empty($date)) return '-';
139
+ $time = is_numeric($date) ? $date : strtotime($date);
140
+ $d = date('d', $time);
141
+ $y = date('Y', $time);
142
+ $mName = self::monthName($time, $lang);
143
+
144
+ // İngilizce'de ay öne gelebilir (July 24, 2026) ama basitlik açısından formatı koruyabiliriz veya dile göre değiştirebiliriz.
145
+ if (strtolower($lang) === 'en') {
146
+ return self::display("{$mName} {$d}, {$y}");
147
+ }
148
+ return self::display("{$d} {$mName} {$y}");
149
+ }
147
150
 
148
- /**
149
- * Sosyal medya tarzı zaman gösterimi (Örn: 5 dakika önce)
150
- */
151
- public static function timeAgo($date, string $lang = 'tr'): string
152
- {
153
- if (empty($date)) return '-';
154
- $time = is_numeric($date) ? $date : strtotime($date);
155
- $diff = time() - $time;
156
- if ($diff < 1) return self::display(($lang === 'tr') ? 'şimdi' : 'just now');
157
-
158
- $tokens = [
159
- 31536000 => 'year',
160
- 2592000 => 'month',
161
- 604800 => 'week',
162
- 86400 => 'day',
163
- 3600 => 'hour',
164
- 60 => 'minute',
165
- 1 => 'second'
166
- ];
167
-
168
- $lang = strtolower($lang);
169
- $translations = [
170
- 'tr' => ['year'=>'yıl', 'month'=>'ay', 'week'=>'hafta', 'day'=>'gün', 'hour'=>'saat', 'minute'=>'dakika', 'second'=>'saniye', 'ago'=>'önce', 'format'=>'{value} {unit} {ago}'],
171
- 'en' => ['year'=>'year', 'month'=>'month', 'week'=>'week', 'day'=>'day', 'hour'=>'hour', 'minute'=>'minute', 'second'=>'second', 'ago'=>'ago', 'format'=>'{value} {unit}s {ago}'],
172
- 'de' => ['year'=>'Jahr', 'month'=>'Monat', 'week'=>'Woche', 'day'=>'Tag', 'hour'=>'Stunde', 'minute'=>'Minute', 'second'=>'Sekunde', 'ago'=>'vor', 'format'=>'{ago} {value} {unit}en'], // simplified
173
- 'fr' => ['year'=>'an', 'month'=>'mois', 'week'=>'semaine', 'day'=>'jour', 'hour'=>'heure', 'minute'=>'minute', 'second'=>'seconde', 'ago'=>'il y a', 'format'=>'{ago} {value} {unit}s'],
174
- 'es' => ['year'=>'año', 'month'=>'mes', 'week'=>'semana', 'day'=>'día', 'hour'=>'hora', 'minute'=>'minuto', 'second'=>'segundo', 'ago'=>'hace', 'format'=>'{ago} {value} {unit}s']
175
- ];
176
- if (!isset($translations[$lang])) $lang = 'en';
177
-
178
- foreach ($tokens as $unit => $text) {
179
- if ($diff < $unit) continue;
180
- $numberOfUnits = floor($diff / $unit);
181
-
182
- // Pluralization logic is basic here, but functional for general use
183
- $unitStr = $translations[$lang][$text];
184
- if ($lang === 'en' && $numberOfUnits == 1) $translations['en']['format'] = '{value} {unit} {ago}';
185
-
186
- $formatted = str_replace(
187
- ['{value}', '{unit}', '{ago}'],
188
- [$numberOfUnits, $unitStr, $translations[$lang]['ago']],
189
- $translations[$lang]['format']
190
- );
191
-
192
- // Fix DE basic plurals roughly
193
- if ($lang === 'de') {
194
- $formatted = str_replace(['Jahren', 'Monaten', 'Wocheen', 'Tagen', 'Stundeen', 'Minuteen', 'Sekundeen'], ['Jahren', 'Monaten', 'Wochen', 'Tagen', 'Stunden', 'Minuten', 'Sekunden'], $formatted);
151
+ /**
152
+ * Sosyal medya tarzı zaman gösterimi (Örn: 5 dakika önce)
153
+ */
154
+ public static function timeAgo($date, string $lang = 'tr'): string
155
+ {
156
+ if (empty($date)) return '-';
157
+ $time = is_numeric($date) ? $date : strtotime($date);
158
+ $diff = time() - $time;
159
+ if ($diff < 1) return self::display(($lang === 'tr') ? 'şimdi' : 'just now');
160
+
161
+ $tokens = [
162
+ 31536000 => 'year',
163
+ 2592000 => 'month',
164
+ 604800 => 'week',
165
+ 86400 => 'day',
166
+ 3600 => 'hour',
167
+ 60 => 'minute',
168
+ 1 => 'second'
169
+ ];
170
+
171
+ $lang = strtolower($lang);
172
+ $translations = [
173
+ 'tr' => ['year' => 'yıl', 'month' => 'ay', 'week' => 'hafta', 'day' => 'gün', 'hour' => 'saat', 'minute' => 'dakika', 'second' => 'saniye', 'ago' => 'önce', 'format' => '{value} {unit} {ago}'],
174
+ 'en' => ['year' => 'year', 'month' => 'month', 'week' => 'week', 'day' => 'day', 'hour' => 'hour', 'minute' => 'minute', 'second' => 'second', 'ago' => 'ago', 'format' => '{value} {unit}s {ago}'],
175
+ 'de' => ['year' => 'Jahr', 'month' => 'Monat', 'week' => 'Woche', 'day' => 'Tag', 'hour' => 'Stunde', 'minute' => 'Minute', 'second' => 'Sekunde', 'ago' => 'vor', 'format' => '{ago} {value} {unit}en'], // simplified
176
+ 'fr' => ['year' => 'an', 'month' => 'mois', 'week' => 'semaine', 'day' => 'jour', 'hour' => 'heure', 'minute' => 'minute', 'second' => 'seconde', 'ago' => 'il y a', 'format' => '{ago} {value} {unit}s'],
177
+ 'es' => ['year' => 'año', 'month' => 'mes', 'week' => 'semana', 'day' => 'día', 'hour' => 'hora', 'minute' => 'minuto', 'second' => 'segundo', 'ago' => 'hace', 'format' => '{ago} {value} {unit}s']
178
+ ];
179
+ if (!isset($translations[$lang])) $lang = 'en';
180
+
181
+ foreach ($tokens as $unit => $text) {
182
+ if ($diff < $unit) continue;
183
+ $numberOfUnits = floor($diff / $unit);
184
+
185
+ // Pluralization logic is basic here, but functional for general use
186
+ $unitStr = $translations[$lang][$text];
187
+ if ($lang === 'en' && $numberOfUnits == 1) $translations['en']['format'] = '{value} {unit} {ago}';
188
+
189
+ $formatted = str_replace(
190
+ ['{value}', '{unit}', '{ago}'],
191
+ [$numberOfUnits, $unitStr, $translations[$lang]['ago']],
192
+ $translations[$lang]['format']
193
+ );
194
+
195
+ // Fix DE basic plurals roughly
196
+ if ($lang === 'de') {
197
+ $formatted = str_replace(['Jahren', 'Monaten', 'Wocheen', 'Tagen', 'Stundeen', 'Minuteen', 'Sekundeen'], ['Jahren', 'Monaten', 'Wochen', 'Tagen', 'Stunden', 'Minuten', 'Sekunden'], $formatted);
198
+ }
199
+ return self::display($formatted);
195
200
  }
196
- return self::display($formatted);
201
+ return '-';
197
202
  }
198
- return '-';
199
- }
200
203
 
201
204
  // --- Metin (String) İşleme Fonksiyonları ---
202
205
 
203
- /**
204
- * Uzun metinleri keser ve sonuna ... ekler
205
- */
206
- public static function truncate(?string $text, int $length = 100, string $append = '...'): string
207
- {
208
- if (empty($text)) return '';
209
- $text = strip_tags($text);
210
- if (mb_strlen($text, 'UTF-8') <= $length) return self::display($text);
211
-
212
- $truncated = mb_substr($text, 0, $length, 'UTF-8');
213
- // Son kelimeyi bölmemek için son boşluğa kadar al
214
- if (strpos($text, ' ') !== false) {
215
- $lastSpace = mb_strrpos($truncated, ' ', 0, 'UTF-8');
216
- if ($lastSpace !== false) {
217
- $truncated = mb_substr($truncated, 0, $lastSpace, 'UTF-8');
206
+ /**
207
+ * Uzun metinleri keser ve sonuna ... ekler
208
+ */
209
+ public static function truncate(?string $text, int $length = 100, string $append = '...'): string
210
+ {
211
+ if (empty($text)) return '';
212
+ $text = strip_tags($text);
213
+ if (mb_strlen($text, 'UTF-8') <= $length) return self::display($text);
214
+
215
+ $truncated = mb_substr($text, 0, $length, 'UTF-8');
216
+ // Son kelimeyi bölmemek için son boşluğa kadar al
217
+ if (strpos($text, ' ') !== false) {
218
+ $lastSpace = mb_strrpos($truncated, ' ', 0, 'UTF-8');
219
+ if ($lastSpace !== false) {
220
+ $truncated = mb_substr($truncated, 0, $lastSpace, 'UTF-8');
221
+ }
218
222
  }
223
+ return self::display($truncated . $append);
219
224
  }
220
- return self::display($truncated . $append);
221
- }
222
225
 
223
226
  // --- Para Birimi Formatlama ---
224
227
 
225
- /**
226
- * Tutar ve para birimi sembolü formatlama
227
- */
228
- public static function money($amount, string $currency = 'usd'): string
229
- {
230
- if ($amount === null || $amount === '') return '-';
231
- $amount = (float)$amount;
232
-
233
- $currencies = [
234
- 'usd' => '$', // US Dollar
235
- 'eur' => '€', // Euro
236
- 'try' => '₺', // Turkish Lira
237
- 'tl' => '₺', // Turkish Lira
238
- 'gbp' => '£', // British Pound
239
- 'jpy' => '¥', // Japanese Yen
240
- 'cny' => '¥', // Chinese Yuan
241
- 'rub' => '₽', // Russian Ruble
242
- 'inr' => '₹', // Indian Rupee
243
- 'aud' => 'A$', // Australian Dollar
244
- 'cad' => 'C$', // Canadian Dollar
245
- 'chf' => 'CHF', // Swiss Franc
246
- 'krw' => '₩', // South Korean Won
247
- 'brl' => 'R$', // Brazilian Real
248
- 'zar' => 'R', // South African Rand
249
- 'sek' => 'kr', // Swedish Krona
250
- 'nok' => 'kr', // Norwegian Krone
251
- 'mxn' => '$', // Mexican Peso
252
- 'sgd' => 'S$', // Singapore Dollar
253
- 'hkd' => 'HK$', // Hong Kong Dollar
254
- 'nzd' => 'NZ$', // New Zealand Dollar
255
- 'aed' => 'د.إ', // UAE Dirham
256
- 'sar' => '﷼', // Saudi Riyal
257
- 'pln' => 'zł' // Polish Zloty
258
- ];
259
-
260
- $currency = strtolower($currency);
261
- $symbol = $currencies[$currency] ?? strtoupper($currency) . ' ';
262
-
263
- // Sayıyı 1.250,50 veya 1,250.50 gibi formatlar. Genel standart olarak 1.250,50 (Avrupa/TR)
264
- // İhtiyaca göre number_format değiştirilebilir. (TR formatı baz alındı)
265
- $formattedAmount = number_format($amount, 2, ',', '.');
266
-
267
- // USD ve GBP gibi birimlerde sembol genelde başa gelir, TL veya EUR'da sona.
268
- if (in_array($currency, ['usd', 'gbp', 'aud', 'cad', 'sgd', 'hkd', 'nzd', 'mxn', 'brl'])) {
269
- return self::display($symbol . $formattedAmount);
270
- }
271
-
272
- return self::display($formattedAmount . ' ' . $symbol);
273
- }
228
+ /**
229
+ * Tutar ve para birimi sembolü formatlama
230
+ */
231
+ public static function money($amount, string $currency = 'usd'): string
232
+ {
233
+ if ($amount === null || $amount === '') return '-';
234
+ $amount = (float)$amount;
235
+
236
+ $currencies = [
237
+ 'usd' => '$', // US Dollar
238
+ 'eur' => '€', // Euro
239
+ 'try' => '₺', // Turkish Lira
240
+ 'tl' => '₺', // Turkish Lira
241
+ 'gbp' => '£', // British Pound
242
+ 'jpy' => '¥', // Japanese Yen
243
+ 'cny' => '¥', // Chinese Yuan
244
+ 'rub' => '₽', // Russian Ruble
245
+ 'inr' => '₹', // Indian Rupee
246
+ 'aud' => 'A$', // Australian Dollar
247
+ 'cad' => 'C$', // Canadian Dollar
248
+ 'chf' => 'CHF', // Swiss Franc
249
+ 'krw' => '₩', // South Korean Won
250
+ 'brl' => 'R$', // Brazilian Real
251
+ 'zar' => 'R', // South African Rand
252
+ 'sek' => 'kr', // Swedish Krona
253
+ 'nok' => 'kr', // Norwegian Krone
254
+ 'mxn' => '$', // Mexican Peso
255
+ 'sgd' => 'S$', // Singapore Dollar
256
+ 'hkd' => 'HK$', // Hong Kong Dollar
257
+ 'nzd' => 'NZ$', // New Zealand Dollar
258
+ 'aed' => 'د.إ', // UAE Dirham
259
+ 'sar' => '﷼', // Saudi Riyal
260
+ 'pln' => 'zł' // Polish Zloty
261
+ ];
262
+
263
+ $currency = strtolower($currency);
264
+ $symbol = $currencies[$currency] ?? strtoupper($currency) . ' ';
265
+
266
+ // Sayıyı 1.250,50 veya 1,250.50 gibi formatlar. Genel standart olarak 1.250,50 (Avrupa/TR)
267
+ // İhtiyaca göre number_format değiştirilebilir. (TR formatı baz alındı)
268
+ $formattedAmount = number_format($amount, 2, ',', '.');
269
+
270
+ // USD ve GBP gibi birimlerde sembol genelde başa gelir, TL veya EUR'da sona.
271
+ if (in_array($currency, ['usd', 'gbp', 'aud', 'cad', 'sgd', 'hkd', 'nzd', 'mxn', 'brl'])) {
272
+ return self::display($symbol . $formattedAmount);
273
+ }
274
274
 
275
- /**
276
- * Metni URL dostu bir slug'a çevirir (Örn: "Merhaba Dünya!" -> "merhaba-dunya")
277
- */
278
- public static function slugify(string ...$texts): string
279
- {
280
- $text = implode('-', $texts);
281
- $text = mb_strtolower($text, 'UTF-8');
282
-
283
- $search = [
284
- 'ç', 'ğ', 'ı', 'ö', 'ş', 'ü', // TR
285
- 'ä', 'ß', // DE
286
- 'ñ', // ES
287
- 'é', 'è', 'ê', 'ë', 'à', 'á', 'â', 'î', 'ï', 'í', 'ô', 'ó', 'ú', 'û', 'ù', 'æ', 'œ' // FR & ES
288
- ];
289
- $replace = [
290
- 'c', 'g', 'i', 'o', 's', 'u',
291
- 'ae', 'ss',
292
- 'n',
293
- 'e', 'e', 'e', 'e', 'a', 'a', 'a', 'i', 'i', 'i', 'o', 'o', 'u', 'u', 'u', 'ae', 'oe'
294
- ];
295
-
296
- $text = str_replace($search, $replace, $text);
297
- $text = preg_replace('/[^a-z0-9\-]/', '-', $text);
298
- $text = preg_replace('/-+/', '-', $text);
299
- return self::display(trim($text, '-'));
300
- }
275
+ return self::display($formattedAmount . ' ' . $symbol);
276
+ }
301
277
 
302
- /**
303
- * Menülerde geçerli sayfa ise belirtilen class'ı döndürür.
304
- */
305
- public static function activeClass(?string $path, string $className = 'active'): string
306
- {
307
- $currentUri = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH);
308
- return ($currentUri === $path) ? self::display($className) : '';
309
- }
278
+ /**
279
+ * Metni URL dostu bir slug'a çevirir (Örn: "Merhaba Dünya!" -> "merhaba-dunya")
280
+ */
281
+ public static function slugify(string ...$texts): string
282
+ {
283
+ $text = implode('-', $texts);
284
+ $text = mb_strtolower($text, 'UTF-8');
285
+
286
+ $search = [
287
+ 'ç',
288
+ 'ğ',
289
+ 'ı',
290
+ 'ö',
291
+ 'ş',
292
+ 'ü', // TR
293
+ 'ä',
294
+ 'ß', // DE
295
+ 'ñ', // ES
296
+ 'é',
297
+ 'è',
298
+ 'ê',
299
+ 'ë',
300
+ 'à',
301
+ 'á',
302
+ 'â',
303
+ 'î',
304
+ 'ï',
305
+ 'í',
306
+ 'ô',
307
+ 'ó',
308
+ 'ú',
309
+ 'û',
310
+ 'ù',
311
+ 'æ',
312
+ 'œ' // FR & ES
313
+ ];
314
+ $replace = [
315
+ 'c',
316
+ 'g',
317
+ 'i',
318
+ 'o',
319
+ 's',
320
+ 'u',
321
+ 'ae',
322
+ 'ss',
323
+ 'n',
324
+ 'e',
325
+ 'e',
326
+ 'e',
327
+ 'e',
328
+ 'a',
329
+ 'a',
330
+ 'a',
331
+ 'i',
332
+ 'i',
333
+ 'i',
334
+ 'o',
335
+ 'o',
336
+ 'u',
337
+ 'u',
338
+ 'u',
339
+ 'ae',
340
+ 'oe'
341
+ ];
342
+
343
+ $text = str_replace($search, $replace, $text);
344
+ $text = preg_replace('/[^a-z0-9\-]/', '-', $text);
345
+ $text = preg_replace('/-+/', '-', $text);
346
+ return self::display(trim($text, '-'));
347
+ }
310
348
 
311
- /**
312
- * Dosya boyutlarını okunabilir formata çevirir (KB, MB, GB vb.)
313
- */
314
- public static function formatSize(int $bytes): string
315
- {
316
- if ($bytes <= 0) return '0 B';
317
- $units = ['B', 'KB', 'MB', 'GB', 'TB'];
318
- $power = floor(log($bytes, 1024));
319
- return self::display(number_format($bytes / pow(1024, $power), 2, ',', '.') . ' ' . $units[$power]);
320
- }
349
+ /**
350
+ * Menülerde geçerli sayfa ise belirtilen class'ı döndürür.
351
+ */
352
+ public static function activeClass(?string $path, string $className = 'active'): string
353
+ {
354
+ $currentUri = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH);
355
+ return ($currentUri === $path) ? self::display($className) : '';
356
+ }
321
357
 
322
- /**
323
- * E-posta adresini KVKK/GDPR kapsamında maskeler (Örn: u***@artilingo.com)
324
- */
325
- public static function maskEmail(?string $email): string
326
- {
327
- if (empty($email)) return '-';
328
- if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) return self::display($email);
329
- list($first, $last) = explode('@', $email);
330
- $first = mb_substr($first, 0, 1, 'UTF-8') . str_repeat('*', max(mb_strlen($first, 'UTF-8') - 1, 3));
331
- return self::display($first . '@' . $last);
332
- }
358
+ /**
359
+ * Dosya boyutlarını okunabilir formata çevirir (KB, MB, GB vb.)
360
+ */
361
+ public static function formatSize(int $bytes): string
362
+ {
363
+ if ($bytes <= 0) return '0 B';
333
364
 
334
- /**
335
- * Telefon numarasını KVKK kapsamında maskeler (Örn: +90 555 *** ** 67)
336
- */
337
- public static function maskPhone(?string $phone): string
338
- {
339
- if (empty($phone)) return '-';
340
- $phoneStr = preg_replace('/[^\d\+]/', '', $phone);
341
- $len = strlen($phoneStr);
342
- if ($len < 6) return self::display($phone);
343
- $start = substr($phoneStr, 0, 3);
344
- $end = substr($phoneStr, -2);
345
- $masked = $start . str_repeat('*', max($len - 5, 3)) . $end;
346
- return self::display($masked);
347
- }
365
+ $units = ['B', 'KB', 'MB', 'GB', 'TB'];
348
366
 
349
- /**
350
- * Veritabanından gelen 16 byte'lık binary UUID verisini 36 karakterlik
351
- * okunabilir (HEX) formata dönüştürür ve ekrana basar.
352
- */
353
- public static function uuid(?string $binaryId): string
354
- {
355
- if (empty($binaryId)) return '-';
356
- return self::display(\Bin\SystemMethod::formatId($binaryId));
357
- }
358
- }
367
+ // (int) ekleyerek float değerini int'e dönüştürüyoruz
368
+ // min() ile de indeksin $units dizisini aşmasını engelliyoruz
369
+ $power = (int) floor(log($bytes, 1024));
370
+ $power = min($power, count($units) - 1);
371
+
372
+ return self::display(number_format($bytes / pow(1024, $power), 2, ',', '.') . ' ' . $units[$power]);
373
+ }
374
+
375
+ /**
376
+ * E-posta adresini KVKK/GDPR kapsamında maskeler (Örn: u***@artilingo.com)
377
+ */
378
+ public static function maskEmail(?string $email): string
379
+ {
380
+ if (empty($email)) return '-';
381
+ if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) return self::display($email);
382
+ list($first, $last) = explode('@', $email);
383
+ $first = mb_substr($first, 0, 1, 'UTF-8') . str_repeat('*', max(mb_strlen($first, 'UTF-8') - 1, 3));
384
+ return self::display($first . '@' . $last);
385
+ }
386
+
387
+ /**
388
+ * Telefon numarasını KVKK kapsamında maskeler (Örn: +90 555 *** ** 67)
389
+ */
390
+ public static function maskPhone(?string $phone): string
391
+ {
392
+ if (empty($phone)) return '-';
393
+ $phoneStr = preg_replace('/[^\d\+]/', '', $phone);
394
+ $len = strlen($phoneStr);
395
+ if ($len < 6) return self::display($phone);
396
+ $start = substr($phoneStr, 0, 3);
397
+ $end = substr($phoneStr, -2);
398
+ $masked = $start . str_repeat('*', max($len - 5, 3)) . $end;
399
+ return self::display($masked);
400
+ }
401
+
402
+ /**
403
+ * Veritabanından gelen 16 byte'lık binary UUID verisini 36 karakterlik
404
+ * okunabilir (HEX) formata dönüştürür ve ekrana basar.
405
+ */
406
+ public static function uuid(?string $binaryId): string
407
+ {
408
+ if (empty($binaryId)) return '-';
409
+ return self::display(\Bin\SystemMethod::formatId($binaryId));
410
+ }
411
+
412
+ /**
413
+ * ArtiFrame Core Dynamic Router
414
+ * URL'yi analiz eder, en uzun eşleşen .php dosyasını bulur ve
415
+ * parametreleri $_GET['param1'], $_GET['param2']... olarak bağlar.
416
+ *
417
+ * @param string|null $requestUri
418
+ * @return void
419
+ */
420
+ public static function routeLink(?string $requestUri = null): void
421
+ {
422
+
423
+ if (!defined('APP_MAINTENANCE')) {
424
+ $rawVal = $_ENV['APP_MAINTENANCE'] ?? false;
425
+
426
+ // filter_var("true", FILTER_VALIDATE_BOOLEAN) -> bool(true) üretir
427
+ define('APP_MAINTENANCE', filter_var($rawVal, FILTER_VALIDATE_BOOLEAN));
428
+ }
429
+
430
+ // ------------------------------------------------------------------
431
+ // 1. BAKIM MODU (MAINTENANCE GUARD)
432
+ // ------------------------------------------------------------------
433
+ $isMaintenance = defined('APP_MAINTENANCE') && (
434
+ \APP_MAINTENANCE === true ||
435
+ \APP_MAINTENANCE === 'true' ||
436
+ \APP_MAINTENANCE === 1 ||
437
+ \APP_MAINTENANCE === '1'
438
+ );
439
+
440
+ $uri = $requestUri ?? ($_SERVER['REQUEST_URI'] ?? '/');
441
+ $path = trim(parse_url($uri, PHP_URL_PATH), '/');
442
+
443
+ $isApi = (strpos($path, 'api/') === 0 || $path === 'api');
444
+
445
+ if ($isMaintenance) {
446
+ http_response_code(503);
447
+ header('Retry-After: 3600');
448
+
449
+ if ($isApi) {
450
+ \Bin\SystemMethod::jsonResponse([
451
+ 'status' => 'error',
452
+ 'message' => 'Service Unavailable / Maintenance Mode',
453
+ 'data' => []
454
+ ], 503);
455
+ } else {
456
+ $maintenanceFile = $_SERVER['DOCUMENT_ROOT'] . '/503.php';
457
+ if (file_exists($maintenanceFile)) {
458
+ require_once $maintenanceFile;
459
+ } else {
460
+ echo '<h1>503 - Bakım Modundayız</h1><p>Sistem şu an bakımdadır, lütfen daha sonra tekrar deneyiniz.</p>';
461
+ }
462
+ }
463
+ exit;
464
+ }
465
+
466
+ if (empty($path)) {
467
+ $path = 'landing';
468
+ }
469
+
470
+ $segments = explode('/', $path);
471
+ $params = [];
472
+ $targetFile = null;
473
+
474
+ // En uzun eşleşen .php dosyasını bulana kadar sondan eleman eksilt
475
+ while (count($segments) > 0) {
476
+ $possiblePath = $_SERVER['DOCUMENT_ROOT'] . '/' . implode('/', $segments) . '.php';
477
+
478
+ if (file_exists($possiblePath)) {
479
+ $targetFile = $possiblePath;
480
+ break;
481
+ }
482
+
483
+ // Bulunamayan parçaları parametre olarak biriktir
484
+ array_unshift($params, array_pop($segments));
485
+ }
486
+
487
+ // Dosya bulunduysa çalıştır
488
+ if ($targetFile) {
489
+ $_GET['params'] = $params;
490
+
491
+ foreach ($params as $index => $value) {
492
+ $paramName = 'param' . ($index + 1);
493
+ $_GET[$paramName] = $value;
494
+ }
495
+
496
+ // Geriye uyumluluk alias'ı
497
+ if (isset($_GET['param1'])) {
498
+ $_GET['id'] = $_GET['param1'];
499
+ }
500
+
501
+ require_once $targetFile;
502
+ exit;
503
+ }
504
+
505
+ // Hiçbir dosya bulunamadıysa 404
506
+ http_response_code(404);
507
+
508
+ if ($isApi) {
509
+ \Bin\SystemMethod::jsonResponse([
510
+ 'status' => 'error',
511
+ 'message' => 'API Endpoint Not Found',
512
+ 'data' => []
513
+ ], 404);
514
+ } else {
515
+ $notFoundFile = $_SERVER['DOCUMENT_ROOT'] . '/404.php';
516
+ if (file_exists($notFoundFile)) {
517
+ require_once $notFoundFile;
518
+ } else {
519
+ echo "<h1>404 - Sayfa Bulunamadı</h1>";
520
+ }
521
+ }
522
+ exit;
523
+ }
524
+ } // end class ViewMethod
525
+
526
+ } // end namespace Bin
359
527
 
360
528
  // Geliştiriciler (Özellikle Juniorlar) için kullanımı en kolay global yardımcı fonksiyonlar
361
- if (!function_exists(__NAMESPACE__ . '\\display')) {
362
- function display($data, string $default = ''): string {
363
- return \Bin\ViewMethod::display($data, $default);
529
+ namespace {
530
+
531
+ if (!function_exists('display')) {
532
+ function display($data, string $default = ''): string
533
+ {
534
+ return \Bin\ViewMethod::display($data, $default);
535
+ }
364
536
  }
365
- }
366
537
 
367
- if (!function_exists(__NAMESPACE__ . '\\escapeUrl')) {
368
- function escapeUrl(?string $url): string {
369
- return \Bin\ViewMethod::escapeUrl($url);
538
+ if (!function_exists('escapeUrl')) {
539
+ function escapeUrl(?string $url): string
540
+ {
541
+ return \Bin\ViewMethod::escapeUrl($url);
542
+ }
370
543
  }
371
- }
372
544
 
373
- if (!function_exists(__NAMESPACE__ . '\\formatDate')) {
374
- function formatDate(?string $date, string $format = 'd.m.Y H:i'): string {
375
- return \Bin\ViewMethod::formatDate($date, $format);
545
+ if (!function_exists('formatDate')) {
546
+ function formatDate(?string $date, string $format = 'd.m.Y H:i'): string
547
+ {
548
+ return \Bin\ViewMethod::formatDate($date, $format);
549
+ }
376
550
  }
377
- }
378
551
 
379
- if (!function_exists(__NAMESPACE__ . '\\csrfField')) {
380
- function csrfField(): string {
381
- return \Bin\ViewMethod::csrfField();
552
+ if (!function_exists('csrfField')) {
553
+ function csrfField(): string
554
+ {
555
+ return \Bin\ViewMethod::csrfField();
556
+ }
382
557
  }
383
- }
384
558
 
385
- if (!function_exists(__NAMESPACE__ . '\\day')) {
386
- function day($date): string {
387
- return \Bin\ViewMethod::day($date);
559
+ if (!function_exists('day')) {
560
+ function day($date): string
561
+ {
562
+ return \Bin\ViewMethod::day($date);
563
+ }
388
564
  }
389
- }
390
565
 
391
- if (!function_exists(__NAMESPACE__ . '\\month')) {
392
- function month($date): string {
393
- return \Bin\ViewMethod::month($date);
566
+ if (!function_exists('month')) {
567
+ function month($date): string
568
+ {
569
+ return \Bin\ViewMethod::month($date);
570
+ }
394
571
  }
395
- }
396
572
 
397
- if (!function_exists(__NAMESPACE__ . '\\year')) {
398
- function year($date): string {
399
- return \Bin\ViewMethod::year($date);
573
+ if (!function_exists('year')) {
574
+ function year($date): string
575
+ {
576
+ return \Bin\ViewMethod::year($date);
577
+ }
400
578
  }
401
- }
402
579
 
403
- if (!function_exists(__NAMESPACE__ . '\\timeOnly')) {
404
- function timeOnly($date): string {
405
- return \Bin\ViewMethod::timeOnly($date);
580
+ if (!function_exists('timeOnly')) {
581
+ function timeOnly($date): string
582
+ {
583
+ return \Bin\ViewMethod::timeOnly($date);
584
+ }
406
585
  }
407
- }
408
586
 
409
- if (!function_exists(__NAMESPACE__ . '\\fulldate')) {
410
- function fulldate($date): string {
411
- return \Bin\ViewMethod::fulldate($date);
587
+ if (!function_exists('fulldate')) {
588
+ function fulldate($date): string
589
+ {
590
+ return \Bin\ViewMethod::fulldate($date);
591
+ }
412
592
  }
413
- }
414
593
 
415
- if (!function_exists(__NAMESPACE__ . '\\monthName')) {
416
- function monthName($date, string $lang = 'tr'): string {
417
- return \Bin\ViewMethod::monthName($date, $lang);
594
+ if (!function_exists('monthName')) {
595
+ function monthName($date, string $lang = 'tr'): string
596
+ {
597
+ return \Bin\ViewMethod::monthName($date, $lang);
598
+ }
418
599
  }
419
- }
420
600
 
421
- if (!function_exists(__NAMESPACE__ . '\\fulldateName')) {
422
- function fulldateName($date, string $lang = 'tr'): string {
423
- return \Bin\ViewMethod::fulldateName($date, $lang);
601
+ if (!function_exists('fulldateName')) {
602
+ function fulldateName($date, string $lang = 'tr'): string
603
+ {
604
+ return \Bin\ViewMethod::fulldateName($date, $lang);
605
+ }
424
606
  }
425
- }
426
607
 
427
- if (!function_exists(__NAMESPACE__ . '\\timeAgo')) {
428
- function timeAgo($date, string $lang = 'tr'): string {
429
- return \Bin\ViewMethod::timeAgo($date, $lang);
608
+ if (!function_exists('timeAgo')) {
609
+ function timeAgo($date, string $lang = 'tr'): string
610
+ {
611
+ return \Bin\ViewMethod::timeAgo($date, $lang);
612
+ }
613
+ }
614
+
615
+ if (!function_exists('truncate')) {
616
+ function truncate(?string $text, int $length = 100, string $append = '...'): string
617
+ {
618
+ return \Bin\ViewMethod::truncate($text, $length, $append);
619
+ }
430
620
  }
431
- }
432
621
 
433
- if (!function_exists(__NAMESPACE__ . '\\truncate')) {
434
- function truncate(?string $text, int $length = 100, string $append = '...'): string {
435
- return \Bin\ViewMethod::truncate($text, $length, $append);
622
+ if (!function_exists('money')) {
623
+ function money($amount, string $currency = 'usd'): string
624
+ {
625
+ return \Bin\ViewMethod::money($amount, $currency);
626
+ }
436
627
  }
437
- }
438
628
 
439
- if (!function_exists(__NAMESPACE__ . '\\money')) {
440
- function money($amount, string $currency = 'usd'): string {
441
- return \Bin\ViewMethod::money($amount, $currency);
629
+ if (!function_exists('slugify')) {
630
+ function slugify(string ...$texts): string
631
+ {
632
+ return \Bin\ViewMethod::slugify(...$texts);
633
+ }
442
634
  }
443
- }
444
635
 
445
- if (!function_exists(__NAMESPACE__ . '\\slugify')) {
446
- function slugify(string ...$texts): string {
447
- return \Bin\ViewMethod::slugify(...$texts);
636
+ if (!function_exists('activeClass')) {
637
+ function activeClass(string $path, string $className = 'active'): string
638
+ {
639
+ return \Bin\ViewMethod::activeClass($path, $className);
640
+ }
448
641
  }
449
- }
450
642
 
451
- if (!function_exists(__NAMESPACE__ . '\\activeClass')) {
452
- function activeClass(string $path, string $className = 'active'): string {
453
- return \Bin\ViewMethod::activeClass($path, $className);
643
+ if (!function_exists('formatSize')) {
644
+ function formatSize(int $bytes): string
645
+ {
646
+ return \Bin\ViewMethod::formatSize($bytes);
647
+ }
454
648
  }
455
- }
456
649
 
457
- if (!function_exists(__NAMESPACE__ . '\\formatSize')) {
458
- function formatSize(int $bytes): string {
459
- return \Bin\ViewMethod::formatSize($bytes);
650
+ if (!function_exists('maskEmail')) {
651
+ function maskEmail(?string $email): string
652
+ {
653
+ return \Bin\ViewMethod::maskEmail($email);
654
+ }
460
655
  }
461
- }
462
656
 
463
- if (!function_exists(__NAMESPACE__ . '\\maskEmail')) {
464
- function maskEmail(?string $email): string {
465
- return \Bin\ViewMethod::maskEmail($email);
657
+ if (!function_exists('maskPhone')) {
658
+ function maskPhone(?string $phone): string
659
+ {
660
+ return \Bin\ViewMethod::maskPhone($phone);
661
+ }
466
662
  }
467
- }
468
663
 
469
- if (!function_exists(__NAMESPACE__ . '\\maskPhone')) {
470
- function maskPhone(?string $phone): string {
471
- return \Bin\ViewMethod::maskPhone($phone);
664
+ if (!function_exists('uuid')) {
665
+ function uuid(?string $binaryId): string
666
+ {
667
+ return \Bin\ViewMethod::uuid($binaryId);
668
+ }
472
669
  }
473
- }
474
670
 
475
- if (!function_exists(__NAMESPACE__ . '\\uuid')) {
476
- function uuid(?string $binaryId): string {
477
- return \Bin\ViewMethod::uuid($binaryId);
671
+ if (!function_exists('routeLink')) {
672
+ function routeLink(?string $requestUri = null)
673
+ {
674
+ return \Bin\ViewMethod::routeLink($requestUri);
675
+ }
478
676
  }
479
677
  }