1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace LaravelUi5\OData\Protocol\Execution;
6:
7: use LaravelUi5\OData\Http\ODataResponse;
8: use LaravelUi5\OData\Edm\Contracts\Container\EntitySetInterface;
9: use LaravelUi5\OData\Edm\Contracts\Container\SingletonInterface;
10: use LaravelUi5\OData\Protocol\Planning\ServiceDocumentQueryPlan;
11:
12: /**
13: * Handles ServiceDocumentQueryPlan — produces the OData service document JSON.
14: *
15: * Emits:
16: * {"@odata.context":"<serviceRoot>$metadata","value":[
17: * {"name":"Products","kind":"EntitySet","url":"Products"},
18: * ...
19: * ]}
20: */
21: final readonly class ServiceDocumentHandler
22: {
23: public function __construct(private string $serviceRoot) {}
24:
25: public function handle(ServiceDocumentQueryPlan $plan): ODataResponse
26: {
27: $context = $this->serviceRoot . '$metadata';
28: $container = $plan->edmx->getEntityContainer();
29:
30: $entries = [];
31:
32: foreach ($container->getEntitySets() as $set) {
33: /** @var EntitySetInterface $set */
34: $entry = ['name' => $set->getName(), 'kind' => 'EntitySet', 'url' => $set->getName()];
35: $entries[] = $entry;
36: }
37:
38: foreach ($container->getSingletons() as $singleton) {
39: /** @var SingletonInterface $singleton */
40: $entry = ['name' => $singleton->getName(), 'kind' => 'Singleton', 'url' => $singleton->getName()];
41: $entries[] = $entry;
42: }
43:
44: $response = new ODataResponse(null, 200, [
45: 'Content-Type' => 'application/json;odata.metadata=minimal;charset=utf-8',
46: 'OData-Version' => '4.0',
47: ]);
48:
49: $response->setCallback(static function () use ($context, $entries): void {
50: echo json_encode([
51: '@odata.context' => $context,
52: 'value' => $entries,
53: ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
54: });
55:
56: return $response;
57: }
58: }
59: