From 5df8516fc8ea4386e9045d72b293d0c8f1417409 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Sun, 2 Jan 2022 01:40:14 +0100 Subject: Validation and submission logic --- composer.json | 14 +++--- composer.lock | 92 +------------------------------------ src/App.php | 106 ++++++++++++++++++++++++++++++++----------- templates/config/config.toml | 4 +- 4 files changed, 90 insertions(+), 126 deletions(-) diff --git a/composer.json b/composer.json index 50e771c..b8bf4cc 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,6 @@ { "name": "flat-file-forms/flat-file-forms", "type": "project", - "autoload": { - "psr-4": { - "FlatFileForms\\": "src/" - } - }, "authors": [ { "name": "Daniel Weipert", @@ -13,9 +8,14 @@ } ], "require": { - "twig/twig": "^3.3", "symfony/http-foundation": "^6.0", - "symfony/routing": "^6.0", + "twig/twig": "^3.3", "yosymfony/toml": "^1.0" + }, + "autoload": { + "psr-4": { + "FlatFileForms\\": "src/" + } } } + diff --git a/composer.lock b/composer.lock index 5e8d52d..92a2de5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "41c64fd992f720f457c4048c1f9a1cd3", + "content-hash": "47a7fb1c682449d24f01f0dbf7509da7", "packages": [ { "name": "symfony/deprecation-contracts", @@ -304,94 +304,6 @@ ], "time": "2021-05-27T12:26:48+00:00" }, - { - "name": "symfony/routing", - "version": "v6.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "362bc14e1187deaef12d1ca0e04bd919580e8e49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/362bc14e1187deaef12d1ca0e04bd919580e8e49", - "reference": "362bc14e1187deaef12d1ca0e04bd919580e8e49", - "shasum": "" - }, - "require": { - "php": ">=8.0.2" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12", - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-12-08T15:13:44+00:00" - }, { "name": "twig/twig", "version": "v3.3.4", @@ -587,5 +499,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } diff --git a/src/App.php b/src/App.php index c0df751..20cec62 100644 --- a/src/App.php +++ b/src/App.php @@ -5,13 +5,10 @@ namespace FlatFileForms; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Yosymfony\Toml\Toml; +use Yosymfony\Toml\TomlBuilder; class App { - private array $routes = [ - - ]; - /** * App constructor. */ @@ -28,33 +25,65 @@ class App $method = $request->getMethod(); $path = $request->getPathInfo(); - // GET - if ($method == 'GET') { - if (str_ends_with($path, '/fields')) { - $content['data'] = Toml::parseFile($contentRoot . $path . '/_fields.toml'); - } - else { - $content['data'] = Toml::parseFile($contentRoot . $path . '.toml'); - } - } - - // POST - else if ($method == 'POST') { - if (str_ends_with($path, 'submit')) { - $formPath = $contentRoot . str_replace('/submit', '', $path); + try { + // GET + if ($method == 'GET') { + if (str_ends_with($path, '/fields')) { + $formPath = $contentRoot . str_replace('/fields', '', $path); - // build fields - $fields = $this->buildFields($formPath); + $content['data'] = $this->buildFields($formPath); + } + else { + $content['data'] = Toml::parseFile($contentRoot . $path . '.toml'); + } + } - foreach ($fields as $field) { - if ($field['required'] ?? false) { - $content['error'] = 'REQUIRED!'; + // POST + else if ($method == 'POST') { + if (str_ends_with($path, '/submit')) { + $formPath = $contentRoot . str_replace('/submit', '', $path); + + $fields = $this->buildFields($formPath); + $fields = $this->validateFields($fields); + + // remove surplus fields from response + $fields = array_map(function ($field) { + return array_intersect_key($field, array_flip([ + 'is_valid', + ])); + }, $fields); + + $content['data'] = $fields; + + $hasInvalidFields = in_array(false, array_column($fields, 'is_valid')); + if ($hasInvalidFields) { + $content['error'] = 'Invalid fields'; + } else { + $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() + ); } } - - $content['data'] = $fields; - $content['POST'] = $_POST; } + } catch (\Exception $exception) { + $content['error'] = $exception->getMessage(); } $response->headers->set('Content-Type', 'application/json'); @@ -69,11 +98,34 @@ class App { $fields = Toml::parseFile($formPath . '/fields/_fields.toml')['field'] ?? []; foreach ($fields as $key => $field) { - $field = array_merge($field, Toml::parseFile($formPath . '/fields/' . $field['file'])); + if (empty($field['name'])) { + $field['name'] = $key; + } + + if (! empty($field['file'])) { + $field = array_merge($field, Toml::parseFile($formPath . '/fields/' . $field['file'])); + } + $fields[$key] = $field; } return $fields; } + + /** + * @param array $fields + */ + public function validateFields($fields) + { + foreach ($fields as $key => &$field) { + $field['is_valid'] = true; + + if (($field['required'] ?? false) && empty($_POST[$field['name']])) { + $field['is_valid'] = false; + } + } + + return $fields; + } } diff --git a/templates/config/config.toml b/templates/config/config.toml index 03977a1..1011e90 100644 --- a/templates/config/config.toml +++ b/templates/config/config.toml @@ -2,8 +2,8 @@ title = "Flat-File Forms" [email] -host = localhost -user = root +host = "localhost" +user = "root" password = 123456 [api] -- cgit v1.2.3