PHPUnit

To install phpunit framework make sure you have installed composer
If not follow instructions from this link http://codeinsightacademy.com/blog/php/composer/

Installation

Install php-xml
As we are going to use phpunit.xml we need to install php-xml

sudo apt install php-xml
#To install specific version
sudo apt install php7.4-xml

Install mbstring

sudo apt-get install php-mbstring

Create composer.json file in project root directory

{
"autoload" : {}
}

Run one of the composer command

composer dump-autoload -o
OR
composer update

Install sluggable

composer require cviebrock/eloquent-sluggable

Install intl
This is required when you are using Code Igniter framework

apt-get install php-intl
#OR specific version
apt-get install php7.4-intl

Install php unit framework

composer require phpunit/phpunit ^9

Create function

global_functions.php

<?php

function add($x = 0, $y = 0) {
        return $x + $y;
}

index.php

<?php

require_once("vendor/autoload.php");

echo add(5, 6);

composer.json

{
    "autoload": {
            "files": ["global_functions.php"]
    },
    "require": {
        "cviebrock/eloquent-sluggable": "^8.0",
        "phpunit/phpunit": "^9"
    }
}

Run index.php file

php index.php

Write Testcase

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>

<phpunit bootstrap = "vendor/autoload.php"
 colors = "true">
    <testsuites>
        <testsuite name="Sample test suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

</phpunit>

tests/GlobalFunctionsTest.php
NOTE: MAKE SURE TO GIVE test PREFIX TO YOUR TEST FUNCTION

<?php

class GlobalFunctionsTest extends \PHPUnit\Framework\TestCase {
        public function testAdd() {
                $result = add(5, 6);
                $this->assertEquals(11, $result);
        }
}

Get all assertions functions from here
https://phpunit.readthedocs.io/en/9.5/assertions.html

Run TestCase from root directory

./vendor/bin/phpunit
testcase output
./vendor/bin/phpunit --testdox
output with function names and result

project directory structure

tree -I "vendor"

Parse ini file

What is INI file

An INI file is a configuration file for computer software that consists of a text-based content with a structure and syntax comprising key–value pairs for properties, and sections that organize the properties.

parse_ini_file function

Parse ini file is a function to parse any configuration file which has key-value pair
This is required when you want to keep all application-level configuration parameters in one place
Maintaining configuration level parameter/variables is easy when you use ini file
You need to make changes in one file and it will reflect changes throughout the application


Syntax

parse_ini_file(file, process_sections, scanner_mode)

myapp.ini

#comment goes here

APP_NAME	= UMS
ADMIN_EMAIL	= admin@umsapp.com


#local database credentials
[localdb]
DB_HOSTNAME	= localhost
DB_USERNAME	= root
DB_PASSWORD	= ""
DB_PORT		= 3306
DB_NAME		= ecom


#production database credentials
[proddb]
PRD_DB_HOSTNAME	= localhost
PRD_DB_USERNAME	= root
PRD_DB_PASSWORD	= ""
PRD_DB_PORT	= 3306
PRD_DB_NAME	= ecom

global_functions.php

function getConnection() {
	
	$db = parse_ini_file('config/myapp.ini', true)['localdb'];
	
	$conn = null;
	
	$servername	= $db['DB_HOSTNAME'];
	$dbname		= $db['DB_NAME'];
	$username 	= $db['DB_USERNAME'];
	$password	= $db['DB_PASSWORD'];
	
	try {
	  $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
	  $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);	
	} catch(PDOException $e) {
	  echo "Error: " . $e->getMessage();
	}
	
	return $conn;
}

Ref: https://www.w3schools.com/php/func_filesystem_parse_ini_file.asp

Composer

A Dependency Manager for PHP

Composer is an application-level package manager for the PHP programming language that provides a standard format for managing dependencies of PHP software and required libraries. It was developed by Nils Adermann and Jordi Boggiano in 2012, who continue to manage the project.


To install composer in windows download and install executable file
https://getcomposer.org/download/

To install in ubuntu

apt install composer

To install latest version of composer on ubuntu

cd ~
curl -sS https://getcomposer.org/installer -o composer-setup.php

sudo php composer-setup.php --install-dir=/usr/bin --filename=composer

OR

sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

composer.json
Keep this file in the project’s root directory
NOTE: This file is mandatory to in root directory to use composer as composer look for this file when you run dump-autoload

{
	"autoload" : {
		"files" : ["lib/global_functions.php"],
	}
}

lib/global_functions.php

function getMessage() {
	
	echo "Hello World" . PHP_EOL;

}

Create autoload file by running any one following command

composer dump-autoload
composer dump-autoload -o

index.php

<?php
require("vendor/autoload.php");
echo "=====================\n";
getMessage();

How to autoload classes using composer

app/admin/Account.php

<?php
namespace App\Admin;

class Account {
	//this is magic method as it will invoked automatically 
        //when you create instance of account
	public function __construct() {
		
		echo "I am from Admin Account" . PHP_EOL;
	}
}

app/user/Account.php

<?php
namespace App\User;

class Account {
	//this is magic method as it will invoked automatically 
	//when you create instance of account
	public function __construct() {
		echo "I am from User Account" . PHP_EOL;
	}	
}

modify composer.json

{
	"autoload" : {
		"files" : ["lib/global_functions.php"],
		"classmap" : ["app"]
	}
}

Once you modify composer.json file run dump-autoload command again to add classmapping in autoload file

composer update

OR

composer dump-autoload -o

modify index.php

<?php

require("vendor/autoload.php");

echo "=====================\n";

getMessage();

echo "=====================\n";

new App\User\Account();

echo "=====================\n";

new App\Admin\Account();

echo "=====================\n";
directory structure

Ref Code: https://gitlab.com/codeinsightacademy/composer-demo.git

PHP User Management System

A user or admin facing problem managing data on excel sheet.
He/She need a system to perform at least following operations

  1. Add Record
  2. Modify Record
  3. Delete Record
  4. Show Listing and Search Data to get specific Information.

User need a system which should be accessible from internet so that he can work from any machine (laptop/desktop/mobile).

You need to develop a web application with best of your knowledge

Roles: Admin

With correct credentials admin should be able to login and see the dashboard.

if credentials are wrong he will stay on login page and show a message – wrong credentials.

On successful login admin can see users list perform all CRUDL operations.

NOTE: you need to use vim editor to edit files

Following are the wireframes for reference.

login.php

dashboard.php

add_user.php

edit_user.php

delete confirm box

Technologies to be used

  • composer for package management and autoload
  • ini for configuration
  • git and gitlab for version control
  • HTML5 CSS3 Bootstrap 5 for UI/UX
  • jquery 3.6 or javascript for validation and AJAX
  • php 7.4 or 8 as backend programming language
  • mysql 8 database
  • PDO for database operations
  • PHPUnit for unit testing
  • python and php for automation script (Use cron jobs to automatically run script)
  • nginx web server
  • use infinityfree / webserver / cloudserver for website hosting
  • Jenkins and git-ftp for CI/CD

MVP / Deliverable

  1. P0
    1. Users Listing
    2. Delete User Record
    3. Add User Record with Profile Picture
      (User status should be enum in database table: enable, disable, blocked, active, inactive)
    4. Update User Record
    5. Session Management Login / Logout
  2. P1
    1. View User Details in Modal Window
    2. Pagination
    3. Sorting
    4. Searching
    5. Filtering
  3. P2
    1. Frontend – Backend Validation
    2. Export CSV Users
    3. Bulk Upload CSV
    4. Activity Log
    5. Export Activity Log
  4. P3
    1. Login with OTP i.e. 2FA (Use Redis to store OTP)
    2. Login Logout for user account
    3. Inactive User status if not logged in for 3 consecutive days
    4. Change Admin and User Password from their respective account
    5. Secret Questions and Forgot Password / Recover Password using secret questions or through the email link
  5. P4
    1. REST API (Web Services) for User CRUDL Operations
    2. Protect REST API using Basic Authentication or JWT token
    3. Login with google API or Facebook API
    4. PHPUnit test for all functionalities
    5. Licensing or limit user registration
  6. P5
    1. Dashboard showing following summary (Use highcharts)
      1. Total User
      2. Active Users
      3. License Count / Usage Count
      4. Online Users
      5. Weekly Registration Stats

Schema

Ref SQL Queries

SELECT * FROM users ORDER BY id DESC;

SELECT * FROM users WHERE id = 3;

DELETE FROM users WHERE id = 3;

INSERT INTO users (id, name, age, city, added_at, updated_at) VALUES (NULL, 'sonam gupta', 18, 'gorakhpur', NOW(), NOW());

UPDATE users SET name = 'Sonam Gupta', age = 20, city = 'Gorakhpur', updated_at = NOW() WHERE id = 5;

Reference

PHP MySQL CRUD App

Php CRUD Application – How to Create Website Using Php – YouTube

Linux Commands

SQL Cheat Sheet

HTML and CSS

Php Fundamentals

Php Basics Tutorial

Php Advanced Tutorial

Javascript Tutorial in Hindi

Javascript Tutorial in English

Flask Cheat Sheet

keyword arguments

Keyword arguments (or named arguments) are values that, when passed into a function, are identifiable by specific parameter names.
keyword argument is preceded by a parameter and the assignment operator, = . Keyword arguments can be likened to dictionaries in that they map a value to a keyword.

The order of the arguments does not matter

def my_function(child3, child2, child1):
  print("The youngest child is " + child3)

my_function(child1 = "Emil", child2 = "Tobias", child3 = "Linus")

The phrase Keyword Arguments are often shortened to kwargs in Python documentations.

arguments vs keyword arguments (*args vs **kwargs)

def foo(*args, **kwargs):
    print(args);
    print(kwargs);
    
foo(5, 6, 7, name="Shailesh", age=32, city="Nagpur");
output

Decorators

A decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure.
Decorators are usually called before the definition of a function you want to decorate.

### CREATE CUSTOM DECORATOR ###
from functools import wraps

def my_decorator(f):
    @wraps(f)
    def msg(*args, **kwargs):
        print("I am from custom decorator")
        print("Arguments:", args)
        print("Keyword Arguments:", kwargs)
        
        return f(*args, **kwargs)
        
    return msg;


@my_decorator    
def add(x, y):
    print(f"{x} + {y} = {x + y}")

    
@my_decorator
def sub(x, y):
    print(f"{x} - {y} = {abs(x - y)}")
    
    
#invoke functions
add(5, y=6)
sub(5, y=6)
output

Flask Framework

Flask is a micro web framework written in Python. It is classified as a microframework because it does not require particular tools or libraries.
It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions.

install flask module

python -m pip install Flask

hello world

from flask import Flask, jsonify, request, render_template

app = Flask(__name__)

#YOUR FUNCTIONS HERE

if __name__ == "__main__":
    app.run(debug=True);
    #app.run(host="0.0.0.0", port=int("1234"), debug=True)

render html template [NOTE: MAKE SURE TO KEEP ALL TEMPLATE FILES IN templates DIRECTORY]

@app.route('/')
def index():
    #return "Hello World";
    
    data = {'company_name': "TCET"}
    return render_template('hello_world.html', data = data)

templates/hello_world.html

<h1>Hello World</h1>
<h3>Welcome to {{data['company_name']}}</h3>

read get value

@app.route('/sqr', methods=['GET'])
def getSqr():
    num1 = int(request.args.get('num1'));
    return f"Square of {num1} is {num1 * num1}"


@app.route('/add', methods=['GET'])
def add():
    num1 = int(request.args.get('num1'));
    num2 = int(request.args.get('num2'));
    
    return f"{num1} + {num2} = {num1 + num2}";

read post value

@app.route('/sub', methods=['POST'])
def sub():
    num1 = int(request.form.get('num1'));
    num2 = int(request.form.get('num2'));
    
    return f"{num1} - {num2} = {num1 - num2}";

read raw json

@app.route('/mul', methods=['POST'])
def mul():
    raw_json = request.get_json();
    num1 = int(raw_json['num1']);
    num2 = int(raw_json['num2']);
    
    return f"{num1} * {num2} = {num1 * num2}";

install pymysql module

python -m pip install PyMySQL

install cors module

python -m pip install -U flask-cors

get users from database

from flask import Flask, jsonify, request
from flask_cors import CORS
import pymysql

app = Flask(__name__)
cors = CORS(app)

@app.route('/users', methods=['GET'])
def get_users():
    # To connect MySQL database
    conn = pymysql.connect(host='localhost', user='root', password = "", db='databasename')
        
    cur = conn.cursor()
    cur.execute("select * from users LIMIT 10")
    output = cur.fetchall()

    print(type(output)); #this will print tuple	

    for rec in output:
        print(rec);
        
    # To close the connection
    conn.close()

    return jsonify(output);

fetch data using javascript fetch api

let url = "http://localhost:5000";
fetch(url)
    .then(response => response.json())
    .then(response => console.table(response));

Flask RESTful API

Flask-RESTful is an extension for Flask that adds support for quickly building REST APIs.

install flask-restful

python -m pip install flask-restful

MyApi Resource

from flask import Flask, request
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class MyApi(Resource):
    def __init__(self):
        print("Constructor called...")
        
    def get(self):
        return {"msg" : "get method"}
        
    def post(self):
        return {"msg" : "post method"}
        
    def put(self):
        return {"msg" : "put method"}
    
    def delete(self):
        return {"msg" : "delete method"}
    
    
api.add_resource(MyApi, '/myapiurl')

if __name__ == "__main__":
    app.run(debug=True)

Authenticate REST API

from flask import Flask, request, make_response
from flask_restful import Resource, Api
from functools import wraps


app = Flask(__name__)
api = Api(app)


#define custom decorator @authorize
def authorize(f):
    @wraps(f)
    def kuchbhi(*args, **kwargs):
        err_msg = "Authentication required";
    
        if(request.authorization == None):
            return make_response('Not Authorized', 403, {'WWW-Authenticate' : err_msg})
            
        unm = request.authorization.username
        pwd = request.authorization.password
        
        if(unm == 'admin' and pwd == 'admin@123'):
            print("Correct username and password")
            return f(*args, **kwargs)
        
        return make_response('Not Authorized', 403, {'WWW-Authenticate' : err_msg})
    
    return kuchbhi


class MyApi(Resource):
    
    def __init__(self):
        print("Constructor called...")

    @authorize 
    def get(self):
        return {"msg" : "get method"}

    @authorize    
    def post(self):
        return {"msg" : "post method"}

    @authorize    
    def put(self):
        return {"msg" : "put method"}

    @authorize
    def delete(self):
        return {"msg" : "delete method"}
    
api.add_resource(MyApi, '/myapiurl')

if __name__ == "__main__":
    app.run(debug=True)


apply authorize decorator to all methods of call

from flask import Flask, request, make_response
from flask_restful import Resource, Api
from functools import wraps

app = Flask(__name__)
api = Api(app)

#define custom decorator authorize
def authorize(f):
    @wraps(f)
    def kuchbhi(*args, **kwargs):
        err_msg = "Authentication required";
    
        if(request.authorization == None):
            return make_response('Not Authorized', 403, {'WWW-Authenticate' : err_msg})
            
        unm = request.authorization.username
        pwd = request.authorization.password
        
        if(unm == 'admin' and pwd == 'admin@123'):
            print("Correct username and password")
            return f(*args, **kwargs)
        
        return make_response('Not Authorized', 403, {'WWW-Authenticate' : err_msg})
    
    return kuchbhi


class MyApi(Resource):
    method_decorators = [authorize]
    
    def __init__(self):
        print("Constructor called...")
        
    def get(self):
        return {"msg" : "get method"}
        
    def post(self):
        return {"msg" : "post method"}
        
    def put(self):
        return {"msg" : "put method"}
    
    def delete(self):
        return {"msg" : "delete method"}
    
api.add_resource(MyApi, '/myapiurl')

if __name__ == "__main__":
    app.run(debug=True)

Testing API

test response status
test_myapiapp.py
where myapiapp.py is the file where all restful api defined

#from filename import app
from rest_api import app
import unittest
import base64

class RestAPITest(unittest.TestCase):
    
    def test_status(self):
        tester = app.test_client(self)
        response = tester.get('/myapiurl')
        self.assertEqual(response.status_code, 200)
   
if __name__ == "__main__":
    unittest.main()

test content type

def test_content_type(self):
    tester = app.test_client(self)
    response = tester.get('/myapiurl')

    self.assertEqual(response.content_type, "application/json")

test content data

def test_content(self):
    tester = app.test_client(self)
    response = tester.get('/myapiurl')        
    self.assertTrue(b'get' in response.data)

To pass Basic Auth credentials in header

creds = base64.b64encode(b"admin:admin@123").decode("utf-8")
response = tester.get('/myapiurl', headers={"Authorization": f"Basic {creds}"})

complete test file code

#from filename import app
from rest_api import app
import unittest
import base64

class RestAPITest(unittest.TestCase):
    
    def test_status(self):
        tester = app.test_client(self)
        #response = tester.get('/myapiurl')
        
        creds = base64.b64encode(b"admin:admin@123").decode("utf-8")
        response = tester.get('/myapiurl', headers={"Authorization": f"Basic {creds}"})
        
        self.assertEqual(response.status_code, 200)
        
    
    def test_content_type(self):
        tester = app.test_client(self)
        #response = tester.get('/myapiurl')
        
        creds = base64.b64encode(b"admin:admin@123").decode("utf-8")
        response = tester.get('/myapiurl', headers={"Authorization": f"Basic {creds}"})
        
        self.assertEqual(response.content_type, "application/json")
        
        
    def test_content(self):
        tester = app.test_client(self)
        #response = tester.get('/myapiurl')
        
        creds = base64.b64encode(b"admin:admin@123").decode("utf-8")
        response = tester.get('/myapiurl', headers={"Authorization": f"Basic {creds}"})
        
        self.assertTrue(b'get' in response.data)
        
        
if __name__ == "__main__":
    unittest.main()
output

REST API CRUD

app.py

import pymysql

from flask import Flask, jsonify, request
from flask_cors import CORS
import pymysql

app = Flask(__name__)
cors = CORS(app)

# To connect MySQL database
conn = pymysql.connect(host='yourhost', user='youruser', password = "yourpassword", db='yourdatabase')

@app.route('/users', methods=['GET'])
def get_users():

    cur = conn.cursor(pymysql.cursors.DictCursor)
    cur.execute("select * from users LIMIT 10")
    output = cur.fetchall()

    print(type(output)); #this will print tuple

    for rec in output:
        print(rec);

    # To close the connection
    #conn.close()

    return jsonify(output);


@app.route('/users/get_one_record', methods=['GET'])
def get_single_user():

    cur = conn.cursor(pymysql.cursors.DictCursor)
    userid = int(request.args.get('id'));
    cur.execute(f"select * from users WHERE id = {userid}")
    output = cur.fetchone()
    
    return jsonify(output);



@app.route('/users', methods=['DELETE'])
def deleteRecord():
    cur = conn.cursor()
    id = int(request.args.get('id'));

    query = f"delete from users where id = {id}";
    #print(query)
    res = cur.execute(query);
    conn.commit();
    print(cur.rowcount, "record(s) deleted")

    return "Record deleted sussesfully"

@app.route('/users', methods=['POST'])
def insertRecord():

        #get raw json values
        raw_json = request.get_json();
        name= raw_json['name'];
        age= raw_json['age'];
        city= raw_json['city'];

        sql="INSERT INTO users (id,name,age,city) VALUES (NULL,'"+name+"','"+str(age)+"','"+city+"')";
        cur= conn.cursor()

        cur.execute(sql);
        conn.commit()
        return "Record inserted Succesfully"

@app.route('/users', methods=['PUT'])
def updateRecord():

        raw_json = request.get_json();

        #print(type(raw_json));

        id = raw_json['id'];
        name= raw_json['name'];
        age= raw_json['age'];
        city= raw_json['city'];
        sql_update_quary=("UPDATE users SET name = '"+name+"',age = '"+str(age)+"',city = '"+city+"'WHERE id = '"+str(id)+"'");
        cur= conn.cursor()
        cur.execute(sql_update_quary);
        conn.commit()
        return "Record Updated Sussecfully";


if __name__ == "__main__":
    #app.run(debug=True);
    app.run(host="0.0.0.0", port=int("1235"), debug=True)

script.js

//const api_url = "<heroku_app_url>"
const api_url = "http://localhost:8080/users"

function loadData(records = []) {
	var table_data = "";
	for(let i=0; i<records.length; i++) {
		table_data += `<tr>`;
		table_data += `<td>${records[i].name}</td>`;
		table_data += `<td>${records[i].age}</td>`;
		table_data += `<td>${records[i].city}</td>`;
		table_data += `<td>`;
		table_data += `<a href="edit.html?id=${records[i].id}"><button class="btn btn-primary">Edit</button></a>`;
		table_data += '&nbsp;&nbsp;';
		table_data += `<button class="btn btn-danger" onclick=deleteData('${records[i].id}')>Delete</button>`;
		table_data += `</td>`;
		table_data += `</tr>`;
	}
	//console.log(table_data);
	document.getElementById("tbody").innerHTML = table_data;
}

function getData() {
	fetch(api_url)
	.then((response) => response.json())
	.then((data) => { 
		console.table(data); 
		loadData(data);
	});
}


function getDataById(id) {
	fetch(`${api_url}/get_one_record?id=${id}`)
	.then((response) => response.json())
	.then((data) => { 
	
		console.log(data);
		document.getElementById("id").value = data.id;
		document.getElementById("name").value = data.name;
		document.getElementById("age").value = data.age;
		document.getElementById("city").value = data.city;
	})
}


function postData() {
	var name = document.getElementById("name").value;
	var age = document.getElementById("age").value;
	var city = document.getElementById("city").value;
	
	data = {name: name, age: age, city: city};
	
	fetch(api_url, {
		method: "POST",
		headers: {
		  'Accept': 'application/json',
		  'Content-Type': 'application/json'
		},
		body: JSON.stringify(data)
	})
	.then((response) => response.json())
	.then((data) => { 
		console.log(data); 
		window.location.href = "index.html";
	})
}	


function putData() {
	
	var id = document.getElementById("id").value;
	var name = document.getElementById("name").value;
	var age = document.getElementById("age").value;
	var city = document.getElementById("city").value;
	
	data = {id: id, name: name, age: age, city: city};
	
	fetch(api_url, {
		method: "PUT",
		headers: {
		  'Accept': 'application/json',
		  'Content-Type': 'application/json'
		},
		body: JSON.stringify(data)
	})
	.then((response) => response.json())
	.then((data) => { 
		console.table(data);
		window.location.href = "index.html";
	})
}


function deleteData(id) {
	user_input = confirm("Are you sure you want to delete this record?");
	if(user_input) {
		//url = "http://localhost:8080/users?id=1234"
		
		fetch(`${api_url}?id=${id}`, {
			method: "DELETE",
			headers: {
			  'Accept': 'application/json',
			  'Content-Type': 'application/json'
			},
			body: JSON.stringify({"_id": id})
		})
		.then((response) => response.json())
		.then((data) => { 
			console.log(data); 
			window.location.reload();
		})
	}
}

index.html

<!DOCTYPE html>
<html>
	<head>
		<title>CIA Institute - Python Flask Project</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"crossorigin="anonymous"></script>
	</head>
	<body class="d-flex flex-column h-100 container">
		<header>
			<nav class="navbar navbar-expand-lg navbar-expand-sm navbar-light bg-light">
			  <div class="container-fluid">
				<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
				  <div class="navbar-nav">
					<a class="nav-link active" aria-current="page" href="#">Listing</a>
					<a class="nav-link" href="add.html">Add New</a>
				  </div>
				</div>
			  </div>
			</nav>
		</header>
		
		<table class="table table-striped table-hover text-center">
			<thead>
				<th>Name</th>
				<th>Age</th>
				<th>City</th>
				<th>Action</th>
			</thead>
			<tbody id="tbody">
				
			</tbody>
			<tfoot>
				
			</tfoot>
		</table>
		
		<footer class="footer mt-auto py-3 bg-light">
		  <div class="container text-center">
			<span class="text-muted"> &copy; CIA Institute 2023</span>
		  </div>
		</footer>
	</body>
	<script src="script.js"></script>
	<script>
		getData();
	</script>
</html>

add.html

<html>
	<head>
		<title>CIA Institute - Python Flask Project</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"crossorigin="anonymous"></script>
	</head>
	<body class="d-flex flex-column h-100 container">
		<header>
			<nav class="navbar navbar-expand-lg navbar-expand-sm navbar-light bg-light">
			  <div class="container-fluid">
				<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
				  <div class="navbar-nav">
					<a class="nav-link" href="index.html">Listing</a>
					<a class="nav-link active" aria-current="page" href="add.html">Add New</a>
				  </div>
				</div>
			  </div>
			</nav>
		</header>
		
		<h3>Add Document</h3>
		
		<form onsubmit="return false;">
		  <div class="mb-3">
			<label for="name" class="form-label">Name</label>
			<input type="text" class="form-control" id="name" autofocus>
		  </div>
		  <div class="mb-3">
			<label for="exampleInputPassword1" class="form-label">Age</label>
			<input type="text" class="form-control" id="age">
		  </div>
		  <div class="mb-3">
			<label for="city" class="form-label">City</label>
			<input type="text" class="form-control" id="city">
		  </div>
		  <button class="btn btn-primary" onclick="return postData()">Submit</button>
		  <a href="index.html" class="btn btn-primary">Cancel</a>
		</form>
		
		<footer class="footer mt-auto py-3 bg-light">
		  <div class="container text-center">
			<span class="text-muted"> &copy; CIA Institute 2022</span>
		  </div>
		</footer>
	</body>
	<script src="script.js"></script>
	<script>
	</script>
</html>

edit.html

<html>
	<head>
		<title>CIA Institute - Python Flask Project</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"crossorigin="anonymous"></script>
	</head>
	<body class="d-flex flex-column h-100 container">
		<header>
			<nav class="navbar navbar-expand-lg navbar-expand-sm navbar-light bg-light">
			  <div class="container-fluid">
				<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
				  <div class="navbar-nav">
					<a class="nav-link" href="index.html">Listing</a>
					<a class="nav-link active" aria-current="page" href="add.html">Add New</a>
				  </div>
				</div>
			  </div>
			</nav>
		</header>
		<h3>Edit Document</h3>
		<form onsubmit="return false;">
			<input type="hidden" class="form-control" id="id">
		  <div class="mb-3">
			<label for="name" class="form-label">Name</label>
			<input type="text" class="form-control" id="name" autofocus>
		  </div>
		  <div class="mb-3">
			<label for="exampleInputPassword1" class="form-label">Age</label>
			<input type="text" class="form-control" id="age">
		  </div>
		  <div class="mb-3">
			<label for="city" class="form-label">City</label>
			<input type="text" class="form-control" id="city">
		  </div>
		  <button class="btn btn-primary" onclick="return putData()">Update</button>
		  <a href="index.html" class="btn btn-primary">Cancel</a>
		</form>
		
		<footer class="footer mt-auto py-3 bg-light">
		  <div class="container text-center">
			<span class="text-muted"> &copy; CIA Institute 2022</span>
		  </div>
		</footer>
	</body>
	<script src="script.js"></script>
	<script>
		const urlParams = new URLSearchParams(window.location.search);
		const id = urlParams.get('id');
		getDataById(id);
	</script>
</html>

JSP User Management System

Create a project user management system

Roles: Admin

With correct credentials admin should be able to login and see the dashboard.

if credentials are wrong he will stay on login page and show a message – wrong credentials.

On successful login admin can see users list perform all CRUDL operations.

Following are the wireframes for reference.



login.jsp

dashboard.jsp

add_user.jsp

edit_user.jsp

delete confirm box

Deploy war on heroku

Signup and select java as primary language https://signup.heroku.com/

Download heroku cli from https://devcenter.heroku.com/articles/heroku-cli

heroku plugins:install java
heroku login

Open another terminal or gitbash and run following command

heroku war:deploy <path_to_war_file> --app <app_name>

Reference Code: https://gitlab.com/tcet/advanced-java

Reference YouTube videos

  1. Introduction to Servlet
  2. MySQL DATABASE CRUDL
  3. Servlet Methods – GET, POST, PUT, DELETE and OPTIONS
  4. DATABASE CONNECTION JDBC MySQL
  5. Show MySQL Data in HTML Table
  6. Session Management – Login / Logout
  7. DML – Insert Update Delete
  8. Bootstrap Integration in JSP

Java Cheat Sheet

Softwares to Install

JDK 11
https://www.oracle.com/in/java/technologies/javase-jdk11-downloads.html

Apache Tomcat Server (version 9)
https://tomcat.apache.org/download-90.cgi

Eclipse EE (2021)
https://www.eclipse.org/downloads/packages/release/neon/3/eclipse-ide-java-ee-developers

Xampp for MySQL (latest version)
https://www.apachefriends.org/download.html

Postman for REST API
https://www.postman.com/downloads/

Addition of Two Numbers

class Main {
	
	public static void main(String args[]) {
		System.out.println(args[0]);
		System.out.println(args[1]);
		
		int num1 = Integer.parseInt(args[0]);
		int num2 = Integer.parseInt(args[1]);

		int add = num1 + num2;
		
		System.out.println(String.format("%s + %s = %s", num1, num2, add));
	}
	
}

Inheritance

class Bank {
	
	protected int balance;
	
	public Bank(int bal) {
		this.balance = bal;
		System.out.println(String.format("Account opened with Balance: %s", this.balance));
	}
	
	public void deposit(int amt) {
		System.out.println(String.format("Deposit Amount: %s", amt));
		this.balance += amt;
	}
	
	public void withdraw(int amt) {
		System.out.println(String.format("Withdraw Amount: %s", amt));
		this.balance -= amt;
	}
	
	public void showBalance() {
		System.out.println(String.format("Available Balance: %s", this.balance));
	}
	
}

class HDFC extends Bank {
	public HDFC(int bal) {
		super(bal);
	}
}

class SBI extends Bank {
	public SBI(int bal) {
		super(bal);
	}
	
	public void withdraw(int amt) {
		super.withdraw(amt);
		super.balance -= 20;
	}
	
}

class Main {
	public static void main(String args[]) {
		Bank bobj = new Bank(1000);
		bobj.showBalance();
		bobj.deposit(500);
		bobj.showBalance();
		bobj.withdraw(300);
		bobj.showBalance();
		
		System.out.println("====================");
		
		HDFC hobj = new HDFC(2000);
		hobj.showBalance();
		hobj.deposit(500);
		hobj.showBalance();
		hobj.withdraw(300);
		hobj.showBalance();
		
		System.out.println("====================");
		
		SBI sobj = new SBI(3000);
		sobj.showBalance();
		sobj.deposit(500);
		sobj.showBalance();
		sobj.withdraw(300);
		sobj.showBalance();
	}
}

Exception Handling

class Main {
	public static void main(String args[]) {
		try {
			
			int num1 = Integer.parseInt(args[0]);
			int num2 = Integer.parseInt(args[1]);
			
			try {
				int div = num1 / num2;
				System.out.println(String.format("Division of %s and %s is %s", num1, num2, div));
			} catch (Exception e) {
				System.out.println(e);
			}
			
			
		} catch (ArrayIndexOutOfBoundsException aie) {
			System.out.println(aie);
			
		} catch (Exception e) {
			System.out.println(e);
		}
		
	}
}

Servlet Demo

Servlet Life Cycle

  1. form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Addition of 2 numbers</title>
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x"
	crossorigin="anonymous">
</head>
<body class="container">
	<form action="CalcServlet" class="m-5">
		<div class="row">
			<div class="col">Number 1</div>
			<div class="col">
				<input type="text" name="num1" placeholder="Enter number" autofocus>
			</div>
		</div>
		<div class="row">
			<div class="col">Number 1</div>
			<div class="col">
				<input type="text" name="num2" placeholder="Enter number">
			</div>
		</div>
		<div class="row">
			<div class="col">
				<input class="btn btn-primary" type="submit" value="Calculate" />
			</div>
		</div>
	</form>
</body>
</html>

2. CalcServlet

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class AddServlet
 */
@WebServlet("/CalcServlet")
public class CalcServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public CalcServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//response.getWriter().append("Served at: ").append(request.getContextPath());
		int num1 = Integer.parseInt(request.getParameter("num1"));
		int num2 = Integer.parseInt(request.getParameter("num2"));
		
		response.getWriter().write(String.format("%s + %s = %s", num1, num2, num1+num2));
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//doGet(request, response);
		int num1 = Integer.parseInt(request.getParameter("num1"));
		int num2 = Integer.parseInt(request.getParameter("num2"));
		
		response.getWriter().write(String.format("%s * %s = %s", num1, num2, num1*num2));
	}
	
	protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//doGet(request, response);
		int num1 = Integer.parseInt(request.getParameter("num1"));
		int num2 = Integer.parseInt(request.getParameter("num2"));
		
		response.getWriter().write(String.format("%s - %s = %s", num1, num2, num1-num2));
	}

	protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//doGet(request, response);
		int num1 = Integer.parseInt(request.getParameter("num1"));
		int num2 = Integer.parseInt(request.getParameter("num2"));
		
		response.getWriter().write(String.format("%s / %s = %s", num1, num2, num1/num2));
	}

	protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//doGet(request, response);
		int num1 = Integer.parseInt(request.getParameter("num1"));
		int num2 = Integer.parseInt(request.getParameter("num2"));
		
		response.getWriter().write(String.format("%s %% %s = %s", num1, num2, num1%num2));
	}

}

DATABASE SQL

CREATE DATABASE

CREATE DATABASE company;

CREATE TABLE

CREATE TABLE users(
    id INT,
    NAME VARCHAR(100) NOT NULL,
    age TINYINT NOT NULL,
    city VARCHAR(200) NOT NULL
);

ALTER TABLE

ALTER TABLE
    users MODIFY id INT PRIMARY KEY AUTO_INCREMENT;

MySQL JDBC

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class CRUDLDemo {
	public static void main(String args[]) {
		String conn_str = "jdbc:mysql://localhost:3306/company";
		String dbusername = "root";
		String dbpassword = "";

		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection conn = DriverManager.getConnection(conn_str, dbusername, dbpassword);

			String select_sql = "SELECT * FROM users";
			Statement stmt = conn.createStatement();

			ResultSet rs = stmt.executeQuery(select_sql);

			while (rs.next()) {
				System.out.println(rs.getInt("id"));
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("age"));
				System.out.println(rs.getString("city"));
			}

//			String insert_sql = "INSERT INTO users VALUES (NULL, 'Priyanka', 30, 'Mumbai', NOW(), NOW())";
//			Statement stmt = conn.createStatement();
//			int result = stmt.executeUpdate(insert_sql);
//			System.out.println(result);

//			String delete_sql = "DELETE FROM users WHERE id = 3";
//			Statement stmt = conn.createStatement();
//			int result = stmt.executeUpdate(delete_sql);
//			System.out.println(result);

//			String update_sql = "UPDATE users SET city = 'Panvel' WHERE id = 2";
//			Statement stmt = conn.createStatement();
//			int result = stmt.executeUpdate(update_sql);
//			System.out.println(result);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

select.jsp

<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<% 

String conn_string = "jdbc:mysql://localhost:3306/company";
String db_username = "root";
String db_password = "";

Connection conn = null;

try{
	Class.forName("com.mysql.cj.jdbc.Driver");
	conn = DriverManager.getConnection(conn_string, db_username, db_password);
} catch(Exception e) {
	out.println(e);
}

String select_sql = "SELECT * FROM users";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(select_sql);

while(rs.next()) {
	out.println(String.format("Id: %s | Name: %s | Age: %s | City: %s<br>", rs.getInt("id"), rs.getString("name"), rs.getInt("age"), rs.getString("city")));
}

%>

insert.jsp

<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%
String conn_string = "jdbc:mysql://localhost:3306/company";
String db_username = "root";
String db_password = "";

Connection conn = null;

try{
	Class.forName("com.mysql.cj.jdbc.Driver");
	conn = DriverManager.getConnection(conn_string, db_username, db_password);
} catch(Exception e) {
	out.println(e);
}

String insert_sql = "INSERT INTO users VALUES (NULL, 'Priyanka', 30, 'Mumbai', NOW(), NOW())";
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate(insert_sql);

if(result == 1) {
	out.println("Record inserted successfully...");
} else {
	out.println("Something went wrong...");
}
%>

update.jsp

<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%
String conn_string = "jdbc:mysql://localhost:3306/company";
String db_username = "root";
String db_password = "";

Connection conn = null;

try{
	Class.forName("com.mysql.cj.jdbc.Driver");
	conn = DriverManager.getConnection(conn_string, db_username, db_password);
} catch(Exception e) {
	out.println(e);
}

String update_sql = "UPDATE users SET name = 'Palkar' WHERE id = 4";
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate(update_sql);

if(result == 1) {
	out.println("Record updated successfully...");
} else {
	out.println("Something went wrong...");
}
%>

delete.jsp

<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%
String conn_string = "jdbc:mysql://localhost:3306/company";
String db_username = "root";
String db_password = "";

Connection conn = null;

try{
	Class.forName("com.mysql.cj.jdbc.Driver");
	conn = DriverManager.getConnection(conn_string, db_username, db_password);
} catch(Exception e) {
	out.println(e);
}

String delete_sql = "DELETE FROM users WHERE id = 4";
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate(delete_sql);

if(result == 1) {
	out.println("Record deleted successfully...");
} else {
	out.println("Something went wrong...");
}
%>

functions.jsp

<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>

<%!
public Connection getConnection() {

		String conn_string = "jdbc:mysql://localhost:3306/company";
		String db_username = "root";
		String db_password = "";

		Connection conn = null;

		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection(conn_string, db_username, db_password);
		} catch (Exception e) {
			System.out.println(e);
		}

		return conn;
}

public void authorize(HttpSession session, HttpServletResponse response) {
	
	if(session.getAttribute("username") == null) {
		try {				
			response.sendRedirect("login_form.jsp?msg=Please login to access this page");
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

%>

include functions and header

<%@include file="functions.jsp" %>
<jsp:include page="header.jsp" />

Mini Car Inventory System

Creating a personal mini car inventory system from scratch using your best knowledge and skills. The system will have inventory of manufacturer and models (cars) of each manufacturer owned.

System should be created using your own frontend and backend framework and should use caching.

Frontend should be a webapp a.k.a. SPA. (Ie: no refreshing/reloading pages)

Technology to be used:

PHP (OOP)
MySql (Normalized Database Schema)
Javascript (JQuery – AJAX)
HTML, CSS and Bootstrap 5

Classes to be created:

Database – Class to deal with each and every operation of database.
Manufacturer – Class to deal with all operations related to car manufacturer.
Model – Class to deal with all operations related to car model.

Page 1: Add Manufacturer.
The page should contain a input box for manufacturer name and a submit button.

Page 2: Add Model.
This page should have a manufacturer dropdown on the right side and model name textbox on the left side (Both should be in the same line)

Add other details below about the car like “Color, manufacturing year, registration number, note and 2 pictures”. Pictures should be uploaded using any ajax plugin.

And lastly there should be a submit button.

Page 3: View Inventory.
This page should populate a table of all the models and manufacturers from the DB.

It should have the columns as below

Serial Number, Manufacturer Name, Model Name, Count

eg.

  1. Maruti WagonR 2
  2. Tata Nano 1

On clicking on the row, a popup will appear which will have details of the individual models like color, manufacturing year etc. (Basically all details from page 2) and a Sold clickable link.

On clicking Sold, the row will be deleted and the DB will be updated accordingly.

In addition to this, on Page 3 when users are viewing the inventory and in case a car is sold, the View Inventory table for the column Count will have to be dynamically updated in case a car is sold at that moment.

Similarly in case the users are on any other page or pop up of the system, they should get an alert saying “make model is sold” when a car is sold.

Wireframes

DATABASE Schema

Code for reference
https://github.com/shaileshsonare/mcis

Docker Cheat Sheet

docker --version
docker version

Dockerfile

FROM php:7-apache
COPY . /var/www/html
WORKDIR /var/www/html
#CMD php index.php
EXPOSE 80
docker build -t helloworldphp7 .

To run docker image

docker run -p 8080:80 -v /c/xampp/htdocs/dockerdemo:/var/www/html -d php:8-apache

OR

docker run -p 8080:80 --name docker-apache -v /c/xampp/htdocs/dockerdemo:/var/www/html:ro -d php:8-apache

OR

docker run -d -p 8080:8080 --name jsp-project -v /root/jsp/:/usr/local/tomcat/webapps/test tomcat:9.0.1-jre8-alpine

To run docker image in interactive mode

docker container run -it <docker-image> /bin/bash

To List all images

docker images
docker images -q

To List all container

docker ps
docker ps -a
docker ps -aq

To remove image

docker rmi imagename

OR

docker rmi $(docker images -aq)

To remove container

docker rm <container-name>

OR

docker rm $(docker ps -aq)

OR

docker rm -f $(docker ps -aq)

To stop container

docker stop <container-name>

OR

docker stop $(docker ps -aq)

To push local image on docker hub

First create repository in dockerhub like we used to create in gitlab/github

docker login
docker tag firstimage YOUR_DOCKERHUB_NAME/firstimage
docker images
docker push YOUR_DOCKERHUB_NAME/firstimage

Working with MySQL

docker pull mysql/mysql-server:latest
docker images
docker create -v /var/lib/mysql --name mysqldata mysql/mysql-server:latest
docker ps -a
docker run -p 3307:3307 -d -e MYSQL_ROOT_PASSWORD=root --volumes-from mysqldata --name=mysqldb1 mysql/mysql-server:latest
docker ps
docker exec -it mysqldb1 bash
mysql -uroot -p