Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
43 views28 pages

PHP Demo Project Docu

Uploaded by

hwangyeji1916
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views28 pages

PHP Demo Project Docu

Uploaded by

hwangyeji1916
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

PHP DEMO

A Project Study Presented to the


School of Architecture, Computing and Engineering
National University Philippines
Lipa City

In Partial Fulfillment of the Requirement for the Courses:


CTADVDBL: Advanced Database System
CTWBDEVL: Web Systems and Technologies

By:
Jei Q. Pastrana

June 5, 2024
Table of Contents
1. Overview
o Sitemap Diagram
2. Processes
o User Flow
o System Architecture
3. Database Design
o ER Diagram
o Schema Description
o Relation Schema and SQL Implementation of the Design
4. Code Logic
o Directory Structure
o Core Modules
o API Documentation
o JavaScript Embedded Codes
o PHP Scripts
o Database Class
5. Testing
o Test Cases
1. Overview
This project is a PHP-based demo application designed to illustrate basic web development
concepts. It includes features such as user registration, login, course enrollment, and data fetching. The
application uses MySQL for database management and Bootstrap for frontend styling.

1.1 Sitemap Diagram

Figure 1. Site Map Diagram

1. Registration Page (register.php)


• Accessible only to authenticated users (checked via session).
• Form to create a new user account.
• Validates and saves user data and profile picture.
• Redirects to home page upon successful registration.

2. Login Page (login.php)


• Entry point for users to log in.
• Authenticates user credentials.
• Redirects based on account type:
§ Home Page (index.php) for admin.
§ User Account Page (user_account.php) for regular users.

3. Home Page (index.php)


• Accessible after successful login based on account type.
• Displays user-specific content.

4. User Account Page (user_account.php)


• Accessible only to logged-in regular users.
• Displays and allows updating of user information.
• Separate sections for updating password and address.
• Validates and saves updated information.

5. Backend Scripts and JSON Files


• check_username.php: Validates if the username is already taken.
• check_email.php: Validates if the email is already taken.
• ph-json/region.json: Contains region data.
• ph-json/province.json: Contains province data.
• ph-json/city.json: Contains city data.
• ph-json/barangay.json: Contains barangay data.
2. Processes
2.1 User Flow
User Registration
Process Description
1. Form Submission User submits the registration form with details.
2. Validation All submitted details will be validated using different scripts.
Insert valid data into the users table and address table using the
3. Database Insertion
signupUser and insertAddress methods.
4. Confirmation User receives a registration confirmation.
Table 1. User Registration

Login
Process Description
1. Form Submission User submits login credentials.
2. Validation Check credentials against the database.
3. Session Creation Create a session for authenticated users.
4. Redirection Redirect to the user dashboard if account_type = 0 and to the admin
dashboard if account_type = 1.
Table 2. Login

Course Enrollment
Process Description
1. Course Listing User submits login credentials.
2. Enrollment Check credentials against the database.
3. Database Update Create a session for authenticated users.
4. Confirmation Redirect to the user dashboard if account_type = 0 and to the admin
dashboard if account_type = 1.
Table 3. Course Enrollment

Data Fetching
Process Description
1. User Data Fetch and display user-specific data with the use of viewdata($id)
mthod.
2. Course Data Fetch and display course details.
Table 4. Data Fetching

2.2 System Architecture

A. Client-Side
• Technologies: HTML, CSS, JavaScript
• Libraries: Bootstrap for styling

B. Server-Side
• Language: PHP
• Frameworks: None

C. Database
• Type: MySQL
• Management Tools: phpMyAdmin for database management
3. Database Design

3.1 Entity Relationship Diagram (Logical Level)

Figure 2. Logical Level

3.2 Entity Relationship Diagram (Physical Level)

Figure 2. Physical Level

3.3 Relation Schema and SQL Implementation of the Design

1. Relation: Users
Attributes:
• user_id
• user_firstname (INT, Primary Key)
• user_lastname (VarChar 255)
• user_sex (VarChar 255)
• user_email (VarChar 255)
• user_name (VarChar 255)
• user_pass (VarChar 255)
• user_profile_picture (VarChar 255)
• account_type (VarChar 255)
Constraints:
• Primary Key: user_id
SQL Query

-- Create the users table


CREATE TABLE users (
user_id INT(11) AUTO_INCREMENT PRIMARY KEY,
user_firstname VARCHAR(255) NOT NULL,
user_lastname VARCHAR(255) NOT NULL,
user_birthday DATE NOT NULL,
user_sex VARCHAR(255) NOT NULL,
user_email VARCHAR(255) NOT NULL,
user_name VARCHAR(255),
user_pass VARCHAR(255),
user_profile_picture VARCHAR(255) NOT NULL
);

2. Relation: User_Address
Attributes:
• address_id
• user_id (INT, Primary Key)
• street (VarChar 255)
• barangay (VarChar 255)
• city VarChar 255)
• province (VarChar 255)

Constraints:
• Primary Key: address_id
• Foreign Key: user_id references Users(user_id)
SQL Query

-- Create the user_address table


CREATE TABLE user_address (
address_id INT(11) AUTO_INCREMENT PRIMARY KEY,
user_id INT(11),
street VARCHAR(255) NOT NULL,
barangay VARCHAR(255) NOT NULL,
city VARCHAR(255),
province VARCHAR(255),
FOREIGN KEY (user_id) REFERENCES users(user_id)ON
UPDATE RESTRICT ON DELETE RESTRICT
);

4. Code Logic

4.1 Directory Structure

/phpdemo
/bootstrap-4.5.3-dist
/bootstrap-5.3.3-dist
/classes
/includes
/ph-json
/uploads
check_email.php
check_file_size.php
...
userinfo.php

4.2 Core Modules


1. Register Page (register.php)
The register page facilitates user sign-up by collecting account, personal, and address
information. Upon submission, it handles file uploads for profile pictures, ensuring they meet specified
criteria (e.g., file type and size). User data is securely stored in the database using prepared statements,
and the user's address is recorded separately. It incorporates a session check to verify if the user is
logged in, redirecting unauthorized access to the login page.

2. Login Page (login.php)


The login page handles user authentication by verifying the provided credentials against stored
records. Upon successful login, user session variables are set, and the user is redirected based on their
account type: either to the main page for admins or to the user account page for regular users. The page
also includes error handling for incorrect login attempts and ensures users cannot access it if they are
already logged in.

3. User Account Page (user_account.php)


The user account page allows logged-in users to view and update their personal details, including
their address and password. It ensures only authorized users with a specific account type can access it.
Users can update their passwords, with checks to ensure new passwords meet security requirements
and match confirmation inputs. Address updates are similarly validated and saved to the database. Each
update action provides feedback via URL parameters.

4. Username and Email Validation


These scripts dynamically validate username and email availability during user registration.
When a user inputs data into the respective fields, an AJAX request is sent to either check_username.php
or check_email.php. The server responds with a JSON object indicating if the username or email already
exists. Based on this response, the input field is visually marked as valid or invalid, and the Next button
is enabled or disabled accordingly. This real-time feedback ensures that users can only proceed with
unique and valid usernames and emails.

5. Multi-step Form Management


The multi-step form script manages user navigation through a multi-step registration process. It
validates each step before allowing the user to proceed. The script checks inputs for validity, including
custom validation for passwords (requiring a mix of uppercase, lowercase, digits, and special characters)
and password confirmation. If any input fails validation, the user is prevented from moving to the next
step. The form’s submission is also intercepted to ensure all steps are validated, improving data integrity
and user experience.

6. Dynamic Address Form Population


This script dynamically populates address fields based on user selections. When a region is
selected, an AJAX request fetches the corresponding provinces from province.json, which are then
populated in the province dropdown. Similarly, selecting a province populates the city dropdown from
city.json, and selecting a city fills the barangay dropdown from barangay.json. Each dropdown update is
accompanied by clearing and resetting dependent fields to maintain data consistency. This dynamic
population ensures accurate and relevant address information, reducing user input errors.

4.3 API Documentation


The project includes several PHP scripts that function as APIs to handle various tasks such as user
registration, authentication, file uploads, and data retrieval. Each API accepts specific HTTP requests
and returns JSON responses to facilitate interaction with the frontend.

API Endpoint check_email.php


Description Checks if an email is already registered in the users table.
Method POST
Request Parameters email (string): The email address to look.
Response exists (boolean): true if the email exists, false otherwise

Code Snippet:
<?php
require_once('classes/database.php');

if (isset($_POST['email'])) {
$email = $_POST['email'];
$con = new database();
$query = $con->opencon()->prepare("SELECT user_email FROM users WHERE
user_email = ?");
$query->execute([$email]);
$existingUser = $query->fetch();

if ($existingUser) {
echo json_encode(['exists' => true]);
} else {
echo json_encode(['exists' => false]);
}
}
?>

API Endpoint check_file_size.php


Description Validates the size of an uploaded file.
Method POST
Request Parameters profile_picture (file): The file to check.
error (string, optional): Error message if the file size exceeds the limit or no
Response file is uploaded.
success (string, optional): Success message if the file size is within the limit.

Code:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if(isset($_FILES["profile_picture"])) {
$file_size = $_FILES["profile_picture"]["size"];
if ($file_size > 500000) {
echo json_encode(array("error" => "File size exceeds 500KB limit."));
} else {
echo json_encode(array("success" => "File size is within the limit."));
}
} else {
echo json_encode(array("error" => "No file uploaded."));
}
} else {
echo json_encode(array("error" => "Invalid request."));
}
?>

API Endpoint check_password.php


Description Validates the current password of the logged-in user.
Method POST
Request Parameters current_password (string): The current password of the user.
valid (boolean): true if the password is correct, false otherwise.
Response
error (string, optional): Error message if the current password is not provided.

Code:
<?php
session_start();
require_once('classes/database.php');

header('Content-Type: application/json');

if (isset($_POST['current_password'])) {
$currentPassword = $_POST['current_password'];
$userId = $_SESSION['user_id'];

$con = new database();


$isValid = $con->validateCurrentPassword($userId, $currentPassword);

echo json_encode(['valid' => $isValid]);


exit;
} else {
echo json_encode(['valid' => false, 'error' => 'Current password not
provided']);
exit;
}
?>

API Endpoint live_search.php


Description Searches for users based on the given search term and returns the results.
Method POST
Request Parameters search (string): The search term to use for finding users.
Response HTML table rows containing user information matching the search term.

Code:
<?php
require_once('classes/database.php');

if ($_SERVER["REQUEST_METHOD"] === "POST") {


if (isset($_POST['search'])) {
$searchterm = $_POST['search'];
$con = new database();

try {
$connection = $con->opencon();

if ($connection) {
$query = $connection->prepare("SELECT users.user_id,
users.user_firstname, users.user_lastname, users.user_birthday, users.user_sex,
users.user_name, users.user_profile_picture, CONCAT(user_address.city,', ',
user_address.province) AS address FROM users INNER JOIN user_address ON
users.user_id = user_address.user_id WHERE users.user_name LIKE ? OR users.user_id
LIKE ? OR CONCAT(user_address.city,', ', user_address.province) LIKE ? ");
$query->execute(["%$searchterm%","%$searchterm%","%$searchterm%"]);
$users = $query->fetchAll(PDO::FETCH_ASSOC);

$html = '';
foreach ($users as $user) {
$html .= '<tr>';
$html .= '<td>' . $user['user_id'] . '</td>';
$html .= '<td><img src="' .
htmlspecialchars($user['user_profile_picture']) . '" alt="Profile Picture"
style="width: 50px; height: 50px; border-radius: 50%;"></td>';
$html .= '<td>' . $user['user_firstname'] . '</td>';
$html .= '<td>' . $user['user_lastname'] . '</td>';
$html .= '<td>' . $user['user_birthday'] . '</td>';
$html .= '<td>' . $user['user_sex'] . '</td>';
$html .= '<td>' . $user['user_name'] . '</td>';
$html .= '<td>' . $user['address'] . '</td>';
$html .= '<td>';
$html .= '<form action="update.php" method="post"
style="display: inline;">';
$html .= '<input type="hidden" name="id" value="' .
$user['user_id'] . '">';
$html .= '<button type="submit" class="btn btn-primary btn-
sm">Edit</button>';
$html .= '</form>';
$html .= '<form method="POST" style="display: inline;">';
$html .= '<input type="hidden" name="id" value="' .
$user['user_id'] . '">';
$html .= '<input type="submit" name="delete" class="btn btn-
danger btn-sm" value="Delete" onclick="return confirm(\'Are you sure you want to
delete this user?\')">';
$html .= '</form>';
$html .= '</td>';
$html .= '</tr>';
}
echo $html;
} else {
echo json_encode(['error' => 'Database connection failed.']);
}
} catch (PDOException $e) {
echo json_encode(['error' => $e->getMessage()]);
}
} else {
echo json_encode(['error' => 'No search query provided.']);
}
}
?>

API Endpoint process_course.php


Manages selected courses, including adding, removing, and saving course
Description
enrollments.
Method POST
action (string): The action to perform (add, remove, save).
Request Parameters
course_id (int, optional): The course ID for add and remove actions.
status (string): success if the action is completed.
Response
error (string, optional): Error message if the database connection fails.

<script>
<?php
session_start();
require_once('classes/database.php');

$con = new database();

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$connection = $con->opencon();
if (!$connection) {
echo json_encode(['error' => 'Database connection failed.']);
exit;
}

$action = $_POST['action'];
$courseId = isset($_POST['course_id']) ? (int)$_POST['course_id'] : 0;

switch ($action) {
case 'add':
if (!in_array($courseId, $_SESSION['selected_courses'])) {
$_SESSION['selected_courses'][] = $courseId;
}
break;

case 'remove':
if (($key = array_search($courseId, $_SESSION['selected_courses'])) !==
false) {
unset($_SESSION['selected_courses'][$key]);
}
break;

case 'save':
$userId = $_SESSION['user_id'];

foreach ($_SESSION['selected_courses'] as $courseId) {


$query = $connection->prepare("INSERT INTO enrollments (user_id,
course_id) VALUES (:user_id, :course_id)");
$query->bindParam(':user_id', $userId, PDO::PARAM_INT);
$query->bindParam(':course_id', $courseId, PDO::PARAM_INT);
$query->execute();
}
// Clear selected courses after saving
$_SESSION['selected_courses'] = [];
break;
}

echo json_encode

4.4 JavaScript Embedded Scripts


These scripts enhance user registration and form handling by providing real-time validation and
dynamic form updates.

Script AJAX for Username Availability Check


Description This script checks the availability of the entered username in real-time.
Usage Triggered when the user inputs a username. Sends an AJAX request to
check_username.php to verify if the username is taken.

<script>
$(document).ready(function(){
$('#username').on('input', function(){
var username = $(this).val();
if(username.length > 0) {
$.ajax({
url: 'check_username.php',
method: 'POST',
data: {username: username},
dataType: 'json',
success: function(response) {
if(response.exists) {
$('#username').removeClass('is-valid').addClass('is-
invalid');
$('#usernameFeedback').text('Username is already taken.');
$('#nextButton').prop('disabled', true); // Disable the
Next button
} else {
$('#username').removeClass('is-invalid').addClass('is-
valid');
$('#usernameFeedback').text('');
$('#nextButton').prop('disabled', false); // Enable the
Next button
}
}
});
} else {
$('#username').removeClass('is-valid is-invalid');
$('#usernameFeedback').text('');
$('#nextButton').prop('disabled', false); // Enable the Next button if
username is empty
}
});
});

Script AJAX for Email Availability Check


Description This script checks the availability of the entered email in real-time.
Usage Triggered when the user inputs an email. Sends an AJAX request to
check_email.php to verify if the email is taken.

<script>
$(document).ready(function(){
$('#email').on('input', function(){
var email = $(this).val();
if(email.length > 0) {
$.ajax({
url: 'check_email.php',
method: 'POST',
data: {email: email},
dataType: 'json',
success: function(response) {
if(response.exists) {
$('#email').removeClass('is-valid').addClass('is-invalid');
$('#emailFeedback').text('Email is already taken.');
$('#nextButton').prop('disabled', true); // Disable the
Next button
} else {
$('#email').removeClass('is-invalid').addClass('is-valid');
$('#emailFeedback').text('');
$('#nextButton').prop('disabled', false); // Enable the
Next button
}
},
error: function(xhr, status, error) {
console.error('AJAX Error:', status, error);
}
});
} else {
$('#email').removeClass('is-valid is-invalid');
$('#emailFeedback').text('');
$('#nextButton').prop('disabled', false); // Enable the Next button if
email is empty
}
});
});

Script Form Validation and MultiStep Logic


Description This script handles form validation and controls the multi-step form navigation.
Usage Validates inputs on-the-fly, moves between form steps, and ensures all required
fields are valid before proceeding.

<script>
document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector("form");
const birthdayInput = document.getElementById("birthday");
const steps = document.querySelectorAll(".form-step");
let currentStep = 0;

const today = new Date().toISOString().split('T')[0];


birthdayInput.setAttribute('max', today);

const inputs = form.querySelectorAll("input, select");


inputs.forEach(input => {
input.addEventListener("input", () => validateInput(input));
input.addEventListener("change", () => validateInput(input));
});

form.addEventListener("submit", (event) => {


if (!validateStep(currentStep)) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add("was-validated");
}, false);

window.nextStep = () => {
if (validateStep(currentStep)) {
steps[currentStep].classList.remove("form-step-active");
currentStep++;
steps[currentStep].classList.add("form-step-active");
}
};

window.prevStep = () => {
steps[currentStep].classList.remove("form-step-active");
currentStep--;
steps[currentStep].classList.add("form-step-active");
};

function validateStep(step) {
let valid = true;
const stepInputs = steps[step].querySelectorAll("input, select");
stepInputs.forEach(input => {
if (!validateInput(input)) {
valid = false;
}
});
return valid;
}

function validateInput(input) {
if (input.name === 'password') {
return validatePassword(input);
} else if (input.name === 'confirmPassword') {
return validateConfirmPassword(input);
} else {
if (input.checkValidity()) {
input.classList.remove("is-invalid");
input.classList.add("is-valid");
return true;
} else {
input.classList.remove("is-valid");
input.classList.add("is-invalid");
return false;
}
}
}

function validatePassword(passwordInput) {
const password = passwordInput.value;
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/;
if (regex.test(password)) {
passwordInput.classList.remove("is-invalid");
passwordInput.classList.add("is-valid");
return true;
} else {
passwordInput.classList.remove("is-valid");
passwordInput.classList.add("is-invalid");
return false;
}
}

function validateConfirmPassword(confirmPasswordInput) {
const passwordInput = form.querySelector("input[name='password']");
const password = passwordInput.value;
const confirmPassword = confirmPasswordInput.value;

if (password === confirmPassword && password !== '') {


confirmPasswordInput.classList.remove("is-invalid");
confirmPasswordInput.classList.add("is-valid");
return true;
} else {
confirmPasswordInput.classList.remove("is-valid");
confirmPasswordInput.classList.add("is-invalid");
return false;
}
}

document.addEventListener("keydown", (event) => {


if (event.key === 'Enter') {
event.preventDefault();
}
});
});

Script PH Address Selector


Description Handles the dynamic loading and updating of address fields (region, province, city,
barangay) based on the selected values.

<script>
var my_handlers = {
// fill province
fill_provinces: function() {
//selected region
var region_code = $(this).val();
// set selected text to input
var region_text = $(this).find("option:selected").text();
let region_input = $('#region-text');
region_input.val(region_text);
//clear province & city & barangay input
$('#province-text').val('');
$('#city-text').val('');
$('#barangay-text').val('');

//province
let dropdown = $('#province');
dropdown.empty();
// dropdown.append('<option selected="true" disabled>Choose
State/Province</option>');
dropdown.prop('selectedIndex', 0);

//city
let city = $('#city');
city.empty();
city.append('<option selected="true" disabled></option>');
city.prop('selectedIndex', 0);

//barangay
let barangay = $('#barangay');
barangay.empty();
barangay.append('<option selected="true" disabled></option>');
barangay.prop('selectedIndex', 0);

// filter & fill


var url = 'ph-json/province.json';
$.getJSON(url, function(data) {
var result = data.filter(function(value) {
return value.region_code == region_code;
});

result.sort(function(a, b) {
return a.province_name.localeCompare(b.province_name);
});

$.each(result, function(key, entry) {


dropdown.append($('<option></option>').attr('value',
entry.province_code).text(entry.province_name));
})

});
},

//added selector
// fill city
fill_cities: function() {
//selected province
var province_code = $(this).val();

// set selected text to input


var province_text = $(this).find("option:selected").text();
let province_input = $('#province-text');
province_input.val(province_text);
//clear city & barangay input
$('#city-text').val('');
$('#barangay-text').val('');

//city
let dropdown = $('#city');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose
city/municipality</option>');
dropdown.prop('selectedIndex', 0);

//barangay
let barangay = $('#barangay');
barangay.empty();
barangay.append('<option selected="true" disabled></option>');
barangay.prop('selectedIndex', 0);

// filter & fill


var url = 'ph-json/city.json';
$.getJSON(url, function(data) {
var result = data.filter(function(value) {
return value.province_code == province_code;
});

result.sort(function(a, b) {
return a.city_name.localeCompare(b.city_name);
});

$.each(result, function(key, entry) {


dropdown.append($('<option></option>').attr('value',
entry.city_code).text(entry.city_name));
})

});
},
// fill barangay
fill_barangays: function() {
// selected barangay
var city_code = $(this).val();

// set selected text to input


var city_text = $(this).find("option:selected").text();
let city_input = $('#city-text');
city_input.val(city_text);
//clear barangay input
$('#barangay-text').val('');

// barangay
let dropdown = $('#barangay');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose
barangay</option>');
dropdown.prop('selectedIndex', 0);

// filter & Fill


var url = 'ph-json/barangay.json';
$.getJSON(url, function(data) {
var result = data.filter(function(value) {
return value.city_code == city_code;
});

result.sort(function(a, b) {
return a.brgy_name.localeCompare(b.brgy_name);
});

$.each(result, function(key, entry) {


dropdown.append($('<option></option>').attr('value',
entry.brgy_code).text(entry.brgy_name));
})

});
},

onchange_barangay: function() {
// set selected text to input
var barangay_text = $(this).find("option:selected").text();
let barangay_input = $('#barangay-text');
barangay_input.val(barangay_text);
},

};

$(function() {
// events
$('#region').on('change', my_handlers.fill_provinces);
$('#province').on('change', my_handlers.fill_cities);
$('#city').on('change', my_handlers.fill_barangays);
$('#barangay').on('change', my_handlers.onchange_barangay);

// load region
let dropdown = $('#region');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose Region</option>');
dropdown.prop('selectedIndex', 0);
const url = 'ph-json/region.json';
// Populate dropdown with list of regions
$.getJSON(url, function(data) {
$.each(data, function(key, entry) {
dropdown.append($('<option></option>').attr('value',
entry.region_code).text(entry.region_name));
})
});

});

4.5 PHP Scripts

Page login.php
This script handles user login, session management, and redirects
Usage
users to a certain page based on account type.
Code
require_once('classes/database.php');
Includes the database class $con = new database();
and starts a session. session_start();
if (isset($_SESSION['username']) &&
isset($_SESSION['account_type'])) {
if ($_SESSION['account_type'] == 0) {
Redirects users if they are header('location:index.php');
already logged in based on } else if ($_SESSION['account_type'] == 1) {
header('location:user_account.php');
their account type.
exit();
}
$error = ""; // Initialize error variable

if (isset($_POST['login'])) {
$username = $_POST['user'];
$password = $_POST['pass'];
$result = $con->check($username, $password);

if ($result) {
$_SESSION['username'] = $result['user_name'];
$_SESSION['account_type'] =
$result['account_type'];
Validates login credentials, $_SESSION['user_id'] = $result['user_id'];
starts a session, and redirects $_SESSION['profilepicture'] =
$result['user_profile_picture'];
based on account type. if ($result['account_type'] == 0) {
header('location:index.php');
} else if ($result['account_type'] == 1) {
header('location:user_account.php');
}
exit();
} else {
$error = "Incorrect username or password. Please
try again.";
}
}

Page user_account.php
This script allows logged-in users to update their password and
Usage
address.
Code
require_once('classes/database.php');
$con = new Database();
session_start();
Starts a session, checks if the
if (!isset($_SESSION['username']) ||
user is logged in, and retrieves $_SESSION['account_type'] != 1) {
user data. header('location:login.php');
exit();
}
$id = $_SESSION['user_id'];
$data = $con->viewdata($id);

if (isset($_POST['updatepassword'])) {
$userId = $_SESSION['user_id'];
$currentPassword = $_POST['current_password'];
$newPassword = $_POST['new_password'];
$confirmPassword = $_POST['confirm_password'];

$con = new database();

if ($con->validateCurrentPassword($userId,
$currentPassword)) {
if ($currentPassword === $newPassword) {
header('Location:
user_account.php?status=samepassword');
exit();
}

if ($newPassword === $confirmPassword) {


$hashedPassword =
Validates current password, password_hash($newPassword, PASSWORD_BCRYPT);
checks new password criteria, if ($con->updatePassword($userId,
and updates the password in $hashedPassword)) {
the database. header('Location:
user_account.php?status=success');
exit();
} else {
header('Location:
user_account.php?status=error');
exit();
}
} else {
header('Location:
user_account.php?status=nomatch');
exit();
}
} else {
header('Location:
user_account.php?status=wrongpassword');
exit();
}
}
if (isset($_POST['updateaddress'])) {
$user_id = $id;
$street = $_POST['user_street'];
$barangay = $_POST['barangay_text'];
$city = $_POST['city_text'];
$province = $_POST['province_text'];

Updates the user's address in if($con->updateUserAddress($user_id, $street,


the database and handles $barangay, $city, $province)){
header('Location:
potential errors. user_account.php?status=success1');
exit();
}else{
header('Location: user_account.php?status=error');
exit();
}
}

4.6 Database Class


The database class provides methods to interact with a MySQL database for user management.
It includes functionalities for user authentication, registration, updating user details, managing user
addresses, and handling user-related data queries. The class uses PDO for secure and efficient database
operations.

Method opencon()
Description Establishes a connection to the MySQL database using PDO.
Return PDO instance representing the database connection.
Code:
function opencon(){
return new PDO('mysql:host=localhost; dbname=student', 'root', '');
}

Method check()
Description Checks if a user with the provided username exists and if the password matches.
$username: Username of the user to be checked.
Parameters
$password: Password to be verified.
Return User data as an associative array if authentication succeeds, otherwise false.

Code:
function check($username, $password) {
// Open database connection
$con = $this->opencon();

// Prepare the SQL query


$query = $con->prepare("SELECT * FROM users WHERE user_name = ?");
$query->execute([$username]);

// Fetch the user data as an associative array


$user = $query->fetch(PDO::FETCH_ASSOC);

// If a user is found, verify the password


if ($user && password_verify($password, $user['user_pass'])) {
return $user;
}

// If no user is found or password is incorrect, return false


return false;
}

Method signupUser()
Description Registers a new user into the database.
$firstname: First name of the user.
$lastname: Last name of the user.
$birthday: Date of birth of the user.
$sex: Sex of the user.
Parameters
$email: Email address of the user.
$username: Username chosen by the user.
$password: Password chosen by the user (hashed).
$profilePicture: Path to the user's profile picture.
Return ID of the newly inserted user.

Code:
function signupUser($firstname, $lastname, $birthday, $sex, $email, $username,
$password, $profilePicture)
{
$con = $this->opencon();
// Save user data along with profile picture path to the database
$con->prepare("INSERT INTO users (user_firstname, user_lastname,
user_birthday, user_sex, user_email, user_name, user_pass, user_profile_picture)
VALUES (?,?,?,?,?,?,?,?)")->execute([$firstname, $lastname, $birthday, $sex,
$email, $username, $password, $profilePicture]);
return $con->lastInsertId();
}

Method insertAddress()
Description Inserts address information for a user into the database.
$user_id: ID of the user whose address is being inserted.
Parameters
$street: Street name.
$barangay: Barangay name.
$city: City name.
$province: Province name.
Return Boolean indicating success or failure of the insertion.

Code:
function insertAddress($user_id, $street, $barangay, $city, $province)
{
try
{
$con = $this->opencon();
$con->beginTransaction();
$con->prepare("INSERT INTO user_address (user_id, street, barangay, city,
province) VALUES (?,?,?,?,?)")->execute([$user_id, $street, $barangay, $city,
$province]);
$con->commit();
return true;
}
catch (PDOException $e) {
$con->rollBack();
return false;
}

Method view()
Description Retrieves a list of users along with their addresses from the database.
Return Array of user data with addresses.

Code:
function view()
{
$con = $this->opencon();
return $con->query("SELECT users.user_id, users.user_firstname,
users.user_lastname, users.user_birthday, users.user_sex, users.user_name,
users.user_profile_picture, CONCAT(user_address.city,', ', user_address.province)
AS address from users INNER JOIN user_address ON users.user_id =
user_address.user_id")->fetchAll();
}

Method delete()
Description Deletes a user and their associated address from the database.
Parameters $id: ID of the user to be deleted.
Return Boolean indicating success or failure of the deletion.

Code:
function delete($id)
{
try {
$con = $this->opencon();
$con->beginTransaction();

// Delete user address


$query = $con->prepare("DELETE FROM user_address WHERE user_id = ?");
$query->execute([$id]);

// Delete user
$query2 = $con->prepare("DELETE FROM users WHERE user_id = ?");
$query2->execute([$id]);

$con->commit();
return true; // Deletion successful
} catch (PDOException $e) {
$con->rollBack();
return false;
}
}
Method viewdata()
Description Retrieves detailed information of a specific user from the database.
Parameters $id: ID of the user whose data is being retrieved.
Return User data as an associative array.

Code:
function viewdata($id){
try {
$con = $this->opencon();
$query = $con->prepare("SELECT users.user_id, users.user_name,
users.user_firstname, users.user_lastname, users.user_birthday, users.user_sex,
users.user_pass, users.user_profile_picture, user_address.street,
user_address.barangay, user_address.city, user_address.province FROM users INNER
JOIN user_address ON users.user_id = user_address.user_id WHERE users.user_id = ?
");
$query->execute([$id]);
return $query->fetch();
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return empty array, etc.)
return [];
}
}

Method updateUser()
Description Updates user information in the database.
$user_id: ID of the user to be updated.
$firstname: Updated first name.
$lastname: Updated last name.
Parameters $birthday: Updated date of birth.
$sex: Updated gender.
$username: Updated username.
$password: Updated password (hashed).
Return Boolean indicating success or failure of the update.

Code:
function updateUser($user_id, $firstname, $lastname, $birthday,$sex, $username,
$password) {
try {
$con = $this->opencon();
$con->beginTransaction();
$query = $con->prepare("UPDATE users SET user_firstname=?,
user_lastname=?,user_birthday=?, user_sex=?,user_name=?, user_pass=? WHERE
user_id=?");
$query->execute([$firstname, $lastname,$birthday,$sex,$username, $password,
$user_id]);
// Update successful
$con->commit();
return true;
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
$con->rollBack();
return false; // Update failed
}
}

Method updateUserAddress ()
Description Updates address information for a user in the database.
$user_id: ID of the user whose address is being updated.
$street: Updated street name.
Parameters $barangay: Updated barangay name.
$city: Updated city name.
$province: Updated province name.
Return Boolean indicating success or failure of the update.
Code:
function updateUserAddress($user_id, $street, $barangay, $city, $province){
try {
$con = $this->opencon();
$con->beginTransaction();
$query = $con->prepare("UPDATE user_address SET street=?, barangay=?,
city=?, province=? WHERE user_id=?");
$query->execute([$street, $barangay, $city, $province, $user_id]);
$con->commit();
return true; // Update successful
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
$con->rollBack();
return false; // Update failed
}
}

Method getusercount()
Description Retrieves the count of male and female users from the database.
Return Associative array containing counts of male and female users.

Code:
function getusercount()
{
$con = $this->opencon();
return $con->query("SELECT SUM(CASE WHEN user_sex = 'Male' THEN 1 ELSE 0 END)
AS male_count,
SUM(CASE WHEN user_sex = 'Female' THEN 1 ELSE 0 END) AS female_count FROM
users;")->fetch();
}

Method checkEmailExists()
Description Checks if an email address already exists in the database.
Parameters $email: Email address to be checked.
Return Email address if it exists, otherwise false.

Code:
function checkEmailExists($email) {
$con = $this->opencon();
$query = $this->$con->prepare("SELECT user_email FROM users WHERE user_email =
?");
$query->execute([$email]);
return $query->fetch();
}

Method validateCurrentPassword()
Description Validates the current password of a user.
$userId: ID of the user whose password is being validated.
Parameters
$currentPassword: Current password to be validated.
Return Email address if it exists, otherwise false.

Code:
function validateCurrentPassword($userId, $currentPassword) {
// Open database connection
$con = $this->opencon();

// Prepare the SQL query


$query = $con->prepare("SELECT user_pass FROM users WHERE user_id = ?");
$query->execute([$userId]);

// Fetch the user data as an associative array


$user = $query->fetch(PDO::FETCH_ASSOC);

// If a user is found, verify the password


if ($user && password_verify($currentPassword, $user['user_pass'])) {
return true;
}

// If no user is found or password is incorrect, return false


return false;
}
Method updatePassword()
Description Updates the password of a user in the database.
$userId: ID of the user whose password is being updated.
Parameters
$hashedPassword: New password (hashed) to be set.
Return Boolean indicating success or failure of the update.

Code:
function updatePassword($userId, $hashedPassword){
try {
$con = $this->opencon();
$con->beginTransaction();
$query = $con->prepare("UPDATE users SET user_pass = ? WHERE user_id = ?");
$query->execute([$hashedPassword, $userId]);
// Update successful
$con->commit();
return true;
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
$con->rollBack();
return false; // Update failed
}
}

Method updateUserProfilePicture()
Description Updates the profile picture path of a user in the database.
$userID: ID of the user whose profile picture path is being updated.
Parameters
$profilePicturePath: New profile picture path.
Return Boolean indicating success or failure of the update.

Code:
function updateUserProfilePicture($userID, $profilePicturePath) {
try {
$con = $this->opencon();
$con->beginTransaction();
$query = $con->prepare("UPDATE users SET user_profile_picture = ? WHERE user_id
= ?");
$query->execute([$profilePicturePath, $userID]);
// Update successful
$con->commit();
return true;
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
$con->rollBack();
return false; // Update failed
}
}

Method fetchAvailableCourses ()
Description Retrieves available courses for a user to enroll in.
Parameters $userId: ID of the user for whom available courses are fetched.
Return Array of available courses.

Code:
function fetchAvailableCourses($userId) {
try {
$con = $this->opencon();
$query = $con->prepare("
SELECT c.course_id, c.course_name, c.course_description,
CASE WHEN e.course_id IS NOT NULL THEN 'Enrolled' ELSE 'Not Enrolled'
END AS enrolled_status
FROM courses c
LEFT JOIN enrollments e ON c.course_id = e.course_id AND e.user_id = ?
WHERE e.course_id IS NULL OR e.user_id != ?
");
$query->execute([$userId, $userId]);
return $query->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
return [];
}
}

Method fetchSelectedCourses ()
Description Retrieves details of selected courses based on provided IDs.
Parameters $selectedCourseIds: Array of course IDs for which details are to be fetched.
Return Array of selected courses details.

Code:
function fetchSelectedCourses($selectedCourseIds) {
try {
$con = $this->opencon();
$placeholders = str_repeat('?,', count($selectedCourseIds) - 1) . '?';
$query = $con->prepare("SELECT course_id, course_name, course_description
FROM courses WHERE course_id IN ($placeholders)");
$query->execute($selectedCourseIds);
return $query->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Handle the exception (e.g., log error, return false, etc.)
return [];
}
}

5. Testing

Test cases are detailed, step-by-step instructions designed to validate that a software application
performs as expected. Each test case includes specific inputs, execution conditions, and expected
outcomes. They are essential components of software testing, ensuring comprehensive examination of
functionality, usability, and performance.

Register Page (register.php)

1. Input Validation

Test Case ID TC001


Test Scenario User Registration
Test Description Register with all valid fields filled.
Test Steps 1. Navigate to registration page.
2. Enter valid username, email, and password.
3. Upload profile picture.
4. Click "Register".
Expected Results Register with all valid fields filled.
Status Pass
Table 5. Test Case for User Registration

Test Case ID TC002


Test Scenario Missing Required Fields
Test Description Register with some required fields left blank.
Test Steps 1. Leave any required field blank (e.g., email or password).
2. Submit the form.
Expected Results Error message indicating the missing fields.
Status Pass
Table 6. Test Case for Missing Required Fields

Test Case ID TC003


Test Scenario Invalid Email Format
Test Description Register with an invalid email format.
Test Steps 1. Enter an invalid email.
2. Submit the form.
Expected Results Error message indicating invalid email format.
Status Pass
Table 7. Test Case for Invalid Email Format

Test Case ID TC004


Test Scenario Password Complexity
Test Description Register with a password not meeting complexity requirements.
Test Steps 1. Enter a password that doesn’t meet the criteria.
2. Submit the form.
Expected Results Error message indicating password does not meet complexity requirements.
Status Pass
Table 8. Test Case for Password Complexity

Test Case ID TC005


Test Scenario SQL Injection
Test Description Attempt SQL injection in input fields.
Test Steps 1. Enter SQL code in any input field ("DROP TABLE users;").
2. Submit the form.
Expected Results Input is sanitized, and an error message is shown
Status Pass
Table 9. Test Case for SQL Injection

2. File Upload

Test Case ID TC006


Test Scenario Valid Image Upload
Test Description Upload a valid image file.
Test Steps 1. Select a valid image file (jpg, png, gif) within size limits.
2. Submit the form.
Expected Results Image is uploaded, and registration is successful.
Status Pass
Table 10. Test Case for Valid Image Upload

Test Case ID TC007


Test Scenario Large File Upload
Test Description Upload a file exceeding size limits.
Test Steps 1. Select an image file larger than 500KB.
2. Submit the form.
Expected Results Error message indicating the file is too large.
Status Pass
Table 11. Test Case for Large File Upload

Test Case ID TC008


Test Scenario Unsupported File Format
Test Description Upload a file in an unsupported format.
Test Steps 1. Select a non-image file (.pdf).
2. Submit the form.
Expected Results Error message indicating the file is too large.
Status Pass
Table 12. Test Case for Unsupported File Format

Test Case ID TC009


Test Scenario Duplicate File Name
Test Description Upload a file with a name that already exists.
Test Steps 1. Upload an image file with the same name as an existing file.
2. Submit the form.
Expected Results File is renamed and uploaded successfully, registration proceeds.
Status Pass
Table 13. Test Case for Unsupported File Format

Login page (login.php)

3. Authentication

Test Case ID TC010


Test Scenario Valid Login
Test Description Login with correct username and password.
Test Steps 1. Enter valid username and password.
2. Submit the form.
Expected Results User is logged in and redirected to the appropriate page based on account type.
Status Pass
Table 14. Test Case for Valid Login

Test Case ID TC011


Test Scenario Invalid Username
Test Description Login with an incorrect username.
Test Steps 1. Enter an incorrect username.
2. Enter a valid password.
3. Submit the form.
Expected Results Error message indicating incorrect username or password.
Status Pass
Table 15. Test Case for Invalid Username

Test Case ID TC013


Test Scenario Empty Fields
Test Description Login with empty fields.
Test Steps 1. Leave username and/or password fields blank.
2. Submit the form.
Expected Results Error message indicating fields cannot be empty.
Status Pass
Table 16. Test Case for Login with Empty Fields

Test Case ID TC014


Test Scenario Admin Redirection
Test Description Verify admin user is redirected to the admin page.
Test Steps 1. Login with admin credentials.
Expected Results User is redirected to the admin home page (index.php).
Status Pass
Table 17. Test Case for Admin Redirection
Test Case ID TC015
Test Scenario User Redirection
Test Description Verify regular user is redirected to the user account page.
Test Steps 1. Login with regular user credentials.
Expected Results User is redirected to the user account home page (user_account.php).
Status Pass
Table 18. Test Case for User Redirection

Test Case ID TC016


Test Scenario Session Initiation
Test Description Verify session starts upon successful login.
Test Steps 1. Login with valid credentials.
Expected Results Session variables are set (username, account_type).
Status Pass
Table 19. Test Case for Session Initiation

Test Case ID TC017


Test Scenario Session Termination
Test Description Verify session ends upon logout.
Test Steps 1. Login with valid credentials.
2. Logout
Expected Results Session variables are cleared, and the user is redirected to the login page.
Status Pass
Table 20. Test Case for Session Termination

Test Case ID TC019


Test Scenario Valid Data Retrieval
Test Description Verify user data is correctly displayed.
Test Steps 1. Login and navigate to the user account page.
Expected Results User data is displayed correctly.
Status Pass
Table 21. Test Case for Valid Data Retrieval

Test Case ID TC020


Test Scenario Invalid Data Retrieval
Test Description Handle cases where user data is not found.
Test Steps 1. Manipulate session to an invalid user ID.
2. Navigate to the user account page.
Expected Results Error message or redirection to login page.
Status Pass
Table 22. Test Case for Valid Data Retrieval

Test Case ID TC021


Test Scenario Valid Password Update
Test Description Update password with valid inputs.
Test Steps 1. Enter correct current password.
2. Enter a new password meeting criteria.
3. Confirm the new password.
4. Submit the form.
Expected Results Password is updated, success message shown.
Status Pass
Table 23. Test Case for Update Password
Test Case ID TC022
Test Scenario Invalid Current Password
Test Description Update password with incorrect current password.
Test Steps 1. Enter incorrect current password.
2. Enter a new password.
3. Confirm the new password.
4. Submit the form.
Expected Results Error message indicating incorrect current password.
Status Pass
Table 24. Test Case for Invalid Current Password

Test Case ID TC023


Test Scenario Password Mismatch
Test Description New password and confirmation do not match.
Test Steps 1. Enter correct current password.
2. Enter a new password.
3. Enter a different confirmation password.
4. Submit the form.
Expected Results Error message indicating passwords do not match.
Status Pass
Table 25. Test Case for Password Mismatch

Test Case ID TC024


Test Scenario Valid Address Update
Test Description Update address with valid inputs.
Test Steps 1. Enter valid street, barangay, city, and province.
2. Submit the form.
Expected Results Address is updated, success message shown.
Status Pass
Table 26. Test Case for Valid Address Update

Test Case ID TC025


Test Scenario Invalid Address Update
Test Description Update address with missing or incorrect fields.
Test Steps 1. Leave some address fields blank.
2. Submit the form.
Expected Results Error message indicating missing or incorrect fields.
Status Pass
Table 27. Test Case for Valid Address Update

Test Case ID TC026


Test Scenario Unique Username
Test Description Validate unique username during registration.
Test Steps 1.
Expected Results
Status
Table 28. Test Case for Unique Name

Test Case ID TC027


Test Scenario Taken Username
Test Description Validate a username already taken.
Test Steps 1. Enter a unique username.
Expected Results Username marked as valid, "Next" button enabled.
Status Pass
Table 29 Test Case for Taken Username

Test Case ID TC028


Test Scenario Empty Username
Test Description Validate empty username field.
Test Steps 1. Leave username field empty.
Expected Results No validation performed, "Next" button enabled.
Status Pass
Table 30. Test Case for Empty Username

Test Case ID TC029


Test Scenario Unique Email
Test Description Validate unique email during registration.
Test Steps 1. Enter a unique email.
Expected Results Email marked as valid, "Next" button enabled.
Status Pass
Table 31. Test Case for Unique Email

Test Case ID TC030


Test Scenario Taken Email
Test Description Validate an email already taken.
Test Steps 1. Enter an email that exists in the database.
Expected Results Error message indicating email is taken, "Next" button disabled.
Status Pass
Table 32. Test Case for Taken Username

Test Case ID TC031


Test Scenario Invalid Email Format
Test Description Validate email with incorrect format.
Test Steps 1. Enter an email in an incorrect format (e.g., "email.com").
Expected Results Error message indicating invalid email format.
Status Pass
Table 33. Test Case for Invalid Email Format

You might also like