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\Exception\BadRequestException;
9: use LaravelUi5\OData\Protocol\Planning\EntityQueryPlan;
10: use LaravelUi5\OData\Protocol\Planning\EntitySetQueryPlan;
11: use LaravelUi5\OData\Protocol\Planning\FunctionInvocationPlan;
12: use LaravelUi5\OData\Protocol\Planning\MetadataQueryPlan;
13: use LaravelUi5\OData\Protocol\Planning\PropertyValuePlan;
14: use LaravelUi5\OData\Protocol\Planning\SingletonQueryPlan;
15: use LaravelUi5\OData\Protocol\Planning\QueryPlan;
16: use LaravelUi5\OData\Protocol\Planning\ServiceDocumentQueryPlan;
17: use LaravelUi5\OData\Service\Contracts\RuntimeSchemaInterface;
18:
19: /**
20: * OData execution engine.
21: *
22: * Receives a fully-resolved QueryPlan from QueryPlanner and dispatches to a
23: * typed handler. Each handler returns an ODataResponse (StreamedResponse).
24: */
25: final readonly class Engine
26: {
27: public function __construct(
28: private RuntimeSchemaInterface $schema,
29: private string $serviceRoot,
30: ) {}
31:
32: public function execute(QueryPlan $plan): ODataResponse
33: {
34: return match (true) {
35: $plan instanceof MetadataQueryPlan => (new MetadataHandler)->handle($plan),
36: $plan instanceof ServiceDocumentQueryPlan => (new ServiceDocumentHandler($this->serviceRoot))->handle($plan),
37: $plan instanceof EntitySetQueryPlan => (new EntitySetHandler($this->schema, $this->serviceRoot))->handle($plan),
38: $plan instanceof EntityQueryPlan => (new EntityHandler($this->schema, $this->serviceRoot))->handle($plan),
39: $plan instanceof FunctionInvocationPlan => (new FunctionInvocationHandler($this->schema, $this->serviceRoot))->handle($plan),
40: $plan instanceof SingletonQueryPlan => (new SingletonHandler($this->schema, $this->serviceRoot))->handle($plan->singleton, $plan->select),
41: $plan instanceof PropertyValuePlan => (new PropertyValueHandler($this->schema, $this->serviceRoot))->handle($plan),
42:
43: default => throw new BadRequestException(
44: 'unsupported_plan',
45: sprintf('No handler for plan type %s', $plan::class)
46: ),
47: };
48: }
49: }
50: