summaryrefslogtreecommitdiff
path: root/src/App.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/App.php')
-rw-r--r--src/App.php350
1 files changed, 38 insertions, 312 deletions
diff --git a/src/App.php b/src/App.php
index 92ceb4a..15be58b 100644
--- a/src/App.php
+++ b/src/App.php
@@ -2,6 +2,10 @@
namespace FlatFileForms;
+use FlatFileForms\Controllers\EntriesController;
+use FlatFileForms\Controllers\FieldsController;
+use FlatFileForms\Controllers\SubmissionController;
+use FlatFileForms\Controllers\ValidationController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Yosymfony\Toml\Toml;
@@ -33,104 +37,34 @@ class App
// check api key
$apiKey = $_GET['key'] ?? $_POST['key'] ?? null;
if (empty($apiKey)) {
- $response->setStatusCode(Response::HTTP_BAD_REQUEST);
- throw new \Exception('API key missing');
+ throw new HttpException('API key missing', Response::HTTP_BAD_REQUEST);
}
if (! in_array($apiKey, $config['api']['keys'])) {
- $response->setStatusCode(Response::HTTP_UNAUTHORIZED);
- throw new \Exception('API key does not match');
+ throw new HttpException('API key does not match', Response::HTTP_UNAUTHORIZED);
}
// GET
if ($method == 'GET') {
if (str_ends_with($path, '/fields')) {
- $this->formPath = $formPath = $contentRoot . str_replace('/fields', '', $path);
+ $formPath = $contentRoot . str_replace('/fields', '', $path);
- $fields = $this->buildFields($formPath, $_GET['page'] ?? null);
+ $builder = new Builder($formPath);
- // flatten paged form
- if ($this->isPagedFieldSet($fields) && isset($_GET['flat'])) {
- $fields = array_merge(...array_values($fields));
- }
+ $fieldsController = new FieldsController();
- $content['data'] = $fields;
+ $content = $fieldsController->getFields($builder);
}
else if (str_ends_with($path, '/entries')) {
if (! isset($_GET['dateFrom'])) {
- $response->setStatusCode(Response::HTTP_BAD_REQUEST);
- throw new \Exception('dateFrom parameter missing');
+ throw new HttpException('dateFrom parameter missing', Response::HTTP_BAD_REQUEST);
}
- $this->formPath = $formPath = $contentRoot . str_replace('/entries', '', $path);
-
- $entries = [];
-
- $dateFrom = new \DateTime($_GET['dateFrom']);
- $dateTo = new \DateTime($_GET['dateTo'] ?? 'now');
-
- $dateRangeYears = range($dateFrom->format('Y'), $dateTo->format('Y'));
- $dateRangeYearsCount = count($dateRangeYears);
- foreach ($dateRangeYears as $dateRangeYearIdx => $dateRangeYear) {
- $yearPath = "$formPath/entries/$dateRangeYear";
- if (! is_dir($yearPath)) {
- continue;
- }
-
- if ($dateRangeYearsCount === 1) {
- $dateRangeMonths = range($dateFrom->format('m'), $dateTo->format('m'));
- }
- else if ($dateRangeYearIdx === 0) {
- $dateRangeMonths = range($dateFrom->format('m'), 12);
- }
- else if ($dateRangeYearIdx === $dateRangeYearsCount - 1) {
- $dateRangeMonths = range(1, $dateTo->format('m'));
- }
- else {
- $dateRangeMonths = range(1, 12);
- }
-
- $dateRangeMonthsCount = count($dateRangeMonths);
- foreach ($dateRangeMonths as $dateRangeMonthIdx => $dateRangeMonth) {
- $monthPath = "$yearPath/" . sprintf('%02d', $dateRangeMonth);
- if (! is_dir($monthPath)) {
- continue;
- }
-
- if ($dateRangeMonthsCount === 1) {
- $dateRangeDays = range($dateFrom->format('d'), $dateTo->format('d'));
- }
- else if ($dateRangeYearIdx === 0 && $dateRangeMonthIdx === 0) {
- $dateRangeDays = range($dateFrom->format('d'), 31);
- }
- else if ($dateRangeYearIdx === $dateRangeYearsCount - 1 && $dateRangeMonthIdx === $dateRangeMonthsCount - 1) {
- $dateRangeDays = range(1, $dateTo->format('d'));
- }
- else {
- $dateRangeDays = range(1, 31);
- }
-
- foreach ($dateRangeDays as $dateRangeDay) {
- $dayPath = "$monthPath/" . sprintf('%02d', $dateRangeDay);
- if (! is_dir($dayPath)) {
- continue;
- }
-
- $entriesForDay = $this->scandir($dayPath);
- foreach ($entriesForDay as $entryForDay) {
- $entry = Toml::parseFile("$dayPath/$entryForDay");
- if (isset($_GET['flat'])) {
- $entries[] = $entry;
- } else {
- $entries[$dateRangeYear][$dateRangeMonth][$dateRangeDay][] = $entry;
- }
- }
- }
-
- }
- }
+ $formPath = $contentRoot . str_replace('/entries', '', $path);
+
+ $entriesController = new EntriesController();
- $content['data'] = $entries;
+ $content = $entriesController->getEntries();
}
else {
@@ -141,46 +75,36 @@ class App
// POST
else if ($method == 'POST') {
if (str_ends_with($path, '/validate')) {
- $this->formPath = $formPath = $contentRoot . str_replace('/validate', '', $path);
+ $formPath = $contentRoot . str_replace('/validate', '', $path);
- $fields = $this->buildFields($formPath, $_GET['page'] ?? null);
+ $builder = new Builder($formPath);
+ $validator = new Validator($formPath);
- $content = $this->validateRequest($fields);
+ $validationController = new ValidationController();
+
+ $content = $validationController->validateRequest($builder, $validator);
}
else if (str_ends_with($path, '/submit')) {
- $this->formPath = $formPath = $contentRoot . str_replace('/submit', '', $path);
-
- $fields = $this->buildFields($formPath);
-
- $content = $this->validateRequest($fields);
-
- // if there were no validation errors then add entry
- if (empty($content['error'])) {
- $date = new \Datetime();
- $entry = [
- 'fields' => $_POST,
- 'date' => $date->format('c'),
- ];
-
- $builder = new TomlBuilder();
- $builder->addValue('date', $entry['date']);
- $builder->addTable('fields');
- foreach ($entry['fields'] as $entryKey => $entryValue) {
- $builder->addValue($entryKey, $entryValue);
- }
-
- $entryDirectory = $formPath . '/entries/' . $date->format('Y/m/d');
- @mkdir($entryDirectory, 0774, true);
- $entryFilename = $date->format('Ymd_Hi_') . hash('adler32', serialize($entry)) . '.toml';
- file_put_contents(
- $entryDirectory . '/' . $entryFilename,
- $builder->getTomlString()
- );
+ $formPath = $contentRoot . str_replace('/submit', '', $path);
+
+ $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();
}
@@ -190,178 +114,10 @@ class App
$response->send();
}
- /**
- * @param array $fields
- */
- public function validateRequest($fields) {
- $content = [];
- $hasInvalidFields = false;
-
- $fields = $this->validateFields($fields);
-
- if ($this->isPagedFieldSet($fields)) {
- // remove surplus field values from response
- $fields = array_map(function ($page) {
- return array_map(function ($field) {
- return array_intersect_key($field, array_flip([
- 'is_valid',
- ]));
- }, $page);
- }, $fields);
-
- $flattened = array_merge(...array_values($fields));
- $hasInvalidFields = in_array(false, array_column($flattened, 'is_valid'));
- } else {
- // remove surplus field values from response
- $fields = array_map(function ($field) {
- return array_intersect_key($field, array_flip([
- 'is_valid',
- ]));
- }, $fields);
-
- $hasInvalidFields = in_array(false, array_column($fields, 'is_valid'));
- }
-
- $content['data'] = $fields;
-
- if ($hasInvalidFields) {
- $content['error'] = 'Invalid fields';
- }
-
- return $content;
- }
-
- /**
- * @param string $formPath
- * @param mixed $page
- */
- public function buildFields($formPath, $page = null)
- {
- $parsed = Toml::parseFile($formPath . '/fields/_fields.toml');
- $fields = [];
-
- // if a page is requested
- if ($page) {
- if (! isset($parsed['page'])) {
- throw new \Exception('Form has no pages');
- }
-
- if (! isset($parsed['page'][$page])) {
- throw new \Exception('Form has no page ' . $page);
- }
-
- $fields = $this->buildSinglePageFields($parsed['page'][$page], $formPath);
- }
-
- // else get all fields
- else {
- // if form is paged
- if (isset($parsed['page'])) {
- $pages = $parsed['page'];
- foreach ($pages as $pageKey => $pageFields) {
- $fields[$pageKey] = $this->buildSinglePageFields($pageFields, $formPath);
- }
- }
-
- // if form is not paged
- else {
- foreach ($parsed['field'] as $key => $field) {
- $fields[$key] = $this->buildSingleField($formPath, $key, $field);
- }
- }
- }
-
- return $fields;
- }
-
- /**
- * @param array $pageFields
- * @param string $formPath
- */
- public function buildSinglePageFields($pageFields, $formPath)
- {
- $fields = [];
-
- if (! empty($pageFields['file'])) {
- $pageFields = array_replace_recursive($pageFields, Toml::parseFile($formPath . '/fields/' . $pageFields['file']));
- }
-
- foreach ($pageFields['field'] as $key => $field) {
- $fields[$key] = $this->buildSingleField($formPath, $key, $field);
- }
-
- return $fields;
- }
-
- /**
- * @param string $formPath
- * @param string $key
- * @param string $field
- */
- public function buildSingleField($formPath, $key, $field)
- {
- if (! empty($field['file'])) {
- $field = array_replace_recursive($field, Toml::parseFile($formPath . '/fields/' . $field['file']));
- }
-
- if (empty($field['name'])) {
- $field['name'] = $key;
- }
-
- return $field;
- }
-
- /**
- * @param array $fields
- */
- public function validateFields($fields)
- {
- if ($this->isPagedFieldSet($fields)) {
- foreach ($fields as $pageKey => &$pageFields) {
- foreach ($pageFields as $key => &$field) {
- $field = $this->validateSingleField($field);
- }
- }
- } else {
- foreach ($fields as $key => &$field) {
- $field = $this->validateSingleField($field);
- }
- }
-
- return $fields;
- }
-
- /**
- * @param array $field
- */
- public function validateSingleField($field)
- {
- $value = $_POST[$field['name']] ?? '';
- $field['is_valid'] = true;
-
- if (isset($field['required']) && empty($value)) {
- $field['is_valid'] = false;
- }
-
- if (isset($field['validation']['pattern']) && preg_match_all('/' . $field['validation']['pattern'] . '/', $value) === 0) {
- $field['is_valid'] = false;
- }
-
- $validationFunctionName = 'validate_' . basename($this->formPath) . '_' . $field['name'];
- if (function_exists($validationFunctionName)) {
- $field = call_user_func($validationFunctionName, $field, $value);
- }
-
- return $field;
- }
-
- /**
- * @param string $formPath
- */
- public function buildConfig($formPath)
+ public function buildConfig(string $requestPath): array
{
$config = [];
- $currentDirectory = $formPath;
+ $currentDirectory = $requestPath;
while (true) {
$configFile = $currentDirectory . '/config/config.toml';
if (file_exists($configFile)) {
@@ -387,34 +143,4 @@ class App
return $config;
}
-
- /**
- * @param array $fields
- */
- public function isPagedFieldSet($fields)
- {
- $firstItem = reset($fields);
-
- return ! (isset($firstItem['name']) && ! is_array($firstItem['name']));
- }
-
- /**
- * @param string|array $paths
- */
- public function scandir($paths)
- {
- $paths = (array)$paths;
-
- $scanned = [];
- foreach ($paths as $path) {
- $filtered = array_values(
- array_filter(
- scandir($path), fn ($item) => ! in_array($item, ['.', '..'])
- )
- );
- array_push($scanned, ...$filtered);
- }
-
- return $scanned;
- }
}