Summary Files Commits Branches @commit @diff @stats
path: root / src
diff options
context:
space:
mode:
Commitf8c1df9a9a24be0ff3811dc33e00f92bf51465ab (patch)
Author
 Kamen Mladenov <kamen.d.mladenov@protonmail.com>
2021-04-03 11:54:52 +0300
Committer
 GitHub <noreply@github.com>
2021-04-03 11:54:52 +0300
Files56dfbe9d57e3150b480928da543b3dba30e11692 /src
devrix-job-board-f8c1df9a9a24be0ff3811dc33e00f92bf51465ab.tar
devrix-job-board-f8c1df9a9a24be0ff3811dc33e00f92bf51465ab.tar.gz
devrix-job-board-f8c1df9a9a24be0ff3811dc33e00f92bf51465ab.zip
Parentaa2e361c3114b53ac7858e118454b9dfaf51ebe4 (diff)
Parentfff8c08ad7f3845eb32671292392cbf08bb738c9 (diff)
Merge pull request #1 from Syndamia/dev v0.1
Implemented main functionality
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="/">&lt; 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="/">&lt; 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="/">&lt; 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">&lt; 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>