Skip to content

Commit 8c94507

Browse files
committed
initial commit
0 parents  commit 8c94507

File tree

18 files changed

+805
-0
lines changed

18 files changed

+805
-0
lines changed

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
DB_CONNECTION=mysql
2+
DB_HOST=127.0.0.1
3+
DB_PORT=3306
4+
DB_NAME=user_management
5+
DB_USERNAME=root
6+
DB_PASSWORD=""

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.phpunit.result.cache
2+
composer.lock
3+
phpstan.neon
4+
phpstan.tests.neon
5+
phpunit.xml
6+
vendor
7+
.env
8+
uploads/*

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# php-user-management
2+
A simple CRUD web project for user management.
3+
4+
## Requirements
5+
```
6+
- XAMPP (Apache and MySQL)
7+
- PHP (version 7.0 or higher)
8+
- Composer
9+
```
10+
Leave `XAMPP` up and running after its installation.
11+
12+
## Database
13+
The database requires to be manually setup for this project.
14+
- Access `phpMyAdmin` through `XAMPP` control panel and select the SQL tab.
15+
16+
- Copy the `ddl.sql` file located in the root of this project and paste it at the query box then click on `Execute`.
17+
18+
- Rename the `.env.example` file to `.env`, set your own values to the variables if required.
19+
20+
## Installation
21+
Download the project by visiting the [releases page](https://github.com/PoweredTable/php-user-management/releases) of this repository and unzip the file, or you could also simply clone it.
22+
23+
To work with `XAMPP`, ensure the project will be located at `XAMPP` folder installation, e.g. `C:\xampp\htdocs`.
24+
25+
Inside the project folder, install the required dependencies using `Composer`.
26+
```bash
27+
composer install
28+
```
29+
30+
## Usage
31+
Access the web page through http://localhost/php-user-management.

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"require": {
3+
"vlucas/phpdotenv": "^5.6"
4+
}
5+
}

ddl.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CREATE DATABASE user_management;
2+
3+
USE user_management;
4+
5+
CREATE TABLE IF NOT EXISTS user (
6+
id INT AUTO_INCREMENT PRIMARY KEY,
7+
name VARCHAR(100) NOT NULL,
8+
email VARCHAR(100) NOT NULL UNIQUE,
9+
phone VARCHAR(15) NOT NULL,
10+
photo_name VARCHAR(255) NOT NULL
11+
);

index.php

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
require_once realpath(__DIR__ . "/src/views/components/user-card.php");
3+
require_once realpath(__DIR__ . "/src/controllers/UserController.php");
4+
5+
$ctrl = new UserController();
6+
$users = $ctrl->readAll();
7+
?>
8+
9+
<?php include realpath(__DIR__ . "/src/views/templates/header.php"); ?>
10+
11+
<div class="box1">
12+
<h3>ALL USERS</h3>
13+
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#create-update-modal" data-mode="create" class="btn btn-primary">NEW USER</button>
14+
</div>
15+
<hr>
16+
<div class="row">
17+
<?php
18+
foreach ($users as $user) {
19+
generateUserCard($user->id, $user->name, $user->email, $user->phone, $user->photoName);
20+
}
21+
?>
22+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
23+
<script>
24+
$(document).ready(function() {
25+
// catch modal show event
26+
$("#create-update-modal").on("show.bs.modal", function(event) {
27+
var button = $(event.relatedTarget); // button that triggered the modal
28+
var mode = button.data("mode");
29+
30+
$("#photo").val("");
31+
32+
if (mode === "create") {
33+
$("#user-id").val("");
34+
$("#photo-name").val("")
35+
$("#name").val("");
36+
$("#email").val("");
37+
$("#phone").val("");
38+
} else if (mode === "update") {
39+
var userId = button.data("user-id");
40+
$.ajax({
41+
url: "public/read-user.php",
42+
method: "GET",
43+
data: {
44+
"user-id": userId
45+
},
46+
dataType: "json",
47+
success: function(response) {
48+
$("#user-id").val(response.id);
49+
$("#photo-name").val(response.photoName);
50+
$("#name").val(response.name);
51+
$("#email").val(response.email);
52+
$("#phone").val(response.phone);
53+
},
54+
error: function(xhr, status, error) {
55+
console.error(xhr.responseText);
56+
}
57+
})
58+
}
59+
});
60+
61+
// catch delete button click
62+
$(".delete-user-btn").click(function() {
63+
var userId = $(this).data("user-id");
64+
if (confirm("Are you sure you want to delete this user?")) {
65+
$.ajax({
66+
url: "public/delete-user.php",
67+
type: "GET",
68+
data: {
69+
"user-id": userId
70+
},
71+
success: function(response) {
72+
$('[data-user-id="' + userId + '"]').closest(".col-md-6").remove();
73+
},
74+
error: function(xhr, status, error) {
75+
console.error(xhr.responseText);
76+
}
77+
});
78+
}
79+
});
80+
81+
// catch modal save button click event
82+
$("#save-changes-btn").click(function() {
83+
var form = $("#create-update-modal form")[0];
84+
var formData = new FormData(form);
85+
86+
var fileData = $("#photo").prop("files")[0];
87+
formData.append("photo", fileData)
88+
89+
var userId = $("#user-id").val();
90+
var url = formData.get("user-id") ? "public/update-user.php" : "public/create-user.php"
91+
92+
$.ajax({
93+
url: url,
94+
method: "POST",
95+
cache: false,
96+
processData: false,
97+
contentType: false,
98+
data: formData,
99+
success: function() {
100+
location.reload();
101+
alert("Request successfully executed!")
102+
},
103+
error: function(xhr, status, error) {
104+
alert(xhr.responseText)
105+
}
106+
});
107+
});
108+
109+
});
110+
</script>
111+
<!-- Create/Update User Modal -->
112+
<div class="modal fade" id="create-update-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
113+
<div class="modal-dialog" role="document">
114+
<div class="modal-content">
115+
<div class="modal-header">
116+
<h5 class="modal-title" id="exampleModalLabel">USER DETAILS</h5>
117+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
118+
<span aria-hidden="true">&times;</span>
119+
</button>
120+
</div>
121+
<div class="modal-body">
122+
<form enctype="multipart/form-data">
123+
<input type="hidden" id="user-id" name="user-id" value="">
124+
<input type="hidden" id="photo-name" name="photo-name" value="">
125+
126+
<div class="form-group">
127+
<label for="name">Name</label>
128+
<input type="text" id="name" name="name" class="form-control">
129+
</div>
130+
131+
<div class="form-group">
132+
<label for="email">E-mail</label>
133+
<input type="email" id="email" name="email" class="form-control">
134+
</div>
135+
136+
<div class="form-group">
137+
<label for="phone">Phone</label>
138+
<input type="tel" id="phone" name="phone" class="form-control">
139+
</div>
140+
141+
<div class="form-group">
142+
<label for="photo">Photo</label>
143+
<input type="file" id="photo" name="photo" accept="image/*" class="form-control">
144+
</div>
145+
</form>
146+
</div>
147+
<div class="modal-footer">
148+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
149+
<button type="button" id="save-changes-btn" class="btn btn-primary">Save changes</button>
150+
</div>
151+
</div>
152+
</div>
153+
</div>
154+
<?php include realpath(__DIR__ . "/src/views/templates/footer.php"); ?>

public/create-user.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
require "functions.php";
3+
require_once realpath(__DIR__ . "/../src/controllers/UserController.php");
4+
5+
6+
if ($_SERVER["REQUEST_METHOD"] == "POST") {
7+
$name = $_POST["name"];
8+
$email = $_POST["email"];
9+
$phone = $_POST["phone"];
10+
11+
// check if all fields including the photo were provided
12+
if (empty($name) || empty($email) || empty($phone)) {
13+
http_response_code(400);
14+
echo json_encode(["error" => "Required fields are missing."]);
15+
exit();
16+
} else if (!isset($_FILES["photo"]) || $_FILES["photo"]["error"] !== UPLOAD_ERR_OK) {
17+
http_response_code(400);
18+
echo json_encode(["error" => "An image must be uploaded when creating a user."]);
19+
exit();
20+
}
21+
22+
// sanitizes user input
23+
$name = sanitizeInput($_POST["name"]);
24+
$email = validateEmail($_POST["email"]);
25+
if ($email === false) {
26+
http_response_code(400);
27+
echo json_encode(["error" => "Not a valid email."]);
28+
exit();
29+
}
30+
$phone = sanitizeInput($_POST["phone"]);
31+
32+
// checks if photo is valid
33+
list($ok, $error) = checkImageFile($_FILES["photo"]);
34+
if (!$ok) {
35+
http_response_code(400);
36+
echo json_encode(["error" => $error]);
37+
exit();
38+
}
39+
40+
// uses the e-mail address as the filename
41+
$normalizedEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
42+
$normalizedEmail = preg_replace("/[^a-zA-Z0-9\.]/", "", $normalizedEmail);
43+
$photoName = $normalizedEmail . "." . pathinfo($_FILES["photo"]["name"], PATHINFO_EXTENSION);
44+
45+
$ctrl = new UserController();
46+
47+
try {
48+
$user = $ctrl->create($name, $email, $phone, $photoName);
49+
} catch (Exception $e) {
50+
http_response_code(404);
51+
echo json_encode(["error" => $e->getMessage()]);
52+
exit();
53+
}
54+
55+
$targetDir = "../uploads/" . $user->id . "/";
56+
57+
$uploadedFile = moveFile($_FILES["photo"], $targetDir, $photoName);
58+
if ($uploadedFile && file_exists($uploadedFile)) {
59+
http_response_code(200);
60+
} else {
61+
http_response_code(404);
62+
echo json_encode(["error" => "Couldn't load photo to server."]);
63+
$ctrl->delete($user->id);
64+
deleteUserFolder($user->id);
65+
}
66+
}

public/delete-user.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
require "functions.php";
3+
require_once realpath(__DIR__ . "/../src/controllers/UserController.php");
4+
5+
6+
if ($_SERVER["REQUEST_METHOD"] == "GET") {
7+
if (!isset($_GET["user-id"])) {
8+
http_response_code(400);
9+
echo json_encode(["error" => "User ID parameter missing."]);
10+
exit();
11+
}
12+
$id = $_GET["user-id"];
13+
14+
$ctrl = new UserController();
15+
16+
try {
17+
$ctrl->delete($id);
18+
deleteUserFolder($id);
19+
} catch (Exception $e) {
20+
http_response_code(404);
21+
echo json_encode(["error" => $e->getMessage()]);
22+
exit();
23+
}
24+
}

0 commit comments

Comments
 (0)