1: <?php
2:
3: namespace LaravelUi5\Core\Commands;
4:
5: use Illuminate\Support\Str;
6: use InvalidArgumentException;
7: use Illuminate\Support\Facades\File;
8: use Illuminate\Console\Command;
9:
10: class BaseGenerator extends Command
11: {
12:
13: protected function assertAppExists(string $app): bool
14: {
15: return File::exists(base_path("ui5/{$app}"));
16: }
17:
18: /**
19: * Parses and validates a name in the format AppName/ObjectName.
20: *
21: * Ensures that both parts use CamelCase and that the separator is present.
22: *
23: * @param string $input The raw input string, e.g. "ProjectKpi/CutOff"
24: * @return array{string, string} [$appName, $objectName]
25: * @throws InvalidArgumentException If format or naming is incorrect
26: */
27: protected function parseCamelCasePair(string $input): array
28: {
29: if (!str_contains($input, '/')) {
30: throw new InvalidArgumentException('Please use the format AppName/ObjectName (e.g. Projects/CutOff).');
31: }
32:
33: [$app, $object] = explode('/', $input, 2);
34:
35: foreach (['App name' => $app, 'Object name' => $object] as $label => $value) {
36: $this->assertCamelCase($label, $value);
37: }
38:
39: return [$app, $object];
40: }
41:
42: protected function assertCamelCase(string $label, string $input): void
43: {
44: if (!preg_match('/^[A-Z][a-zA-Z0-9]+$/', $input)) {
45: throw new InvalidArgumentException("{$label} must be CamelCase (e.g. ProjectKpi, CutOff).");
46: }
47: }
48:
49: /**
50: * Compiles a stub file by replacing all placeholders with the provided values.
51: *
52: * This method loads a stub file from the predefined `resources/stubs` directory
53: * and replaces all placeholder tokens (e.g., `{{ className }}`) with the corresponding
54: * values from the `$replacements` array.
55: *
56: * @param string $stubName The name of the stub file (e.g., 'TileClass.stub').
57: * @param array<string, string> $replacements An associative array of placeholder names
58: * and their replacement values.
59: * Keys should match the placeholder names
60: * without curly braces.
61: *
62: * @return string The compiled stub content with all placeholders replaced.
63: */
64: protected function compileStub(string $stubName, array $replacements): string
65: {
66: $stub = File::get(__DIR__ . "/../../resources/stubs/$stubName");
67:
68: foreach ($replacements as $key => $value) {
69: $stub = str_replace("{{ $key }}", $value, $stub);
70: }
71:
72: return $stub;
73: }
74:
75: /**
76: * @param string $sourcePath The distribution directory of the UI5 resources
77: * @param string $targetPath The src path of the LaravelUi5 module, e.g. ./ui5/Users/src
78: * @param array $toCopy Array with file names to copy
79: * @return void
80: */
81: protected function copyDistAssets(string $sourcePath, string $targetPath, array $toCopy): void
82: {
83: $source = $sourcePath;
84: $target = $targetPath . '../resources/ui5/';
85:
86: File::ensureDirectoryExists($target);
87: File::ensureDirectoryExists($target . 'i18n');
88:
89: foreach ($toCopy as $file) {
90: $from = "{$source}/{$file}";
91: $to = $target . $file;
92: if (file_exists($from)) {
93: File::copy($from, $to);
94: if ($this->output->isVerbose()) {
95: $this->info("{$file}");
96: }
97: }
98: }
99: }
100: }
101: