doAction('init'); global $request; global $response; $request = Request::createFromGlobals(); $response = new Response(); $content = [ 'data' => [], ]; $contentRoot = $_ENV['app']['contentFolderPath']; $method = $request->getMethod(); $path = $request->getPathInfo(); $config = []; try { $config = $this->buildConfig($contentRoot . $path); // check referrer if (! empty($config['api']['referrer'])) { $referrerDomain = $_SERVER['HTTP_REFERER'] ?? ''; $referrerIp = $_SERVER['REMOTE_ADDR'] ?? 0; $referrerIsMatch = false; foreach ($config['api']['referrer'] as $referrer) { if ( ($referrer['domain'] ?? $referrerDomain) === $referrerDomain && ($referrer['ip'] ?? $referrerIp) === $referrerIp ) { $referrerIsMatch = true; break; } } if (! $referrerIsMatch) { throw new HttpException('Referrer mismatch', Response::HTTP_UNAUTHORIZED); } } // check api key $apiKey = $_GET['key'] ?? $_POST['key'] ?? null; if (empty($apiKey)) { throw new HttpException('API key missing', Response::HTTP_BAD_REQUEST); } if (! in_array($apiKey, $config['api']['keys'])) { throw new HttpException('API key does not match', Response::HTTP_UNAUTHORIZED); } // GET if ($method == 'GET') { if (str_ends_with($path, '/fields')) { $formPath = $contentRoot . str_replace('/fields', '', $path); $form = new Form($formPath); $builder = new Builder($formPath); $fieldsController = new FieldsController(); $content = $fieldsController->getFields($builder); } else if (str_ends_with($path, '/entries')) { if (! isset($_GET['dateFrom'])) { throw new HttpException('dateFrom parameter missing', Response::HTTP_BAD_REQUEST); } $formPath = $contentRoot . str_replace('/entries', '', $path); $form = new Form($formPath); $entriesController = new EntriesController(); $content = $entriesController->getEntries($formPath); } else { $content['data'] = Yaml::parseFile($contentRoot . $path . '.yaml'); } } // POST else if ($method == 'POST') { if (str_ends_with($path, '/validate')) { $formPath = $contentRoot . str_replace('/validate', '', $path); $form = new Form($formPath); $builder = new Builder($formPath); $validator = new Validator($formPath); $validationController = new ValidationController(); $content = $validationController->validateRequest($builder, $validator); } else if (str_ends_with($path, '/submit')) { $formPath = $contentRoot . str_replace('/submit', '', $path); $form = new Form($formPath); $builder = new Builder($formPath); $validator = new Validator($formPath); $submissionController = new SubmissionController(); $content = $submissionController->submit($builder, $validator, $formPath); if (! empty($content['error'])) { throw new HttpException($content['error'], Response::HTTP_UNPROCESSABLE_ENTITY); } } } } catch (\Exception $exception) { if ($exception instanceof HttpException) { $response->setStatusCode($exception->getCode()); } $content['error'] = basename(get_class($exception)) . ': ' . $exception->getMessage(); } $content = $hooks->applyFilter('response:content', $content, $response); $response->headers->set('Content-Type', 'application/json'); $response->headers->set('Access-Control-Allow-Origin', implode(',', $config['api']['cors']['origins'])); $response->setContent(json_encode($content)); $response->send(); } public function buildConfig(string $requestPath): array { $config = []; $currentDirectory = $requestPath; while (true) { $configFile = $currentDirectory . '/config/config.yaml'; if (file_exists($configFile)) { $parsedConfig = Yaml::parseFile($configFile); $apiKeys = array_merge($parsedConfig['api']['keys'] ?? [], $config['api']['keys'] ?? []); $config = array_replace_recursive($parsedConfig, $config); $config['api']['keys'] = $apiKeys; } // include custom functions $functionsFile = $currentDirectory . '/config/functions.php'; if (file_exists($functionsFile)) { include_once $functionsFile; } if ($currentDirectory == $_ENV['app']['contentFolderPath'] || $currentDirectory == '/') { break; } $currentDirectory = dirname($currentDirectory); } return $config; } }