Skip to content

Commit 61829aa

Browse files
committed
Introduced Interface for ServiceEndpoints
1 parent 99781ab commit 61829aa

File tree

5 files changed

+126
-32
lines changed

5 files changed

+126
-32
lines changed

src/Endpoint.php

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,14 @@
22

33
namespace Flat3\Lodata;
44

5-
class Endpoint
5+
use Flat3\Lodata\Interfaces\ServiceEndpointInterface;
6+
7+
class Endpoint implements ServiceEndpointInterface
68
{
7-
/**
8-
* @var string $serviceUri the &lt;service-uri> of the <code>Flat3\Lodata\Model</code>.
9-
*/
109
protected $serviceUri;
1110

12-
/**
13-
* @var string $route the route prefix configured in <code>'lodata.prefix'</code>
14-
*/
1511
protected $route;
1612

17-
/**
18-
* @var string $endpoint the full url to the ODataService endpoint
19-
*/
2013
protected $endpoint;
2114

2215
public function __construct(string $serviceUri)
@@ -31,10 +24,6 @@ public function __construct(string $serviceUri)
3124
$this->endpoint = url($this->route) . '/';
3225
}
3326

34-
/**
35-
* @return string the path within the odata URI space, like in
36-
* https://<server>:<port>/<config('lodata.prefix')>/<service-uri>/$metadata
37-
*/
3827
public function endpoint(): string
3928
{
4029
return $this->endpoint;
@@ -45,29 +34,18 @@ public function route(): string
4534
return $this->route;
4635
}
4736

48-
/**
49-
* This method is intended to be overridden by subclasses.
50-
*
51-
* The value of the function will be presented in the Schema Namespace attribute,
52-
* https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html#sec_Schema
53-
*
54-
* @return string
55-
*/
56-
public function getNamespace(): string
37+
public function namespace(): string
5738
{
58-
// override this function to set Schema Namespace attribute
5939
return config('lodata.namespace');
6040
}
6141

62-
/**
63-
* This method is intended to be overridden by subclasses.
64-
*
65-
* Discovers Schema and Annotations of the `$metadata` file for
66-
* the service.
67-
*/
42+
public function cachedMetadataXMLPath(): ?string
43+
{
44+
return null;
45+
}
46+
6847
public function discover(Model $model): Model
6948
{
70-
// override this function to register all of your $metadata capabilities
7149
return $model;
7250
}
7351
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Flat3\Lodata\Interfaces;
4+
5+
use Flat3\Lodata\Model;
6+
7+
/**
8+
* Interface for defining a custom OData service endpoint.
9+
*
10+
* Implementers can use this interface to expose a specific service under a custom path,
11+
* define its namespace, route behavior, and optionally provide a statically generated
12+
* $metadata document.
13+
*/
14+
interface ServiceEndpointInterface
15+
{
16+
17+
/**
18+
* Returns the relative endpoint identifier within the OData service URI space.
19+
*
20+
* This is the part that appears between the configured Lodata prefix and
21+
* the `$metadata` segment, e.g.:
22+
* https://<server>:<port>/<config('lodata.prefix')>/<endpoint>/$metadata
23+
*
24+
* @return string The relative OData endpoint path
25+
*/
26+
public function endpoint(): string;
27+
28+
/**
29+
* Returns the full request route to this service endpoint.
30+
*
31+
* This typically resolves to the route path used by Laravel to handle
32+
* incoming requests for this specific service instance.
33+
*
34+
* @return string The full HTTP route to the endpoint
35+
*/
36+
public function route(): string;
37+
38+
/**
39+
* Returns the XML namespace used in the `$metadata` document.
40+
*
41+
* This value is injected as the `Namespace` attribute of the <Schema> element
42+
* in the OData CSDL document, and must be globally unique per service.
43+
*
44+
* @see https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html#sec_Schema
45+
*
46+
* @return string The schema namespace for the service
47+
*/
48+
public function namespace(): string;
49+
50+
/**
51+
* Returns the absolute filesystem path to a statically annotated `$metadata` file.
52+
*
53+
* This method can be overridden to provide a custom pre-generated CSDL XML file
54+
* for the OData metadata endpoint. If a path is returned, it will be used as-is
55+
* instead of dynamically generating the schema from model definitions.
56+
* Return `null` to fall back to automatic schema generation.
57+
*
58+
* @return string|null Full path to a static $metadata XML file, or null for dynamic generation
59+
*/
60+
public function cachedMetadataXMLPath(): ?string;
61+
62+
/**
63+
* Builds or enriches the model used for schema generation and metadata discovery.
64+
*
65+
* This method should populate the provided `Model` instance with entity sets,
66+
* types, annotations, and operations that define the service schema. It is
67+
* invoked during the metadata bootstrapping process when an OData service request
68+
* is processed.
69+
*
70+
* @param Model $model The schema model to populate
71+
* @return Model The enriched model instance representing the OData service
72+
*/
73+
public function discover(Model $model): Model;
74+
}

src/Model.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public function getTypeDefinition(string $name): ?Type
199199
*/
200200
public static function getNamespace(): string
201201
{
202-
return app(Endpoint::class)->getNamespace();
202+
return app(Endpoint::class)->namespace();
203203
}
204204

205205
/**

src/PathSegment/Metadata.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
namespace Flat3\Lodata\PathSegment;
66

77
use Flat3\Lodata\Controller\Transaction;
8+
use Flat3\Lodata\Endpoint;
89
use Flat3\Lodata\Exception\Internal\PathNotHandledException;
910
use Flat3\Lodata\Exception\Protocol\BadRequestException;
1011
use Flat3\Lodata\Interfaces\PipeInterface;
1112
use Flat3\Lodata\Interfaces\ResponseInterface;
13+
use Flat3\Lodata\PathSegment\Metadata\CachedXML;
1214
use Flat3\Lodata\Transaction\MediaType;
1315
use Flat3\Lodata\Transaction\MediaTypes;
1416
use Illuminate\Http\Request;
@@ -45,6 +47,9 @@ public static function pipe(
4547
return new Metadata\JSON();
4648

4749
default:
50+
if (app(Endpoint::class)->cachedMetadataXMLPath()) {
51+
return new CachedXML();
52+
}
4853
return new Metadata\XML();
4954
}
5055
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Flat3\Lodata\PathSegment\Metadata;
4+
5+
use Flat3\Lodata\Controller\Response;
6+
use Flat3\Lodata\Controller\Transaction;
7+
use Flat3\Lodata\Endpoint;
8+
use Flat3\Lodata\Interfaces\ContextInterface;
9+
use Flat3\Lodata\Interfaces\StreamInterface;
10+
use Flat3\Lodata\PathSegment\Metadata;
11+
use Flat3\Lodata\Transaction\MediaType;
12+
use RuntimeException;
13+
14+
class CachedXML extends Metadata implements StreamInterface
15+
{
16+
public function response(Transaction $transaction, ?ContextInterface $context = null): Response
17+
{
18+
$transaction->sendContentType((new MediaType)->parse(MediaType::xml));
19+
20+
return $transaction->getResponse()->setCallback(function () use ($transaction) {
21+
$this->emitStream($transaction);
22+
});
23+
}
24+
25+
public function emitStream(Transaction $transaction): void
26+
{
27+
$path = app(Endpoint::class)->cachedMetadataXMLPath();
28+
if (!file_exists($path)) {
29+
throw new RuntimeException("Metadata file not found: {$path}");
30+
}
31+
$content = file_get_contents($path);
32+
if (false === $content) {
33+
throw new RuntimeException("Failed to read metadata file: {$path}");
34+
}
35+
$transaction->sendOutput($content);
36+
}
37+
}

0 commit comments

Comments
 (0)