1: <?php
2:
3: namespace LaravelUi5\Core\Enums;
4:
5: use LaravelUi5\Core\Exceptions\InvalidPathException;
6: use LaravelUi5\Core\Ui5\Contracts\Ui5ActionInterface;
7: use LaravelUi5\Core\Ui5\Contracts\Ui5AppInterface;
8: use LaravelUi5\Core\Ui5\Contracts\Ui5ArtifactInterface;
9: use LaravelUi5\Core\Ui5\Contracts\Ui5CardInterface;
10: use LaravelUi5\Core\Ui5\Contracts\Ui5DashboardInterface;
11: use LaravelUi5\Core\Ui5\Contracts\Ui5KpiInterface;
12: use LaravelUi5\Core\Ui5\Contracts\Ui5LibraryInterface;
13: use LaravelUi5\Core\Ui5\Contracts\Ui5ModuleInterface;
14: use LaravelUi5\Core\Ui5\Contracts\Ui5ReportInterface;
15: use LaravelUi5\Core\Ui5\Contracts\Ui5TileInterface;
16:
17: /**
18: * Enum representing the types of UI5 artifacts supported by the system.
19: *
20: * Each artifact type corresponds to a distinct kind of module or UI component
21: * that can be registered, versioned, and deployed within the Laravel-based UI5 integration.
22: *
23: * @see Ui5ArtifactInterface
24: */
25: enum ArtifactType: int
26: {
27: /**
28: * A UI5 module providing a logical container for artifacts such as applications,
29: * cards, KPIs, actions, or libraries. Modules define the namespace scope and slug
30: * used for routing and access control, and typically correspond to a PHP package
31: * or subdirectory within the `ui5/` structure.
32: *
33: * Modules themselves are not directly routable or versioned as standalone resources,
34: * but serve as the root context for all included artifacts.
35: *
36: * @see Ui5ModuleInterface
37: */
38: case Module = 0;
39:
40: /**
41: * A standalone UI5 application with its own routing, Component.js, and entry point.
42: * Typically served as a separate HTML page.
43: *
44: * @see Ui5AppInterface
45: */
46: case Application = 1;
47:
48: /**
49: * A reusable UI5 library containing controls, formatters, helpers, or shared logic.
50: * Can be imported by multiple applications.
51: *
52: * @see Ui5LibraryInterface
53: */
54: case Library = 2;
55:
56: /**
57: * A UI5 Integration Card, such as ObjectCard, ListCard, or TableCard.
58: * Usually configured via a manifest and rendered inside a dashboard or shell.
59: *
60: * @see Ui5CardInterface
61: */
62: case Card = 3;
63:
64: /**
65: * A backend-powered report providing structured tabular or aggregated data.
66: * Typically supports parameterization and optional export (e.g., CSV, Excel).
67: *
68: * @see Ui5ReportInterface
69: */
70: case Report = 4;
71:
72: /**
73: * A Tile definition, representing a lightweight but versioned UI5 artifact.
74: *
75: * Tiles act as *UI composition units* within dashboards, launchpads, or other
76: * shell containers. Each tile provides metadata such as title, description,
77: * icon, and target, and may reference other artifacts (e.g., KPI, Report, App).
78: *
79: * Unlike Cards, Tiles are not intended for complex rendering or configuration.
80: * They primarily serve as *entry points* or *compact visual summaries*,
81: * often embedding KPIs or linking to other routable artifacts.
82: *
83: * Characteristics:
84: * - Routable: No. Tiles are embedded only, never accessed via URL directly.
85: * - Versionable: Yes. Tile layout, label, or KPI binding may change over time.
86: * - Discoverable: Yes. Tiles are registered in the Ui5Registry.
87: *
88: * @see Ui5TileInterface
89: */
90: case Tile = 5;
91:
92: /**
93: * A KPI (Key Performance Indicator) definition, representing a reusable
94: * and versioned *data artifac* within the system.
95: *
96: * KPIs encapsulate metadata such as ID, title, unit, aggregation logic,
97: * thresholds, and applicable contexts. They provide the data basis for
98: * visualization in Tiles, Cards, or Dashboards.
99: *
100: * Characteristics:
101: * - Routable: No. KPIs are data definitions, not standalone UI routes.
102: * - Versionable: Yes. Thresholds, aggregation rules, or calculation logic
103: * may evolve over time.
104: * - Reusable: Yes. The same KPI can appear in multiple Tiles, Cards, or
105: * Dashboards.
106: * - Discoverable: Yes. KPIs are registered in the Ui5Registry.
107: *
108: * @see Ui5KpiInterface
109: */
110: case Kpi = 6;
111:
112: /**
113: * A dashboard aggregating multiple Cards or Tiles in a layout.
114: * May be statically defined (via manifest) or assembled dynamically.
115: *
116: * @see Ui5DashboardInterface
117: */
118: case Dashboard = 7;
119:
120: /**
121: * A backend-bound action that can be triggered via direct API route.
122: * UI5 Actions are invokable controller classes designed for stateless interaction,
123: * such as toggling flags, triggering workflows, or executing custom business logic.
124: *
125: * Actions are uniquely addressable within their module via an HTTP method and route segment.
126: *
127: * @see Ui5ActionInterface
128: */
129: case Action = 8;
130:
131: /**
132: * A Resource is a lightweight, read-only UI5 artifact that exposes
133: * structured data for consumption by the client (e.g., cards, dashboards, lists).
134: *
135: * @see Ui5ResourceInterface
136: */
137: case Resource = 9;
138:
139: /**
140: * A Ui5Dialog represents a globale invokable View/Controller pair bound to
141: * a named URI segment.
142: *
143: * @see Ui5DialogInterface
144: */
145: case Dialog = 10;
146:
147: /**
148: * Returns a human-readable label for the artifact type.
149: *
150: * @return string
151: */
152: public function label(): string
153: {
154: return match ($this) {
155: self::Module => 'Module',
156: self::Application => 'Application',
157: self::Library => 'Library',
158: self::Card => 'Card',
159: self::Report => 'Report',
160: self::Tile => 'Tile',
161: self::Kpi => 'KPI',
162: self::Dashboard => 'Dashboard',
163: self::Action => 'Action',
164: self::Resource => 'Resource',
165: self::Dialog => 'Dialog',
166: };
167: }
168:
169: /**
170: * Returns the composed URL key (slug path) for a given artifact.
171: *
172: * The URL key determines the routing path used by the UI5 frontend and Laravel
173: * backend to locate and invoke this artifact. It forms the core part of the
174: * dynamic route segment that appears in URLs like:
175: *
176: * /ui5/app/{slug}/{version}
177: * /ui5/card/{module}/{slug}
178: * /ui5/api/{module}/{action}
179: *
180: * This method mirrors the routing conventions defined in `routes/ui5.php`
181: * and must remain in sync with the corresponding Route::pattern definitions.
182: *
183: * In cases where no slug is required (e.g., Applications or Libraries),
184: * the returned path includes only the module-level key (e.g. "app/core").
185: *
186: * In cases where the artifact is not addressable via URL (e.g., abstract types),
187: * this method returns `null`.
188: *
189: * @param Ui5ArtifactInterface $artifact The artifact to generate the URL key for
190: * @return string|null URL key (e.g. "card/core/budget") or null if an artifact type is not routable
191: */
192: public static function urlKeyFromArtifact(Ui5ArtifactInterface $artifact): ?string
193: {
194: return match ($artifact->getType()) {
195: self::Application => "app/{$artifact->getModule()->getSlug()}",
196: self::Library => "lib/{$artifact->getModule()->getSlug()}",
197: self::Card => "card/{$artifact->getModule()->getSlug()}/{$artifact->getSlug()}",
198: self::Action => "api/{$artifact->getModule()->getSlug()}/{$artifact->getSlug()}",
199: self::Resource => "resource/{$artifact->getModule()->getSlug()}/{$artifact->getSlug()}",
200: self::Dashboard => "dashboard/{$artifact->getSlug()}",
201: self::Report => "report/{$artifact->getSlug()}",
202: self::Dialog => "dialog/{$artifact->getSlug()}",
203: self::Module, self::Tile, self::Kpi => null,
204: };
205: }
206:
207: /**
208: * Resolve a UI5 artifact urlKey from a request path.
209: *
210: * This method inspects the path relative to the configured UI5 route prefix
211: * and attempts to construct a valid urlKey suitable for Ui5Registry lookup.
212: *
213: * Expected formats:
214: * - app/{module}
215: * - lib/{module}
216: * - card/{module}/{slug}
217: * - dashboard/{slug}
218: * - report/{module}.{slug}
219: * - api/{module}/{slug}
220: * - resource/{module}/{slug}
221: *
222: * Behavior:
223: * - Returns the normalized urlKey string (e.g. "card/foo/bar").
224: * - Aborts with HTTP 400 if the path matches a UI5 artifact type
225: * but is incomplete or malformed.
226: * - Aborts with HTTP 400 if the path has fewer than two parts
227: * or does not map to a known artifact type.
228: *
229: * @param string $path Relative request path below the UI5 route prefix
230: * @return string|null urlKey for Ui5Registry lookup or null if infrastructure route
231: */
232: public static function urlKeyFromPath(string $path): ?string
233: {
234: $parts = explode('/', trim($path, '/'));
235: if (count($parts) < 2) {
236: throw new InvalidPathException($path);
237: }
238: return match ($parts[0]) {
239: 'app' => "app/" . $parts[1],
240: 'lib' => "lib/" . $parts[1],
241: 'dashboard' => "dashboard/" . $parts[1],
242: 'report' => "report/" . $parts[1],
243: 'dialog' => "dialog/" . $parts[1],
244: 'card' => isset($parts[2])
245: ? "card/" . $parts[1] . "/" . $parts[2]
246: : null,
247: 'api' => isset($parts[2])
248: ? "api/" . $parts[1] . "/" . $parts[2]
249: : null,
250: 'resource' => isset($parts[2])
251: ? "resource/" . $parts[1] . "/" . $parts[2]
252: : null,
253: default => null,
254: };
255: }
256: }
257: