@artilingo/artiframe-cli 2.0.4 → 2.0.5
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.
- package/LICENSE +660 -660
- package/bin/artiframe.js +0 -0
- package/bin/artiframe.php +0 -0
- package/core-stubs/app/ApiAuthControl.php +76 -0
- package/core-stubs/app/ApiControl.php +81 -35
- package/core-stubs/app/AuthControl.php +39 -0
- package/core-stubs/app/Database.php +36 -35
- package/core-stubs/app/DotEnv.php +19 -1
- package/core-stubs/app/ViewControl.php +47 -1
- package/core-stubs/bin/SQLMethod.php +261 -0
- package/core-stubs/bin/SystemMethod.php +115 -74
- package/core-stubs/bin/ViewMethod.php +19 -5
- package/core-stubs/docs/de.html +4325 -4347
- package/core-stubs/docs/en.html +4325 -4347
- package/core-stubs/docs/es.html +4325 -4347
- package/core-stubs/docs/fr.html +4325 -4347
- package/core-stubs/docs/tr.html +117 -46
- package/core-stubs/public/403.php +52 -0
- package/core-stubs/public/assets/css/components/header.css +174 -0
- package/core-stubs/public/assets/css/components/mobilenav.css +198 -0
- package/core-stubs/public/assets/css/components/sidebar.css +184 -0
- package/core-stubs/public/assets/css/root/app.css +975 -38
- package/core-stubs/public/assets/css/root/root.css +64 -0
- package/core-stubs/public/assets/js/components/header.js +380 -0
- package/core-stubs/public/assets/js/components/mobilenav.js +97 -0
- package/core-stubs/public/assets/js/components/theme-modal.js +74 -0
- package/core-stubs/public/assets/js/root/app.js +1870 -0
- package/core-stubs/public/includes/footer.php +4 -5
- package/core-stubs/public/includes/head-auth.php +65 -0
- package/core-stubs/public/includes/head.php +56 -17
- package/core-stubs/public/includes/header.php +135 -1
- package/core-stubs/public/includes/mobilenav.php +75 -3
- package/core-stubs/public/includes/sidebar.php +186 -1
- package/core-stubs/public/includes/theme-modal.php +1 -0
- package/db-studio/debug.log +3 -0
- package/db-studio/index.html +1755 -0
- package/db-studio/launcher.html +102 -0
- package/db-studio/launcher.js +180 -0
- package/db-studio/logo.svg +22 -0
- package/db-studio/main.js +568 -0
- package/db-studio/package-lock.json +1034 -0
- package/db-studio/package.json +16 -0
- package/db-studio/preload.js +29 -0
- package/devops-studio/api-inspector.js +222 -0
- package/devops-studio/index.html +1892 -0
- package/devops-studio/logo.svg +22 -0
- package/devops-studio/main.js +67 -0
- package/devops-studio/make-wizard.js +635 -0
- package/devops-studio/package-lock.json +871 -0
- package/devops-studio/package.json +12 -0
- package/package.json +5 -2
- package/scripts/postinstall.js +44 -8
- package/server-studio/.json-404-guard +1 -0
- package/server-studio/index.html +283 -0
- package/server-studio/logo.svg +22 -0
- package/server-studio/main.js +133 -0
- package/server-studio/package-lock.json +1179 -0
- package/server-studio/package.json +15 -0
- package/server-studio/router.php +99 -0
- package/src/App.php +29 -0
- package/src/Commands/AddCommand.php +26 -9
- package/src/Commands/DbExportCommand.php +131 -0
- package/src/Commands/DbStartCommand.php +46 -0
- package/src/Commands/DevopsCommand.php +35 -0
- package/src/Commands/GoCommand.php +48 -48
- package/src/Commands/ListCommand.php +68 -68
- package/src/Commands/MakeApiCommand.php +6 -1
- package/src/Commands/MakeViewCommand.php +25 -2
- package/src/Commands/NewProjectCommand.php +16 -11
- package/src/Commands/OptimizeCommand.php +61 -0
- package/src/Commands/RemoveCommand.php +35 -7
- package/src/Commands/ServeCommand.php +46 -91
- package/src/Commands/ShowCommand.php +24 -24
- package/src/Commands/UpgradeCommand.php +39 -10
- package/stubs/make/api-switch-case.stub +1 -1
- package/stubs/make/auth-api-standart.stub +20 -0
- package/stubs/make/auth-api-switch-case.stub +38 -0
- package/stubs/make/auth-view.stub +26 -0
- package/stubs/make/class.stub +10 -2
- package/stubs/make/view.stub +3 -0
- package/stubs/service/image.stub +334 -334
- package/stubs/service/iyzico.stub +637 -637
- package/stubs/service/jwt.stub +312 -312
- package/stubs/service/phpmailer.stub +143 -143
- package/stubs/service/pusher.stub +232 -232
- package/stubs/service/qrcode.stub +169 -169
- package/stubs/service/redis.stub +361 -361
- package/stubs/service/s3.stub +377 -377
- package/stubs/service/stripe.stub +526 -526
- package/stubs/service/twilio.stub +361 -361
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* ArtiFrame Database Mini-ORM & SQL Helpers
|
|
4
|
+
*
|
|
5
|
+
* @package ArtiFrame
|
|
6
|
+
* @author Artilingo
|
|
7
|
+
* @license AGPLv3
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
namespace Bin {
|
|
11
|
+
|
|
12
|
+
class SQLMethod
|
|
13
|
+
{
|
|
14
|
+
/**
|
|
15
|
+
* Güvenli ve hızlı bir PDO Prepare & Execute sarmalayıcısı.
|
|
16
|
+
*/
|
|
17
|
+
public static function executeStmt(string $sql, array $params = []): \PDOStatement
|
|
18
|
+
{
|
|
19
|
+
// App\Database PSR-4 ile otomatik yüklenir. Sadece kullanıldığı yerde devreye girer.
|
|
20
|
+
$db = \App\Database::getInstance();
|
|
21
|
+
\App\Database::ping();
|
|
22
|
+
|
|
23
|
+
$stmt = $db->prepare($sql);
|
|
24
|
+
$stmt->execute($params);
|
|
25
|
+
|
|
26
|
+
return $stmt;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static function dbInsert(string $table, array $data): string
|
|
30
|
+
{
|
|
31
|
+
if (empty($data)) {
|
|
32
|
+
throw new \InvalidArgumentException("Eklenecek veri (data) boş olamaz.");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Tablo adını güvenlik için ters tırnak (backtick) ile saralım
|
|
36
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
37
|
+
|
|
38
|
+
$columns = [];
|
|
39
|
+
$placeholders = [];
|
|
40
|
+
$params = [];
|
|
41
|
+
|
|
42
|
+
foreach ($data as $key => $value) {
|
|
43
|
+
$columns[] = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $key) . "`";
|
|
44
|
+
$placeholders[] = "?";
|
|
45
|
+
$params[] = $value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
$sql = "INSERT INTO {$table} (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")";
|
|
49
|
+
self::executeStmt($sql, $params);
|
|
50
|
+
|
|
51
|
+
return \App\Database::getInstance()->lastInsertId();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static function dbUpdate(string $table, array $data, array $where): int
|
|
55
|
+
{
|
|
56
|
+
if (empty($data)) {
|
|
57
|
+
throw new \InvalidArgumentException("Güncellenecek veri (data) boş olamaz.");
|
|
58
|
+
}
|
|
59
|
+
if (empty($where)) {
|
|
60
|
+
throw new \InvalidArgumentException("BOMBA RİSKİ: Neye göre güncelleneceği (where) boş olamaz! Tüm tabloyu güncelleyemezsiniz.");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
64
|
+
|
|
65
|
+
$setParts = [];
|
|
66
|
+
$params = [];
|
|
67
|
+
foreach ($data as $key => $value) {
|
|
68
|
+
$setParts[] = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $key) . "` = ?";
|
|
69
|
+
$params[] = $value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
[$whereParts, $whereParams] = self::parseWhere($where);
|
|
73
|
+
$params = array_merge($params, $whereParams);
|
|
74
|
+
|
|
75
|
+
$sql = "UPDATE {$table} SET " . implode(', ', $setParts) . " WHERE " . implode(' AND ', $whereParts);
|
|
76
|
+
$stmt = self::executeStmt($sql, $params);
|
|
77
|
+
|
|
78
|
+
return $stmt->rowCount();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public static function dbDelete(string $table, array $where): int
|
|
82
|
+
{
|
|
83
|
+
if (empty($where)) {
|
|
84
|
+
throw new \InvalidArgumentException("BOMBA RİSKİ: Neye göre silineceği (where) boş olamaz! Tüm tabloyu silemezsiniz.");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
88
|
+
|
|
89
|
+
[$whereParts, $params] = self::parseWhere($where);
|
|
90
|
+
|
|
91
|
+
$sql = "DELETE FROM {$table} WHERE " . implode(' AND ', $whereParts);
|
|
92
|
+
$stmt = self::executeStmt($sql, $params);
|
|
93
|
+
|
|
94
|
+
return $stmt->rowCount();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* WHERE dizisini güvenli SQL ve Parametrelere çevirir.
|
|
100
|
+
*/
|
|
101
|
+
private static function parseWhere(array $where): array
|
|
102
|
+
{
|
|
103
|
+
$whereParts = [];
|
|
104
|
+
$params = [];
|
|
105
|
+
|
|
106
|
+
foreach ($where as $key => $value) {
|
|
107
|
+
$key = trim($key);
|
|
108
|
+
// İçinde operatör varsa (Örn: "yas >" veya "isim LIKE")
|
|
109
|
+
if (preg_match('/^([a-zA-Z0-9_\.]+)\s*(>=|<=|!=|<>|>|<|LIKE|NOT LIKE)$/i', $key, $matches)) {
|
|
110
|
+
$column = $matches[1];
|
|
111
|
+
$operator = strtoupper($matches[2]);
|
|
112
|
+
} else {
|
|
113
|
+
$column = preg_replace('/[^a-zA-Z0-9_\.]/', '', $key);
|
|
114
|
+
$operator = '=';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Tabloadi.Sutun formatını güvenli backtick içine al: `tabloadi`.`sutun`
|
|
118
|
+
$colParts = explode('.', $column);
|
|
119
|
+
$safeCol = implode('.', array_map(fn($p) => "`$p`", $colParts));
|
|
120
|
+
|
|
121
|
+
$whereParts[] = "{$safeCol} {$operator} ?";
|
|
122
|
+
$params[] = $value;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return [$whereParts, $params];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public static function dbGet(string $table, array $where = [], string $orderBy = ''): mixed
|
|
129
|
+
{
|
|
130
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
131
|
+
|
|
132
|
+
$sql = "SELECT * FROM {$table}";
|
|
133
|
+
$params = [];
|
|
134
|
+
|
|
135
|
+
if (!empty($where)) {
|
|
136
|
+
[$whereParts, $params] = self::parseWhere($where);
|
|
137
|
+
$sql .= " WHERE " . implode(' AND ', $whereParts);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!empty($orderBy)) {
|
|
141
|
+
// Sadece a-z, boşluk ve virgüle izin ver (Injection koruması)
|
|
142
|
+
$orderBy = preg_replace('/[^a-zA-Z0-9_ \.,]/', '', $orderBy);
|
|
143
|
+
$sql .= " ORDER BY {$orderBy}";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
$sql .= " LIMIT 1";
|
|
147
|
+
|
|
148
|
+
return self::executeStmt($sql, $params)->fetch(\PDO::FETCH_ASSOC);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public static function dbList(string $table, array $where = [], string $orderBy = '', string|int $limit = ''): array
|
|
152
|
+
{
|
|
153
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
154
|
+
|
|
155
|
+
$sql = "SELECT * FROM {$table}";
|
|
156
|
+
$params = [];
|
|
157
|
+
|
|
158
|
+
if (!empty($where)) {
|
|
159
|
+
[$whereParts, $params] = self::parseWhere($where);
|
|
160
|
+
$sql .= " WHERE " . implode(' AND ', $whereParts);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!empty($orderBy)) {
|
|
164
|
+
$orderBy = preg_replace('/[^a-zA-Z0-9_ \.,]/', '', $orderBy);
|
|
165
|
+
$sql .= " ORDER BY {$orderBy}";
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!empty($limit)) {
|
|
169
|
+
// Sadece rakam ve virgüle izin ver (Örn: "0, 20" veya "20")
|
|
170
|
+
$limit = preg_replace('/[^0-9, ]/', '', (string)$limit);
|
|
171
|
+
$sql .= " LIMIT {$limit}";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return self::executeStmt($sql, $params)->fetchAll(\PDO::FETCH_ASSOC);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public static function dbCount(string $table, array $where = []): int
|
|
178
|
+
{
|
|
179
|
+
$table = "`" . preg_replace('/[^a-zA-Z0-9_]/', '', $table) . "`";
|
|
180
|
+
|
|
181
|
+
$sql = "SELECT COUNT(*) FROM {$table}";
|
|
182
|
+
$params = [];
|
|
183
|
+
|
|
184
|
+
if (!empty($where)) {
|
|
185
|
+
[$whereParts, $params] = self::parseWhere($where);
|
|
186
|
+
$sql .= " WHERE " . implode(' AND ', $whereParts);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return (int) self::executeStmt($sql, $params)->fetchColumn(0);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public static function dbRow(string $sql, array $params = [], int $fetchStyle = \PDO::FETCH_ASSOC): mixed
|
|
193
|
+
{
|
|
194
|
+
return self::executeStmt($sql, $params)->fetch($fetchStyle);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public static function dbRows(string $sql, array $params = [], int $fetchStyle = \PDO::FETCH_ASSOC): array
|
|
198
|
+
{
|
|
199
|
+
return self::executeStmt($sql, $params)->fetchAll($fetchStyle);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public static function dbValue(string $sql, array $params = [], int $column = 0): mixed
|
|
203
|
+
{
|
|
204
|
+
return self::executeStmt($sql, $params)->fetchColumn($column);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
namespace {
|
|
211
|
+
if (!function_exists('dbExecute')) {
|
|
212
|
+
function dbExecute(string $sql, array $params = []): \PDOStatement {
|
|
213
|
+
return \Bin\SQLMethod::executeStmt($sql, $params);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!function_exists('dbInsert')) {
|
|
217
|
+
function dbInsert(string $table, array $data): string {
|
|
218
|
+
return \Bin\SQLMethod::dbInsert($table, $data);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!function_exists('dbUpdate')) {
|
|
222
|
+
function dbUpdate(string $table, array $data, array $where): int {
|
|
223
|
+
return \Bin\SQLMethod::dbUpdate($table, $data, $where);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!function_exists('dbDelete')) {
|
|
227
|
+
function dbDelete(string $table, array $where): int {
|
|
228
|
+
return \Bin\SQLMethod::dbDelete($table, $where);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!function_exists('dbGet')) {
|
|
232
|
+
function dbGet(string $table, array $where = [], string $orderBy = ''): mixed {
|
|
233
|
+
return \Bin\SQLMethod::dbGet($table, $where, $orderBy);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (!function_exists('dbList')) {
|
|
237
|
+
function dbList(string $table, array $where = [], string $orderBy = '', string|int $limit = ''): array {
|
|
238
|
+
return \Bin\SQLMethod::dbList($table, $where, $orderBy, $limit);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!function_exists('dbCount')) {
|
|
242
|
+
function dbCount(string $table, array $where = []): int {
|
|
243
|
+
return \Bin\SQLMethod::dbCount($table, $where);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (!function_exists('dbRow')) {
|
|
247
|
+
function dbRow(string $sql, array $params = [], int $fetchStyle = \PDO::FETCH_ASSOC): mixed {
|
|
248
|
+
return \Bin\SQLMethod::dbRow($sql, $params, $fetchStyle);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!function_exists('dbRows')) {
|
|
252
|
+
function dbRows(string $sql, array $params = [], int $fetchStyle = \PDO::FETCH_ASSOC): array {
|
|
253
|
+
return \Bin\SQLMethod::dbRows($sql, $params, $fetchStyle);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!function_exists('dbValue')) {
|
|
257
|
+
function dbValue(string $sql, array $params = [], int $column = 0): mixed {
|
|
258
|
+
return \Bin\SQLMethod::dbValue($sql, $params, $column);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -47,7 +47,7 @@ namespace Bin {
|
|
|
47
47
|
* @param string $value
|
|
48
48
|
* @return string
|
|
49
49
|
*/
|
|
50
|
-
public static function
|
|
50
|
+
public static function stripHtml(string $value): string
|
|
51
51
|
{
|
|
52
52
|
return strip_tags(trim($value));
|
|
53
53
|
}
|
|
@@ -98,6 +98,65 @@ namespace Bin {
|
|
|
98
98
|
return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Beni Hatırla: Güvenli Cookie Oluşturur (14 Gün)
|
|
103
|
+
*/
|
|
104
|
+
public static function setRememberMeCookie(string $kullaniciIdHex): void
|
|
105
|
+
{
|
|
106
|
+
$expires = time() + (14 * 24 * 60 * 60); // 14 gün
|
|
107
|
+
$secret = $_ENV['DB_PASSWORD'] ?? 'SinavOrtagim2026';
|
|
108
|
+
$data = $kullaniciIdHex . '|' . $expires;
|
|
109
|
+
$hash = hash_hmac('sha256', $data, $secret);
|
|
110
|
+
$cookieValue = base64_encode($data . '|' . $hash);
|
|
111
|
+
|
|
112
|
+
// HTTPOnly, Secure
|
|
113
|
+
setcookie('remember_me', $cookieValue, $expires, '/', '', true, true);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Beni Hatırla: Cookie'yi doğrular ve kullaniciId (hex) döner
|
|
118
|
+
*/
|
|
119
|
+
public static function validateRememberMeCookie(): ?string
|
|
120
|
+
{
|
|
121
|
+
if (empty($_COOKIE['remember_me'])) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$cookieValue = base64_decode($_COOKIE['remember_me']);
|
|
126
|
+
if (!$cookieValue) return null;
|
|
127
|
+
|
|
128
|
+
$parts = explode('|', $cookieValue);
|
|
129
|
+
if (count($parts) !== 3) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[$kullaniciIdHex, $expires, $hash] = $parts;
|
|
134
|
+
|
|
135
|
+
if (time() > (int)$expires) {
|
|
136
|
+
self::clearRememberMeCookie();
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
$secret = $_ENV['DB_PASSWORD'] ?? 'SinavOrtagim2026';
|
|
141
|
+
$data = $kullaniciIdHex . '|' . $expires;
|
|
142
|
+
$expectedHash = hash_hmac('sha256', $data, $secret);
|
|
143
|
+
|
|
144
|
+
if (!hash_equals($expectedHash, $hash)) {
|
|
145
|
+
return null; // Kurcalanmış
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return $kullaniciIdHex;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Beni Hatırla: Cookie'yi siler (Çıkış yaparken kullanılır)
|
|
153
|
+
*/
|
|
154
|
+
public static function clearRememberMeCookie(): void
|
|
155
|
+
{
|
|
156
|
+
setcookie('remember_me', '', time() - 3600, '/', '', true, true);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
101
160
|
/**
|
|
102
161
|
* API'ler için hızlı ve standart JSON yanıt (response) oluşturur.
|
|
103
162
|
* Kullanıldığı anda işlemi sonlandırır (exit).
|
|
@@ -336,7 +395,7 @@ namespace Bin {
|
|
|
336
395
|
*
|
|
337
396
|
* @return string 16-byte raw binary string
|
|
338
397
|
*/
|
|
339
|
-
public static function
|
|
398
|
+
public static function generateBinaryId(): string
|
|
340
399
|
{
|
|
341
400
|
// Get current timestamp in milliseconds (48-bit)
|
|
342
401
|
$ts = (int)(microtime(true) * 1000);
|
|
@@ -398,9 +457,9 @@ namespace Bin {
|
|
|
398
457
|
*
|
|
399
458
|
* @return string 36-character hyphenated UUID string
|
|
400
459
|
*/
|
|
401
|
-
public static function
|
|
460
|
+
public static function generateStringId(): string
|
|
402
461
|
{
|
|
403
|
-
return self::formatId(self::
|
|
462
|
+
return self::formatId(self::generateBinaryId());
|
|
404
463
|
}
|
|
405
464
|
|
|
406
465
|
/**
|
|
@@ -435,61 +494,54 @@ namespace Bin {
|
|
|
435
494
|
return $asString ? (string) $result : $result;
|
|
436
495
|
}
|
|
437
496
|
|
|
438
|
-
|
|
439
|
-
* Sadece sayılardan oluşan rastgele bir OTP (One-Time Password) kodu üretir.
|
|
440
|
-
* @param int $length Hanelerin sayısı (Varsayılan 6)
|
|
441
|
-
*/
|
|
442
|
-
public static function otpInt(int $length = 6): int
|
|
443
|
-
{
|
|
444
|
-
if ($length < 1) $length = 1;
|
|
445
|
-
if ($length > 18) $length = 18; // PHP 64-bit safe max length
|
|
497
|
+
|
|
446
498
|
|
|
447
|
-
|
|
448
|
-
$max = (int) str_pad('9', $length, '9');
|
|
499
|
+
|
|
449
500
|
|
|
450
|
-
|
|
451
|
-
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
452
504
|
|
|
453
505
|
/**
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
* @param string $case 'c': Sadece küçük, 'C': Sadece büyük, 'cC'/'Cc': Karışık
|
|
506
|
+
* Hexadecimal string'i binary formata çevirir. Zaten binary ise dokunmaz.
|
|
507
|
+
* ID dönüşümlerinde kod tekrarını (DRY) engellemek için kullanılır.
|
|
457
508
|
*/
|
|
458
|
-
public static function
|
|
509
|
+
public static function convertToBinaryId(?string $id): ?string
|
|
459
510
|
{
|
|
460
|
-
$
|
|
461
|
-
$
|
|
462
|
-
|
|
463
|
-
$chars = match (strtolower($case)) {
|
|
464
|
-
'c' => $lower,
|
|
465
|
-
'cc' => $lower . $upper,
|
|
466
|
-
default => $upper,
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
$otp = '';
|
|
470
|
-
$maxIndex = strlen($chars) - 1;
|
|
471
|
-
for ($i = 0; $i < $length; $i++) {
|
|
472
|
-
$otp .= $chars[random_int(0, $maxIndex)];
|
|
511
|
+
if (empty($id)) return $id;
|
|
512
|
+
if (strlen($id) === 32 && ctype_xdigit($id)) {
|
|
513
|
+
return hex2bin($id);
|
|
473
514
|
}
|
|
474
|
-
|
|
475
|
-
return $otp;
|
|
515
|
+
return $id;
|
|
476
516
|
}
|
|
477
|
-
|
|
478
517
|
/**
|
|
479
|
-
*
|
|
518
|
+
* Güvenli ve rastgele bir OTP (One Time Password) kodu üretir.
|
|
519
|
+
*
|
|
480
520
|
* @param int $length Hanelerin sayısı (Varsayılan 6)
|
|
481
|
-
* @param string $
|
|
521
|
+
* @param string $type 'numeric', 'alpha' veya 'alphanumeric'
|
|
522
|
+
* @param string $case 'lower', 'upper' veya 'mixed' (Sadece harf içeren durumlarda geçerli)
|
|
482
523
|
*/
|
|
483
|
-
public static function
|
|
524
|
+
public static function generateOTP(int $length = 6, string $type = 'numeric', string $case = 'upper'): string
|
|
484
525
|
{
|
|
485
526
|
$numbers = '0123456789';
|
|
486
527
|
$lower = 'abcdefghijklmnopqrstuvwxyz';
|
|
487
528
|
$upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
488
529
|
|
|
489
|
-
$chars = match (
|
|
490
|
-
'
|
|
491
|
-
'
|
|
492
|
-
|
|
530
|
+
$chars = match ($type) {
|
|
531
|
+
'numeric' => $numbers,
|
|
532
|
+
'alpha' => match ($case) {
|
|
533
|
+
'lower' => $lower,
|
|
534
|
+
'upper' => $upper,
|
|
535
|
+
'mixed' => $lower . $upper,
|
|
536
|
+
default => $upper
|
|
537
|
+
},
|
|
538
|
+
'alphanumeric' => match ($case) {
|
|
539
|
+
'lower' => $numbers . $lower,
|
|
540
|
+
'upper' => $numbers . $upper,
|
|
541
|
+
'mixed' => $numbers . $lower . $upper,
|
|
542
|
+
default => $numbers . $upper
|
|
543
|
+
},
|
|
544
|
+
default => $numbers
|
|
493
545
|
};
|
|
494
546
|
|
|
495
547
|
$otp = '';
|
|
@@ -500,16 +552,6 @@ namespace Bin {
|
|
|
500
552
|
|
|
501
553
|
return $otp;
|
|
502
554
|
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Gelen veriyi (özellikle BigInt ID'leri) güvenli bir şekilde string'e çevirir.
|
|
506
|
-
* Javascript'te 15 haneyi aşan sayılardaki veri kaybını engellemek için
|
|
507
|
-
* View dosyalarında data-id=<?= stringer($id) ?> şeklinde kullanılır.
|
|
508
|
-
*/
|
|
509
|
-
public static function stringer($value): string
|
|
510
|
-
{
|
|
511
|
-
return (string) $value;
|
|
512
|
-
}
|
|
513
555
|
} // end class SystemMethod
|
|
514
556
|
|
|
515
557
|
} // end namespace Bin
|
|
@@ -532,9 +574,9 @@ namespace {
|
|
|
532
574
|
}
|
|
533
575
|
|
|
534
576
|
if (!function_exists('sanitizeString')) {
|
|
535
|
-
function
|
|
577
|
+
function stripHtml(string $value): string
|
|
536
578
|
{
|
|
537
|
-
return \Bin\SystemMethod::
|
|
579
|
+
return \Bin\SystemMethod::stripHtml($value);
|
|
538
580
|
}
|
|
539
581
|
}
|
|
540
582
|
|
|
@@ -658,9 +700,9 @@ namespace {
|
|
|
658
700
|
}
|
|
659
701
|
|
|
660
702
|
if (!function_exists('byteId')) {
|
|
661
|
-
function
|
|
703
|
+
function generateBinaryId(): string
|
|
662
704
|
{
|
|
663
|
-
return \Bin\SystemMethod::
|
|
705
|
+
return \Bin\SystemMethod::generateBinaryId();
|
|
664
706
|
}
|
|
665
707
|
}
|
|
666
708
|
|
|
@@ -672,9 +714,9 @@ namespace {
|
|
|
672
714
|
}
|
|
673
715
|
|
|
674
716
|
if (!function_exists('makeId')) {
|
|
675
|
-
function
|
|
717
|
+
function generateStringId(): string
|
|
676
718
|
{
|
|
677
|
-
return \Bin\SystemMethod::
|
|
719
|
+
return \Bin\SystemMethod::generateStringId();
|
|
678
720
|
}
|
|
679
721
|
}
|
|
680
722
|
|
|
@@ -692,31 +734,30 @@ namespace {
|
|
|
692
734
|
}
|
|
693
735
|
}
|
|
694
736
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
701
742
|
|
|
702
|
-
|
|
703
|
-
function
|
|
743
|
+
if (!function_exists('generateOTP')) {
|
|
744
|
+
function generateOTP(int $length = 6, string $type = 'numeric', string $case = 'upper'): string
|
|
704
745
|
{
|
|
705
|
-
return \Bin\SystemMethod::
|
|
746
|
+
return \Bin\SystemMethod::generateOTP($length, $type, $case);
|
|
706
747
|
}
|
|
707
748
|
}
|
|
708
749
|
|
|
709
|
-
if (!function_exists('
|
|
710
|
-
function
|
|
750
|
+
if (!function_exists('toBin')) {
|
|
751
|
+
function convertToBinaryId(?string $id): ?string
|
|
711
752
|
{
|
|
712
|
-
return \Bin\SystemMethod::
|
|
753
|
+
return \Bin\SystemMethod::convertToBinaryId($id);
|
|
713
754
|
}
|
|
714
755
|
}
|
|
715
756
|
|
|
716
|
-
if (!function_exists('
|
|
717
|
-
function
|
|
757
|
+
if (!function_exists('generateOTP')) {
|
|
758
|
+
function generateOTP(int $length = 6, string $type = 'numeric', string $case = 'upper'): string
|
|
718
759
|
{
|
|
719
|
-
return \Bin\SystemMethod::
|
|
760
|
+
return \Bin\SystemMethod::generateOTP($length, $type, $case);
|
|
720
761
|
}
|
|
721
762
|
}
|
|
722
763
|
}
|
|
@@ -35,6 +35,16 @@ namespace Bin {
|
|
|
35
35
|
return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Metin içindeki @kullaniciadi formatındaki etiketleri linklere dönüştürür.
|
|
40
|
+
* XSS koruması için metnin önce display() fonksiyonundan geçmiş olması önerilir.
|
|
41
|
+
*/
|
|
42
|
+
public static function parseMentions(string $text): string
|
|
43
|
+
{
|
|
44
|
+
$text = self::display($text);
|
|
45
|
+
return preg_replace('/@([A-Za-z0-9_]{3,30})/', '<a href="/user/profil/" class="cm-mention-link">@</a>', $text);
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
/**
|
|
39
49
|
* URL'leri güvenli hale getirir, zararlı karakterleri temizler.
|
|
40
50
|
*/
|
|
@@ -156,7 +166,9 @@ namespace Bin {
|
|
|
156
166
|
if (empty($date)) return '-';
|
|
157
167
|
$time = is_numeric($date) ? $date : strtotime($date);
|
|
158
168
|
$diff = time() - $time;
|
|
169
|
+
|
|
159
170
|
if ($diff < 1) return self::display(($lang === 'tr') ? 'şimdi' : 'just now');
|
|
171
|
+
if ($diff >= 604800) return self::display(date('d.m.Y', $time));
|
|
160
172
|
|
|
161
173
|
$tokens = [
|
|
162
174
|
31536000 => 'year',
|
|
@@ -420,12 +432,7 @@ namespace Bin {
|
|
|
420
432
|
public static function routeLink(?string $requestUri = null): void
|
|
421
433
|
{
|
|
422
434
|
|
|
423
|
-
if (!defined('APP_MAINTENANCE')) {
|
|
424
|
-
$rawVal = $_ENV['APP_MAINTENANCE'] ?? false;
|
|
425
435
|
|
|
426
|
-
// filter_var("true", FILTER_VALIDATE_BOOLEAN) -> bool(true) üretir
|
|
427
|
-
define('APP_MAINTENANCE', filter_var($rawVal, FILTER_VALIDATE_BOOLEAN));
|
|
428
|
-
}
|
|
429
436
|
|
|
430
437
|
// ------------------------------------------------------------------
|
|
431
438
|
// 1. BAKIM MODU (MAINTENANCE GUARD)
|
|
@@ -640,6 +647,13 @@ namespace {
|
|
|
640
647
|
}
|
|
641
648
|
}
|
|
642
649
|
|
|
650
|
+
if (!function_exists('parseMentions')) {
|
|
651
|
+
function parseMentions(string $text): string
|
|
652
|
+
{
|
|
653
|
+
return \Bin\ViewMethod::parseMentions($text);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
643
657
|
if (!function_exists('formatSize')) {
|
|
644
658
|
function formatSize(int $bytes): string
|
|
645
659
|
{
|