Updated API

This commit is contained in:
Maximilian Giller 2020-11-06 21:04:45 +01:00
parent fd5a824b89
commit 5c30876c80
18 changed files with 469 additions and 207 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ juggl/config/config.txt
juggl/config/config.path
juggl/config/config.php
graphics
.vscode

View file

@ -0,0 +1,8 @@
<?php
$config = [
"host" => "localhost",
"dbname" => "juggl",
"username" => "juggl",
"password" => "?=5,}f_F&){;@xthx-[i",
"table_prefix" => "ju_"
];

View file

@ -0,0 +1,28 @@
<?php
session_start();
require_once(__DIR__ . "/services/apiBranch.inc.php");
require_once(__DIR__ . "/services/responses.inc.php");
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
class EndRecordBranch extends ApiBranch
{
function get(ParamCleaner $params)
{
respondStatus(405);
}
function post(ParamCleaner $params)
{
$user_id = $params->get("user_id");
$params->select("request");
if ($params->exists(["end_time", "record_id"]) == false) {
respondStatus(400, "Missing parameter");
}
updateEndRecord($user_id, $params);
}
}
$branch = new EndRecordBranch();
$branch->execute();

View file

@ -0,0 +1,34 @@
<?php
session_start();
require_once(__DIR__ . "/services/apiBranch.inc.php");
require_once(__DIR__ . "/services/jsonBuilder.inc.php");
require_once(__DIR__ . "/services/responses.inc.php");
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
class GetRecordBranch extends ApiBranch
{
function get(ParamCleaner $params)
{
respondStatus(405);
}
function post(ParamCleaner $params)
{
$user_id = $params->get("user_id");
$params->select("request");
if ($params->exists(["record_id"]) == false) {
respondStatus(400, "Missing parameter");
}
$record = getTimeRecord($user_id, $params->get("record_id"));
$json = new JsonBuilder();
$json->addRecords([$record]);
respondJson($json);
}
}
$branch = new GetRecordBranch();
$branch->execute();

View file

@ -1,8 +1,10 @@
<?php
require_once(__DIR__ . "/basicEnum.inc.php");
class DbOperations {
function __construct ($tablePrefix = null) {
class DbOperations
{
function __construct($tablePrefix = null)
{
$this->resetQuery();
$this->tablePrefix = $tablePrefix;
@ -14,14 +16,15 @@ class DbOperations {
}
}
function resetQuery() {
function resetQuery()
{
$this->query = "";
$this->data = array();
$this->table = "";
$this->tablePrefix = "";
}
private function openConnection () {
private function openConnection()
{
$host = $this->config['host'];
$dbname = $this->config['dbname'];
$dsn = "mysql:host=$host;dbname=$dbname";
@ -31,7 +34,8 @@ class DbOperations {
$this->pdo = new PDO($dsn, $this->config['username'], $this->config['password'], $options);
}
function select (string $table, array $attributes = array()) {
function select(string $table, array $attributes = array())
{
$this->table = $this->tablePrefix . $table;
if (count($attributes) == 0)
$formattedAttributes = "*";
@ -51,13 +55,15 @@ class DbOperations {
}
function orderBy (string $attribute, string $order = Order::ASC) {
function orderBy(string $attribute, string $order = Order::ASC)
{
$this->addToQuery("ORDER BY $attribute $order");
return $this;
}
static function getLatestIdInTable (string $table, string $attribute = "id") {
static function getLatestIdInTable(string $table, string $attribute = "id")
{
$db = new DbOperations();
$db->select($table, array($attribute));
$db->orderBy($attribute, Order::DESC);
@ -65,7 +71,8 @@ class DbOperations {
return $db->execute()[0][$attribute];
}
function insert (string $table, array $data) {
function insert(string $table, array $data)
{
$this->table = $this->tablePrefix . $table;
$attributes = implode(", ", array_keys($data));
@ -80,7 +87,8 @@ class DbOperations {
return $this;
}
function insertMultiple (string $table, array $attributes, array $data) {
function insertMultiple(string $table, array $attributes, array $data)
{
$this->table = $this->tablePrefix . $table;
$attributesString = implode(", ", $attributes);
@ -107,7 +115,8 @@ class DbOperations {
return $this;
}
function update (string $table, array $data) {
function update(string $table, array $data)
{
$this->table = $this->tablePrefix . $table;
$sets = array();
@ -122,7 +131,8 @@ class DbOperations {
return $this;
}
function delete (string $table) {
function delete(string $table)
{
$this->table = $this->tablePrefix . $table;
$this->addToQuery("DELETE FROM $this->tablePrefix$table");
@ -130,12 +140,25 @@ class DbOperations {
return $this;
}
private function addToQuery (string $phrase) {
function limit(int $limit, int $offset = null)
{
$this->addToQuery("LIMIT $limit");
if ($offset != null) {
$this->addToQuery("OFFSET $offset");
}
return $this;
}
private function addToQuery(string $phrase)
{
$delimeter = " ";
$this->query = implode($delimeter, array($this->query, $phrase));
}
function where (string $attribute, string $comparison, $value, string $connector = Combination::AND) {
function where(string $attribute, string $comparison, $value, string $connector = Combination::AND)
{
if (Comparison::isValidValue($comparison) == false)
return;
@ -149,7 +172,33 @@ class DbOperations {
return $this;
}
function innerJoin (string $table, string $externAttribute, string $internAttribute = "", string $internTable = "") {
function whereOneOf(string $attribute, string $comparison, $values, string $connector = Combination::AND)
{
if (Comparison::isValidValue($comparison) == false)
return;
$keyWord = "WHERE";
if (!(strpos($this->query, $keyWord) === false))
$keyWord = $connector;
$whereClause = "$keyWord ( ";
for ($i = 0; $i < sizeof($values); $i++) {
if ($i > 0) {
$whereClause .= " OR ";
}
$valueId = $this->addData($values[$i], $attribute . '_' . $i);
$whereClause .= "$attribute $comparison $valueId";
}
$whereClause .= " )";
$this->addToQuery($whereClause);
return $this;
}
function innerJoin(string $table, string $externAttribute, string $internAttribute = "", string $internTable = "")
{
if ($internTable === "") {
$internTable = substr($this->table, sizeof($this->tablePrefix));
}
@ -164,14 +213,29 @@ class DbOperations {
return $this;
}
private function addData($data, $attribute) {
private function addData($data, $attribute)
{
$name = str_replace(".", "", $attribute);
$this->data[$name] = $data;
return ":" . $name;
}
function execute() {
function addSql($sql)
{
$this->addToQuery($sql);
}
function addValue($value)
{
$identifier = "customIdentifier" . $this->customValueId;
$this->customValueId += 1;
$this->addToQuery($this->addData($value, $identifier));
}
function execute()
{
try {
$this->openConnection();
@ -193,7 +257,8 @@ class DbOperations {
}
}
function sql(string $sqlStatement, array $data) {
function sql(string $sqlStatement, array $data)
{
$this->query = $sqlStatement;
foreach ($data as $attribute => $value) {
@ -202,7 +267,8 @@ class DbOperations {
}
}
abstract class Comparison extends BasicEnum {
abstract class Comparison extends BasicEnum
{
const EQUAL = "=";
const GREATER_THAN = ">";
const GREATER_THAN_OR_EQUAL = ">=";
@ -212,13 +278,14 @@ abstract class Comparison extends BasicEnum {
const LIKE = "LIKE";
}
abstract class Combination extends BasicEnum {
abstract class Combination extends BasicEnum
{
const AND = "AND";
const OR = "OR";
}
abstract class Order extends BasicEnum {
abstract class Order extends BasicEnum
{
const ASC = "ASC";
const DESC = "DESC";
}
?>

View file

@ -0,0 +1,49 @@
<?php
class JsonBuilder
{
function __construct()
{
$this->jsonData = array();
}
function getJson()
{
return json_encode($this->jsonData, JSON_FORCE_OBJECT);
}
function getArray()
{
return $this->jsonData;
}
function addRecords(array $records)
{
$columns = array(
"record_id" => "",
"start_time" => "",
"end_time" => "",
"duration" => "",
"user_id" => "",
"project_id" => "",
"start_device_id" => ""
);
foreach ($records as $record) {
$this->jsonData['records'] = array();
$this->jsonData['records'][] = $this->createJsonArray($record, $columns);
}
return $this;
}
private function createJsonArray(array $data, array $columns)
{
$jsonArray = array();
foreach ($columns as $key => $column) {
if ($column === "") {
$column = $key;
}
$jsonArray[$key] = $data[$column];
}
return $jsonArray;
}
}

View file

@ -0,0 +1,167 @@
<?php
require_once(__DIR__ . "/services/dbOperations.inc.php");
function addStartRecord($user_id, $params, $project_id = null, $start_device_id = null)
{
$data = [
"user_id" => $user_id,
"start_time" => $params->get("start_time"),
"project_id" => $project_id,
"start_device_id" => $start_device_id
];
$db = new DbOperations();
$db->insert("time_records", $data);
$db->execute();
}
function addTimeRecord($user_id, $params, $project_id = null, $start_device_id = null)
{
$data = [
"user_id" => $user_id,
"start_time" => $params->get("start_time"),
"end_time" => $params->get("end_time"),
"duration" => $params->get("duration"),
"project_id" => $project_id,
"start_device_id" => $start_device_id
];
$db = new DbOperations();
$db->insert("time_records", $data);
$db->execute();
}
function getTimeRecord($user_id, $record_id)
{
$db = new DbOperations();
$db->select("time_records");
$db->where("user_id", Comparison::EQUAL, $user_id);
$db->where("record_id", Comparison::EQUAL, $record_id);
$result = $db->execute();
if (count($result) <= 0) {
return null;
}
$result = $result[0];
// Is still running?
if ($result["end_time"] == null) {
$result["duration"] = calcDuration($result["start_time"]);
}
return $result;
}
function getProjectRecord($user_id, $project_id, $finished = null)
{
$db = new DbOperations();
$db->select("time_records");
$db->where("user_id", Comparison::EQUAL, $user_id);
$db->where("project_id", Comparison::EQUAL, $project_id);
if ($finished != null) {
$comp = Comparison::UNEQUAL;
if ($finished == false) {
$comp = Comparison::EQUAL;
}
$db->where("end_time", $comp, null);
}
$db->orderBy("start_time", Order::DESC);
$result = $db->execute();
if (count($result) <= 0) {
return null;
}
$result = $result[0];
// Is still running?
if ($result["end_time"] == null) {
$result["duration"] = calcDuration($result["start_time"]);
}
return $result;
}
function updateEndRecord($user_id, $params)
{
$record_id = $params->get("record_id");
// Get start instance to calculate duration
$start_time = getTimeRecord($user_id, $record_id)[0]["start_time"];
$data = [
"end_time" => $params->get("end_time"),
"duration" => calcDuration($start_time, $params->get("end_time"))
];
$db = new DbOperations();
$db->update("time_records", $data);
$db->where("user_id", Comparison::EQUAL, $user_id);
$db->where("record_id", Comparison::EQUAL, $record_id);
$db->execute();
}
function updateTimeRecord($user_id, $params)
{
$data = [];
$anythingUpdated = false;
if ($params->exists(["start_time"])) {
$data["start_time"] = $params->get("start_time");
$anythingUpdated = true;
}
if ($params->exists(["end_time"])) {
$data["end_time"] = $params->get("end_time");
$anythingUpdated = true;
}
if ($params->exists(["duration"])) {
$data["duration"] = $params->get("duration");
$anythingUpdated = true;
}
if ($params->exists(["project_id"])) {
$data["project_id"] = $params->get("project_id");
$anythingUpdated = true;
}
if ($params->exists(["start_device_id"])) {
$data["start_device_id"] = $params->get("start_device_id");
$anythingUpdated = true;
}
if ($anythingUpdated == false) {
return;
}
$db = new DbOperations();
$db->update("time_records", $data);
$db->where("user_id", Comparison::EQUAL, $user_id);
$db->where("record_id", Comparison::EQUAL, $params->get("record_id"));
$db->execute();
}
function isProjectValid($project_id, $user_id)
{
$db = new DbOperations();
$db->select("projects");
$db->where("project_id", Comparison::EQUAL, $project_id);
$db->where("user_id", Comparison::EQUAL, $user_id);
return count($db->execute()) == 1;
}
function isDeviceValid($start_device_id, $user_id)
{
$db = new DbOperations();
$db->select("devices");
$db->where("start_device_id", Comparison::EQUAL, $start_device_id);
$db->where("user_id", Comparison::EQUAL, $user_id);
return count($db->execute()) == 1;
}
function calcDuration($start_time, $end_time = "NOW")
{
return (int)((new DateTime($start_time))->diff(new DateTime($end_time))->format("%s"));
}

View file

@ -0,0 +1,50 @@
<?php
session_start();
require_once(__DIR__ . "/services/apiBranch.inc.php");
require_once(__DIR__ . "/services/jsonBuilder.inc.php");
require_once(__DIR__ . "/services/responses.inc.php");
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
class StartRecordBranch extends ApiBranch
{
function get(ParamCleaner $params)
{
respondStatus(405);
}
function post(ParamCleaner $params)
{
$user_id = $params->get("user_id");
$params->select("request");
if ($params->exists(["start_time"]) == false) {
respondStatus(400, "Missing parameter");
}
$project_id = $params->get("project_id");
if (isProjectValid($project_id, $user_id) == false) {
$project_id = null;
}
$device_id = $params->get("start_device_id");
if (isDeviceValid($device_id, $user_id) == false) {
$device_id = null;
}
// Does a running record for that project already exist?
if (getProjectRecord($user_id, $project_id, false) != null) {
respondStatus(409, "Project record already started");
}
addStartRecord($user_id, $params, $project_id, $device_id);
$record = getProjectRecord($user_id, $project_id, false);
$json = new JsonBuilder();
$json->addRecords([$record]);
respondJson($json);
}
}
$branch = new StartRecordBranch();
$branch->execute();

View file

@ -1,37 +0,0 @@
<?php
class JsonBuilder {
function __construct () {
$this->jsonData = array();
}
function getJson () {
return json_encode($this->jsonData, JSON_FORCE_OBJECT);
}
function getArray () {
return $this->jsonData;
}
function addCategories (array $categories) {
$columns = array("id" => "",
"name" => "");
foreach ($categories as $category) {
$this->jsonData['categories'] = array();
$this->jsonData['categories'][] = $this->createJsonArray($category, $columns);
}
return $this;
}
private function createJsonArray (array $data, array $columns) {
$jsonArray = array();
foreach ($columns as $key => $column) {
if ($column === "") {
$column = $key;
}
$jsonArray[$key] = $data[$column];
}
return $jsonArray;
}
}
?>

View file

@ -1,110 +0,0 @@
<?php
session_start();
require_once(__DIR__."/services/apiBranch.inc.php");
require_once(__DIR__."/services/dbOperations.inc.php");
require_once(__DIR__."/services/jsonBuilder.inc.php");
require_once(__DIR__."/services/responses.inc.php");
class TimeTrackingBranch extends ApiBranch {
function get (ParamCleaner $params) {
respondStatus(404);
}
function post (ParamCleaner $params) {
$user_id = $params->get("user_id");
$params->select("request");
// Is id given, should update?
if ($params->exists(["record_id"])) {
$this->updateTimeRecord($user_id, $params);
} else {
if ($params->exists(["start_time", "end_time", "duration"]) == false) {
respondStatus(400, "Missing parameter");
}
$project_id = $params->get("project_id");
if ($this->isProjectValid($project_id, $user_id) == false) {
$project_id = null;
}
$device_id = $params->get("device_id");
if ($this->isDeviceValid($device_id, $user_id) == false) {
$device_id = null;
}
$this->addTimeRecord($user_id, $params, $project_id, $device_id);
}
}
private function isProjectValid ($project_id, $user_id) {
$db = new DbOperations();
$db->select("projects");
$db->where("project_id", Comparison::EQUAL, $project_id);
$db->where("user_id", Comparison::EQUAL, $user_id);
return count($db->execute()) == 1;
}
private function isDeviceValid ($device_id, $user_id) {
$db = new DbOperations();
$db->select("devices");
$db->where("device_id", Comparison::EQUAL, $device_id);
$db->where("user_id", Comparison::EQUAL, $user_id);
return count($db->execute()) == 1;
}
private function addTimeRecord ($user_id, $params, $project_id = null, $device_id = null) {
$data = ["user_id" => $user_id,
"start_time" => $params->get("start_time"),
"end_time" => $params->get("end_time"),
"duration" => $params->get("duration"),
"project_id" => $project_id,
"device_id" => $device_id];
$db = new DbOperations();
$db->insert("time_records", $data);
$db->execute();
}
private function updateTimeRecord ($user_id, $params) {
$data = ["user_id" => $user_id,
"record_id" => $params->get("record_id")
];
$anythingUpdated = false;
if ($params->exists(["start_time"])) {
$data["start_time"] = $params->get("start_time");
$anythingUpdated = true;
}
if ($params->exists(["end_time"])) {
$data["end_time"] = $params->get("end_time");
$anythingUpdated = true;
}
if ($params->exists(["duration"])) {
$data["duration"] = $params->get("duration");
$anythingUpdated = true;
}
if ($params->exists(["project_id"])) {
$data["project_id"] = $params->get("project_id");
$anythingUpdated = true;
}
if ($params->exists(["device_id"])) {
$data["device_id"] = $params->get("device_id");
$anythingUpdated = true;
}
if ($anythingUpdated == false) {
return;
}
$db = new DbOperations();
$db->update("time_records", $data);
$db->execute();
}
}
$branch = new TimeTrackingBranch();
$branch->execute();
?>

View file

@ -14,12 +14,17 @@ Juggl Documentation
ToDo
High Priority
Tracking Windows Client
Refactor TimeLogger
Offline BackUps
Nur tracking wenn aktiviert
Time tracking
API interface
Web interface
General
Hold some kind of current state
e.g. "Currently working on"
Low Priority
Timetracking API
Setting null does not work
Web interface
Datbase