Compare commits

...

14 Commits

Author SHA1 Message Date
tracer 5ed539a471 added routes for the addressbook 2022-10-25 15:57:46 +02:00
tracer 5bc0b7966b addressbook seems functional 2022-10-25 15:57:17 +02:00
tracer d0e1d2e87d temporary removed welcome line 2022-10-25 15:56:35 +02:00
tracer 1b794f775d fixed a wrong named variable 2022-10-25 15:53:28 +02:00
tracer 744117d958 added CRUD implementation 2022-10-25 15:52:46 +02:00
tracer cce18f6516 added update() 2022-10-25 15:51:51 +02:00
tracer a973a4362f added AddressBookController 2022-10-25 15:51:23 +02:00
tracer 3bf0c2b44f added error handling 2022-10-25 15:50:57 +02:00
tracer ec022d09e4 added js include 2022-10-25 15:50:25 +02:00
tracer 148eff1557 added js include 2022-10-25 15:48:36 +02:00
tracer ab4a00d25c added router->path() 2022-10-25 15:48:11 +02:00
tracer 753b832cbc inserted addressbook 2022-10-25 15:47:31 +02:00
tracer e5f4656d71 removed header & footer 2022-10-25 15:46:52 +02:00
tracer 117903ac7c finished descending sorting 2022-10-25 15:46:06 +02:00
13 changed files with 232 additions and 79 deletions

View File

@ -1,2 +1,3 @@
As I was not allowed to use any framework, respectively no foreign code, most of the time was spent, well creating some kind of framework myself. :-) As I was not allowed to use any framework, respectively no foreign code, most of the time was spent, well creating some kind of framework myself. :-)
The address book itself was then done in a few hours.

View File

@ -30,8 +30,7 @@ function editAddress(id) {
}) })
}) })
.then( .then(
response => response.text() // .json(), etc. response => response.text()
// same as function(response) {return response.text();}
).then( ).then(
html => console.log(html) html => console.log(html)
); );
@ -58,5 +57,60 @@ function editAddress(id) {
} }
} }
function deleteAddress() { function deleteAddress(id) {
console.log("del")
if (confirm('Are you sure?')) {
const url = "/address/delete";
fetch(url, {
method: "POST",
body: JSON.stringify({
id: id
})
})
.then(
response => response.text()
).then(
html => console.log(html)
);
let row = document.getElementById('row_' + id)
row.parentNode.removeChild(row)
}
}
function sortBy(column) {
console.log("sortby: " + column)
const table = document.getElementById('address_table');
let dirty = true;
// loop until clean
while (dirty) {
console.log('dirty', dirty)
// assume we are finished
dirty = false
const rows = table.rows;
console.log(rows)
for (let i = 1; i < (rows.length - 2); i++) {
let x = rows[i]
let rowXId = x.id
let rowXNumber = rowXId.charAt(rowXId.length -1)
let valueX = document.getElementById(column + '_' + rowXNumber).value
let y = rows[i + 1]
let rowYId = y.id
let rowYNumber = rowYId.charAt(rowYId.length -1)
let valueY = document.getElementById(column + '_' + rowYNumber).value
console.log(valueX, valueY)
// mind asc & desc
let sortOrder = 1
console.log(valueX.localeCompare(valueY))
if (valueX.localeCompare(valueY) === sortOrder) {
console.log('switch A')
// switch rows
x.parentNode.insertBefore(y, x);
dirty = true
}
}
}
} }

View File

@ -64,5 +64,16 @@ $router->addRoute(name: 'app_admin_users_delete', route: '/admin/users/delete/{n
$addressBookAdmin->adminUserDelete(parameters: $parameters); $addressBookAdmin->adminUserDelete(parameters: $parameters);
}); });
$router->addRoute(name: 'address_add', route: '/address/add', callback: function () use ($addressBook) {
$addressBook->addAddress();
});
$router->addRoute(name: 'address_add', route: '/address/update', callback: function () use ($addressBook) {
$addressBook->updateAddress();
});
$router->addRoute(name: 'address_add', route: '/address/delete', callback: function () use ($addressBook) {
$addressBook->deleteAddress();
});
$router->handleRouting(); $router->handleRouting();

View File

@ -13,7 +13,6 @@ use App\Entity\User;
use App\Service\Router; use App\Service\Router;
use App\Service\Template; use App\Service\Template;
use App\Repository\UserRepository; use App\Repository\UserRepository;
use JetBrains\PhpStorm\NoReturn;
class AddressBookAdminController class AddressBookAdminController
{ {
@ -39,7 +38,7 @@ class AddressBookAdminController
public function admin(): never public function admin(): never
{ {
// TODO $this->adminCheck(); $this->adminCheck();
$this->template->render(templateName: 'admin/index.html.php', vars: [ $this->template->render(templateName: 'admin/index.html.php', vars: [
'user' => $this->user, 'user' => $this->user,
'router' => $this->router 'router' => $this->router
@ -49,7 +48,7 @@ class AddressBookAdminController
public function adminUser(): never public function adminUser(): never
{ {
// TODO $this->adminCheck(); $this->adminCheck();
$users = $this->userRepository->findAll(); $users = $this->userRepository->findAll();
@ -62,7 +61,7 @@ class AddressBookAdminController
public function adminUserEdit(array $parameters): never public function adminUserEdit(array $parameters): never
{ {
// TODO $this->adminCheck(); $this->adminCheck();
if (!empty($_POST)) { if (!empty($_POST)) {
if (!empty($_POST['is_admin'])) { if (!empty($_POST['is_admin'])) {
@ -108,8 +107,7 @@ class AddressBookAdminController
// TODO currently breaks on inserting a duplicate nick // TODO currently breaks on inserting a duplicate nick
if (!empty($_POST)) { if (!empty($_POST)) {
$isAdmin = empty($_POST['is_admin']) ? 0 : 1; $isAdmin = empty($_POST['is_admin']) ? 0 : 1;
echo "isA: $isAdmin"; $user = new User(nick: $_POST['nick'], newPassword: $_POST['new_password'], first: $_POST['first'], last: $_POST['last'], isAdmin: $isAdmin);
$user = new User(nick: $_POST['nick'], password: $_POST['password'], first: $_POST['first'], last: $_POST['last'], isAdmin: $isAdmin);
if ($this->userRepository->insert(user: $user)) { if ($this->userRepository->insert(user: $user)) {
$users = $this->userRepository->findAll(); $users = $this->userRepository->findAll();

View File

@ -10,30 +10,78 @@
namespace App\Controller; namespace App\Controller;
use App\Entity\User; use App\Entity\User;
use App\Entity\AddressBookEntry;
use App\Enums\UserAuth;
use App\Service\Router; use App\Service\Router;
use App\Service\Template; use App\Service\Template;
use App\Repository\UserRepository; use App\Repository\AddressRepository;
use JetBrains\PhpStorm\NoReturn;
class AddressBookController class AddressBookController
{ {
public function __construct( public function __construct(
private readonly Template $template, private readonly Template $template,
private readonly User $user, private readonly User $user,
private readonly UserRepository $userRepository, private readonly AddressRepository $addressRepository,
private readonly Router $router private readonly Router $router
) )
{ {
// empty body // empty body
} }
#[NoReturn] public function main(): never
public function main(): void
{ {
if ($this->user->getAuth() != UserAuth::AUTH_ANONYMOUS) {
$addresses = $this->addressRepository->findAll();
}
$this->template->render(templateName: 'index.html.php', vars: [ $this->template->render(templateName: 'index.html.php', vars: [
'user' => $this->user,
'router' => $this->router,
'addresses' => $addresses ?? []
]);
}
public function addAddress(): never
{
if (!empty($_POST)) {
$address = new AddressBookEntry(owner: $_POST['owner'], first: $_POST['first'], last: $_POST['last'], street: $_POST['street'], zip: $_POST['zip'], city: $_POST['city'], phone: $_POST['phone']);
if ($this->addressRepository->insert(address: $address)) {
$addresses = $this->addressRepository->findAll();
$this->template->render(templateName: 'index.html.php', vars: [
'user' => $this->user,
'addresses' => $addresses,
'router' => $this->router
]);
} else {
die("Error inserting user");
}
}
$this->template->render(templateName: 'addressbook/add_address.html.php', vars: [
'user' => $this->user, 'user' => $this->user,
'router' => $this->router 'router' => $this->router
]); ]);
} }
public function updateAddress(): void
{
$_POST = json_decode(json: file_get_contents(filename: "php://input"), associative: true);
$address = new AddressBookEntry(owner: $_POST['owner'], first: $_POST['first'], last: $_POST['last'], street: $_POST['street'], zip: $_POST['zip'], city: $_POST['city'], phone: $_POST['phone'], id: $_POST['id']);
$this->addressRepository->update(address: $address);
}
public function deleteAddress(): void
{
echo "in del";
$_POST = json_decode(json: file_get_contents(filename: "php://input"), associative: true);
if ($address = $this->addressRepository->findByID(id: $_POST['id'])) {
$this->addressRepository->delete(addressBookEntry: $address);
}
}
} }

View File

@ -11,7 +11,6 @@ namespace App\Repository;
use App\Entity\AddressBookEntry; use App\Entity\AddressBookEntry;
use App\Service\DatabaseConnection; use App\Service\DatabaseConnection;
use App\Entity\User;
use PDO; use PDO;
use PDOException; use PDOException;
@ -27,7 +26,6 @@ class AddressRepository
public function findAll(string $orderBy = 'last'): array public function findAll(string $orderBy = 'last'): array
{ {
$users = [];
$sql = " $sql = "
SELECT id, owner, first, last, street, zip, city, phone SELECT id, owner, first, last, street, zip, city, phone
FROM " . DatabaseConnection::TABLE_ADDRESSES . " FROM " . DatabaseConnection::TABLE_ADDRESSES . "
@ -54,7 +52,7 @@ class AddressRepository
{ {
$sql = " $sql = "
SELECT id, owner, first, last, street, zip, city, phone SELECT id, owner, first, last, street, zip, city, phone
FROM " . DatabaseConnection::TABLE_USERS . " FROM " . DatabaseConnection::TABLE_ADDRESSES . "
WHERE id = :id"; WHERE id = :id";
try { try {
@ -104,39 +102,36 @@ class AddressRepository
} }
public function update(Address $address): bool|int public function update(AddressBookEntry $address): bool|int
{ {
/* $id = $address->getId();
$id = $user->getId(); $owner = $address->getOwner();
$nick = $user->getNick(); $first = $address->getFirst();
$first = $user->getFirst(); $last = $address->getLast();
$last = $user->getLast(); $street = $address->getStreet();
$isAdmin = $user->isAdmin() ? 1 : 0; $zip = $address->getZip();
$city = $address->getCity();
if ($user->getPassword()) { $phone = $address->getPhone();
$password = $user->getPassword();
} else {
$current = $this->findByID(id: $id);
$password = $current->getPassword();
}
$sql = " $sql = "
UPDATE " . DatabaseConnection::TABLE_USERS . " SET UPDATE " . DatabaseConnection::TABLE_ADDRESSES . " SET
nick = :nick,
password = :password,
first = :first, first = :first,
last = :last, last = :last,
is_admin = :is_admin street = :street,
zip = :zip,
city = :city,
phone = :phone
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id); $statement->bindParam(param: 'id', var: $id);
$statement->bindParam(param: 'nick', var: $nick);
$statement->bindParam(param: 'password', var: $password);
$statement->bindParam(param: 'first', var: $first); $statement->bindParam(param: 'first', var: $first);
$statement->bindParam(param: 'last', var: $last); $statement->bindParam(param: 'last', var: $last);
$statement->bindParam(param: 'is_admin', var: $isAdmin); $statement->bindParam(param: 'street', var: $street);
$statement->bindParam(param: 'zip', var: $zip);
$statement->bindParam(param: 'city', var: $city);
$statement->bindParam(param: 'phone', var: $phone);
$statement->execute(); $statement->execute();
return $statement->rowCount(); return $statement->rowCount();
@ -144,8 +139,6 @@ class AddressRepository
echo $e->getMessage(); echo $e->getMessage();
return false; return false;
} }
*/
return false;
} }

View File

@ -13,6 +13,7 @@ use App\Controller\AddressBookAdminController;
use App\Controller\AddressBookController; use App\Controller\AddressBookController;
use App\Controller\SecurityController; use App\Controller\SecurityController;
use App\Entity\User; use App\Entity\User;
use App\Repository\AddressRepository;
use App\Repository\UserRepository; use App\Repository\UserRepository;
/* /*
@ -26,6 +27,7 @@ class Container
private AddressBookController $addressBook; private AddressBookController $addressBook;
private AddressBookAdminController $addressBookAdmin; private AddressBookAdminController $addressBookAdmin;
private AddressRepository $addressRepository;
private Config $config; private Config $config;
private DatabaseConnection $databaseConnection; private DatabaseConnection $databaseConnection;
private Router $router; private Router $router;
@ -41,13 +43,14 @@ class Container
$this->template = new Template(templateDir: dirname(path: __DIR__, levels: 2) . '/templates/'); $this->template = new Template(templateDir: dirname(path: __DIR__, levels: 2) . '/templates/');
$this->router = new Router(template: $this->template); $this->router = new Router(template: $this->template);
$this->userRepository = new UserRepository(databaseConnection: $this->databaseConnection); $this->userRepository = new UserRepository(databaseConnection: $this->databaseConnection);
$this->addressRepository = new AddressRepository(databaseConnection: $this->databaseConnection);
$this->securityController = new SecurityController(template: $this->template, userRepository: $this->userRepository, router: $this->router); $this->securityController = new SecurityController(template: $this->template, userRepository: $this->userRepository, router: $this->router);
if (empty($_SESSION['user_id'])) { if (empty($_SESSION['user_id'])) {
$this->user = new User(); // ANONYMOUS $this->user = new User(); // ANONYMOUS
} else { } else {
$this->user = $this->userRepository->findByID(id: $_SESSION['user_id']); $this->user = $this->userRepository->findByID(id: $_SESSION['user_id']);
} }
$this->addressBook = new AddressBookController(template: $this->template, user: $this->user, userRepository: $this->userRepository, router: $this->router); $this->addressBook = new AddressBookController(template: $this->template, user: $this->user, addressRepository: $this->addressRepository, router: $this->router);
$this->addressBookAdmin = new AddressBookAdminController(template: $this->template, user: $this->user, userRepository: $this->userRepository, router: $this->router); $this->addressBookAdmin = new AddressBookAdminController(template: $this->template, user: $this->user, userRepository: $this->userRepository, router: $this->router);
} }

View File

@ -36,6 +36,7 @@ class DatabaseConnection
username: $dbUser, username: $dbUser,
password: $dbPassword password: $dbPassword
); );
$this->dbConnection->setAttribute(attribute: PDO::ATTR_ERRMODE, value: PDO::ERRMODE_EXCEPTION);
} }
public function getConnection(): PDO public function getConnection(): PDO

View File

@ -107,7 +107,7 @@ class Router
if ($route->getName() == $routeName) { if ($route->getName() == $routeName) {
if ($vars) { if ($vars) {
// build route // build route for dynamic routes
$route = $route->getRoute(); $route = $route->getRoute();
// replace placeholder with current values // replace placeholder with current values
foreach ($vars as $key => $value) { foreach ($vars as $key => $value) {
@ -120,6 +120,15 @@ class Router
} }
} }
// no 404, this is reached only if the code is wrong // no 404, this is reached only if the code is wrong
// TODO doesn't find the last route
/*
foreach (array_merge($this->dynamicRoutes, $this->staticRoutes) as $route) {
echo $route->getRoute() . '<br>';
if ($routeName == $route->getRoute()) {
echo "equal";
}
}
die("Missing Route: $routeName"); die("Missing Route: $routeName");
*/
} }
} }

View File

@ -1,3 +1,3 @@
<!-- mind the javascript --> <script src="/assets/js/functions.js"></script>
</body> </body>
</html> </html>

View File

@ -1,32 +1,24 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>Address Book <title>Address Book
<?php if (!empty($user)): ?> <?php if (!empty($user->getNick())): ?>
&nbsp;-&nbsp;<?= $user->getNick() ?> &nbsp;-&nbsp;<?= $user->getNick() ?>
<?php endif; ?> <?php endif; ?>
</title> </title>
<link rel="stylesheet" href="/assets/styles/main.css"> <link rel="stylesheet" href="/assets/styles/main.css">
</head> </head>
<body> <body>
<h1>Address Book</h1> <h1>Address Book</h1>
<a href="<?= $router->path('app_main'); ?>">🏠 Home</a> <a href="<?= $router->path('app_main'); ?>">🏠 Home</a>
<a href="<?= $router->path('app_admin'); ?>"> Admin</a> <a href="<?= $router->path('app_admin'); ?>"> Admin</a>
<?php if (empty($user) || $user->getAuth() == \App\Enums\UserAuth::AUTH_ANONYMOUS): ?> <?php if (empty($user) || $user->getAuth() == \App\Enums\UserAuth::AUTH_ANONYMOUS): ?>
<a href="/login">🚪Login</a> <a href="<?= $router->path('app_login'); ?>">🚪Login</a>
<?php else: ?> <?php else: ?>
<a href="/logout">🚪Logout</a> <a href="<?= $router->path('app_logout'); ?>">🚪Logout</a>
<?php endif; ?> <?php endif; ?>
<?php <?php if (!empty($user->getNick())): ?>
if ($user->getAuth() == \App\Enums\UserAuth::AUTH_ANONYMOUS) {
echo "no";
} else {
echo "yes";
}
?>
<?php if (!empty($user) && !$user->getAuth() == \App\Enums\UserAuth::AUTH_ANONYMOUS): ?>
<br> <br>
Welcome back, <?= $user->getNick(); ?> <-- TODO fix for anonymous Welcome back, <?= $user->getNick(); ?> -->
<?php endif; ?> <?php endif; ?>
<br> <br>

View File

@ -1,9 +1,54 @@
<?php include '_header.html.php' ?> <?php include '_header.html.php' ?>
<br> <br>
Welcome to Address Book <h2>Welcome to Address Book</h2>
<?php if(!empty($addresses)): ?>
<form method="POST">
<table id="address_table">
<tr>
<th id="first" onclick="sortBy('first')">First</th>
<th id="last" onclick="sortBy('last')">Last</th>
<th id="street" onclick="sortBy('street')">Street</th>
<th id="zip" onclick="sortBy('zip')">Zip</th>
<th id="city" onclick="sortBy('city')">City</th>
<th id="phone" onclick="sortBy('phone')">Phone</th>
<th colspan="2">&nbsp;</th>
</tr>
<?php foreach ($addresses as $address): ?>
<?php $id = $address->getId(); ?>
<tr id="row_<?= $id ?>">
<td><input type="text" id="first_<?= $id ?>" value="<?= $address->getFirst(); ?>" disabled></td>
<td><input type="text" id="last_<?= $id ?>" value="<?= $address->getLast(); ?>" disabled></td>
<td><input type="text" id="street_<?= $id ?>" value="<?= $address->getStreet(); ?>" disabled></td>
<td><input type="text" id="zip_<?= $id ?>" value="<?= $address->getZip(); ?>" disabled></td>
<td><input type="text" id="city_<?= $id ?>" value="<?= $address->getCity(); ?>" disabled></td>
<td><input type="text" id="phone_<?= $id ?>" value="<?= $address->getPhone(); ?>" disabled></td>
<td>
<input type="button" value="Edit" id="edit_button_<?= $id ?>" onclick="editAddress(<?= $id ?>)">
</td>
<td>
<input type="button" value="Delete" onclick="deleteAddress(<?= $id ?>)">
<input type="hidden" id="owner_<?= $id ?>" value="<?= $id ?>">
</td>
</tr>
<?php endforeach; ?>
<tr style="display:none;">
<td id="first_sort">asc</td>
<td id="last_sort">asc</td>
<td id="street_sort">asc</td>
<td id="zip_sort">asc</td>
<td id="city_sort">asc</td>
<td id="phone_sort">asc</td>
</tr>
</table>
</form>
<!-- TODO why is the route not found? $addPath = $router->path('/address/add'); -->
<input type="button" value="Add Address" onclick="addAddress('address/add')">
<?php else: ?>
Your addresses wil be listed soon Your addresses wil be listed soon
<?php endif; ?>
<?php include '_footer.html.php' ?> <?php include '_footer.html.php' ?>

View File

@ -1,5 +1,3 @@
<?php include dirname(path: __DIR__) . '/_header.html.php'; ?>
<h2>404 Page not found</h2> <h2>404 Page not found</h2>
<?php include dirname(path: __DIR__) . '/_footer.html.php' ?> The requested URL cannot be found on this server.