diff --git a/BaseClass.php b/BaseClass.php new file mode 100644 index 0000000..13ff72f --- /dev/null +++ b/BaseClass.php @@ -0,0 +1,73 @@ +<?php + /* + * Author : Anthony Gauthier + * Owner : Anthony Gauthier + * Date created : 2017-04-04 + * Date modified : 2017-04-04 + * Software : YOUR PROJECT + * File : BaseClass.php + * Description : Class that detains all the basic find/delete/insert/update for any given object + */ + require_once("models/mapper/ObjectMapping.php"); + + class BaseClass { + protected $Mapper; + + public function __construct($className, $object) { + $this->Mapper = new ObjectMapping($className, $object); + } + + public function __destruct() {} + + function toJSON(){ + $var = $this->getObjectAttributes(); + + foreach ($var as &$value) { + if (is_object($value) && method_exists($value,'toJSON')) { + $value = $value->toJSON(); + } + } + return $var; + } + + public function getObjectAttributes() { + //Retrieve attributes and remove the Mapper from the list + $attributes = get_object_vars($this); + unset($attributes["Mapper"]); + + return $attributes; + } + + public function findObjectById($id) { + $mappedObject = $this->Mapper->findById($id); + + return $mappedObject; + } + + public function getObjectArray() { + $objectArray = array(); + $objectArray = $this->Mapper->getObjectArray(); + + return $objectArray; + } + + public function getCurrentObject() { + $mappedObject = $this->Mapper->getCurrentObject($this); + + return $mappedObject; + } + + public function insertObject() { + $this->Mapper->insertObject($this); + } + + public function updateObject() { + $this->Mapper->updateObject($this); + } + + public function deleteObject() { + $this->Mapper->deleteObject($this); + } + + } +?> \ No newline at end of file diff --git a/mapper/Database.php b/mapper/Database.php new file mode 100644 index 0000000..51f104e --- /dev/null +++ b/mapper/Database.php @@ -0,0 +1,404 @@ +<?php +/* +* Author : Anthony Gauthier +* Owner : Anthony Gauthier +* Date created : 2017-03-19 +* Date modified : 2017-04-04 +* Software : YOUR PROJECT +* File : Database.php +* Description : Database wrapper +*/ + // namespace ObjectMapping; + + class Database { + /** + * Variables + * + * @var [string] $Host + * @var [string] $Database + * @var [string] $User + * @var [string] $Password + * @var [mysqli] $Instance + */ + protected $Host; + protected $Database; + protected $User; + protected $Sql; + protected $Password; + protected $Instance; + + /** + * Database::__construct() + * Constructor & destructor + */ + public function __construct() { + $this->Host = "SERVER_HOST"; + $this->User = "MYSQL_USER"; + $this->Password = "MYSQL_PASSWORD"; + $this->Database = "MYSQL_DATABASE"; + } + + public function __destruct() {} + + /** + * Database::connect() + * Opens up the connection to the database based on the object's attributes¸ + * + * @return void + */ + public function connect() { + + $con = mysqli_connect($this->Host, $this->User, $this->Password, $this->Database, "3306"); + + if(mysqli_connect_errno()) { + die($this->getError()); + } else { + $this->Instance = $con; + } + + return $this->Instance; + } + + + /** + * Database::disconnect() + * Closes the database's connection to avoid conflict and release memory + * + * @return void + */ + public function disconnect() { + if(!mysqli_close($this->Instance)) { + die($this->getError()); + } + } + + /** + * Database::select() + * Format SQL and returns query content + * + * @param [string] $table + * @param [array] $columns + * @param [array] $wheres + * @param [array] $joins + * @param [array] $orderbys + * @return [array] $results + */ + public function select($table, $columns=null, $wheres=null, $joins=null, $orderbys=null) { + //Variables + $return = array(); + + if($table != "" || $table != null) { + //Open up connection + $this->connect(); + + //SELECT statement + $this->Sql = "SELECT "; + + //COLUMNS + if($columns != "" || $columns != null) { + foreach($columns as $index=>$column) { + if($index == 0) { + $this->Sql .= $column; + } else { + $this->Sql .= ", " . $column; + } + } + } else { + $this->Sql .= "*"; + } + + //FROM statement + $this->Sql .= " FROM " . $table; + + //JOINS + if($joins != "" || $joins != null) { + foreach($joins as $join) { + $this->Sql .= $join["orientation"] . " JOIN " . $join["referenced_table"] . " ON " . $join["table_name"] . "." . $join["column_name"] . " = " . $join["referenced_table"] . "." . $join["referenced_column"]; + } + } + + //WHERE statement + if($wheres != "" || $wheres != null) { + foreach($wheres as $index=>$where) { + //if string format SQL + if(gettype($where["value"]) == "string" && !is_numeric($where["value"])) { + $where["value"] = "'".$where["value"]."'"; + $where["value"] = htmlentities(utf8_encode($where["value"])); + $where["condition"] = "LIKE"; + } + + if($index == 0) { + $this->Sql .= " WHERE " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + if(sizeof($wheres) == $index) { + $this->Sql .= " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + $this->Sql .= " " . $where["operation"] . " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } + } + } + } + + //ORDER BY statement + if($orderbys != "" || $orderbys != null) { + foreach($orderbys as $index=>$orderby) { + if($index == 0) { + $this->Sql .= " ORDER BY " . $orderby; + } else { + $this->Sql .= ", " . $orderby; + } + } + } + + $this->Sql .= ";"; + + $results = $this->Instance->query($this->Sql); + + if(!$results) { + die($this->getError()); + } + + while($row = $results->fetch_assoc()) { + $return[] = $row; + } + + array_walk_recursive($return, function(&$item, $key){ + $item = html_entity_decode(utf8_decode($item)); + }); + + $this->disconnect(); + + return $return; + } else { + die("Must provide a table to query the database."); + } + } + + /** + * Database::insert() + * Format SQL and inserts into database + * + * @param [type] $table + * @param [type] $columns + * @param [type] $values + * @return void + */ + public function insert($table, $columns, $values) { + if($table != "" || $table != null) { + $this->connect(); + $this->Sql = "INSERT INTO " . $table; + + if(($columns != "" || $columns != null) || sizeof($columns) != sizeof($values)) { + $this->Sql .= "("; + + //COLUMNS + foreach($columns as $index=>$column) { + if($index == 0) { + $this->Sql .= $column; + } else { + $this->Sql .= ", " . $column; + } + } + + $this->Sql .= ") VALUES ("; + + if($values != "" || $values != null) { + + //VALUES + foreach($values as $index=>$value) { + if(gettype($value) == "string" && !is_numeric($value)) { + $value = "'".trim(htmlentities(utf8_encode($value)))."'"; + } + + if($index == 0) { + $this->Sql .= $value; + } else { + $this->Sql .= ", " . $value; + } + } + + $this->Sql .= ");"; + + //insert into database + if(!$this->Instance->query($this->Sql)) { + die($this->getError()); + } + } + } else { + die("Either set columns or set the same amount of columns/values to insert"); + } + + $this->disconnect(); + } else { + die("Must provide a table to insert to"); + } + } + + /** + * Database::delete() + * Format SQL and deletes the specific row in the database + * + * @param [string] $table + * @param [array] $columns + * @param [array] $values + * @return [boolean] ? (true) row deleted : error; + */ + public function delete($table, $wheres=null) { + if($table != "" || $table != null) { + $this->connect(); + $this->Sql = "DELETE FROM " . $table; + + //WHERE + if($wheres != "" || $wheres != null) { + foreach($wheres as $index=>$where) { + //if string format SQL + if(gettype($where["value"]) == "string" && !is_numeric($where["value"])) { + $where["value"] = "'".trim($where["value"])."'"; + $where["value"] = htmlentities(utf8_encode($where["value"])); + $where["condition"] = "LIKE"; + } + + if($index == 0) { + $this->Sql .= " WHERE " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + if(sizeof($wheres) == $index) { + $this->Sql .= " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + $this->Sql .= " " . $where["operation"] . " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } + } + } + } + + $this->Sql .= ";"; + + //delete from database + if(!$this->Instance->query($this->Sql)) { + die($this->getError()); + } + + $this->disconnect(); + } else { + die("Must provide a table to delete from"); + } + } + + /** + * Database::update() + * Format SQL and updates the specific row in the database + * + * @return [boolean] ? (true) row updated : error; + */ + public function update($table, $columns, $values, $wheres=null) { + if($table != "" || $table != null) { + $this->connect(); + $this->Sql = "UPDATE " . $table; + + //SET columns, [...] + if(($columns != "" || $columns != null) || sizeof($columns) != sizeof($values)) { + $this->Sql .= " SET "; + + //COLUMNS + foreach($columns as $index=>$column) { + if(gettype($values[$index]) == "string" && !is_numeric($values[$index])) { + $values[$index] = "'".trim($values[$index])."'"; + $values[$index] = htmlentities(utf8_encode($values[$index])); + } + + if($index == 0) { + $this->Sql .= "" . $column . " = " . $values[$index]; + } else { + $this->Sql .= ", " . $column . " = " . $values[$index]; + } + } + } else { + die("Either set columns or set the same amount of columns/values to insert"); + } + + //WHERE + if($wheres != "" || $wheres != null) { + foreach($wheres as $index=>$where) { + //if string format SQL + if(gettype($where["value"]) == "string" && !is_numeric($where["value"])) { + $where["value"] = "'".$where["value"]."'"; + $where["value"] = htmlentities(utf8_encode($where["value"])); + $where["condition"] = "LIKE"; + } + + if($index == 0) { + $this->Sql .= " WHERE " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + if(sizeof($wheres) == $index) { + $this->Sql .= " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } else { + $this->Sql .= " " . $where["operation"] . " " . $where["column"] . " " . $where["condition"] . " " . $where["value"]; + } + } + } + } + + $this->Sql .= ";"; + + //update in database + if(!$this->Instance->query($this->Sql)) { + die($this->getError()); + } + + $this->disconnect(); + } else { + die("Must provide a table to delete from"); + } + } + + //TODO. Check error with ObjectMapping class + public function getJoinsArray($table) { + $fk_array = array(); + $return = array(); + $this->Sql = "SHOW CREATE TABLE " . $table; + + $results = $this->Instance->query($this->Sql); + + if(!$results) { + die($this->getError()); + } + + while($row = $results->fetch_assoc()) { + $fk_array[] = $row; + } + + $fk_array = explode("FOREIGN KEY", $fk_array[0]["Create Table"]); + + foreach($fk_array as $fk) { + if(strpos($fk, "REFERENCES")) { + //Isolate referenced table + $referenced_table = substr($fk, strpos($fk, "REFERENCES")); + $referenced_table = substr($referenced_table, strpos($referenced_table, "`") + 1); + $referenced_table = substr($referenced_table, 0, strpos($referenced_table, "`")); + //Isolate referenced column + $referenced_column = substr($fk, strrpos($fk, "(") + 2); + $referenced_column = substr($referenced_column, 0, strpos($fk, ")") - 4); + //Isolate current table's column (should be the same as referenced) + $column_name = substr($fk, 3, strpos($fk, ")") - 4); + + $return[] = array( + "orientation" => "INNER", + "referenced_table" => $referenced_table, + "referenced_column" => $referenced_column, + "column_name" => $column_name, + "table_name" => $table + ); + } + } + + return $return; + } + + public function getSql() { + return $this->Sql; + } + + private function getError() { + return "<br/>" . $this->Sql . "<br/> SQL Exception #" . $this->Instance->errno . " : " . $this->Instance->error . "<br/>"; + } + } +?> \ No newline at end of file diff --git a/mapper/ObjectMapping.php b/mapper/ObjectMapping.php new file mode 100644 index 0000000..2971a79 --- /dev/null +++ b/mapper/ObjectMapping.php @@ -0,0 +1,259 @@ +<?php +/* +* Author : Anthony Gauthier +* Owner : Anthony Gauthier +* Date created : 2017-03-24 +* Date modified : 2017-04-04 +* Software : YOUR PROJECT +* File : ObjectMapping.php +* Description : Object Mapping class, serves as a database abstraction layer +*/ + require_once("ObjectMappingInterface.php"); + require_once("Database.php"); + + class ObjectMapping implements ObjectMappingInterface { + /** + * Variables + * + * @var [Database] $Database + * @var [string] $Table + * @var [object] $Object + */ + protected $Database; + protected $Table; + protected $Object; + protected $TableJoins; + + /** + * ObjectMapping::__construct() + * Constructor & destructor + * @param [string] $t + * @param [object] $o + */ + public function __construct($t, $o) { + $className = get_class($o); + + $this->Database = new Database(); + $this->Table = $t; + $this->Object = $o; + $this->TableJoins = null; + // $this->TableJoins = $this->Database->getJoinsArray($this->Table); + } + + public function __destruct() {} + + /** + * Retrieves a record in the database by ID + * + * @param [int] $id + * @return $this->Object + */ + public function findById($id) { + $where = array( + array( + "column" => "ID".$this->Table, + "value" => $id, + "condition" => "=" + ) + ); + + if($this->Database->connect()) { + $rows = array(); + $rows = $this->Database->select($this->Table, null, $where, $this->TableJoins); + $this->mapObject($this->Object, $rows); + + return $this->Object; + } + } + + /** + * getObjectArray + * + * @return void + */ + public function getObjectArray($wheres=null) { + $return = array(); + $rows = array(); + $className = get_class($this->Object); + + if($this->Database->connect()) { + $rows = $this->Database->select($this->Table, null, $wheres, $this->TableJoins); + $this->mapObject($this->Object, $rows, $return); + } + + return $return; + } + + /** + * findByParam + * + * @param [type] $array + * @return void + */ + public function findByParam($array) { + //TODO. Will return array of objects ? + } + + /** + * getCurrentObject + * + * @param [type] $obj + * @return void + */ + public function getCurrentObject($obj=null) { + if($obj != null) + $this->Object = $obj; + + $objectAttributes = $this->Object->getObjectAttributes($obj); + $wheres = array(); + $className = get_class($this->Object); + + foreach($objectAttributes as $attributeName=>$attributeValue) { + if(($attributeName != "ID".$className) && ($attributeValue != null || $attributeValue != 0 || $attributeValue != "")) { + array_push($wheres, array( + "column" => $attributeName, + "value" => $attributeValue, + "condition" => "=", + "operation" => "AND" + )); + } + } + + if($this->Database->connect()) { + $row = $this->Database->select($this->Table, null, $wheres, $this->TableJoins); + $this->mapObject($this->Object, $row); + } + + return $this->Object; + } + + /** + * insertObject + * + * @param [type] $obj + * @return void + */ + public function insertObject($obj=null) { + if($obj != null) + $this->Object = $obj; + + $objectAttributes = $this->Object->getObjectAttributes($obj); + $columns = array(); + $values = array(); + + foreach($objectAttributes as $attributeName=>$attributeValue) { + $getterName = "get" . $attributeName; + + array_push($columns, $attributeName); + array_push($values , $this->Object->$getterName()); + } + + $this->Database->insert($this->Table, $columns, $values); + } + + /** + * updateObject + * + * @param [type] $obj + * @return void + */ + public function updateObject($obj=null) { + if($obj != null) + $this->Object = $obj; + + $className = get_class($this->Object); + $getterName = "getID" . $className; + $objectID = $this->Object->$getterName(); + $columns = array(); + $values = array(); + $where = array( + array( + "column" => "ID".$this->Table, + "value" => $objectID, + "condition" => "=" + ) + ); + + $objectAttributes = $this->Object->getObjectAttributes($obj); + + foreach($objectAttributes as $attributeName=>$attributeValue) { + if($attributeName != "ID".$className) { + $getterName = "get" . $attributeName; + + array_push($columns, $attributeName); + array_push($values , $this->Object->$getterName()); + } + } + + $this->Database->update($this->Table, $columns, $values, $where); + } + + /** + * deleteObject + * + * @param [type] $obj + * @return void + */ + public function deleteObject($obj=null) { + if($obj != null) + $this->Object = $obj; + + $className = get_class($this->Object); + $getterName = "getID" . $className; + $objectID = $obj->$getterName(); + $where = array( + array( + "column" => "ID".$this->Table, + "value" => $objectID, + "condition" => "=" + ) + ); + + $this->Database->delete($this->Table, $where); + $this->__destruct(); + } + /** + * Undocumented function + * + * @param [type] $obj - referenced object + * @param [type] $rows - rows retrived by DB + * @param [type] $objArr - referenced object array + * @return void + */ + public function mapObject(&$obj, $rows, &$objArr=null) { + $attributes = $obj->getObjectAttributes($obj); + + foreach($rows as $row) { + $className = get_class($obj); + $this->Object = new $className(); + + + + foreach($attributes as $key=>$attribute) { + $setterName = "set".$key; + + //If object contains other objects + if(strpos($key, "ID") !== false && $key != "ID".$className) { + $linkedClassName = str_replace("ID", "", $key); + + /** VERY SPECIFIC TO WORKERTRACKER **/ + if(strpos($linkedClassName, "Current") !== false) { + $linkedClassName = str_replace("Current", "", $linkedClassName); + } + + $objectToPush = new $linkedClassName(); + $objectToPush = $objectToPush->findObjectById($row[$key]); + $obj->$setterName($objectToPush); + } else { + $obj->$setterName($row[$key]); + } + } + + //add to array if array isset - getObjectArray() + if(isset($objArr)) { + $objArr[] = $obj; + } + } + } + } +?> \ No newline at end of file diff --git a/mapper/ObjectMappingInterface.php b/mapper/ObjectMappingInterface.php new file mode 100644 index 0000000..9b72ad7 --- /dev/null +++ b/mapper/ObjectMappingInterface.php @@ -0,0 +1,24 @@ +<?php +/* +* Author : Anthony Gauthier +* Owner : Anthony Gauthier +* Date created : 2017-03-24 +* Date modified : 2017-03-24 +* Software : YOUR PROJECT +* File : ObjectMappingInterface.php +* Description : Object Mapping Interface +*/ + /** + * Interface defining all the methods the ObjectMapping class + * will be using + */ + interface ObjectMappingInterface { + public function findById($id); + public function findByParam($array); + public function getCurrentObject(); + public function getObjectArray($wheres); + public function insertObject(); + public function updateObject(); + public function deleteObject(); + } +?> \ No newline at end of file