diff --git a/Router.php b/Router.php
index f9318dc..dad1d9b 100644
--- a/Router.php
+++ b/Router.php
@@ -15,6 +15,10 @@ spl_autoload_register(function ($class_name) {
elseif(file_exists(__DIR__ . "/models/" . $class_name . ".php")) {
include_once __DIR__."/models/Model.php";
include_once __DIR__ . "/models/" . $class_name . ".php";
+// echo "Load class ".__DIR__."/models/".$class_name.'.php'."
\n";
+ }elseif(file_exists(__DIR__ . "/models/Plan/" . $class_name . ".php")) {
+ include_once __DIR__."/models/Model.php";
+ include_once __DIR__ . "/models/Plan/" . $class_name . ".php";
// echo "Load class ".__DIR__."/models/".$class_name.'.php'."
\n";
}
});
diff --git a/application/Auth.php b/application/Auth.php
index d9ff8f7..bf7f65b 100644
--- a/application/Auth.php
+++ b/application/Auth.php
@@ -227,6 +227,7 @@ class Auth {
}
public static function currentUserId(){
+ $a = Auth::getInstance();
return $_SESSION['user_id'];
}
}
diff --git a/application/WebPage.php b/application/WebPage.php
index 2bf82aa..c158c35 100644
--- a/application/WebPage.php
+++ b/application/WebPage.php
@@ -14,6 +14,7 @@ class WebPage {
public $pr = ""; // project root
public $err = array();
public $msg = array();
+ public $data = array();
public function __construct(){
diff --git a/models/Model.php b/models/Model.php
index 589211c..5aa0748 100644
--- a/models/Model.php
+++ b/models/Model.php
@@ -9,8 +9,11 @@ abstract class Model {
protected static $table;
protected static $tableExtends = null;
protected static $fields;
+ protected $isLoaded = false;
+ protected $initialValues = [];
+ protected $errors = [];
- public function __construct(){
+ public function __construct($id = 0){
foreach (static::$fields as $field => $type){
switch ($type){
case "INT":
@@ -23,6 +26,29 @@ abstract class Model {
break;
}
}
+
+
+ if($id > 0){
+ try {
+ $firstField = array_keys(static::$fields)[0];
+ $result = DB::query("SELECT `".implode("`, `", array_keys(static::$fields))."` FROM ".static::$database.".".static::$table . " t1 WHERE `$firstField` = ?", $id )->fetch_assoc();
+
+ $values = [];
+ foreach (static::$fields as $field => $type){
+ $this->{ $field } = $result[$field];
+
+ // cache initial value
+ $values[$field] = $this->{$field};
+ }
+
+ $this->isLoaded = true;
+
+ } catch (DatabaseException $e) {
+ $this->errors[] = $e;
+ }
+ }
+
+ $this->initialValues = $this->asArray();
}
/**
@@ -95,6 +121,7 @@ abstract class Model {
$result = array();
while($row = $q->fetch_assoc()){
$res = new static();
+ $res->isLoaded = true;
/* Alternative for non-joined queries:
foreach (static::$fields as $key => $ignore){
@@ -118,9 +145,67 @@ abstract class Model {
return false;
}
+ public function isLoaded() : bool {
+ return $this->isLoaded;
+ }
+
// public function set($value, )
+ /**
+ * @throws DatabaseException
+ */
public function save(){
+ $newFields = [];
+ $newValues = [];
+ $allExceptFirstFields = [];
+ $allExceptFirstValues = [];
+
+ $fieldCount = 0;
+ foreach(static::$fields as $field => $type){
+ $currValue = $this->{ $field };
+ if(!empty($this->initialValues) && $currValue != $this->initialValues[$field]){
+ $newFields[] = $field;
+ $newValues[] = $currValue;
+ }
+ if($fieldCount > 0){
+ $allExceptFirstFields[] = $field;
+ $allExceptFirstValues[] = $currValue;
+ }
+
+ $fieldCount++;
+ }
+
+ if(!empty($this->initialValues) && empty($newValues)){
+ return false;
+ }
+
+ if($this->isLoaded()){
+ $updateSets = [];
+ foreach($newFields as $field){
+ $updateSets[] = "`$field` = ?";
+ }
+
+ DB::query(sprintf('UPDATE %s.%s SET %s WHERE %s LIMIT 1', static::$database, static::$table, implode(', ', $updateSets), "`" . array_keys(static::$fields)[0] . "` = ?"), array_merge($newValues, [$this->{array_keys(static::$fields)[0]}]));
+ }
+ else {
+ $sql = sprintf('INSERT INTO %s.%s (%s) VALUE (%s)', static::$database, static::$table, implode(', ', $newFields), implode(', ', array_fill(0, count($newFields), '?')));
+
+ DB::query($sql, $newValues);
+ $insertid = DB::insert_id();
+ $this->{ array_keys(static::$fields)[0] } = $insertid;
+ $this->isLoaded = true;
+ return $insertid;
+ }
+
+ return true;
+ }
+
+ public function asArray(): array {
+ $arr = [];
+ foreach ($this as $key => $val){
+ $arr[$key] = $val;
+ }
+ return $arr;
}
}
\ No newline at end of file
diff --git a/models/Plan/PlanStore.php b/models/Plan/PlanStore.php
new file mode 100644
index 0000000..f580d36
--- /dev/null
+++ b/models/Plan/PlanStore.php
@@ -0,0 +1,30 @@
+ "INT",
+ "space_id" => "INT",
+ "name" => "VARCHAR",
+ "created" => "DATETIME",
+ "state" => [ 'planning', 'shopping', 'closed' ]
+ ];
+
+ public static function getUserSpaces(){
+ $spaces = array_merge(
+ static::get([ 'owner_id' => Auth::currentUserId() ]),
+ PlanSpaceMember::get([ 'member_id' => Auth::currentUserId() ])
+ );
+
+ foreach ($spaces as $s){
+ if($s->space_name == ""){
+ $spaceOwner = User::get(['user_id' => $s->owner_id])[0];
+ $s->space_name = $spaceOwner->full_name != "" ? sprintf('%ss space', $spaceOwner->full_name ) : "A users space";;
+ }
+ }
+
+ return $spaces;
+ }
+}
\ No newline at end of file
diff --git a/models/Plan/PlanStoreItem.php b/models/Plan/PlanStoreItem.php
new file mode 100644
index 0000000..c98e0fe
--- /dev/null
+++ b/models/Plan/PlanStoreItem.php
@@ -0,0 +1,29 @@
+ "INT",
+ "space_name" => "VARCHAR",
+ "owner_id" => "INT",
+ "space_type" => [ 'STORE', 'CHECK', 'CALORIES' ]
+ ];
+
+ public static function getUserSpaces(){
+ $spaces = array_merge(
+ static::get([ 'owner_id' => Auth::currentUserId() ]),
+ PlanSpaceMember::get([ 'member_id' => Auth::currentUserId() ])
+ );
+
+ foreach ($spaces as $s){
+ if($s->space_name == ""){
+ $spaceOwner = User::get(['user_id' => $s->owner_id])[0];
+ $s->space_name = $spaceOwner->full_name != "" ? sprintf('%ss space', $spaceOwner->full_name ) : "A users space";;
+ }
+ }
+
+ return $spaces;
+ }
+}
\ No newline at end of file
diff --git a/models/PlanSpace.php b/models/PlanSpace.php
index 2292fa1..c98e0fe 100644
--- a/models/PlanSpace.php
+++ b/models/PlanSpace.php
@@ -7,14 +7,23 @@ class PlanSpace extends Model {
protected static $fields = [
"space_id" => "INT",
"space_name" => "VARCHAR",
- "owner_id" => "VARCHAR",
+ "owner_id" => "INT",
"space_type" => [ 'STORE', 'CHECK', 'CALORIES' ]
];
public static function getUserSpaces(){
- return array_merge(
+ $spaces = array_merge(
static::get([ 'owner_id' => Auth::currentUserId() ]),
PlanSpaceMember::get([ 'member_id' => Auth::currentUserId() ])
);
+
+ foreach ($spaces as $s){
+ if($s->space_name == ""){
+ $spaceOwner = User::get(['user_id' => $s->owner_id])[0];
+ $s->space_name = $spaceOwner->full_name != "" ? sprintf('%ss space', $spaceOwner->full_name ) : "A users space";;
+ }
+ }
+
+ return $spaces;
}
}
\ No newline at end of file
diff --git a/models/User.php b/models/User.php
new file mode 100644
index 0000000..451f8d2
--- /dev/null
+++ b/models/User.php
@@ -0,0 +1,15 @@
+ "INT",
+ "md5_id" => "VARCHAR",
+ "full_name" => "VARCHAR",
+ "user_email" => "VARCHAR",
+ "user_level" => "INT",
+ "date" => "DATE"
+ ];
+}
\ No newline at end of file
diff --git a/templates/default/plan/index.html b/templates/default/plan/index.html
index 97e991c..6866f10 100644
--- a/templates/default/plan/index.html
+++ b/templates/default/plan/index.html
@@ -15,7 +15,7 @@
diff --git a/www/api/v2/api.php b/www/api/v2/api.php
index 8723582..15f8f8d 100644
--- a/www/api/v2/api.php
+++ b/www/api/v2/api.php
@@ -33,7 +33,13 @@ abstract class Api {
}
if($this->success){
- $this->execute();
+ try {
+ $this->execute();
+ }
+ catch (Exception | DatabaseException $e){
+ $this->success = false;
+ $this->message = $e;
+ }
}
$this->printResult();
@@ -52,6 +58,9 @@ abstract class Api {
echo json_encode( $returns );
}
+ /**
+ * @throws DatabaseException
+ */
protected function execute(){ }
/**
diff --git a/www/api/v2/index.php b/www/api/v2/index.php
index 7a49ebd..901f454 100644
--- a/www/api/v2/index.php
+++ b/www/api/v2/index.php
@@ -1,5 +1,13 @@
"API not found." ]);
diff --git a/www/api/v2/plan/create.php b/www/api/v2/plan/create.php
new file mode 100644
index 0000000..ef95476
--- /dev/null
+++ b/www/api/v2/plan/create.php
@@ -0,0 +1,42 @@
+ [
+ [
+ "name" => "space_id",
+ "keyword" => "space_id",
+ "type" => VERIFY_STRING
+ ],
+ [
+ "name" => "name",
+ "keyword" => "name",
+ "type" => VERIFY_STRING
+ ]
+ ]
+ ];
+
+ /**
+ * @throws DatabaseException
+ */
+ function execute(){
+ try {
+ $store = new PlanStore();
+ $store->space_id = $this->data['space_id'];
+ $store->name = $this->data['name'];
+
+ $this->result = $store->save();
+
+ $this->success = true;
+ $this->message = "OK";
+ }
+ catch (DatabaseException $e){
+ $this->success = false;
+ $this->message = "Error: " . $e;
+ }
+ }
+}
+
+$request = new CreateStoreApi();
+
diff --git a/www/api/v2/plan/modify.php b/www/api/v2/plan/modify.php
new file mode 100644
index 0000000..158a447
--- /dev/null
+++ b/www/api/v2/plan/modify.php
@@ -0,0 +1,46 @@
+ [
+ [
+ "name" => "store_id",
+ "keyword" => "store_id",
+ "type" => VERIFY_INT
+ ],
+ [
+ "name" => "newname",
+ "keyword" => "newname",
+ "type" => VERIFY_STRING
+ ],
+ [
+ "name" => "state",
+ "keyword" => "state",
+ "type" => VERIFY_STRING
+ ],
+ ]
+ ];
+
+ function execute(){
+
+ $store = PlanStore::get(['plan_store_id' => $this->data['store_id']])[0];
+ if(isset($this->data['newname'])){
+ $store->name = $this->data['newname'];
+ }
+ elseif(isset($this->data['state'])){
+ $store->state = $this->data['state'];
+ }
+
+
+ $store->save();
+
+ $this->result = $store;
+
+ $this->success = true;
+ $this->message = "OK";
+ }
+}
+
+$request = new ModifyStoreApi();
+
diff --git a/www/api/v2/plan/stores.php b/www/api/v2/plan/stores.php
new file mode 100644
index 0000000..c75e0f6
--- /dev/null
+++ b/www/api/v2/plan/stores.php
@@ -0,0 +1,36 @@
+ [
+ [
+ "name" => "space",
+ "keyword" => "space",
+ "type" => VERIFY_INT
+ ],
+ ],
+ "URI" => [
+ [
+ "name" => "space",
+ "keyword" => "space",
+ "type" => VERIFY_INT
+ ],
+ ]
+ ];
+
+ /**
+ * @throws DatabaseException
+ */
+ function execute(){
+ $stores = PlanStore::get(['space_id' => $this->data['space'] ]);
+
+ $this->result = $stores;
+
+ $this->success = true;
+ $this->message = "OK";
+ }
+}
+
+$request = new GetStoresApi();
+
diff --git a/www/api/v2/space/create.php b/www/api/v2/space/create.php
new file mode 100644
index 0000000..a5a51c6
--- /dev/null
+++ b/www/api/v2/space/create.php
@@ -0,0 +1,35 @@
+ [
+ [
+ "name" => "space_name",
+ "keyword" => "space_name",
+ "type" => VERIFY_STRING
+ ],
+ [
+ "name" => "space_type",
+ "keyword" => "space_type",
+ "type" => VERIFY_STRING
+ ],
+ ]
+ ];
+
+ function execute(){
+
+ $space = new PlanSpace();
+ $space->space_name = $this->data['space_name'];
+ $space->space_type = $this->data['space_type'] ?? 'STORE';
+ $space->owner_id = Auth::currentUserId();
+
+ $this->result = $space->save();
+
+ $this->success = true;
+ $this->message = "OK";
+ }
+}
+
+$request = new CreateSpacesApi();
+
diff --git a/www/api/v2/space/get.php b/www/api/v2/space/get.php
index 65d032b..6b2a098 100644
--- a/www/api/v2/space/get.php
+++ b/www/api/v2/space/get.php
@@ -1,7 +1,5 @@
result = PlanSpace::get();
+ $this->result = PlanSpace::getUserSpaces();
+
$this->success = true;
$this->message = "OK";
}
diff --git a/www/plan/plan.js b/www/plan/plan.js
index 19e6e3c..a16d57d 100644
--- a/www/plan/plan.js
+++ b/www/plan/plan.js
@@ -227,7 +227,8 @@ class Store {
}
if(prevState !== state){
- ajaxReq({ plan: 'setState', storeID: this.storeID, state: this.state });
+ // ajaxReq({ plan: 'setState', storeID: this.storeID, state: this.state });
+ qAPI('plan/modify', 'POST', { store_id: this.storeID, state: this.state })
}
}
@@ -612,7 +613,7 @@ class Store {
getStoreID(){
let that = this;
- return ajaxReq({ plan: 'saveStore', storeName: this.title })
+ return qAPI('plan/create', 'POST', { space_id: spaceID, name: this.title })
.done(json => {
console.log("getStore:", json);
that.storeID = json['data'];
@@ -624,7 +625,14 @@ class Store {
this.title = newName;
if(this.storeID !== null){
- return ajaxReq({ plan: 'renameStore', storeID: this.storeID, newName: newName });
+ return qAPI('plan/modify', 'POST', { store_id: this.storeID, newname: newName })
+ // return ajaxReq({ plan: 'renameStore', storeID: this.storeID, newName: newName });
+ }
+ else {
+ return qAPI('plan/create', 'POST', { space_id: spaceID, name: this.title }).done(json => {
+ this.storeID = json.data;
+ });
+
}
// Return blank ajax as a false
@@ -663,63 +671,54 @@ function updateTotalPrice(){
}
let spaceID = 0;
-function getSpaces(){
- $("#stores").html("Loading...");
- return ajaxReq({plan: 'spaces'}).done(json => {
- let optionsHtml = "";
-
- // console.log(json);
-
- let spaceNum = 1;
- for(const spaceI in json.data.spaces){
- const space = json.data.spaces[spaceI];
- if(spaceID === 0){
- spaceID = space['space_id'];
- }
- let spaceName = space['space_name'] || "Space "+spaceNum;
- optionsHtml += "\n";
- spaceNum++;
- }
-
- let spaceSelectElem = $("#spaceSelect");
- spaceSelectElem
- .html(optionsHtml)
- .on('change', ev => {
- spaceID = $(ev.target).val();
- getStores(spaceID);
- });
-
- if(typeof json.data.lastSpace !== "undefined"){
- spaceID = Number(json.data.lastSpace);
- spaceSelectElem.val(spaceID);
- }
- });
+// function getSpaces(){
+ // $("#stores").html("Loading...");
+ // return ajaxReq({plan: 'spaces'}).done(json => {
+ // let optionsHtml = "";
+ //
+ // console.log(json);
+ //
+ // let spaceNum = 1;
+ // for(const spaceI in json.data.spaces){
+ // const space = json.data.spaces[spaceI];
+ // if(spaceID === 0){
+ // spaceID = space['space_id'];
+ // }
+ // let spaceName = space['space_name'] || "Space "+spaceNum;
+ // optionsHtml += "\n";
+ // spaceNum++;
+ // }
+ // .html(optionsHtml)
-}
-getSpaces().done(() => { getStores(spaceID); });
+
+ // if(typeof json.data.lastSpace !== "undefined"){
+ // spaceID = Number(json.data.lastSpace);
+ // spaceSelectElem.val(spaceID);
+ // }
+ // });
+
+// }
+// getSpaces().done(() => { getStores(spaceID); });
+
+let spaceSelectElem = $("#spaceSelect");
+spaceSelectElem.on('change', ev => {
+ // console.debug('Change space');
+ spaceID = $(ev.target).val();
+ getStores(spaceID);
+}).trigger('change');
+
// GET STORES
function getStores(spaceID){
spaceID = spaceID || 0;
- // $("#stores").html("");
stores = [];
- let options = { plan: '' };
- if(spaceID !== 0){
- options = { plan: '', space: spaceID }
- }
-
- return $.getJSON('do.php', options)
+ return qAPI('plan/stores/'+spaceID )
.done(json => {
- if(handleJsonErrors(json)){
- return;
- }
-
$("#stores").html("");
- // console.log(json);
for(const store in json.data){
let storeKey = stores.length;
@@ -735,12 +734,13 @@ function getStores(spaceID){
stores[storeKey].setState(json.data[store].state, 1);
}
updateTotalPrice();
- })
- .fail(handleAjaxErrors);
+ });
}
function ajaxReq( data ){
+ console.log("REQUEST STOPPED", data);
+ return false;
if(typeof spaceID !== "undefined" && spaceID !== 0){
data.space = spaceID;
}
@@ -756,10 +756,31 @@ function ajaxReq( data ){
.fail(handleAjaxErrors);
}
+function qAPI( path, method, data ){
+ method = method || 'GET';
+ data = data || {};
+
+ // if(typeof spaceID !== "undefined" && spaceID !== 0){
+ // data.space = spaceID;
+ // }
+
+ return $.ajax({
+ method: method,
+ url: "/api/v2/" + path,
+ data: data,
+ dataType: 'JSON'
+ })
+ .done(json => {
+ return !handleJsonErrors(json);
+ })
+ .fail(handleAjaxErrors);
+}
+
function handleJsonErrors(json){
- if(typeof json.status != "undefined" && json.status !== 0){
+ if(typeof json.status != "undefined" && json.status !== true && json.status !== 0){
if(json.message === "Not logged in"){
- location.href = '../login.php';
+ // location.href = '../login.php';
+ alert("Not logged in...");
}
else {
alert(json.message);