diff --git a/.gitignore b/.gitignore index b4c3368..48a117a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ -.idea -.vs -.code +.* vendor + composer.lock *.phar /dist +# sqlite database files +*.sqlite + views-mappings.php # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. diff --git a/Documentation/how-to-dev.md b/Documentation/how-to-dev.md index 88e9d75..0af8da5 100644 --- a/Documentation/how-to-dev.md +++ b/Documentation/how-to-dev.md @@ -102,6 +102,7 @@ the file is replaced with `prod-config-file.php` by the CI when deploying to the The two profiles declares an `_asset(string $uri)` function, used by the `/config.php::asset` method, but with different implementations : ### Development profile + ```php $hostname = getHostName(); $front_url = "http://$hostname:5173"; @@ -110,8 +111,6 @@ function _asset(string $assetURI): string { global $front_url; return $front_url . "/" . $assetURI; } - - ``` The simplest profile, simply redirect all assets to the development server diff --git a/ci/.drone.yml b/ci/.drone.yml index cb1a90f..8a28ad7 100644 --- a/ci/.drone.yml +++ b/ci/.drone.yml @@ -32,7 +32,7 @@ steps: - sed -iE 's/\\/\\*PROFILE_FILE\\*\\/\\s*".*"/"profiles\\/prod-config-profile.php"/' config.php - composer install && composer update - rm profiles/dev-config-profile.php - - mv src config.php profiles vendor /outputs/ + - mv src config.php sql profiles vendor /outputs/ - image: eeacms/rsync:latest name: Deliver on staging server branch @@ -49,4 +49,3 @@ steps: - chmod 0600 ~/.ssh - chmod 0500 ~/.ssh/id_rsa* - rsync -avz -e "ssh -p 80 -o 'StrictHostKeyChecking=no'" --delete /outputs/* iqball@maxou.dev:/server/nginx/IQBall/$DRONE_BRANCH - diff --git a/composer.json b/composer.json index 7cfbb6b..c3bb579 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,8 @@ }, "require": { "altorouter/altorouter": "1.2.0", - "ext-json": "*" + "ext-json": "*", + "ext-pdo": "*", + "ext-pdo_sqlite": "*" } } \ No newline at end of file diff --git a/config.php b/config.php index 11e7c2c..592ee38 100644 --- a/config.php +++ b/config.php @@ -16,4 +16,8 @@ function asset(string $assetURI): string { return _asset($assetURI); } +global $_data_source_name; +$data_source_name = $_data_source_name; +const DATABASE_USER = _DATABASE_USER; +const DATABASE_PASSWORD = _DATABASE_PASSWORD; diff --git a/front/ViewRenderer.tsx b/front/ViewRenderer.tsx index ffaf886..17148dc 100644 --- a/front/ViewRenderer.tsx +++ b/front/ViewRenderer.tsx @@ -11,6 +11,8 @@ export function renderView(Component: FunctionComponent, args: {}) { document.getElementById('root') as HTMLElement ); + console.log(args) + root.render( diff --git a/front/views/DisplayResults.tsx b/front/views/DisplayResults.tsx index faf5e28..c4bbd1b 100644 --- a/front/views/DisplayResults.tsx +++ b/front/views/DisplayResults.tsx @@ -1,12 +1,19 @@ -import ReactDOM from "react-dom/client"; -import React from "react"; +interface DisplayResultsProps { + results: readonly { name: string, description: string}[] +} -export default function DisplayResults({password, username}: any) { +export default function DisplayResults({results}: DisplayResultsProps) { + const list = results + .map(({name, description}) => +
+

username: {name}

+

description: {description}

+
+ ) return (
-

username: {username}

-

password: {password}

+ {list}
) } diff --git a/front/views/SampleForm.tsx b/front/views/SampleForm.tsx index 5108697..604e362 100644 --- a/front/views/SampleForm.tsx +++ b/front/views/SampleForm.tsx @@ -1,16 +1,15 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; + export default function SampleForm() { return (

Hello, this is a sample form made in react !

-
+ - - - - + + + +
) diff --git a/profiles/dev-config-profile.php b/profiles/dev-config-profile.php index 3ce4986..316ff44 100644 --- a/profiles/dev-config-profile.php +++ b/profiles/dev-config-profile.php @@ -4,9 +4,17 @@ $hostname = getHostName(); $front_url = "http://$hostname:5173"; const _SUPPORTS_FAST_REFRESH = true; +$_data_source_name = "sqlite:${_SERVER['DOCUMENT_ROOT']}/../dev-database.sqlite"; -function _asset(string $assetURI): string { +// no user and password needed for sqlite databases +const _DATABASE_USER = null; +const _DATABASE_PASSWORD = null; + +function _asset(string $assetURI): string +{ global $front_url; return $front_url . "/" . $assetURI; } + + diff --git a/profiles/prod-config-profile.php b/profiles/prod-config-profile.php index d76826c..dfd4d02 100644 --- a/profiles/prod-config-profile.php +++ b/profiles/prod-config-profile.php @@ -5,6 +5,12 @@ require "../views-mappings.php"; const _SUPPORTS_FAST_REFRESH = false; +$database_file = __DIR__ . "/../database.sqlite"; +$_data_source_name = "sqlite:/$database_file"; + +// no user and password needed for sqlite databases +const _DATABASE_USER = null; +const _DATABASE_PASSWORD = null; function _asset(string $assetURI): string { diff --git a/public/index.php b/public/index.php index 23737f5..14b0756 100644 --- a/public/index.php +++ b/public/index.php @@ -2,8 +2,11 @@ require "../vendor/autoload.php"; require "../config.php"; +require "../sql/database.php"; +use App\Connexion; use App\Controller\SampleFormController; +use App\Gateway\FormResultGateway; /** * relative path of the index.php's directory from the server's document root. @@ -21,14 +24,15 @@ function get_base_path() { } $basePath = get_base_path(); +$con = new Connexion(get_database()); // routes initialization $router = new AltoRouter(); $router->setBasePath($basePath); -$sampleFormController = new SampleFormController(); +$sampleFormController = new SampleFormController(new FormResultGateway($con)); $router->map("GET", "/", fn() => $sampleFormController->displayForm()); -$router->map("POST", "/result", fn() => $sampleFormController->displayResults($_POST)); +$router->map("POST", "/submit", fn() => $sampleFormController->submitForm($_POST)); $match = $router->match(); diff --git a/sql/database.php b/sql/database.php new file mode 100644 index 0000000..6fae3ea --- /dev/null +++ b/sql/database.php @@ -0,0 +1,30 @@ +query("SELECT COUNT(*) FROM sqlite_master WHERE type = 'table'")->fetchColumn() > 0; + + if ($database_exists) { + return $pdo; + } + + foreach (scandir(__DIR__) as $file) { + if (preg_match("/.*\.sql$/i", $file)) { + $content = file_get_contents(__DIR__ . "/" . $file); + + $pdo->exec($content); + } + } + + + return $pdo; +} + + + diff --git a/sql/setup-tables.sql b/sql/setup-tables.sql new file mode 100644 index 0000000..0c6fbe7 --- /dev/null +++ b/sql/setup-tables.sql @@ -0,0 +1,8 @@ + +-- drop tables here +DROP TABLE IF EXISTS FormEntries; + +CREATE TABLE FormEntries(name varchar, description varchar); + + + diff --git a/src/Connexion.php b/src/Connexion.php new file mode 100644 index 0000000..c8b4015 --- /dev/null +++ b/src/Connexion.php @@ -0,0 +1,47 @@ +pdo = $pdo; + } + + /** + * execute a request + * @param string $query + * @param array $args + * @return void + */ + public function exec(string $query, array $args) { + $stmnt = $this->pdo->prepare($query); + foreach ($args as $name => $value) { + $stmnt->bindValue($name, $value[0], $value[1]); + } + $stmnt->execute(); + } + + /** + * Execute a request, and return the returned rows + * @param string $query the SQL request + * @param array $args an array containing the arguments label, value and type: ex: `[":label" => [$value, PDO::PARAM_TYPE]` + * @return array the returned rows of the request + */ + public function fetch(string $query, array $args): array { + $stmnt = $this->pdo->prepare($query); + foreach ($args as $name => $value) { + $stmnt->bindValue($name, $value[0], $value[1]); + } + $stmnt->execute(); + return $stmnt->fetchAll(); + } + +} \ No newline at end of file diff --git a/src/Controller/SampleFormController.php b/src/Controller/SampleFormController.php index 5c4dfbd..57625e9 100644 --- a/src/Controller/SampleFormController.php +++ b/src/Controller/SampleFormController.php @@ -3,13 +3,28 @@ namespace App\Controller; require_once __DIR__ . "/../react-display.php"; +use App\Gateway\FormResultGateway; class SampleFormController { + + private FormResultGateway $gateway; + + /** + * @param FormResultGateway $gateway + */ + public function __construct(FormResultGateway $gateway) + { + $this->gateway = $gateway; + } + + public function displayForm() { send_react_front("views/SampleForm.tsx", []); } - public function displayResults(array $request) { - send_react_front("views/DisplayResults.tsx", $request); + public function submitForm(array $request) { + $this->gateway->insert($request["name"], $request["description"]); + $results = ["results" => $this->gateway->listResults()]; + send_react_front("views/DisplayResults.tsx", $results); } } \ No newline at end of file diff --git a/src/Gateway/FormResultGateway.php b/src/Gateway/FormResultGateway.php new file mode 100644 index 0000000..fe0c601 --- /dev/null +++ b/src/Gateway/FormResultGateway.php @@ -0,0 +1,33 @@ +con = $con; + } + + + function insert(string $username, string $description) { + $this->con->exec( + "INSERT INTO FormEntries VALUES (:name, :description)", + [ + ":name" => [$username, PDO::PARAM_STR], + "description" => [$description, PDO::PARAM_STR] + ] + ); + } + + function listResults(): array { + return $this->con->fetch("SELECT * FROM FormEntries", []); + } +} \ No newline at end of file