Files
seatmapv1/src/Tqdev/PhpCrudApi/Api.php
zino 1392bd3a96 Squashed 'seatmap-webapi/' content from commit 02d4bf7
git-subtree-dir: seatmap-webapi
git-subtree-split: 02d4bf7404b8fcb788502ca45c813946b6c4f5b9
2021-01-20 12:59:59 +01:00

216 lines
8.8 KiB
PHP

<?php
namespace Tqdev\PhpCrudApi;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Tqdev\PhpCrudApi\Cache\CacheFactory;
use Tqdev\PhpCrudApi\Column\DefinitionService;
use Tqdev\PhpCrudApi\Column\ReflectionService;
use Tqdev\PhpCrudApi\Controller\CacheController;
use Tqdev\PhpCrudApi\Controller\ColumnController;
use Tqdev\PhpCrudApi\Controller\GeoJsonController;
use Tqdev\PhpCrudApi\Controller\JsonResponder;
use Tqdev\PhpCrudApi\Controller\OpenApiController;
use Tqdev\PhpCrudApi\Controller\RecordController;
use Tqdev\PhpCrudApi\Database\GenericDB;
use Tqdev\PhpCrudApi\GeoJson\GeoJsonService;
use Tqdev\PhpCrudApi\Middleware\AuthorizationMiddleware;
use Tqdev\PhpCrudApi\Middleware\BasicAuthMiddleware;
use Tqdev\PhpCrudApi\Middleware\CorsMiddleware;
use Tqdev\PhpCrudApi\Middleware\CustomizationMiddleware;
use Tqdev\PhpCrudApi\Middleware\DbAuthMiddleware;
use Tqdev\PhpCrudApi\Middleware\FirewallMiddleware;
use Tqdev\PhpCrudApi\Middleware\IpAddressMiddleware;
use Tqdev\PhpCrudApi\Middleware\JoinLimitsMiddleware;
use Tqdev\PhpCrudApi\Middleware\JwtAuthMiddleware;
use Tqdev\PhpCrudApi\Middleware\MultiTenancyMiddleware;
use Tqdev\PhpCrudApi\Middleware\PageLimitsMiddleware;
use Tqdev\PhpCrudApi\Middleware\ReconnectMiddleware;
use Tqdev\PhpCrudApi\Middleware\Router\SimpleRouter;
use Tqdev\PhpCrudApi\Middleware\SanitationMiddleware;
use Tqdev\PhpCrudApi\Middleware\SslRedirectMiddleware;
use Tqdev\PhpCrudApi\Middleware\ValidationMiddleware;
use Tqdev\PhpCrudApi\Middleware\XmlMiddleware;
use Tqdev\PhpCrudApi\Middleware\XsrfMiddleware;
use Tqdev\PhpCrudApi\OpenApi\OpenApiService;
use Tqdev\PhpCrudApi\Record\ErrorCode;
use Tqdev\PhpCrudApi\Record\RecordService;
use Tqdev\PhpCrudApi\ResponseUtils;
class Api implements RequestHandlerInterface
{
private $router;
private $responder;
private $debug;
public function __construct(Config $config)
{
$db = new GenericDB(
$config->getDriver(),
$config->getAddress(),
$config->getPort(),
$config->getDatabase(),
$config->getTables(),
$config->getUsername(),
$config->getPassword()
);
$prefix = sprintf('phpcrudapi-%s-', substr(md5(__FILE__), 0, 8));
$cache = CacheFactory::create($config->getCacheType(), $prefix, $config->getCachePath());
$reflection = new ReflectionService($db, $cache, $config->getCacheTime());
$responder = new JsonResponder();
$router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime(), $config->getDebug());
foreach ($config->getMiddlewares() as $middleware => $properties) {
switch ($middleware) {
case 'sslRedirect':
new SslRedirectMiddleware($router, $responder, $properties);
break;
case 'cors':
new CorsMiddleware($router, $responder, $properties, $config->getDebug());
break;
case 'firewall':
new FirewallMiddleware($router, $responder, $properties);
break;
case 'basicAuth':
new BasicAuthMiddleware($router, $responder, $properties);
break;
case 'jwtAuth':
new JwtAuthMiddleware($router, $responder, $properties);
break;
case 'dbAuth':
new DbAuthMiddleware($router, $responder, $properties, $reflection, $db);
break;
case 'reconnect':
new ReconnectMiddleware($router, $responder, $properties, $reflection, $db);
break;
case 'validation':
new ValidationMiddleware($router, $responder, $properties, $reflection);
break;
case 'ipAddress':
new IpAddressMiddleware($router, $responder, $properties, $reflection);
break;
case 'sanitation':
new SanitationMiddleware($router, $responder, $properties, $reflection);
break;
case 'multiTenancy':
new MultiTenancyMiddleware($router, $responder, $properties, $reflection);
break;
case 'authorization':
new AuthorizationMiddleware($router, $responder, $properties, $reflection);
break;
case 'xsrf':
new XsrfMiddleware($router, $responder, $properties);
break;
case 'pageLimits':
new PageLimitsMiddleware($router, $responder, $properties, $reflection);
break;
case 'joinLimits':
new JoinLimitsMiddleware($router, $responder, $properties, $reflection);
break;
case 'customization':
new CustomizationMiddleware($router, $responder, $properties, $reflection);
break;
case 'xml':
new XmlMiddleware($router, $responder, $properties, $reflection);
break;
}
}
foreach ($config->getControllers() as $controller) {
switch ($controller) {
case 'records':
$records = new RecordService($db, $reflection);
new RecordController($router, $responder, $records);
break;
case 'columns':
$definition = new DefinitionService($db, $reflection);
new ColumnController($router, $responder, $reflection, $definition);
break;
case 'cache':
new CacheController($router, $responder, $cache);
break;
case 'openapi':
$openApi = new OpenApiService($reflection, $config->getOpenApiBase(), $config->getControllers(), $config->getCustomOpenApiBuilders());
new OpenApiController($router, $responder, $openApi);
break;
case 'geojson':
$records = new RecordService($db, $reflection);
$geoJson = new GeoJsonService($reflection, $records);
new GeoJsonController($router, $responder, $geoJson);
break;
}
}
foreach ($config->getCustomControllers() as $className) {
if (class_exists($className)) {
$records = new RecordService($db, $reflection);
new $className($router, $responder, $records);
}
}
$this->router = $router;
$this->responder = $responder;
$this->debug = $config->getDebug();
}
private function parseBody(string $body) /*: ?object*/
{
$first = substr($body, 0, 1);
if ($first == '[' || $first == '{') {
$object = json_decode($body);
$causeCode = json_last_error();
if ($causeCode !== JSON_ERROR_NONE) {
$object = null;
}
} else {
parse_str($body, $input);
foreach ($input as $key => $value) {
if (substr($key, -9) == '__is_null') {
$input[substr($key, 0, -9)] = null;
unset($input[$key]);
}
}
$object = (object) $input;
}
return $object;
}
private function addParsedBody(ServerRequestInterface $request): ServerRequestInterface
{
$parsedBody = $request->getParsedBody();
if ($parsedBody) {
$request = $this->applyParsedBodyHack($request);
} else {
$body = $request->getBody();
if ($body->isReadable()) {
if ($body->isSeekable()) {
$body->rewind();
}
$contents = $body->getContents();
if ($body->isSeekable()) {
$body->rewind();
}
if ($contents) {
$parsedBody = $this->parseBody($contents);
$request = $request->withParsedBody($parsedBody);
}
}
}
return $request;
}
private function applyParsedBodyHack(ServerRequestInterface $request): ServerRequestInterface
{
$parsedBody = $request->getParsedBody();
if (is_array($parsedBody)) { // is it really?
$contents = json_encode($parsedBody);
$parsedBody = $this->parseBody($contents);
$request = $request->withParsedBody($parsedBody);
}
return $request;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return $this->router->route($this->addParsedBody($request));
}
}