1: <?php
2:
3: namespace LaravelUi5\Core\Controllers;
4:
5: use Illuminate\Routing\Controller;
6: use LaravelUi5\Core\Contracts\Ui5ContextInterface;
7: use LaravelUi5\Core\Exceptions\MissingAssetException;
8: use LaravelUi5\Core\Ui5\Capabilities\HasAssetsInterface;
9: use Symfony\Component\HttpFoundation\BinaryFileResponse;
10:
11: /**
12: * Delivers static assets for UI5 applications or libraries (e.g., JS, CSS, i18n).
13: *
14: * Assets are resolved via the Ui5Registry based on artifact slug and type.
15: * The version segment is accepted in the URL for cache-busting but currently
16: * ignored in path resolution.
17: *
18: * Example routes:
19: * - GET /app/users/1.0.0/Component.js
20: * - GET /lib/core/1.0.0/resources/i18n/i18n.properties
21: */
22: class AssetController extends Controller
23: {
24: public function __invoke(
25: Ui5ContextInterface $context,
26: string $type,
27: string $slug,
28: string $version,
29: string $file
30: ): BinaryFileResponse
31: {
32:
33: $artifact = $context->artifact();
34:
35: if (!($artifact instanceof HasAssetsInterface)) {
36: throw new MissingAssetException($type, $slug, $version, $file);
37: }
38:
39: $path = $artifact->getAssetPath($file);
40:
41: if (!$path || !file_exists($path)) {
42: throw new MissingAssetException($type, $slug, $version, $file);
43: }
44:
45: if ('PRO' !== config('ui5.active')) {
46: return $this->serveFile($path, $file);
47: }
48:
49: if ($this->allowedInProduction($file)) {
50: return $this->serveFile($path, $file);
51: }
52:
53: throw new MissingAssetException($type, $slug, $version, $file);
54: }
55:
56: private function allowedInProduction(string $file): bool
57: {
58: return str_ends_with($file, 'Component-preload.js')
59: || str_ends_with($file, 'library-preload.js')
60: || str_ends_with($file, '.css')
61: || str_ends_with($file, '.properties');
62: }
63:
64: private function serveFile(string $path, string $file): BinaryFileResponse
65: {
66: $mime = match (true) {
67: str_ends_with($file, '.js') => 'application/javascript',
68: str_ends_with($file, '.js.map') => 'application/json',
69: str_ends_with($file, '.json') => 'application/json',
70: str_ends_with($file, '.css') => 'text/css',
71: str_ends_with($file, '.properties') => 'text/plain; charset=utf-8',
72: default => 'application/octet-stream',
73: };
74:
75: return response()->file($path, ['Content-Type' => $mime]);
76: }
77: }
78: