1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace LaravelUi5\OData\Service;
6:
7: use LaravelUi5\OData\Edm\Contracts\Container\EntitySetInterface;
8: use LaravelUi5\OData\Edm\Contracts\Container\FunctionImportInterface;
9: use LaravelUi5\OData\Edm\Contracts\Container\SingletonInterface;
10: use LaravelUi5\OData\Edm\Contracts\EdmxInterface;
11: use LaravelUi5\OData\Service\Contracts\EntitySetResolverInterface;
12: use LaravelUi5\OData\Service\Contracts\FunctionResolverInterface;
13: use LaravelUi5\OData\Service\Contracts\RuntimeSchemaInterface;
14: use LaravelUi5\OData\Service\Contracts\SingletonResolverInterface;
15:
16: /**
17: * Frozen runtime schema — an EdmxInterface paired with its resolver maps.
18: *
19: * Resolver maps are keyed by spl_object_id of each EntitySetInterface /
20: * FunctionImportInterface instance. Since EdmxInterface is frozen, the
21: * container always returns the same instances, making object identity a
22: * correct and stable key for the lifetime of this schema.
23: */
24: final readonly class RuntimeSchema implements RuntimeSchemaInterface
25: {
26: /**
27: * @param array<int, EntitySetResolverInterface> $resolvers keyed by spl_object_id
28: * @param array<int, FunctionResolverInterface> $functionResolvers keyed by spl_object_id
29: * @param array<int, SingletonResolverInterface> $singletonResolvers keyed by spl_object_id
30: */
31: public function __construct(
32: private EdmxInterface $edmx,
33: private array $resolvers,
34: private array $functionResolvers = [],
35: private array $singletonResolvers = [],
36: ) {}
37:
38: public function getEdmx(): EdmxInterface
39: {
40: return $this->edmx;
41: }
42:
43: public function getResolver(EntitySetInterface $set): EntitySetResolverInterface
44: {
45: $key = spl_object_id($set);
46:
47: return $this->resolvers[$key]
48: ?? throw new \RuntimeException(
49: sprintf('No resolver bound for entity set "%s".', $set->getName())
50: );
51: }
52:
53: public function getFunctionResolver(FunctionImportInterface $import): FunctionResolverInterface
54: {
55: $key = spl_object_id($import);
56:
57: return $this->functionResolvers[$key]
58: ?? throw new \RuntimeException(
59: sprintf('No resolver bound for function import "%s".', $import->getName())
60: );
61: }
62:
63: public function getSingletonResolver(SingletonInterface $singleton): SingletonResolverInterface
64: {
65: $key = spl_object_id($singleton);
66:
67: return $this->singletonResolvers[$key]
68: ?? throw new \RuntimeException(
69: sprintf('No resolver bound for singleton "%s".', $singleton->getName())
70: );
71: }
72: }
73: