1: <?php
2:
3: namespace LaravelUi5\Core\Introspection\App;
4:
5: use JsonException;
6: use LaravelUi5\Core\Contracts\Ui5Descriptor;
7: use LaravelUi5\Core\Introspection\Ui5I18n;
8: use LogicException;
9:
10: final readonly class Ui5AppDescriptor extends Ui5Descriptor
11: {
12: public function __construct(
13: private string $namespace,
14: private string $version,
15: private string $title,
16: private string $description,
17: private string $vendor,
18: private array $dependencies,
19: private array $routes,
20: private array $targets,
21: )
22: {
23: }
24:
25: /* -- Introspection API ------------------------------------------------ */
26:
27: public function getNamespace(): string
28: {
29: return $this->namespace;
30: }
31:
32: public function getVersion(): string
33: {
34: return $this->version;
35: }
36:
37: public function getTitle(): string
38: {
39: return $this->title;
40: }
41:
42: public function getDescription(): string
43: {
44: return $this->description;
45: }
46:
47: public function getVendor(): string
48: {
49: return $this->vendor;
50: }
51:
52: public function getDependencies(): array
53: {
54: return $this->dependencies;
55: }
56:
57: /** @return Ui5Route[] */
58: public function getRoutes(): array
59: {
60: return $this->routes;
61: }
62:
63: /** @return array<string, Ui5Target> keyed by target name */
64: public function getTargets(): array
65: {
66: return $this->targets;
67: }
68:
69: /* -- Factory ---------------------------------------------------------- */
70:
71: /**
72: * @throws JsonException
73: */
74: public static function fromManifestJson(string $path, Ui5I18n $i18n, string $vendor): self
75: {
76: $manifestPath = "{$path}/manifest.json";
77:
78: if (!is_file($manifestPath)) {
79: throw new LogicException("manifest.json not found at {$manifestPath}");
80: }
81:
82: $manifest = json_decode(
83: file_get_contents($manifestPath),
84: true,
85: 512,
86: JSON_THROW_ON_ERROR
87: );
88:
89: $sapApp = $manifest['sap.app'] ?? null;
90: if (!$sapApp || !isset($sapApp['id'])) {
91: throw new LogicException('Invalid manifest.json: missing sap.app.id');
92: }
93:
94: $namespace = $sapApp['id'];
95:
96: $version = $sapApp['applicationVersion']['version'] ?? '0.0.0';
97:
98: // Dependencies: sap.ui5.dependencies.libs (keys only!)
99: $libs = $manifest['sap.ui5']['dependencies']['libs'] ?? [];
100: if (!is_array($libs)) {
101: throw new LogicException('Invalid manifest.json: sap.ui5.dependencies.libs must be an object');
102: }
103:
104: $dependencies = array_keys($libs);
105:
106: $routing = $manifest['sap.ui5']['routing'] ?? [];
107: $routes = [];
108: foreach ($routing['routes'] ?? [] as $route) {
109: if (!isset($route['name'], $route['pattern'], $route['target'])) {
110: continue;
111: }
112:
113: $routes[] = new Ui5Route(
114: name: $route['name'],
115: pattern: $route['pattern'],
116: target: $route['target']
117: );
118: }
119:
120: $targets = [];
121:
122: foreach ($routing['targets'] ?? [] as $key => $target) {
123: if (!isset($target['viewName']) && !isset($target['name'])) {
124: continue;
125: }
126:
127: $targets[$key] = new Ui5Target(
128: key: $key,
129: name: $target['viewName'] ?? $target['name'],
130: );
131: }
132:
133: return new self(
134: namespace: $namespace,
135: version: $version,
136: title: $i18n->getTitle(),
137: description: $i18n->getDescription(),
138: vendor: $vendor,
139: dependencies: $dependencies,
140: routes: $routes,
141: targets: $targets,
142: );
143: }
144: }
145: