|
@@ -2779,6 +2779,61 @@ class ColumnController
|
2779
|
2779
|
}
|
2780
|
2780
|
}
|
2781
|
2781
|
|
|
2782
|
+// file: src/Tqdev/PhpCrudApi/Controller/GeoJsonController.php
|
|
2783
|
+
|
|
2784
|
+class GeoJsonController
|
|
2785
|
+{
|
|
2786
|
+ private $service;
|
|
2787
|
+ private $responder;
|
|
2788
|
+ private $geoJsonConverter;
|
|
2789
|
+
|
|
2790
|
+ public function __construct(Router $router, Responder $responder, GeoJsonService $service)
|
|
2791
|
+ {
|
|
2792
|
+ $router->register('GET', '/geojson/*', array($this, '_list'));
|
|
2793
|
+ $router->register('GET', '/geojson/*/*', array($this, 'read'));
|
|
2794
|
+ $this->service = $service;
|
|
2795
|
+ $this->responder = $responder;
|
|
2796
|
+ }
|
|
2797
|
+
|
|
2798
|
+ public function _list(ServerRequestInterface $request): ResponseInterface
|
|
2799
|
+ {
|
|
2800
|
+ $table = RequestUtils::getPathSegment($request, 2);
|
|
2801
|
+ $params = RequestUtils::getParams($request);
|
|
2802
|
+ if (!$this->service->hasTable($table)) {
|
|
2803
|
+ return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
|
|
2804
|
+ }
|
|
2805
|
+ return $this->responder->success($this->service->_list($table, $params));
|
|
2806
|
+ }
|
|
2807
|
+
|
|
2808
|
+ public function read(ServerRequestInterface $request): ResponseInterface
|
|
2809
|
+ {
|
|
2810
|
+ $table = RequestUtils::getPathSegment($request, 2);
|
|
2811
|
+ if (!$this->service->hasTable($table)) {
|
|
2812
|
+ return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
|
|
2813
|
+ }
|
|
2814
|
+ if ($this->service->getType($table) != 'table') {
|
|
2815
|
+ return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
|
|
2816
|
+ }
|
|
2817
|
+ $id = RequestUtils::getPathSegment($request, 3);
|
|
2818
|
+ $params = RequestUtils::getParams($request);
|
|
2819
|
+ if (strpos($id, ',') !== false) {
|
|
2820
|
+ $ids = explode(',', $id);
|
|
2821
|
+ $result = [];
|
|
2822
|
+ for ($i = 0; $i < count($ids); $i++) {
|
|
2823
|
+ array_push($result, $this->service->read($table, $ids[$i], $params));
|
|
2824
|
+ }
|
|
2825
|
+ return $this->responder->success($result);
|
|
2826
|
+ } else {
|
|
2827
|
+ $response = $this->service->read($table, $id, $params);
|
|
2828
|
+ if ($response === null) {
|
|
2829
|
+ return $this->responder->error(ErrorCode::RECORD_NOT_FOUND, $id);
|
|
2830
|
+ }
|
|
2831
|
+ return $this->responder->success($response);
|
|
2832
|
+ }
|
|
2833
|
+ }
|
|
2834
|
+
|
|
2835
|
+}
|
|
2836
|
+
|
2782
|
2837
|
// file: src/Tqdev/PhpCrudApi/Controller/OpenApiController.php
|
2783
|
2838
|
|
2784
|
2839
|
class OpenApiController
|
|
@@ -4417,6 +4472,175 @@ class TypeConverter
|
4417
|
4472
|
}
|
4418
|
4473
|
}
|
4419
|
4474
|
|
|
4475
|
+// file: src/Tqdev/PhpCrudApi/GeoJson/Feature.php
|
|
4476
|
+
|
|
4477
|
+class Feature implements \JsonSerializable
|
|
4478
|
+{
|
|
4479
|
+ private $properties;
|
|
4480
|
+ private $geometry;
|
|
4481
|
+
|
|
4482
|
+ public function __construct(array $properties, Geometry $geometry)
|
|
4483
|
+ {
|
|
4484
|
+ $this->properties = $properties;
|
|
4485
|
+ $this->geometry = $geometry;
|
|
4486
|
+ }
|
|
4487
|
+
|
|
4488
|
+ public function serialize()
|
|
4489
|
+ {
|
|
4490
|
+ return [
|
|
4491
|
+ 'type' => 'Feature',
|
|
4492
|
+ 'properties' => $this->properties,
|
|
4493
|
+ 'geometry' => $this->geometry,
|
|
4494
|
+ ];
|
|
4495
|
+ }
|
|
4496
|
+
|
|
4497
|
+ public function jsonSerialize()
|
|
4498
|
+ {
|
|
4499
|
+ return $this->serialize();
|
|
4500
|
+ }
|
|
4501
|
+}
|
|
4502
|
+
|
|
4503
|
+// file: src/Tqdev/PhpCrudApi/GeoJson/FeatureCollection.php
|
|
4504
|
+
|
|
4505
|
+class FeatureCollection implements \JsonSerializable
|
|
4506
|
+{
|
|
4507
|
+ private $features;
|
|
4508
|
+
|
|
4509
|
+ public function __construct(array $features)
|
|
4510
|
+ {
|
|
4511
|
+ $this->features = $features;
|
|
4512
|
+ }
|
|
4513
|
+
|
|
4514
|
+ public static function fromListDocument(ListDocument $records, string $geometryColumnName): FeatureCollection
|
|
4515
|
+ {
|
|
4516
|
+ $features = array();
|
|
4517
|
+ foreach ($records->getRecords() as $record) {
|
|
4518
|
+ if (isset($record[$geometryColumnName])) {
|
|
4519
|
+ $geometry = Geometry::fromWkt($record[$geometryColumnName]);
|
|
4520
|
+ unset($record[$geometryColumnName]);
|
|
4521
|
+ $features[] = new Feature($record, $geometry);
|
|
4522
|
+ }
|
|
4523
|
+ }
|
|
4524
|
+ return new FeatureCollection($features);
|
|
4525
|
+ }
|
|
4526
|
+
|
|
4527
|
+ public function serialize()
|
|
4528
|
+ {
|
|
4529
|
+ return [
|
|
4530
|
+ 'type' => 'FeatureCollection',
|
|
4531
|
+ 'features' => $this->features,
|
|
4532
|
+ ];
|
|
4533
|
+ }
|
|
4534
|
+
|
|
4535
|
+ public function jsonSerialize()
|
|
4536
|
+ {
|
|
4537
|
+ return $this->serialize();
|
|
4538
|
+ }
|
|
4539
|
+}
|
|
4540
|
+
|
|
4541
|
+// file: src/Tqdev/PhpCrudApi/GeoJson/GeoJsonService.php
|
|
4542
|
+
|
|
4543
|
+class GeoJsonService
|
|
4544
|
+{
|
|
4545
|
+ private $reflection;
|
|
4546
|
+ private $records;
|
|
4547
|
+
|
|
4548
|
+ public function __construct(ReflectionService $reflection, RecordService $records)
|
|
4549
|
+ {
|
|
4550
|
+ $this->reflection = $reflection;
|
|
4551
|
+ $this->records = $records;
|
|
4552
|
+ }
|
|
4553
|
+
|
|
4554
|
+ public function hasTable(string $table): bool
|
|
4555
|
+ {
|
|
4556
|
+ return $this->reflection->hasTable($table);
|
|
4557
|
+ }
|
|
4558
|
+
|
|
4559
|
+ private function getGeometryColumnName(string $tableName, string $geometryParam): string
|
|
4560
|
+ {
|
|
4561
|
+ $table = $this->reflection->getTable($tableName);
|
|
4562
|
+ foreach ($table->getColumnNames() as $columnName) {
|
|
4563
|
+ if ($geometryParam && $geometryParam != $columnName) {
|
|
4564
|
+ continue;
|
|
4565
|
+ }
|
|
4566
|
+ $column = $table->getColumn($columnName);
|
|
4567
|
+ if ($column->isGeometry()) {
|
|
4568
|
+ return $columnName;
|
|
4569
|
+ }
|
|
4570
|
+ }
|
|
4571
|
+ return "";
|
|
4572
|
+ }
|
|
4573
|
+
|
|
4574
|
+ public function _list(string $tableName, array $params): FeatureCollection
|
|
4575
|
+ {
|
|
4576
|
+ $geometryParam = isset($params['geometry']) ? $params['geometry'] : '';
|
|
4577
|
+ $geometryColumnName = $this->getGeometryColumnName($tableName, $geometryParam);
|
|
4578
|
+ $records = $this->records->_list($tableName, $params);
|
|
4579
|
+ return FeatureCollection::fromListDocument($records, $geometryColumnName);
|
|
4580
|
+ }
|
|
4581
|
+
|
|
4582
|
+ public function read(string $tableName, string $id, array $params) /*: ?object*/
|
|
4583
|
+ {
|
|
4584
|
+ return $this->records->read($tableName, $id, $params);
|
|
4585
|
+ }
|
|
4586
|
+}
|
|
4587
|
+
|
|
4588
|
+// file: src/Tqdev/PhpCrudApi/GeoJson/Geometry.php
|
|
4589
|
+
|
|
4590
|
+class Geometry implements \JsonSerializable
|
|
4591
|
+{
|
|
4592
|
+ private $type;
|
|
4593
|
+ private $geometry;
|
|
4594
|
+
|
|
4595
|
+ public static $types = [
|
|
4596
|
+ "Point",
|
|
4597
|
+ "MultiPoint",
|
|
4598
|
+ "LineString",
|
|
4599
|
+ "MultiLineString",
|
|
4600
|
+ "Polygon",
|
|
4601
|
+ "MultiPolygon",
|
|
4602
|
+ "GeometryCollection",
|
|
4603
|
+ ];
|
|
4604
|
+
|
|
4605
|
+ public function __construct(string $type, array $coordinates)
|
|
4606
|
+ {
|
|
4607
|
+ $this->type = $type;
|
|
4608
|
+ $this->coordinates = $coordinates;
|
|
4609
|
+ }
|
|
4610
|
+
|
|
4611
|
+ public static function fromWkt(string $wkt): Geometry
|
|
4612
|
+ {
|
|
4613
|
+ $bracket = strpos($wkt, '(');
|
|
4614
|
+ $type = strtoupper(trim(substr($wkt, 0, $bracket)));
|
|
4615
|
+ foreach (Geometry::$types as $typeName) {
|
|
4616
|
+ if (strtoupper($typeName) == $type) {
|
|
4617
|
+ $type = $typeName;
|
|
4618
|
+ }
|
|
4619
|
+ }
|
|
4620
|
+ $coordinates = substr($wkt, $bracket);
|
|
4621
|
+ $coordinates = preg_replace('|([0-9\-\.]+ )+([0-9\-\.]+)|', '[\1\2]', $coordinates);
|
|
4622
|
+ $coordinates = str_replace(['(', ')', ' '], ['[', ']', ','], $coordinates);
|
|
4623
|
+ $coordinates = json_decode($coordinates);
|
|
4624
|
+ if ($type == 'Point') {
|
|
4625
|
+ $coordinates = $coordinates[0];
|
|
4626
|
+ }
|
|
4627
|
+ return new Geometry($type, $coordinates);
|
|
4628
|
+ }
|
|
4629
|
+
|
|
4630
|
+ public function serialize()
|
|
4631
|
+ {
|
|
4632
|
+ return [
|
|
4633
|
+ 'type' => $this->type,
|
|
4634
|
+ 'coordinates' => $this->coordinates,
|
|
4635
|
+ ];
|
|
4636
|
+ }
|
|
4637
|
+
|
|
4638
|
+ public function jsonSerialize()
|
|
4639
|
+ {
|
|
4640
|
+ return $this->serialize();
|
|
4641
|
+ }
|
|
4642
|
+}
|
|
4643
|
+
|
4420
|
4644
|
// file: src/Tqdev/PhpCrudApi/Middleware/Base/Middleware.php
|
4421
|
4645
|
|
4422
|
4646
|
abstract class Middleware implements MiddlewareInterface
|
|
@@ -7031,6 +7255,11 @@ class Api implements RequestHandlerInterface
|
7031
|
7255
|
$openApi = new OpenApiService($reflection, $config->getOpenApiBase());
|
7032
|
7256
|
new OpenApiController($router, $responder, $openApi);
|
7033
|
7257
|
break;
|
|
7258
|
+ case 'geojson':
|
|
7259
|
+ $records = new RecordService($db, $reflection);
|
|
7260
|
+ $geoJson = new GeoJsonService($reflection, $records);
|
|
7261
|
+ new GeoJsonController($router, $responder, $geoJson);
|
|
7262
|
+ break;
|
7034
|
7263
|
}
|
7035
|
7264
|
}
|
7036
|
7265
|
$this->router = $router;
|