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\SingletonInterface;
9: use LaravelUi5\OData\Protocol\Planning\SelectList;
10: use LaravelUi5\OData\Service\Contracts\RuntimeSchemaInterface;
11:
12: /**
13: * Handles singleton requests — returns a single named entity instance.
14: *
15: * Emits:
16: * {"@odata.context":"<serviceRoot>$metadata#<SingletonName>","prop":"value",...}
17: */
18: final readonly class SingletonHandler
19: {
20: public function __construct(
21: private RuntimeSchemaInterface $schema,
22: private string $serviceRoot,
23: ) {}
24:
25: public function handle(SingletonInterface $singleton, SelectList $select): ODataResponse
26: {
27: $resolver = $this->schema->getSingletonResolver($singleton);
28: $entity = $resolver->resolve();
29: $context = $this->serviceRoot . '$metadata#' . $singleton->getName();
30:
31: $selectKeys = SelectHelper::allowedKeys($select);
32:
33: $response = new ODataResponse(null, 200, [
34: 'Content-Type' => 'application/json;odata.metadata=minimal;charset=utf-8',
35: 'OData-Version' => '4.0',
36: ]);
37:
38: $response->setCallback(static function () use ($context, $entity, $selectKeys): void {
39: $entity = $selectKeys !== null ? array_intersect_key($entity, $selectKeys) : $entity;
40: $payload = array_merge(['@odata.context' => $context], $entity);
41: echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
42: });
43:
44: return $response;
45: }
46: }
47: