Skip to content

Commit d618004

Browse files
committed
Added Endpoint Discovery
1 parent b737077 commit d618004

File tree

14 files changed

+208
-47
lines changed

14 files changed

+208
-47
lines changed

config.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,9 @@
103103
* Configuration for OpenAPI schema generation
104104
*/
105105
'openapi' => [],
106+
107+
/**
108+
* Configuration for multiple service endpoints
109+
*/
110+
'endpoints' => [],
106111
];

doc/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ module.exports = {
134134
children: [
135135
'getting-started/',
136136
'getting-started/configuration',
137+
'getting-started/endpoint',
137138
'getting-started/facade',
138139
'getting-started/routing',
139140
'getting-started/authentication',

doc/getting-started/endpoint.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Service Endpoints
2+
3+
At this point we assume you already published the `lodata.php` config file to your project.
4+
5+
In case you want to distribute different service endpoints with your Laravel app, you can do so by providing one or more service endpoints to the package. This especially comes in handy when following a modularized setup.
6+
7+
Each of your modules could register its own service endpoint with an `\Flat3\Lodata\Endpoint` like this:
8+
9+
```php
10+
/**
11+
* At the end of `config/lodata.php`
12+
*/
13+
'endpoints' => [
14+
'projects' ⇒ \App\Projects\ProjectEndpoint::class,
15+
],
16+
```
17+
18+
With that configuration a separate `$metadata` service file will be available via `https://<server>:<port>/<lodata.prefix>/projects/$metadata`.
19+
20+
If the `endpoints` array stays empty (the default), only one global service endpoint is created.
21+
22+
## Selective Discovery
23+
24+
With endpoints, you can now discover all your entities and annotations in a separate class via the `discover` function.
25+
26+
```php
27+
use App\Model\Contact;
28+
use Flat3\Lodata\Model;
29+
30+
/**
31+
* Discovers Schema and Annotations of the `$metadata` file for
32+
* the service.
33+
*/
34+
public function discover(Model $model): Model
35+
{
36+
// register all of your $metadata capabilities
37+
$model->discover(Contact::class);
38+
39+
return $model;
40+
}
41+
```
42+
43+
Furthermore, the `discover` function will only be executed when serving actual oData routes. This will enhance page speed for routes outside the `config('lodata.prefix')` URI space.

doc/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
},
66
"devDependencies": {
77
"@kawarimidoll/vuepress-plugin-tailwind": "^2.0.0",
8-
"@vuepress/plugin-back-to-top": "^1.9.5",
9-
"@vuepress/plugin-nprogress": "^1.9.5",
10-
"vuepress": "^1.9.5",
8+
"@vuepress/plugin-back-to-top": "^1.9.10",
9+
"@vuepress/plugin-nprogress": "^1.9.10",
10+
"vuepress": "^1.9.10",
1111
"vuepress-plugin-container": "^2.1.5",
1212
"vuepress-plugin-sitemap": "^2.3.1"
1313
}

src/Controller/ODCFF.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
use Flat3\Lodata\Exception\Protocol\NotFoundException;
99
use Flat3\Lodata\Facades\Lodata;
1010
use Flat3\Lodata\Helper\Constants;
11-
use Flat3\Lodata\ServiceProvider;
11+
use Flat3\Lodata\Endpoint;
12+
use Illuminate\Contracts\Container\BindingResolutionException;
1213
use Illuminate\Http\Response;
1314
use Illuminate\Routing\Controller;
1415
use Illuminate\Support\Facades\App;
@@ -27,6 +28,7 @@ class ODCFF extends Controller
2728
* Generate an ODCFF response for the provided entity set identifier
2829
* @param string $identifier Identifier
2930
* @return Response Client response
31+
* @throws BindingResolutionException
3032
*/
3133
public function get(string $identifier): Response
3234
{
@@ -165,7 +167,7 @@ public function get(string $identifier): Response
165167
$formula = $mashupDoc->createElement('Formula');
166168
$formulaContent = $mashupDoc->createCDATASection(sprintf(
167169
'let Source = OData.Feed("%1$s", null, [Implementation="2.0"]), %2$s_table = Source{[Name="%2$s",Signature="table"]}[Data] in %2$s_table',
168-
ServiceProvider::endpoint(),
170+
app()->make(Endpoint::class)->endpoint(),
169171
$resourceId,
170172
));
171173
$formula->appendChild($formulaContent);

src/Controller/PBIDS.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
use Flat3\Lodata\Helper\Constants;
88
use Flat3\Lodata\Helper\JSON;
9-
use Flat3\Lodata\ServiceProvider;
9+
use Flat3\Lodata\Endpoint;
1010
use Flat3\Lodata\Transaction\MediaType;
11+
use Illuminate\Contracts\Container\BindingResolutionException;
1112
use Illuminate\Http\Response;
1213
use Illuminate\Routing\Controller;
1314
use Illuminate\Support\Facades\App;
@@ -23,6 +24,7 @@ class PBIDS extends Controller
2324
/**
2425
* Generate a PowerBI data source discovery file
2526
* @return Response Client response
27+
* @throws BindingResolutionException
2628
*/
2729
public function get(): Response
2830
{
@@ -42,7 +44,7 @@ public function get(): Response
4244
'details' => [
4345
'protocol' => 'odata',
4446
'address' => [
45-
'url' => ServiceProvider::endpoint(),
47+
'url' => app()->make(Endpoint::class)->endpoint(),
4648
],
4749
],
4850
],

src/Controller/Transaction.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
use Flat3\Lodata\Interfaces\ResponseInterface;
3131
use Flat3\Lodata\Interfaces\TransactionInterface;
3232
use Flat3\Lodata\NavigationProperty;
33+
use Flat3\Lodata\Endpoint;
3334
use Flat3\Lodata\Operation;
3435
use Flat3\Lodata\PathSegment;
35-
use Flat3\Lodata\ServiceProvider;
3636
use Flat3\Lodata\Singleton;
3737
use Flat3\Lodata\Transaction\IEEE754Compatible;
3838
use Flat3\Lodata\Transaction\MediaType;
@@ -58,6 +58,7 @@
5858
use Flat3\Lodata\Transaction\ParameterList;
5959
use Flat3\Lodata\Transaction\Version;
6060
use Flat3\Lodata\Type\Collection;
61+
use Illuminate\Contracts\Container\BindingResolutionException;
6162
use Illuminate\Support\Arr;
6263
use Illuminate\Support\Facades\App;
6364
use Illuminate\Support\Str;
@@ -784,7 +785,7 @@ public function getPath(): string
784785
*/
785786
public function getRequestPath(): string
786787
{
787-
$route = ServiceProvider::route();
788+
$route = app()->make(Endpoint::class)->route();
788789
return Str::substr($this->request->path(), strlen($route));
789790
}
790791

@@ -947,20 +948,22 @@ private function getSystemQueryOptions(bool $prefixed = true): array
947948
* Get the service document context URL
948949
* https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_ServiceDocument
949950
* @return string Context URL
951+
* @throws BindingResolutionException
950952
*/
951953
public function getContextUrl(): string
952954
{
953-
return ServiceProvider::endpoint().'$metadata';
955+
return self::getResourceUrl().'$metadata';
954956
}
955957

956958
/**
957959
* Get the service document resource URL
958960
* https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_ServiceDocument
959961
* @return string Resource URL
962+
* @throws BindingResolutionException
960963
*/
961964
public static function getResourceUrl(): string
962965
{
963-
return ServiceProvider::endpoint();
966+
return app()->make(Endpoint::class)->endpoint();
964967
}
965968

966969
/**

src/Endpoint.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Flat3\Lodata;
4+
5+
class Endpoint
6+
{
7+
/**
8+
* @var string $serviceUri the &lt;service-uri> of the <code>Flat3\Lodata\Model</code>.
9+
*/
10+
protected $serviceUri;
11+
12+
/**
13+
* @var string $route the route prefix configured in <code>'lodata.prefix'</code>
14+
*/
15+
protected $route;
16+
17+
/**
18+
* @var string $endpoint the full url to the ODataService endpoint
19+
*/
20+
protected $endpoint;
21+
22+
public function __construct(string $serviceUri)
23+
{
24+
$this->serviceUri = rtrim($serviceUri, '/');
25+
26+
$prefix = rtrim(config('lodata.prefix'), '/');
27+
$this->route = ('' === $serviceUri)
28+
? $prefix
29+
: $prefix . '/' . $this->serviceUri;
30+
31+
$this->endpoint = url($this->route) . '/';
32+
}
33+
34+
/**
35+
* @return string the path within the odata URI space, like in
36+
* https://<server>:<port>/<config('lodata.prefix')>/<service-uri>/$metadata
37+
*/
38+
public function endpoint(): string
39+
{
40+
return $this->endpoint;
41+
}
42+
43+
public function route(): string
44+
{
45+
return $this->route;
46+
}
47+
48+
/**
49+
* Discovers Schema and Annotations of the `$metadata` file for
50+
* the service.
51+
*/
52+
public function discover(Model $model): Model
53+
{
54+
// override this function to register all of your $metadata capabilities
55+
return $model;
56+
}
57+
}

src/Entity.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Flat3\Lodata\Interfaces\ResourceInterface;
2424
use Flat3\Lodata\Interfaces\ResponseInterface;
2525
use Flat3\Lodata\Transaction\MetadataContainer;
26+
use Illuminate\Contracts\Container\BindingResolutionException;
2627
use Illuminate\Http\Request;
2728
use Illuminate\Support\Str;
2829

@@ -154,6 +155,9 @@ public function offsetSet($offset, $value): void
154155
}
155156
}
156157

158+
/**
159+
* @throws BindingResolutionException
160+
*/
157161
public static function pipe(
158162
Transaction $transaction,
159163
string $currentSegment,
@@ -175,8 +179,9 @@ public static function pipe(
175179
}
176180

177181
$entityId = $id->getValue();
178-
if (Str::startsWith($entityId, ServiceProvider::endpoint())) {
179-
$entityId = Str::substr($entityId, strlen(ServiceProvider::endpoint()));
182+
$endpoint = app()->make(Endpoint::class)->endpoint();
183+
if (Str::startsWith($entityId, $endpoint)) {
184+
$entityId = Str::substr($entityId, strlen($endpoint));
180185
}
181186

182187
return EntitySet::pipe($transaction, $entityId);

src/Model.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Flat3\Lodata\Interfaces\ResourceInterface;
1818
use Flat3\Lodata\Interfaces\ServiceInterface;
1919
use Flat3\Lodata\Traits\HasAnnotations;
20+
use Illuminate\Contracts\Container\BindingResolutionException;
2021

2122
/**
2223
* Model
@@ -339,10 +340,11 @@ public function discover($discoverable): self
339340
/**
340341
* Get the REST endpoint of this OData model
341342
* @return string REST endpoint
343+
* @throws BindingResolutionException
342344
*/
343345
public function getEndpoint(): string
344346
{
345-
return ServiceProvider::endpoint();
347+
return app()->make(Endpoint::class)->endpoint();
346348
}
347349

348350
/**
@@ -351,7 +353,7 @@ public function getEndpoint(): string
351353
*/
352354
public function getPbidsUrl(): string
353355
{
354-
return ServiceProvider::endpoint().'_lodata/odata.pbids';
356+
return $this->getEndpoint().'_lodata/odata.pbids';
355357
}
356358

357359
/**
@@ -361,7 +363,7 @@ public function getPbidsUrl(): string
361363
*/
362364
public function getOdcUrl(string $set): string
363365
{
364-
return sprintf('%s_lodata/%s.odc', ServiceProvider::endpoint(), $set);
366+
return sprintf('%s_lodata/%s.odc', $this->getEndpoint(), $set);
365367
}
366368

367369
/**
@@ -370,6 +372,6 @@ public function getOdcUrl(string $set): string
370372
*/
371373
public function getOpenApiUrl(): string
372374
{
373-
return ServiceProvider::endpoint().'openapi.json';
375+
return $this->getEndpoint().'openapi.json';
374376
}
375377
}

0 commit comments

Comments
 (0)