diff options
Merge pull request #1 from Syndamia/dev v0.1
Implemented main functionality
18 files changed, 622 insertions, 0 deletions
| -rw-r--r-- | src/controllers/BaseController.php | 36 | ||||
| -rw-r--r-- | src/controllers/CreateOfferController.php | 21 | ||||
| -rw-r--r-- | src/controllers/DashboardController.php | 31 | ||||
| -rw-r--r-- | src/controllers/DashboardLoginController.php | 25 | ||||
| -rw-r--r-- | src/controllers/EditOfferController.php | 30 | ||||
| -rw-r--r-- | src/controllers/LandingController.php | 16 | ||||
| -rw-r--r-- | src/document-bot.php | 2 | ||||
| -rw-r--r-- | src/document-top.php | 5 | ||||
| -rw-r--r-- | src/index.php | 34 | ||||
| -rw-r--r-- | src/models/Company.php | 47 | ||||
| -rw-r--r-- | src/models/DB.php | 176 | ||||
| -rw-r--r-- | src/models/DBModel.php | 21 | ||||
| -rw-r--r-- | src/models/JobOffer.php | 93 | ||||
| -rw-r--r-- | src/views/create-offer.php | 22 | ||||
| -rw-r--r-- | src/views/dashboard-login.php | 13 | ||||
| -rw-r--r-- | src/views/dashboard.php | 17 | ||||
| -rw-r--r-- | src/views/edit-offer.php | 25 | ||||
| -rw-r--r-- | src/views/landing.php | 8 |
diff --git a/src/controllers/BaseController.php b/src/controllers/BaseController.php new file mode 100644 index 0000000..2c2a647 --- /dev/null +++ b/src/controllers/BaseController.php @@ -0,0 +1,36 @@ +<?php +class BaseController { + public static function invoke() { + switch ($_SERVER["REQUEST_METHOD"]) { + case "POST": + static::post(); + break; + case "PUT": + static::put(); + break; + case "DELETE": + static::delete(); + break; + default: + static::get(); + break; + } + } + + protected static function get() { + echo "GET method not implemented!"; + } + + protected static function post() { + + echo "POST method not implemented!"; + } + + protected static function put() { + echo "PUT method not implemented!"; + } + + protected static function delete() { + echo "DELETE method not implemented!"; + } +} diff --git a/src/controllers/CreateOfferController.php b/src/controllers/CreateOfferController.php new file mode 100644 index 0000000..a223463 --- /dev/null +++ b/src/controllers/CreateOfferController.php @@ -0,0 +1,21 @@ +<?php +include_once('controllers/BaseController.php'); +include_once('models/Company.php'); + +class CreateOfferController extends BaseController { + private static $companies; + + public static function get() { + self::$companies = Company::getAllFromDB(); + include 'views/create-offer.php'; + } + + public static function post() { + $newJobOffer = new JobOffer($_POST['title'], $_POST['description'], $_POST['company'], $_POST['salary']); + JobOffer::insertIntoDB($newJobOffer); + + // Redirect to landing page + header("Location: /", TRUE, 301); + exit(); + } +} diff --git a/src/controllers/DashboardController.php b/src/controllers/DashboardController.php new file mode 100644 index 0000000..548f60b --- /dev/null +++ b/src/controllers/DashboardController.php @@ -0,0 +1,31 @@ +<?php +include_once('controllers/BaseController.php'); +include_once('models/JobOffer.php'); +include_once('models/Company.php'); +include_once('controllers/EditOfferController.php'); + +class DashboardController extends BaseController { + public static $companies = array(); + + public static function get() { + $jobs = JobOffer::getAllFromDB(); + foreach(Company::getAllFromDB() as $company) { + self::$companies[$company->id] = $company->name; + } + include "views/dashboard.php"; + } + + public static function post() { + switch($_POST['_method']) { + case "get": + EditOfferController::get(); + break; + case "put": + EditOfferController::put(); + break; + case "delete": + EditOfferController::delete(); + break; + } + } +} diff --git a/src/controllers/DashboardLoginController.php b/src/controllers/DashboardLoginController.php new file mode 100644 index 0000000..fe2009b --- /dev/null +++ b/src/controllers/DashboardLoginController.php @@ -0,0 +1,25 @@ +<?php +include_once('controllers/BaseController.php'); +include_once('controllers/DashboardController.php'); + +class DashboardLoginController extends BaseController { + private static $message; + + public static function get() { + include "views/dashboard-login.php"; + } + + public static function post() { + if (isset($_POST['_method'])) { + DashboardController::invoke(); + } + else if ($_POST['username'] == "admin" && $_POST['password'] == "admin") { + // Load normal dashboard + DashboardController::get(); + } + else { + self::$message = "Bad credentials!"; + include "views/dashboard-login.php"; + } + } +} diff --git a/src/controllers/EditOfferController.php b/src/controllers/EditOfferController.php new file mode 100644 index 0000000..ae49c5b --- /dev/null +++ b/src/controllers/EditOfferController.php @@ -0,0 +1,30 @@ +<?php +include_once('controllers/BaseController.php'); +include_once('models/JobOffer.php'); +include_once('models/Company.php'); +include_once('controllers/DashboardController.php'); + +class EditOfferController extends BaseController { + private static $job; + private static $companies; + + public static function get() { + self::$job = JobOffer::getFromDBById($_POST['jobId']); + self::$companies = Company::getAllFromDB(); + include "views/edit-offer.php"; + } + + public static function put() { + $newJobOffer = new JobOffer($_POST['title'], $_POST['description'], $_POST['company'], $_POST['salary']); + $newJobOffer->id = $_POST['id']; + JobOffer::updateFromDB($newJobOffer); + + DashboardController::get(); + } + + public static function delete() { + JobOffer::deleteFromDB($_POST['jobId']); + + DashboardController::get(); + } +} diff --git a/src/controllers/LandingController.php b/src/controllers/LandingController.php new file mode 100644 index 0000000..ffa8644 --- /dev/null +++ b/src/controllers/LandingController.php @@ -0,0 +1,16 @@ +<?php +include_once("models/JobOffer.php"); +include_once('models/Company.php'); +include_once("controllers/BaseController.php"); + +class LandingController extends BaseController { + private static $companies = array(); + + public static function get() { + $jobs = JobOffer::getAllFromDB(); + foreach(Company::getAllFromDB() as $company) { + self::$companies[$company->id] = $company->name; + } + include "views/landing.php"; + } +} diff --git a/src/document-bot.php b/src/document-bot.php new file mode 100644 index 0000000..7fb2bd6 --- /dev/null +++ b/src/document-bot.php @@ -0,0 +1,2 @@ + </body> +</html> diff --git a/src/document-top.php b/src/document-top.php new file mode 100644 index 0000000..c6f9116 --- /dev/null +++ b/src/document-top.php @@ -0,0 +1,5 @@ +<html> + <head> + <title>DevriX Job Board</title> + </head> + <body> diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..676cd56 --- /dev/null +++ b/src/index.php @@ -0,0 +1,34 @@ +<?php require "document-top.php"; ?> + +<?php +include_once("controllers/LandingController.php"); +include_once("controllers/CreateOfferController.php"); +include_once("controllers/DashboardLoginController.php"); + +/* The landing page practically acts as our page router. + * All request get redirected to here (look at the devrix-job-board.conf) + * Thanks https://www.taniarascia.com/the-simplest-php-router/ + */ + +$request = $_SERVER['REQUEST_URI']; + +switch ($request) { + case "": + case "/": + LandingController::invoke(); + break; + case "/CreateOffer": + case "/CreateOffer/": + CreateOfferController::invoke(); + break; + case "/Dashboard": + case "/Dashboard/": + DashboardLoginController::invoke(); + break; + default: + http_response_code(404); + break; +} +?> + +<?php require "document-bot.php"; ?> diff --git a/src/models/Company.php b/src/models/Company.php new file mode 100644 index 0000000..1dfb05e --- /dev/null +++ b/src/models/Company.php @@ -0,0 +1,47 @@ +<?php +include_once("models/DBModel.php"); + +class Company extends DBModel { + public string $name; + + function __construct(string $name) { + $this->name = $name; + } + + /* + * Everything from here is static functionality + */ + + public const TABLE_NAME = "companies"; + + static function __constructStatic() { + $columns = array( + "name " . DB::STRING_TYPE, + ); + self::$DB->createTable(self::TABLE_NAME, $columns); + } + + /* Create */ + + /** + * Inserts the giveb JobOffer into the databse. The id is automatically generated in the database. + * + * @param Company $com + */ + static function insertIntoDB($com) { + self::$DB->insertValue(self::TABLE_NAME, $com->name); + } + + /* Read */ + + /** + * Returns all Companies from the database. + * + * @return Company[] + */ + static function getAllFromDB() { + return self::$DB->getAllValues(self::TABLE_NAME); + } +} + +Company::__constructStatic(); diff --git a/src/models/DB.php b/src/models/DB.php new file mode 100644 index 0000000..8174831 --- /dev/null +++ b/src/models/DB.php @@ -0,0 +1,176 @@ +<?php +/** + * The model that has the database functionality. DO NOT instantiate this class! If you need an instance, extend the DBModel class! + */ +class DB { + private static $servername = "localhost"; + private static $username = "root"; + private static $password = "password"; + private static $dbname = "devrix_job_board"; + + public const STRING_TYPE = "VARCHAR(100)"; + public const FLOAT_TYPE = "DOUBLE(16,4)"; + public const INTEGER_TYPE = "INT"; + + private PDO $connection; + + function __construct() { + // Try to connect + try { + $this->connection = new PDO("mysql:host=" . self::$servername, self::$username, self::$password); + $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + catch (PDOException $e) { + echo "[DB Exception]: " . $e->getMessage(); + } + + // Make sure the actual db exists + $createDBQuery = "CREATE DATABASE IF NOT EXISTS " . self::$dbname . ";"; + + $this->connection->exec($createDBQuery); + + // Connect to the actual database + $this->connection->exec("USE " . self::$dbname); + } + + /** + * @return string + */ + static function genFK(string $currentColumn, string $foreignTable, string $foreignColumn) { + return "CONSTRAINT fk_{$currentColumn}_{$foreignTable} FOREIGN KEY ({$currentColumn}) REFERENCES {$foreignTable}($foreignColumn)"; + } + + /* Create */ + + /** + * Creates a table, with the given name and given column information. + * **WARNING**: The method also creates an auto-incremented int id column, **DO NOT** specify it! + * + * @param string[] $columns + * Represents the column information. Each value must be like: "column_name data_type", where the data_type should be taken + * from the constant values of DB class. + * Example value: array("first_name " . DB::STRING_TYPE, "age " . DB::INTEGER_TYPE, "income " . DB::FLOAT_TYPE) + * + * @param string[] $foreignKeys - OPTIONAL + * Represents the foreign keys. All foreign keys **MUST** be generated the the static DB method genFK. + * Example value: array(DB::genFK("jobId", "jobs", "id"), DB::genFK("cityId", "cities", "id")) + */ + function createTable(string $tableName, array $columns, array $foreignKeys = null) { + $query = "CREATE TABLE IF NOT EXISTS {$tableName}( + id INT NOT NULL AUTO_INCREMENT, "; + + foreach ($columns as $column) { + $query .= "{$column}, "; + } + + $query .= "PRIMARY KEY (id), "; + + foreach ($foreignKeys as $fk) { + $query .= "{$fk}, "; + } + + $query = rtrim($query, ", "); + $query .= ");"; + + try { + $this->connection->exec($query); + } + catch (PDOException $e) { + echo "[DB Exception]: " . $e->getMessage(); + } + } + + /** + * Inserts a value in a given table. + * + * @param string[] $values + * Represents the data that should be inserted. The values should be ordered the same way the table columns are ordered. + * Example: "John", 20, 2000.3 + * **WARNING**: DO NOT insert the id value + */ + function insertValue(string $tableName, ...$values) { + $query = "INSERT INTO {$tableName} VALUES(NULL, "; + + foreach($values as $value) { + if (gettype($value) == "string") { + $query .= "'{$value}', "; + } + else { + $query .= "{$value}, "; + } + } + $query = rtrim($query, ", "); + + $query .= ");"; + + try { + $this->connection->exec($query); + } + catch (PDOException $e) { + echo "[DB Exception]: " . $e->getMessage(); + } + } + + /* Read */ + + /** + * Returns the next value that has the given id. + */ + function getById(string $tableName, int $id) { + $sth = $this->connection->prepare("SELECT * FROM `{$tableName}` WHERE id = {$id}"); + $sth->execute(); + + return $sth->fetch(PDO::FETCH_OBJ); + } + + /** + * Returns all values inside a table. + */ + function getAllValues(string $tableName) { + $sth = $this->connection->prepare("SELECT * FROM `{$tableName}`"); + $sth->execute(); + + return $sth->fetchAll(PDO::FETCH_OBJ); + } + + /* Update */ + + /** + * Updates the value with the given id inside the specified table. + * + * @param string[] $values + * Represents the data that should be updated. There should always be an even amount of data, where you alternate the column name and column value. + * Example: "first_name", "John", "age", 20, "income", 2000.3 + */ + function updateById(string $tableName, int $id, ...$values) { + $query = "UPDATE {$tableName} SET "; + + for ($i = 0; $i < sizeof($values); $i += 2) { + $query .= "{$values[$i]} = " . (gettype($values[$i+1]) == "string" ? "'{$values[$i+1]}'" : $values[$i+1]) . ", "; + } + $query = rtrim($query, ", "); + + $query .= " WHERE id = {$id};"; + + try { + $this->connection->exec($query); + } + catch (PDOException $e) { + echo "[DB Exception]: " . $e->getMessage(); + } + } + + /* Delete */ + + /** + * Deletes the value with the given id inside the given table. + */ + function deleteById(string $tableName, int $id) { + try { + $this->connection->exec("DELETE FROM {$tableName} WHERE id = {$id}"); + } + catch (PDOException $e) { + echo "[DB Exception]: " . $e->getMessage(); + } + } +} diff --git a/src/models/DBModel.php b/src/models/DBModel.php new file mode 100644 index 0000000..4e10c18 --- /dev/null +++ b/src/models/DBModel.php @@ -0,0 +1,21 @@ +<?php +include_once("DB.php"); + +/** + * A class, mainly for holding the static DB class intance. You can also get your model id from here. + */ +abstract class DBModel { + /** + * Used ONLY for gotten values form the database. Must not be assigned to, since it is AUTO_INCREMENT. + * The id column is set by default in the DB class. + */ + public int $id; + + protected static DB $DB; + + public static function __constructStatic() { + self::$DB = new DB(); + } +} + +DBModel::__constructStatic(); diff --git a/src/models/JobOffer.php b/src/models/JobOffer.php new file mode 100644 index 0000000..b86ff86 --- /dev/null +++ b/src/models/JobOffer.php @@ -0,0 +1,93 @@ +<?php +include_once("models/DBModel.php"); +include_once("models/Company.php"); + +/** + * Model that contains the required JobOffer properties. It also contains the request methods to the job_offers table. + */ +class JobOffer extends DBModel { + public string $title; + public string $description; + public int $companyId; + public float $salary; + + function __construct(string $title, string $description, int $companyId, float $salary) { + $this->title = $title; + $this->description = $description; + $this->companyId = $companyId; + $this->salary = $salary; + } + + /* + * Everything from here is static functionality + */ + + public const TABLE_NAME = "job_offers"; + + static function __constructStatic() { + $columns = array( + "title " . DB::STRING_TYPE, + "description " . DB::STRING_TYPE, + "companyId " . DB::INTEGER_TYPE, // Requires a foreign key + "salary " . DB::FLOAT_TYPE, + ); + $foreignKeys = array( + DB::genFK("companyId", Company::TABLE_NAME, "id") + ); + self::$DB->createTable(self::TABLE_NAME, $columns, $foreignKeys); + } + + /* Create */ + + /** + * Inserts the giveb JobOffer into the databse. The id is automatically generated in the database. + * + * @param JobOffer $jb + */ + static function insertIntoDB($jb) { + self::$DB->insertValue(self::TABLE_NAME, $jb->title, $jb->description, $jb->companyId, $jb->salary); + } + + /* Read */ + + /** + * Returns the JobOffer with the given id from the database. + * + * @return JobOffer + */ + static function getFromDBById(int $id) { + return self::$DB->getById(self::TABLE_NAME, $id); + } + + /** + * Returns all JobOffers from the database. + * + * @return JobOffer[] + */ + static function getAllFromDB() { + return self::$DB->getAllValues(self::TABLE_NAME); + } + + /* Update */ + + /** + * Updates the given JobOffer from the database. + * **WARNING**: the JobOffer **MUST** have it's database id. + * + * @param JobOffer $jb + */ + static function updateFromDB($jb) { + self::$DB->updateById(self::TABLE_NAME, $jb->id, "title", $jb->title, "description", $jb->description, "companyId", $jb->companyId, "salary", $jb->salary); + } + + /* Delete */ + + /** + * Deletes the JobOffer with the given id from the database. + */ + static function deleteFromDB(int $id) { + self::$DB->deleteById(self::TABLE_NAME, $id); + } +} + +JobOffer::__constructStatic(); diff --git a/src/views/create-offer.php b/src/views/create-offer.php new file mode 100644 index 0000000..19f2186 --- /dev/null +++ b/src/views/create-offer.php @@ -0,0 +1,22 @@ +<form method="post"> + <label for="title">Job Title: </label> + <input type="text" name="title"> + <br> + <label for="description">Job Description: </label> + <textarea type="text" name="description"></textarea> + <br> + <label for="company">Company: </label> + <select name="company"> + <?php + foreach(self::$companies as $company) { + echo "<option value=\"{$company->id}\">{$company->name}</option>"; + } + ?> + </select> + <br> + <label for="salary">Salary: </label> + <input type="number" name="salary" min="1" placeholder="1"> + <br> + <input type="submit" value="Submit"> +</form> +<a href="/">< Back</a> diff --git a/src/views/dashboard-login.php b/src/views/dashboard-login.php new file mode 100644 index 0000000..a4cefe7 --- /dev/null +++ b/src/views/dashboard-login.php @@ -0,0 +1,13 @@ +<form method="post"> + <label for="username">Username: </label> + <input type="text" name="username"> + <br> + <label for="password">Password</label> + <input type="password" name="password"> + <br> + <input type="submit" value="Login"> +</form> +<?php + echo self::$message; +?> +<a href="/">< Back</a> diff --git a/src/views/dashboard.php b/src/views/dashboard.php new file mode 100644 index 0000000..06be539 --- /dev/null +++ b/src/views/dashboard.php @@ -0,0 +1,17 @@ +<?php + foreach($jobs as $job) { + echo "{$job->id} {$job->title} {$job->description} " . self::$companies[$job->companyId] . " {$job->salary} + <form method=\"post\"> + <input type=\"hidden\" name=\"_method\" value=\"get\"> + <input type=\"hidden\" name=\"jobId\" value=\"{$job->id}\"> + <input type=\"submit\" value=\"Edit\"> + </form> + <form method=\"post\"> + <input type=\"hidden\" name=\"_method\" value=\"delete\"> + <input type=\"hidden\" name=\"jobId\" value=\"{$job->id}\"> + <input type=\"submit\" value=\"Delete\"> + </form> + <br>"; + } +?> +<a href="/">< Back</a> diff --git a/src/views/edit-offer.php b/src/views/edit-offer.php new file mode 100644 index 0000000..a6d699e --- /dev/null +++ b/src/views/edit-offer.php @@ -0,0 +1,25 @@ +<form method="post"> + <input type="hidden" name="id" value="<?php echo self::$job->id?>"> + <label for="title">Job Title: </label> + <input type="text" name="title" value="<?php echo self::$job->title ?>"> + <br> + <label for="description">Job Description: </label> + <textarea type="text" name="description"><?php echo self::$job->description ?></textarea> + <br> + <label for="company">Company: </label> + <select name="company" selected="<?php echo self::$job->companyId ?>"> + <?php + foreach(self::$companies as $company) { + echo "<option value=\"{$company->id}\""; + echo (self::$job->companyId == $company->id ? "selected" : "") . ">{$company->name}</option>"; + } + ?> + </select> + <br> + <label for="salary">Salary: </label> + <input type="number" name="salary" min="1" placeholder="1" value="<?php echo self::$job->salary ?>"> + <br> + <input type="hidden" name="_method" value="put"> + <input type="submit" value="Update"> +</form> +<a href="/Dashboard">< Back to Dashboard</a> diff --git a/src/views/landing.php b/src/views/landing.php new file mode 100644 index 0000000..6124f90 --- /dev/null +++ b/src/views/landing.php @@ -0,0 +1,8 @@ +<?php + foreach($jobs as $job) { + echo "{$job->title} {$job->description} " . self::$companies[$job->companyId] . " {$job->salary}<br>"; + } +?> + +<a href="/CreateOffer">Create a new Job Offer</a> +<a href="/Dashboard">Dashboard</a> |
