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)); } }