Skip to content

Commit f5cf900

Browse files
committed
Some GeoJSON works..
1 parent 2df56c0 commit f5cf900

File tree

7 files changed

+245
-0
lines changed

7 files changed

+245
-0
lines changed

src/Tqdev/PhpCrudApi/Api.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
use Tqdev\PhpCrudApi\Column\ReflectionService;
1010
use Tqdev\PhpCrudApi\Controller\CacheController;
1111
use Tqdev\PhpCrudApi\Controller\ColumnController;
12+
use Tqdev\PhpCrudApi\Controller\GeoJsonController;
1213
use Tqdev\PhpCrudApi\Controller\OpenApiController;
1314
use Tqdev\PhpCrudApi\Controller\RecordController;
1415
use Tqdev\PhpCrudApi\Controller\Responder;
1516
use Tqdev\PhpCrudApi\Database\GenericDB;
17+
use Tqdev\PhpCrudApi\GeoJson\GeoJsonService;
1618
use Tqdev\PhpCrudApi\Middleware\AuthorizationMiddleware;
1719
use Tqdev\PhpCrudApi\Middleware\BasicAuthMiddleware;
1820
use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
@@ -112,6 +114,11 @@ public function __construct(Config $config)
112114
$openApi = new OpenApiService($reflection, $config->getOpenApiBase());
113115
new OpenApiController($router, $responder, $openApi);
114116
break;
117+
case 'geojson':
118+
$records = new RecordService($db, $reflection);
119+
$geoJson = new GeoJsonService($reflection, $records);
120+
new GeoJsonController($router, $responder, $geoJson);
121+
break;
115122
}
116123
}
117124
$this->router = $router;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
namespace Tqdev\PhpCrudApi\Controller;
3+
4+
use Psr\Http\Message\ResponseInterface;
5+
use Psr\Http\Message\ServerRequestInterface;
6+
use Tqdev\PhpCrudApi\GeoJson\GeoJsonService;
7+
use Tqdev\PhpCrudApi\Middleware\Router\Router;
8+
use Tqdev\PhpCrudApi\Record\ErrorCode;
9+
use Tqdev\PhpCrudApi\RequestUtils;
10+
11+
class GeoJsonController
12+
{
13+
private $service;
14+
private $responder;
15+
private $geoJsonConverter;
16+
17+
public function __construct(Router $router, Responder $responder, GeoJsonService $service)
18+
{
19+
$router->register('GET', '/geojson/*', array($this, '_list'));
20+
$router->register('GET', '/geojson/*/*', array($this, 'read'));
21+
$this->service = $service;
22+
$this->responder = $responder;
23+
}
24+
25+
public function _list(ServerRequestInterface $request): ResponseInterface
26+
{
27+
$table = RequestUtils::getPathSegment($request, 2);
28+
$params = RequestUtils::getParams($request);
29+
if (!$this->service->hasTable($table)) {
30+
return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
31+
}
32+
return $this->responder->success($this->service->_list($table, $params));
33+
}
34+
35+
public function read(ServerRequestInterface $request): ResponseInterface
36+
{
37+
$table = RequestUtils::getPathSegment($request, 2);
38+
if (!$this->service->hasTable($table)) {
39+
return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
40+
}
41+
if ($this->service->getType($table) != 'table') {
42+
return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
43+
}
44+
$id = RequestUtils::getPathSegment($request, 3);
45+
$params = RequestUtils::getParams($request);
46+
if (strpos($id, ',') !== false) {
47+
$ids = explode(',', $id);
48+
$result = [];
49+
for ($i = 0; $i < count($ids); $i++) {
50+
array_push($result, $this->service->read($table, $ids[$i], $params));
51+
}
52+
return $this->responder->success($result);
53+
} else {
54+
$response = $this->service->read($table, $id, $params);
55+
if ($response === null) {
56+
return $this->responder->error(ErrorCode::RECORD_NOT_FOUND, $id);
57+
}
58+
return $this->responder->success($response);
59+
}
60+
}
61+
62+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
namespace Tqdev\PhpCrudApi\GeoJson;
3+
4+
class Feature implements \JsonSerializable
5+
{
6+
private $properties;
7+
private $geometry;
8+
9+
public function __construct(array $properties, Geometry $geometry)
10+
{
11+
$this->properties = $properties;
12+
$this->geometry = $geometry;
13+
}
14+
15+
public function serialize()
16+
{
17+
return [
18+
'type' => 'Feature',
19+
'properties' => $this->properties,
20+
'geometry' => $this->geometry,
21+
];
22+
}
23+
24+
public function jsonSerialize()
25+
{
26+
return $this->serialize();
27+
}
28+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
namespace Tqdev\PhpCrudApi\GeoJson;
3+
4+
use Tqdev\PhpCrudApi\Record\Document\ListDocument;
5+
6+
class FeatureCollection implements \JsonSerializable
7+
{
8+
private $features;
9+
10+
public function __construct(array $features)
11+
{
12+
$this->features = $features;
13+
}
14+
15+
public static function fromListDocument(ListDocument $records, string $geometryColumnName): FeatureCollection
16+
{
17+
$features = array();
18+
foreach ($records->getRecords() as $record) {
19+
if (isset($record[$geometryColumnName])) {
20+
$geometry = Geometry::fromWkt($record[$geometryColumnName]);
21+
unset($record[$geometryColumnName]);
22+
$features[] = new Feature($record, $geometry);
23+
}
24+
}
25+
return new FeatureCollection($features);
26+
}
27+
28+
public function serialize()
29+
{
30+
return [
31+
'type' => 'FeatureCollection',
32+
'features' => $this->features,
33+
];
34+
}
35+
36+
public function jsonSerialize()
37+
{
38+
return $this->serialize();
39+
}
40+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
namespace Tqdev\PhpCrudApi\GeoJson;
3+
4+
use Tqdev\PhpCrudApi\Column\ReflectionService;
5+
use Tqdev\PhpCrudApi\GeoJson\FeatureCollection;
6+
use Tqdev\PhpCrudApi\Record\RecordService;
7+
8+
class GeoJsonService
9+
{
10+
private $reflection;
11+
private $records;
12+
13+
public function __construct(ReflectionService $reflection, RecordService $records)
14+
{
15+
$this->reflection = $reflection;
16+
$this->records = $records;
17+
}
18+
19+
public function hasTable(string $table): bool
20+
{
21+
return $this->reflection->hasTable($table);
22+
}
23+
24+
private function getGeometryColumnName(string $tableName, string $geometryParam): string
25+
{
26+
$table = $this->reflection->getTable($tableName);
27+
foreach ($table->getColumnNames() as $columnName) {
28+
if ($geometryParam && $geometryParam != $columnName) {
29+
continue;
30+
}
31+
$column = $table->getColumn($columnName);
32+
if ($column->isGeometry()) {
33+
return $columnName;
34+
}
35+
}
36+
return "";
37+
}
38+
39+
public function _list(string $tableName, array $params): FeatureCollection
40+
{
41+
$geometryParam = isset($params['geometry']) ? $params['geometry'] : '';
42+
$geometryColumnName = $this->getGeometryColumnName($tableName, $geometryParam);
43+
$records = $this->records->_list($tableName, $params);
44+
return FeatureCollection::fromListDocument($records, $geometryColumnName);
45+
}
46+
47+
public function read(string $tableName, string $id, array $params) /*: ?object*/
48+
{
49+
return $this->records->read($tableName, $id, $params);
50+
}
51+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
namespace Tqdev\PhpCrudApi\GeoJson;
3+
4+
class Geometry implements \JsonSerializable
5+
{
6+
private $type;
7+
private $geometry;
8+
9+
public static $types = [
10+
"Point",
11+
"MultiPoint",
12+
"LineString",
13+
"MultiLineString",
14+
"Polygon",
15+
"MultiPolygon",
16+
"GeometryCollection",
17+
];
18+
19+
public function __construct(string $type, array $coordinates)
20+
{
21+
$this->type = $type;
22+
$this->coordinates = $coordinates;
23+
}
24+
25+
public static function fromWkt(string $wkt): Geometry
26+
{
27+
$bracket = strpos($wkt, '(');
28+
$type = strtoupper(trim(substr($wkt, 0, $bracket)));
29+
foreach (Geometry::$types as $typeName) {
30+
if (strtoupper($typeName) == $type) {
31+
$type = $typeName;
32+
}
33+
}
34+
$coordinates = substr($wkt, $bracket);
35+
$coordinates = preg_replace('|([0-9\-\.]+ )+([0-9\-\.]+)|', '[\1\2]', $coordinates);
36+
$coordinates = str_replace(['(', ')', ' '], ['[', ']', ','], $coordinates);
37+
$coordinates = json_decode($coordinates);
38+
if ($type == 'Point') {
39+
$coordinates = $coordinates[0];
40+
}
41+
return new Geometry($type, $coordinates);
42+
}
43+
44+
public function serialize()
45+
{
46+
return [
47+
'type' => $this->type,
48+
'coordinates' => $this->coordinates,
49+
];
50+
}
51+
52+
public function jsonSerialize()
53+
{
54+
return $this->serialize();
55+
}
56+
}

src/index.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'username' => 'php-crud-api',
1111
'password' => 'php-crud-api',
1212
'database' => 'php-crud-api',
13+
'controllers' => 'openapi,records,geojson',
1314
]);
1415
$request = RequestFactory::fromGlobals();
1516
$api = new Api($config);

0 commit comments

Comments
 (0)