1: <?php
2:
3: namespace LaravelUi5\Core\Commands;
4:
5: use Exception;
6: use Illuminate\Support\Facades\File;
7: use Illuminate\Support\Str;
8: use Illuminate\Filesystem\Filesystem;
9:
10: class GenerateUi5ReportCommand extends BaseGenerator
11: {
12: protected $signature = 'ui5:report
13: {name : The report in the form App/Report}
14: {--php-ns-prefix=Pragmatiqu : The namespace prefix for the php package}
15: {--js-ns-prefix=io.pragmatiqu : Root namespace prefix for JS artifacts}
16: {--actions=}
17: {--title=}
18: {--description=}
19: {--formats=html,pdf}';
20:
21: protected $description = 'Create a new UI5 report artifact with all related resources';
22:
23: protected Filesystem $files;
24:
25: public function __construct(Filesystem $files)
26: {
27: parent::__construct();
28: $this->files = $files;
29: }
30:
31: /**
32: * @throws Exception
33: */
34: public function handle(): int
35: {
36: $name = $this->argument('name');
37: [$app, $reportName] = $this->parseCamelCasePair($name);
38:
39: if (!$this->assertAppExists($app)) {
40: $this->components->error("App {$app} does not exist.");
41: return self::FAILURE;
42: }
43:
44: $app = Str::studly($app);
45: $urlKey = Str::snake($reportName);
46: $slug = Str::slug($app);
47: $reportNamespace = Str::studly($reportName);
48: $targetPath = base_path("ui5/{$app}/src/Reports/{$reportNamespace}");
49: $resourcesPath = base_path("ui5/{$app}/resources/ui5/reports/{$urlKey}");
50: $phpNamespacePrefix = rtrim($this->option('php-ns-prefix'), '\\');
51: $jsPrefix = rtrim($this->option('js-ns-prefix'), '.');
52: $phpNamespace = "{$phpNamespacePrefix}\\{$app}\\Reports\\$reportNamespace";
53: $jsNamespace = "{$jsPrefix}.reports.{$urlKey}";
54:
55: if (File::exists("$targetPath/Report.php")) {
56: $this->components->error("Ui5Report {$reportName} already exists.");
57: return self::FAILURE;
58: }
59:
60: File::ensureDirectoryExists($targetPath);
61:
62: $title = $this->option('title') ?? $reportNamespace;
63: $description = $this->option('description') ?? 'Report generated via ui5:report';
64: $formats = explode(',', $this->option('formats'));
65: $actions = explode(',', $this->option('actions'));
66:
67: // Create Ui5Report
68: $this->files->put("$targetPath/Report.php", $this->compileStub('Ui5Report.stub', [
69: 'namespace' => $phpNamespace,
70: 'ui5Namespace' => $jsNamespace,
71: 'app' => Str::kebab($app),
72: 'urlKey' => $urlKey,
73: 'slug' => $slug,
74: 'title' => $title,
75: 'description' => $description,
76: 'formats' => $this->formatArray($formats),
77: 'actionEntry' => $this->formatActionEntry($actions),
78: ]));
79:
80: // Create ReportDataProvider
81: $this->files->put("$targetPath/Provider.php", $this->compileStub('ReportProvider.stub', [
82: 'namespace' => $phpNamespace,
83: 'name' => 'Report'
84: ]));
85:
86: // Create Actions
87: foreach ($actions as $action) {
88: if ('' !== $action) {
89: $actionClass = "{$action}Action";
90: $this->files->put("$targetPath/$actionClass.php", $this->compileStub('ReportAction.stub', [
91: 'name' => $actionClass,
92: 'namespace' => $phpNamespace,
93: 'action' => $action
94: ]));
95: }
96: }
97:
98: // Create UI5 blade templates
99: File::ensureDirectoryExists($resourcesPath);
100:
101: $this->files->put("$resourcesPath/Report.controller.js", $this->compileStub('Report.controller.stub', [
102:
103: ]));
104: $this->files->put("$resourcesPath/Report.view.xml", $this->compileStub('Report.view.stub', [
105:
106: ]));
107: $this->files->put("$resourcesPath/report.blade.php", $this->compileStub('report.blade.stub', [
108:
109: ]));
110:
111: $this->components->info("UI5 Report '$reportName' and corresponding artifacts in Ui5App {$app} created successfully.");
112: $this->components->info("💡 Don’t forget to register this report in your module");
113:
114: return self::SUCCESS;
115: }
116:
117: protected function formatArray(array $items): string
118: {
119: return '[' . implode(', ', array_map(fn($i) => "'{$i}'", $items)) . ']';
120: }
121:
122: protected function formatActionEntry(array $actions): string
123: {
124: $actionEntries = [];
125:
126: foreach ($actions as $action) {
127: $action = trim($action);
128: if ($action === '') continue;
129:
130: $key = Str::snake($action); // z.B. 'discard_hours'
131: $class = Str::studly($action) . 'Action'; // z.B. 'DiscardHoursAction'
132:
133: $actionEntries[] = "'$key' => {$class}::class";
134: }
135:
136: return implode(",\n ", $actionEntries);
137: }
138: }
139: