val to * this array that represents the table being modeled. This array is * used by db table IO functions to construct SQL queries. */ protected $fields = array(); protected $db; /* * Instanciate an object representing an existing database entity * named by the given GUID. If no such GUID exists, an exception * is thrown. If NULL is passed, no database lookups are attempted. * This is helpful for assembling new database objects. */ public function __construct(?string $guid = NULL) { $this->db = database::getInstance(); if ($guid) $this->loadObj($guid); } /* * This function will iterate the $fields array and initialize this * object's class properties based on the table=>fields mapping. If * no such GUID exists, an exception is thrown. */ private function loadObj(string $guid) : void { $guid = $this->db->esc($guid); if (!$this->isGUID($guid)) throw new Exception("GUID " . $guid . " does not exist"); foreach ($this->fields as $tbl => $flds) { $tbl = $this->db->esc($tbl); $query = "SELECT * FROM " . $tbl . " WHERE guid = '" . $guid . "'"; $res = $this->db->query($query)[0]; foreach ($flds as $fld) { if (isset($res[$fld])) $this->$fld = $res[$fld]; } } } /* * This function will update this object in the database, or insert new * data if this object does not yet have a GUID. This function uses the * $fields array to construct SQL queries. */ public function saveObj() : void { /* update existing object */ if (isset($this->guid)) { $this->updated = $this->getCurrentTimestamp(); foreach ($this->fields as $tbl => $flds) { $tbl = $this->db->esc($tbl); $udstr = ""; foreach ($flds as $fld) { if (!isset($this->$fld)) continue; $fld = $this->db->esc($fld); $udstr .= $fld . " = '" . $this->db->esc($this->$fld) . "', "; } if (strlen($udstr) > 0) { $udstr = substr($udstr, 0, -2); // remove ", " from the end $query = "UPDATE " . $tbl . " SET " . $udstr . " WHERE guid = '" . $this->db->esc($this->guid) . "'"; $this->db->query($query); } } } /* create new object */ else { $this->guid = $this->getNewGUID(); $this->created = $this->getCurrentTimestamp(); $this->updated = $this->created; foreach ($this->fields as $tbl => $flds) { $tbl = $this->db->esc($tbl); $fldstr = ""; $valstr = ""; foreach ($flds as $fld) { if (!isset($this->$fld)) continue; $fld = $this->db->esc($fld); $fldstr .= $fld . ", "; $valstr .= "'" . $this->db->esc($this->$fld) . "', "; } if (strlen($fldstr) > 0) { $fldstr = substr($fldstr, 0, -2); // remove ", " $valstr = substr($valstr, 0, -2); $query = "INSERT INTO " . $tbl . " (" . $fldstr . ") VALUES (" . $valstr . ")"; $this->db->query($query); } } } } /* * This function will remove this object from the database by deleting * rows with this object's GUID from tables in $fields. If this object * does not have a GUID, throw an exception. */ public function delObj() : void { if (!isset($this->guid)) throw new Exception("GUID (null) does not exist"); $guid = $this->db->esc($this->guid); foreach ($this->fields as $tbl => $flds) { $tbl = $this->db->esc($tbl); $query = "DELETE FROM " . $tbl . " WHERE guid = '" . $guid . "'"; $this->db->query($query); } /* garbage collection */ $query = "DELETE FROM members WHERE guid = '" . $guid . "' OR member = '" . $guid . "'"; $this->db->query($query); $query = "DELETE FROM views WHERE guid = '" . $guid . "' OR viewer = '" . $guid . "'"; $this->db->query($query); } /* * Get a random sha256 blob, returned as a hexadecimal string */ public function getBlob() : string { return hash("sha256", openssl_random_pseudo_bytes(64)); } /* * Get current timestamp as a string for object database purposes */ private function getCurrentTimestamp() : string { $query = "SELECT now() AS stamp"; $res = $this->db->query($query); return $res[0]['stamp']; } /* * Check whether the given GUID exists */ private function isGUID(string $guid) : bool { $guid = $this->db->esc($guid); $query = "SELECT guid FROM objects WHERE guid = '" . $guid . "'"; $res = $this->db->query($query); return count($res) > 0; } /* * Get a new, unique GUID for a new system object */ private function getNewGUID() : string { do $guid = substr($this->getBlob(), 0, 8); while ($this->isGUID($guid)); return $guid; } } ?>