@artilingo/artiframe-cli 1.0.8 → 1.1.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.
- package/LICENSE +661 -0
- package/README.md +1 -1
- package/bin/artiframe.php +1 -1
- package/core-stubs/app/Database.php +1 -1
- package/core-stubs/app/DotEnv.php +1 -1
- package/core-stubs/app/R2Manager.php +1 -1
- package/core-stubs/bin/SystemMethod.php +292 -16
- package/core-stubs/bin/ViewMethod.php +146 -37
- package/core-stubs/docs/de.html +4419 -951
- package/core-stubs/docs/en.html +4419 -952
- package/core-stubs/docs/es.html +4419 -947
- package/core-stubs/docs/fr.html +4102 -533
- package/core-stubs/docs/tr.html +4978 -951
- package/core-stubs/stubs/service/image.stub +334 -0
- package/core-stubs/stubs/service/iyzico.stub +637 -0
- package/core-stubs/stubs/service/jwt.stub +312 -0
- package/core-stubs/stubs/service/pusher.stub +232 -0
- package/core-stubs/stubs/service/redis.stub +361 -0
- package/core-stubs/stubs/service/s3.stub +377 -0
- package/core-stubs/stubs/service/sentry.stub +139 -0
- package/core-stubs/stubs/service/stripe.stub +526 -0
- package/core-stubs/stubs/service/twilio.stub +361 -0
- package/package.json +4 -4
- package/src/App.php +70 -1
- package/src/Commands/AddCommand.php +392 -0
- package/src/Commands/GoCommand.php +48 -0
- package/src/Commands/ListCommand.php +67 -0
- package/src/Commands/MakeApiCommand.php +4 -4
- package/src/Commands/MakeClassCommand.php +8 -8
- package/src/Commands/MakeViewCommand.php +3 -3
- package/src/Commands/NewProjectCommand.php +187 -33
- package/src/Commands/RemoveCommand.php +121 -0
- package/src/Commands/ServeCommand.php +71 -0
- package/src/Commands/ShowCommand.php +24 -0
- package/src/Commands/VersionCommand.php +4 -4
- package/src/Lang/de.php +56 -0
- package/src/Lang/en.php +56 -0
- package/src/Lang/es.php +56 -0
- package/src/Lang/fr.php +56 -0
- package/src/Lang/tr.php +56 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
namespace ArtiFrame\Cli\Commands;
|
|
3
|
+
|
|
4
|
+
use ArtiFrame\Cli\Services\Translator;
|
|
5
|
+
|
|
6
|
+
class AddCommand
|
|
7
|
+
{
|
|
8
|
+
private Translator $translator;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ArtiFrame'in desteklediği paket kayıt defteri.
|
|
12
|
+
*
|
|
13
|
+
* 'composer' => Composer paket adı
|
|
14
|
+
* 'type' => 'integrated' | 'direct'
|
|
15
|
+
* 'service' => Oluşturulacak sınıf dosyası yolu (integrated için)
|
|
16
|
+
* 'stub' => Stub dosya adı (integrated için)
|
|
17
|
+
* 'env' => .env dosyasına eklenecek satırlar (integrated için)
|
|
18
|
+
*/
|
|
19
|
+
private array $registry = [
|
|
20
|
+
// ── Entegrasyonlu Paketler (Composer + Servis Sınıfı + .env) ───
|
|
21
|
+
'iyzico' => [
|
|
22
|
+
'composer' => 'iyzipay/iyzipay-php',
|
|
23
|
+
'type' => 'integrated',
|
|
24
|
+
'service' => 'src/Service/Iyzico.php',
|
|
25
|
+
'stub' => 'iyzico.stub',
|
|
26
|
+
'env' => [
|
|
27
|
+
'# ── iyzico ──────────────────────',
|
|
28
|
+
'IYZICO_API_KEY=',
|
|
29
|
+
'IYZICO_SECRET_KEY=',
|
|
30
|
+
'IYZICO_BASE_URL=https://sandbox-api.iyzipay.com',
|
|
31
|
+
],
|
|
32
|
+
],
|
|
33
|
+
'stripe' => [
|
|
34
|
+
'composer' => 'stripe/stripe-php',
|
|
35
|
+
'type' => 'integrated',
|
|
36
|
+
'service' => 'src/Service/Stripe.php',
|
|
37
|
+
'stub' => 'stripe.stub',
|
|
38
|
+
'env' => [
|
|
39
|
+
'# ── stripe ──────────────────────',
|
|
40
|
+
'STRIPE_SECRET_KEY=',
|
|
41
|
+
'STRIPE_PUBLISHABLE_KEY=',
|
|
42
|
+
'STRIPE_WEBHOOK_SECRET=',
|
|
43
|
+
],
|
|
44
|
+
],
|
|
45
|
+
'jwt' => [
|
|
46
|
+
'composer' => 'firebase/php-jwt',
|
|
47
|
+
'type' => 'integrated',
|
|
48
|
+
'service' => 'src/Auth/JwtAuth.php',
|
|
49
|
+
'stub' => 'jwt.stub',
|
|
50
|
+
'env' => [
|
|
51
|
+
'# ── jwt ─────────────────────────',
|
|
52
|
+
'JWT_SECRET_KEY=',
|
|
53
|
+
'JWT_ALGORITHM=HS256',
|
|
54
|
+
'JWT_EXPIRY=3600',
|
|
55
|
+
],
|
|
56
|
+
],
|
|
57
|
+
'image' => [
|
|
58
|
+
'composer' => 'intervention/image',
|
|
59
|
+
'type' => 'integrated',
|
|
60
|
+
'service' => 'src/Service/ImageProcessor.php',
|
|
61
|
+
'stub' => 'image.stub',
|
|
62
|
+
'env' => [
|
|
63
|
+
'# ── image ───────────────────────',
|
|
64
|
+
'IMAGE_DRIVER=gd',
|
|
65
|
+
'IMAGE_QUALITY=80',
|
|
66
|
+
],
|
|
67
|
+
],
|
|
68
|
+
's3' => [
|
|
69
|
+
'composer' => 'aws/aws-sdk-php',
|
|
70
|
+
'type' => 'integrated',
|
|
71
|
+
'service' => 'src/Service/S3Storage.php',
|
|
72
|
+
'stub' => 's3.stub',
|
|
73
|
+
'env' => [
|
|
74
|
+
'# ── aws s3 ──────────────────────',
|
|
75
|
+
'AWS_ACCESS_KEY_ID=',
|
|
76
|
+
'AWS_SECRET_ACCESS_KEY=',
|
|
77
|
+
'AWS_DEFAULT_REGION=eu-central-1',
|
|
78
|
+
'AWS_BUCKET=',
|
|
79
|
+
'AWS_ENDPOINT=',
|
|
80
|
+
],
|
|
81
|
+
],
|
|
82
|
+
'sentry' => [
|
|
83
|
+
'composer' => 'sentry/sentry',
|
|
84
|
+
'type' => 'integrated',
|
|
85
|
+
'service' => 'config/sentry.php',
|
|
86
|
+
'stub' => 'sentry.stub',
|
|
87
|
+
'env' => [
|
|
88
|
+
'# ── sentry ──────────────────────',
|
|
89
|
+
'SENTRY_DSN=',
|
|
90
|
+
],
|
|
91
|
+
],
|
|
92
|
+
'redis' => [
|
|
93
|
+
'composer' => 'predis/predis',
|
|
94
|
+
'type' => 'integrated',
|
|
95
|
+
'service' => 'src/Service/RedisCache.php',
|
|
96
|
+
'stub' => 'redis.stub',
|
|
97
|
+
'env' => [
|
|
98
|
+
'# ── redis ───────────────────────',
|
|
99
|
+
'REDIS_HOST=127.0.0.1',
|
|
100
|
+
'REDIS_PORT=6379',
|
|
101
|
+
'REDIS_PASSWORD=',
|
|
102
|
+
'REDIS_DATABASE=0',
|
|
103
|
+
],
|
|
104
|
+
],
|
|
105
|
+
'pusher' => [
|
|
106
|
+
'composer' => 'pusher/pusher-php-server',
|
|
107
|
+
'type' => 'integrated',
|
|
108
|
+
'service' => 'src/Service/Pusher.php',
|
|
109
|
+
'stub' => 'pusher.stub',
|
|
110
|
+
'env' => [
|
|
111
|
+
'# ── pusher ──────────────────────',
|
|
112
|
+
'PUSHER_APP_ID=',
|
|
113
|
+
'PUSHER_APP_KEY=',
|
|
114
|
+
'PUSHER_APP_SECRET=',
|
|
115
|
+
'PUSHER_CLUSTER=eu',
|
|
116
|
+
],
|
|
117
|
+
],
|
|
118
|
+
'twilio' => [
|
|
119
|
+
'composer' => 'twilio/sdk',
|
|
120
|
+
'type' => 'integrated',
|
|
121
|
+
'service' => 'src/Service/Twilio.php',
|
|
122
|
+
'stub' => 'twilio.stub',
|
|
123
|
+
'env' => [
|
|
124
|
+
'# ── twilio ──────────────────────',
|
|
125
|
+
'TWILIO_SID=',
|
|
126
|
+
'TWILIO_AUTH_TOKEN=',
|
|
127
|
+
'TWILIO_FROM_NUMBER=',
|
|
128
|
+
],
|
|
129
|
+
],
|
|
130
|
+
|
|
131
|
+
// ── Direkt Kullanılabilir Paketler (Sadece Composer) ───────────
|
|
132
|
+
'phpmailer' => [
|
|
133
|
+
'composer' => 'phpmailer/phpmailer',
|
|
134
|
+
'type' => 'direct',
|
|
135
|
+
],
|
|
136
|
+
'mpdf' => [
|
|
137
|
+
'composer' => 'mpdf/mpdf',
|
|
138
|
+
'type' => 'direct',
|
|
139
|
+
],
|
|
140
|
+
'dompdf' => [
|
|
141
|
+
'composer' => 'dompdf/dompdf',
|
|
142
|
+
'type' => 'direct',
|
|
143
|
+
],
|
|
144
|
+
'spreadsheet' => [
|
|
145
|
+
'composer' => 'phpoffice/phpspreadsheet',
|
|
146
|
+
'type' => 'direct',
|
|
147
|
+
],
|
|
148
|
+
'qrcode' => [
|
|
149
|
+
'composer' => 'endroid/qr-code',
|
|
150
|
+
'type' => 'direct',
|
|
151
|
+
],
|
|
152
|
+
'guzzle' => [
|
|
153
|
+
'composer' => 'guzzlehttp/guzzle',
|
|
154
|
+
'type' => 'direct',
|
|
155
|
+
],
|
|
156
|
+
'uuid' => [
|
|
157
|
+
'composer' => 'ramsey/uuid',
|
|
158
|
+
'type' => 'direct',
|
|
159
|
+
],
|
|
160
|
+
'carbon' => [
|
|
161
|
+
'composer' => 'nesbot/carbon',
|
|
162
|
+
'type' => 'direct',
|
|
163
|
+
],
|
|
164
|
+
'monolog' => [
|
|
165
|
+
'composer' => 'monolog/monolog',
|
|
166
|
+
'type' => 'direct',
|
|
167
|
+
],
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
public function __construct(Translator $translator)
|
|
171
|
+
{
|
|
172
|
+
$this->translator = $translator;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public function execute(array $args): void
|
|
176
|
+
{
|
|
177
|
+
$packageAlias = strtolower($args[0] ?? '');
|
|
178
|
+
|
|
179
|
+
// ── Parametre kontrolü ───────────────────────────────────
|
|
180
|
+
if ($packageAlias === '') {
|
|
181
|
+
echo PHP_EOL;
|
|
182
|
+
echo " ❌ " . $this->translator->get('ADD_MISSING_NAME') . PHP_EOL;
|
|
183
|
+
echo PHP_EOL;
|
|
184
|
+
$this->showAvailablePackages();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ── "list" alt komutu ────────────────────────────────────
|
|
189
|
+
if ($packageAlias === 'list') {
|
|
190
|
+
$this->showAvailablePackages();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── Kayıt defterinde ara ─────────────────────────────────
|
|
195
|
+
if (!isset($this->registry[$packageAlias])) {
|
|
196
|
+
echo PHP_EOL;
|
|
197
|
+
echo " ❌ " . $this->translator->get('ADD_NOT_FOUND', ['name' => $packageAlias]) . PHP_EOL;
|
|
198
|
+
echo PHP_EOL;
|
|
199
|
+
$this->showAvailablePackages();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
$package = $this->registry[$packageAlias];
|
|
204
|
+
$composerName = $package['composer'];
|
|
205
|
+
|
|
206
|
+
// ── Composer kontrolü ────────────────────────────────────
|
|
207
|
+
if (!$this->isComposerInstalled()) {
|
|
208
|
+
echo PHP_EOL;
|
|
209
|
+
echo " ❌ " . $this->translator->get('COMPOSER_MISSING_TITLE') . PHP_EOL;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ── composer.json kontrolü ───────────────────────────────
|
|
214
|
+
$projectRoot = getcwd();
|
|
215
|
+
if (!file_exists($projectRoot . '/composer.json')) {
|
|
216
|
+
echo PHP_EOL;
|
|
217
|
+
echo " ❌ " . $this->translator->get('ADD_NO_PROJECT') . PHP_EOL;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── Zaten kurulu mu? ─────────────────────────────────────
|
|
222
|
+
if ($this->isAlreadyInstalled($projectRoot, $composerName)) {
|
|
223
|
+
echo PHP_EOL;
|
|
224
|
+
echo " ⚠️ " . $this->translator->get('ADD_ALREADY', ['name' => $packageAlias]) . PHP_EOL;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Kurulum başlasın ─────────────────────────────────────
|
|
229
|
+
echo PHP_EOL;
|
|
230
|
+
echo " 📦 " . $this->translator->get('ADD_INSTALLING', ['name' => $packageAlias, 'composer' => $composerName]) . PHP_EOL;
|
|
231
|
+
echo PHP_EOL;
|
|
232
|
+
|
|
233
|
+
$command = 'composer require ' . escapeshellarg($composerName);
|
|
234
|
+
$exitCode = 0;
|
|
235
|
+
passthru($command, $exitCode);
|
|
236
|
+
|
|
237
|
+
if ($exitCode !== 0) {
|
|
238
|
+
echo PHP_EOL;
|
|
239
|
+
echo " ❌ " . $this->translator->get('ADD_FAILED', ['name' => $packageAlias]) . PHP_EOL;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ── Entegrasyonlu paket ise ek işlemler ──────────────────
|
|
244
|
+
if ($package['type'] === 'integrated') {
|
|
245
|
+
$this->copyServiceStub($projectRoot, $package, $packageAlias);
|
|
246
|
+
$this->appendEnvVariables($projectRoot, $package, $packageAlias);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ── Başarılı ─────────────────────────────────────────────
|
|
250
|
+
echo PHP_EOL;
|
|
251
|
+
echo " ╔══════════════════════════════════════════════════╗" . PHP_EOL;
|
|
252
|
+
echo " ║ ✅ " . $this->translator->get('ADD_SUCCESS', ['name' => $packageAlias, 'composer' => $composerName]) . PHP_EOL;
|
|
253
|
+
echo " ╚══════════════════════════════════════════════════╝" . PHP_EOL;
|
|
254
|
+
|
|
255
|
+
if ($package['type'] === 'integrated') {
|
|
256
|
+
echo PHP_EOL;
|
|
257
|
+
echo " 📄 " . $this->translator->get('ADD_SERVICE_CREATED', ['path' => $package['service']]) . PHP_EOL;
|
|
258
|
+
echo " 🔑 " . $this->translator->get('ADD_ENV_UPDATED') . PHP_EOL;
|
|
259
|
+
echo " ⚙️ " . $this->translator->get('ADD_EDIT_ENV') . PHP_EOL;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
echo PHP_EOL;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─── Servis Sınıfı Kopyalama ─────────────────────────────────
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* CLI'daki stub dosyasını projenin içine kopyalar.
|
|
269
|
+
*/
|
|
270
|
+
private function copyServiceStub(string $projectRoot, array $package, string $alias): void
|
|
271
|
+
{
|
|
272
|
+
$stubPath = \ARTIFRAME_CLI_ROOT . '/core-stubs/stubs/service/' . $package['stub'];
|
|
273
|
+
$targetPath = $projectRoot . '/' . $package['service'];
|
|
274
|
+
|
|
275
|
+
if (!file_exists($stubPath)) {
|
|
276
|
+
echo " ⚠️ " . $this->translator->get('ADD_STUB_MISSING', ['name' => $alias]) . PHP_EOL;
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Hedef dizini oluştur
|
|
281
|
+
$targetDir = dirname($targetPath);
|
|
282
|
+
if (!is_dir($targetDir)) {
|
|
283
|
+
mkdir($targetDir, 0755, true);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Zaten varsa üzerine yazma
|
|
287
|
+
if (file_exists($targetPath)) {
|
|
288
|
+
echo " ⚠️ " . $this->translator->get('ADD_SERVICE_EXISTS', ['path' => $package['service']]) . PHP_EOL;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
copy($stubPath, $targetPath);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ─── .env Değişkenleri Ekleme ────────────────────────────────
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* .env ve .env.example dosyalarına gerekli anahtarları ekler.
|
|
299
|
+
*/
|
|
300
|
+
private function appendEnvVariables(string $projectRoot, array $package, string $alias): void
|
|
301
|
+
{
|
|
302
|
+
if (empty($package['env'])) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
$envBlock = PHP_EOL . implode(PHP_EOL, $package['env']) . PHP_EOL;
|
|
307
|
+
|
|
308
|
+
// .env dosyasına ekle
|
|
309
|
+
$envFile = $projectRoot . '/.env';
|
|
310
|
+
if (file_exists($envFile)) {
|
|
311
|
+
// Zaten eklenmişse tekrar ekleme
|
|
312
|
+
$currentContent = file_get_contents($envFile);
|
|
313
|
+
if (str_contains($currentContent, $package['env'][0])) {
|
|
314
|
+
return; // Başlık satırı zaten var, atla
|
|
315
|
+
}
|
|
316
|
+
file_put_contents($envFile, $envBlock, FILE_APPEND);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// .env.example dosyasına ekle
|
|
320
|
+
$envExample = $projectRoot . '/.env.example';
|
|
321
|
+
if (file_exists($envExample)) {
|
|
322
|
+
$currentContent = file_get_contents($envExample);
|
|
323
|
+
if (!str_contains($currentContent, $package['env'][0])) {
|
|
324
|
+
file_put_contents($envExample, $envBlock, FILE_APPEND);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ─── Yardımcı Metodlar ───────────────────────────────────────
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Paketin zaten kurulu olup olmadığını kontrol eder.
|
|
333
|
+
*/
|
|
334
|
+
private function isAlreadyInstalled(string $projectRoot, string $composerName): bool
|
|
335
|
+
{
|
|
336
|
+
$lockFile = $projectRoot . '/composer.lock';
|
|
337
|
+
if (!file_exists($lockFile)) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
$lockContent = file_get_contents($lockFile);
|
|
341
|
+
return str_contains($lockContent, '"' . $composerName . '"');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Kayıtlı tüm paketleri kategorili bir şekilde listeler.
|
|
346
|
+
*/
|
|
347
|
+
private function showAvailablePackages(): void
|
|
348
|
+
{
|
|
349
|
+
$g = "\033[38;2;0;157;108m"; // green
|
|
350
|
+
$y = "\033[38;5;220m"; // yellow
|
|
351
|
+
$d = "\033[38;2;100;100;100m"; // dim
|
|
352
|
+
$c = "\033[38;5;81m"; // cyan
|
|
353
|
+
$w = "\033[1;37m"; // white bold
|
|
354
|
+
$r = "\033[0m"; // reset
|
|
355
|
+
|
|
356
|
+
echo PHP_EOL;
|
|
357
|
+
echo " " . $w . $this->translator->get('ADD_LIST_TITLE') . $r . PHP_EOL;
|
|
358
|
+
echo " " . $d . "─────────────────────────────────────────────────────────────" . $r . PHP_EOL;
|
|
359
|
+
echo PHP_EOL;
|
|
360
|
+
|
|
361
|
+
// Entegrasyonlu Paketler
|
|
362
|
+
echo " " . $y . "⚡ " . $this->translator->get('ADD_CAT_INTEGRATED') . $r . PHP_EOL;
|
|
363
|
+
echo PHP_EOL;
|
|
364
|
+
|
|
365
|
+
foreach ($this->registry as $alias => $info) {
|
|
366
|
+
if ($info['type'] === 'integrated') {
|
|
367
|
+
$service = $info['service'] ?? '';
|
|
368
|
+
echo " " . $g . " add " . $alias . $r . $d . str_repeat(' ', max(1, 16 - strlen($alias))) . $info['composer'] . " → " . $service . $r . PHP_EOL;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
echo PHP_EOL;
|
|
373
|
+
|
|
374
|
+
// Direkt Paketler
|
|
375
|
+
echo " " . $c . "📦 " . $this->translator->get('ADD_CAT_DIRECT') . $r . PHP_EOL;
|
|
376
|
+
echo PHP_EOL;
|
|
377
|
+
|
|
378
|
+
foreach ($this->registry as $alias => $info) {
|
|
379
|
+
if ($info['type'] === 'direct') {
|
|
380
|
+
echo " " . $g . " add " . $alias . $r . $d . str_repeat(' ', max(1, 16 - strlen($alias))) . $info['composer'] . $r . PHP_EOL;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
echo PHP_EOL;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private function isComposerInstalled(): bool
|
|
388
|
+
{
|
|
389
|
+
$check = shell_exec('composer --version 2>&1');
|
|
390
|
+
return $check !== null && str_contains($check, 'Composer');
|
|
391
|
+
}
|
|
392
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
namespace ArtiFrame\Cli\Commands;
|
|
3
|
+
|
|
4
|
+
use ArtiFrame\Cli\Services\Translator;
|
|
5
|
+
|
|
6
|
+
class GoCommand
|
|
7
|
+
{
|
|
8
|
+
private Translator $translator;
|
|
9
|
+
|
|
10
|
+
public function __construct(Translator $translator)
|
|
11
|
+
{
|
|
12
|
+
$this->translator = $translator;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public function execute(array $args): void
|
|
16
|
+
{
|
|
17
|
+
$target = $args[0] ?? null;
|
|
18
|
+
|
|
19
|
+
if (!$target) {
|
|
20
|
+
echo "
|
|
21
|
+
❌ " . $this->translator->get('GO_MISSING_DIR') . "
|
|
22
|
+
|
|
23
|
+
";
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if ($target === 'back') {
|
|
28
|
+
$target = '..';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!is_dir($target)) {
|
|
32
|
+
$notFound = str_replace(':dir', $target, $this->translator->get('GO_NOT_FOUND'));
|
|
33
|
+
echo "
|
|
34
|
+
❌ " . $notFound . "
|
|
35
|
+
|
|
36
|
+
";
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
chdir($target);
|
|
41
|
+
echo "
|
|
42
|
+
✅ " . $this->translator->get('GO_SUCCESS') . "
|
|
43
|
+
";
|
|
44
|
+
echo " " . getcwd() . "
|
|
45
|
+
|
|
46
|
+
";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
namespace ArtiFrame\Cli\Commands;
|
|
3
|
+
|
|
4
|
+
use ArtiFrame\Cli\Services\Translator;
|
|
5
|
+
|
|
6
|
+
class ListCommand
|
|
7
|
+
{
|
|
8
|
+
private Translator $translator;
|
|
9
|
+
|
|
10
|
+
public function __construct(Translator $translator)
|
|
11
|
+
{
|
|
12
|
+
$this->translator = $translator;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public function execute(array $args): void
|
|
16
|
+
{
|
|
17
|
+
$dir = getcwd();
|
|
18
|
+
$projectName = basename($dir);
|
|
19
|
+
|
|
20
|
+
echo "
|
|
21
|
+
📂 " . $projectName . "/
|
|
22
|
+
";
|
|
23
|
+
|
|
24
|
+
$priorityOrder = [
|
|
25
|
+
'bin', 'config', 'src', 'app', 'public', '.agents',
|
|
26
|
+
'vendor', '.env', '.env.example', '.gitignore',
|
|
27
|
+
'composer.json', 'composer.lock', 'schema.sql',
|
|
28
|
+
'README.md', 'OKUBENI.md', 'LESEMICH.md', 'LISEZMOI.md', 'LEAME.md',
|
|
29
|
+
'kilavuz.html', 'guide.html', 'handbuch.html', 'guide_fr.html', 'guia.html', 'LICENSE',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
$entries = array_filter(scandir($dir), fn($e) => $e !== '.' && $e !== '..');
|
|
33
|
+
|
|
34
|
+
usort($entries, function ($a, $b) use ($priorityOrder) {
|
|
35
|
+
$ia = array_search($a, $priorityOrder);
|
|
36
|
+
$ib = array_search($b, $priorityOrder);
|
|
37
|
+
$ia = ($ia === false) ? 99 : $ia;
|
|
38
|
+
$ib = ($ib === false) ? 99 : $ib;
|
|
39
|
+
return $ia <=> $ib;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
$entries = array_values($entries);
|
|
43
|
+
$total = count($entries);
|
|
44
|
+
|
|
45
|
+
foreach ($entries as $i => $entry) {
|
|
46
|
+
$isLast = ($i === $total - 1);
|
|
47
|
+
$connector = $isLast ? '└──' : '├──';
|
|
48
|
+
$fullPath = $dir . DIRECTORY_SEPARATOR . $entry;
|
|
49
|
+
|
|
50
|
+
if (is_dir($fullPath)) {
|
|
51
|
+
$subItems = array_filter(scandir($fullPath), fn($e) => $e !== '.' && $e !== '..');
|
|
52
|
+
$subCount = count($subItems);
|
|
53
|
+
$countStr = $subCount > 0 ? ' ' . $this->translator->get('DIR_ITEM_COUNT', ['count' => $subCount]) : '';
|
|
54
|
+
echo " │ {$connector} 📂 {$entry}/{$countStr}
|
|
55
|
+
";
|
|
56
|
+
} else {
|
|
57
|
+
$size = filesize($fullPath);
|
|
58
|
+
$sizeStr = $size > 1024 ? round($size / 1024, 1) . ' KB' : $size . ' B';
|
|
59
|
+
echo " │ {$connector} 📄 {$entry} [{$sizeStr}]
|
|
60
|
+
";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
echo " │
|
|
64
|
+
|
|
65
|
+
";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -22,12 +22,12 @@ class MakeApiCommand
|
|
|
22
22
|
|
|
23
23
|
if (!$type || !in_array($type, ['standart', 'switch-case'])) {
|
|
24
24
|
echo "❌ " . $this->translator->get('ERROR_API_TYPE') . PHP_EOL;
|
|
25
|
-
|
|
25
|
+
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
if (!$target) {
|
|
29
29
|
echo "❌ " . $this->translator->get('ERROR_API_PATH_REQUIRED') . PHP_EOL;
|
|
30
|
-
|
|
30
|
+
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// Normalize path
|
|
@@ -42,7 +42,7 @@ class MakeApiCommand
|
|
|
42
42
|
$apiPath = $projectRoot . '/public/api/' . $type . '/' . $target;
|
|
43
43
|
|
|
44
44
|
if (!$this->safeguard->checkTarget($apiPath)) {
|
|
45
|
-
|
|
45
|
+
return;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
$stubName = 'api-' . $type . '.stub';
|
|
@@ -50,7 +50,7 @@ class MakeApiCommand
|
|
|
50
50
|
|
|
51
51
|
if (!file_exists($stubPath)) {
|
|
52
52
|
echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
|
|
53
|
-
|
|
53
|
+
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Generate File
|
|
@@ -22,17 +22,13 @@ class MakeClassCommand
|
|
|
22
22
|
if (!$target || strpos($target, '/') === false && strpos($target, '\\') === false) {
|
|
23
23
|
echo "❌ " . $this->translator->get('DIR_REQUIRED_ERROR') . PHP_EOL;
|
|
24
24
|
echo "Example: /src/Service/PaymentService" . PHP_EOL;
|
|
25
|
-
|
|
25
|
+
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Normalize path
|
|
29
29
|
$target = ltrim(str_replace('\\', '/', $target), '/');
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
if (!str_starts_with($target, 'app/') && !str_starts_with($target, 'src/')) {
|
|
33
|
-
echo "❌ " . $this->translator->get('ERROR_CLASS_ROOT') . PHP_EOL;
|
|
34
|
-
exit(1);
|
|
35
|
-
}
|
|
31
|
+
$isCustomRoot = !str_starts_with($target, 'app/') && !str_starts_with($target, 'src/');
|
|
36
32
|
|
|
37
33
|
// Ensure .php extension
|
|
38
34
|
if (!str_ends_with($target, '.php')) {
|
|
@@ -43,13 +39,13 @@ class MakeClassCommand
|
|
|
43
39
|
$classPath = $projectRoot . '/' . $target;
|
|
44
40
|
|
|
45
41
|
if (!$this->safeguard->checkTarget($classPath)) {
|
|
46
|
-
|
|
42
|
+
return;
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
$stubPath = $projectRoot . '/bin/stubs/class.stub';
|
|
50
46
|
if (!file_exists($stubPath)) {
|
|
51
47
|
echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
|
|
52
|
-
|
|
48
|
+
return;
|
|
53
49
|
}
|
|
54
50
|
|
|
55
51
|
// Determine Namespace and Class Name
|
|
@@ -77,6 +73,10 @@ class MakeClassCommand
|
|
|
77
73
|
|
|
78
74
|
echo $this->translator->get('SUCCESS_CLASS', ['path' => $target]) . PHP_EOL;
|
|
79
75
|
echo $this->translator->get('NAMESPACE_LABEL') . ' ' . $namespace . PHP_EOL;
|
|
76
|
+
|
|
77
|
+
if ($isCustomRoot) {
|
|
78
|
+
shell_exec('composer dump-autoload -q');
|
|
79
|
+
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
private function ensureDirectoryExists(string $path): void
|
|
@@ -21,7 +21,7 @@ class MakeViewCommand
|
|
|
21
21
|
|
|
22
22
|
if (!$target) {
|
|
23
23
|
echo "❌ " . $this->translator->get('ERROR_VIEW_PATH_REQUIRED') . PHP_EOL;
|
|
24
|
-
|
|
24
|
+
return;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Normalize path
|
|
@@ -36,7 +36,7 @@ class MakeViewCommand
|
|
|
36
36
|
$viewPath = $projectRoot . '/public/' . $target;
|
|
37
37
|
|
|
38
38
|
if (!$this->safeguard->checkTarget($viewPath)) {
|
|
39
|
-
|
|
39
|
+
return;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// Determine hierarchy for assets
|
|
@@ -57,7 +57,7 @@ class MakeViewCommand
|
|
|
57
57
|
if (!file_exists($stubPath)) {
|
|
58
58
|
echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
|
|
59
59
|
echo $this->translator->get('ERROR_RUN_FROM_ROOT') . PHP_EOL;
|
|
60
|
-
|
|
60
|
+
return;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// Generate Files
|