diff --git a/app/contacts/resources/classes/contacts.php b/app/contacts/resources/classes/contacts.php index 9677767420..46c435917b 100644 --- a/app/contacts/resources/classes/contacts.php +++ b/app/contacts/resources/classes/contacts.php @@ -119,7 +119,7 @@ if (!class_exists('contacts')) { $p = new permissions; $database = new database; foreach ($this->tables as $table) { - $p->add($database->singular($table).'_delete', 'temp'); + $p->add(database::singular($table).'_delete', 'temp'); } //execute delete @@ -132,7 +132,7 @@ if (!class_exists('contacts')) { //revoke temp permissions $database = new database; foreach ($this->tables as $table) { - $p->delete($database->singular($table).'_delete', 'temp'); + $p->delete(database::singular($table).'_delete', 'temp'); } //set message @@ -163,11 +163,11 @@ if (!class_exists('contacts')) { $x = 0; foreach ($records as $property_name => $properties) { $database = new database; - if (permission_exists($database->singular($property_name).'_delete')) { + if (permission_exists(database::singular($property_name).'_delete')) { if (is_array($properties) && @sizeof($properties) != 0) { foreach ($properties as $property) { if ($property['checked'] == 'true' && is_uuid($property['uuid'])) { - $array[$property_name][$x][$database->singular($property_name).'_uuid'] = $property['uuid']; + $array[$property_name][$x][database::singular($property_name).'_uuid'] = $property['uuid']; $array[$property_name][$x]['contact_uuid'] = $this->contact_uuid; $array[$property_name][$x]['domain_uuid'] = $_SESSION['domain_uuid']; $x++; diff --git a/app/dialplans/dialplan_edit.php b/app/dialplans/dialplan_edit.php index 8ace6b4186..4858a9efab 100644 --- a/app/dialplans/dialplan_edit.php +++ b/app/dialplans/dialplan_edit.php @@ -273,7 +273,8 @@ $database = new database; $database->app_name = 'dialplans'; $database->app_uuid = $app_uuid; - $database->uuid($dialplan_uuid); + if ( strlen($dialplan_uuid)>0 ) + $database->uuid($dialplan_uuid); $database->save($array); unset($array); diff --git a/core/user_logs/resources/classes/user_logs.php b/core/user_logs/resources/classes/user_logs.php index be19e55f3e..73326487dd 100644 --- a/core/user_logs/resources/classes/user_logs.php +++ b/core/user_logs/resources/classes/user_logs.php @@ -73,6 +73,7 @@ if (!class_exists('user_logs')) { * add user_logs */ public static function add($result) { + $array = []; //prepare the array $array['user_logs'][0]["timestamp"] = 'now()'; $array['user_logs'][0]["domain_uuid"] = $result['domain_uuid']; @@ -97,7 +98,8 @@ if (!class_exists('user_logs')) { $database = new database; $database->app_name = 'authentication'; $database->app_uuid = 'a8a12918-69a4-4ece-a1ae-3932be0e41f1'; - $database->uuid($user_log_uuid); + if (strlen($user_log_uuid)>0) + $database->uuid($user_log_uuid); $database->save($array, false); $message = $database->message; diff --git a/resources/classes/database.php b/resources/classes/database.php index 7ca3800b95..5cd5fef2eb 100644 --- a/resources/classes/database.php +++ b/resources/classes/database.php @@ -30,43 +30,340 @@ include "root.php"; if (!class_exists('database')) { class database { + const TABLE_PREFIX = "v_"; + /** - * Define the class variables + * Database connection + * @access private + * @var PDO object */ - public $db; - public $driver; - public $type; - public $host; - public $port; - public $db_name; - public $db_secure; - public $db_cert_authority; - public $username; - public $password; - public $path; - public $table; - public $where; //array - public $order_by; //array - public $order_type; - public $limit; - public $offset; - public $fields; - public $count; - public $sql; - public $result; - public $app_name; - public $app_uuid; - public $domain_uuid; + private $db; + /** + * Driver to use. + * @access private + * @var string Can be pgsql, mysql, sqlite, odbc + */ + private $driver; + /** + * Alias of driver. + * @access private + * @var string Can be pgsql, mysql, sqlite, odbc + * @see $driver + */ + private $type; + /** + * Host for database connection + * @access private + * @var string host name or IP address. + */ + private $host; + /** + * Port number + * @access private + * @var int 1025 - 65534 + */ + private $port; + /** + * Database name + * @access private + * @var string + */ + private $db_name; + /** + * Database security + * @access private + * @var boolean + */ + private $db_secure; + /** + * Specifies the file name of the client SSL certificate + * @access private + * @var string full path + */ + private $db_cert_authority; + /** + * Username used to connect + * @access private + * @var string + */ + private $username; + /** + * Password used to connect + * @access private + * @var string + */ + private $password; + /** + * Full path to file name. + * @access private + * @var string full path to file name + */ + private $path; + /** + * Table name. + * @access private + * @var string sanitized + */ + private $table; + /** + * Where clause(s) of an SQL statement. + *
Array of arrays must be passed with each having the + * following keys: + *
Example Usage:
+ *$db->where['SearchTerm'] = ['name'=>'MyColumn','operator'=>'=','value'=>'MySearchTerm'
$db->where['NextSearchTerm'] = ['name'=>'MyColumn','operator'=>'=','value'=>'MyOtherSearchTerm'
Below is equivalent to the above.
+ *$db->where[0] = ['name'=>'MyColumn','operator'=>'=','value'=>'MyValue'
$db->where[1] = ['name'=>'MyColumn','operator'=>'=>','value'=>'MyValue'
Array of arrays must be passed with each having the + * following keys: + *
Example Usage:
+ *$db->where['SearchTerm'] = ['name'=>'MyColumn','operator'=>'=','value'=>'MySearchTerm'
$db->where['NextSearchTerm'] = ['name'=>'MyColumn','operator'=>'=','value'=>'MyOtherSearchTerm'
Below is equivalent to the above.
+ *$db->where[0] = ['name'=>'MyColumn','operator'=>'=','value'=>'MyValue'
$db->where[1] = ['name'=>'MyColumn','operator'=>'=>','value'=>'MyValue'
Array of fields.
+ *Fields are specified in 'name'=>'value' format. + *
Used by {@link database::add() } and {@link database::update() }
+ * @access private + * @var array Array of columns + * @see database::add() + * @see database::update() + */ + private $fields; + /** + * Unknown property + * @var unknown + * @access private + */ + private $count; + /** + * Unknown property + * @var unknown + * @access private + */ + private $sql; + /** + *Stores the result from the most recent query. The type will be based on what was requested.
+ *NOTE: If an error occurred on the last query the result is set to an empty string.
+ * @var mixed + */ + private $result; + /** + * Stores the application name making the request. + * @var string App name making database request. + * @see $app_uuid + * @access private + */ + private $app_name; + /** + * Stores the application UUID making the request. + * @var string + * @see $app_name + * @access private + */ + private $app_uuid; + /** + *Stores the domain UUID making the request.
+ *This is defaulted to the Session domain UUID.
+ * @access private + * @uses $_SESSION['domain_uuid']Message for the query results.
+ * @var array Contains the message array after a query + * @access private + */ + private $message; /** * Called when the object is created */ public function __construct() { - if (!isset($this->domain_uuid) && isset($_SESSION['domain_uuid'])) { +// $this->domain_uuid is still null +// if (!isset($this->domain_uuid) && isset($_SESSION['domain_uuid'])) { + if (isset($_SESSION['domain_uuid'])) { $this->domain_uuid = $_SESSION['domain_uuid']; } } + /** + *Magic function called whenever a property is attempted to be set.
+ *This is used to protect the values stored in the object properties.
+ * @param mixed $name Name of object property + * @param mixed $value Value of property + */ + public function __set($name,$value) { + switch($name) { + case 'name': + case 'app_name': + $this->app_name = self::sanitize($value); + break; + case 'message': + if(is_array($value)) { + $this->message = $value; + } else { + trigger_error('Message property must be set to array type', E_USER_ERROR); + } + break; + case 'table': + $this->table = self::sanitize($value); + break; + case 'db_name': + $this->db_name = self::sanitize($value); + break; + case 'db': + if($name instanceof PDO) { + $this->db = $value; + } else { + trigger_error('db property must be a PDO object!', E_USER_ERROR); + } + break; + case 'count': + break; + case 'path': + $value = realpath($value); + if(file_exists($value)) { + $this->path = $value; + } else { + trigger_error('Unable to find database path file!', E_USER_ERROR); + } + break; + case 'db_cert_authority': + if(!file_exists($value)) { + trigger_error('db cert authority not found!', E_USER_WARNING); + } + $this->db_cert_authority = $value; + break; + case 'port': + $value = (int)$value; // force cast to int + if($value > 1023 && $value < 65536) { $this->port = $value; } //valid values are 1024...65535 + else { trigger_error('Port not a valid range', E_USER_ERROR); } + break; + case 'app_uuid': + case 'domain_uuid': + if(is_uuid($value)) { $this->domain_uuid = $value; } + else { trigger_error('Domain or App UUID not valid', E_USER_ERROR); } + break; + case 'type': + case 'driver': + switch($value) { + case 'pgsql': + case 'mysql': + case 'sqlite': + case 'odbc': + $this->type = $value; + $this->driver = $value; + break; + default: + trigger_error("Type/Driver must be set to pgsql,mysql,sqlite,odbc", E_USER_ERROR); + break; + } + case 'offset': + case 'limit': + if(is_int($value)) { + $this->$name = $value; + } else { + trigger_error('Offset or Limit not set to valid integer. Resetting to zero!', E_USER_WARNING); + } + break; + case '': + trigger_error('Database property must not be empty', E_USER_ERROR); + break; + case 'null': + case null: + trigger_error('Database property must not be null', E_USER_ERROR); + break; + case 'debug': + $this->debug = $value; + } + } + + /** + * Magic function called whenever a property is requested. + *If any case statement is removed then access to the variable will be removed.
+ * @param mixed $name object property + * @return mixed + */ + public function __get($name) { + //remove any case statement below to remove access to the variable + switch($name) { + case 'name': + return $this->app_name; + case 'app_name': + case 'app_uuid': + case 'db': + case 'db_cert_authority': + case 'db_name': + case 'db_secure': + case 'domain_uuid': + case 'driver': + case 'fields': + case 'host': + case 'limit': + case 'message': + case 'offset': + case 'order_by': + case 'order_type': + case 'password': + case 'path': + case 'port': + case 'result': + case 'sql': + case 'table': + case 'type': + case 'username': + case 'where': + case 'debug': + return $this->$name; + case 'count': + return $this->count(); + default: + trigger_error('Object property not available', E_USER_ERROR); + } + } + /** * Called when there are no references to a particular object * unset the variables used in the class @@ -78,7 +375,11 @@ include "root.php"; } /** - * Connect to the database + *Connect to the database.
+ *Database driver must be set before calling connect.
+ *For types other than sqlite. Execution will stop on failure.
+ * @depends database::driver Alias of database::type. + * */ public function connect() { @@ -123,12 +424,6 @@ include "root.php"; if (!isset($this->password) && isset($db_password)) { $this->password = $db_password; } if (!isset($this->path) && isset($db_path)) { $this->path = $db_path; } } - if (strlen($this->driver) == 0) { - $this->driver = $this->type; - } - - //sanitize the database name - $this->db_name = preg_replace('#[^a-zA-Z0-9_\-\.]#', '', $this->db_name); if ($this->driver == "sqlite") { if (strlen($this->db_name) == 0) { @@ -195,7 +490,7 @@ include "root.php"; try { if (strlen($this->host) > 0) { if (strlen($this->port) == 0) { $this->port = "5432"; } - if ($this->db_secure == true) { + if ($this->db_secure === true) { $this->db = new PDO("pgsql:host=$this->host port=$this->port dbname=$this->db_name user=$this->username password=$this->password sslmode=verify-ca sslrootcert=$this->db_cert_authority"); } else { @@ -223,7 +518,13 @@ include "root.php"; } } - public function tables() { + /** + * Returns the table names from the database. + * @return array tables + * @depends connect() + */ + public function tables() : array { + $result = []; //connect to the database if needed if (!$this->db) { $this->connect(); @@ -267,7 +568,12 @@ include "root.php"; return $result; } - public function table_info() { + /** + * Returns table information from the database. + * @return array table info + * @depends connect() + */ + public function table_info() : array { //public $db; //public $type; //public $table; @@ -277,9 +583,7 @@ include "root.php"; if (!$this->db) { $this->connect(); } - //sanitize the names - $this->table = preg_replace('#[^a-zA-Z0-9_\-]#', '', $this->table); - $this->db_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $this->db_name); + //get the table info if (strlen($this->table) == 0) { return false; } if ($this->type == "sqlite") { @@ -310,7 +614,20 @@ include "root.php"; return $prep_statement->fetchAll(PDO::FETCH_ASSOC); } - public function table_exists ($db_type, $db_name, $table_name) { + /** + * Checks if the table exists in the database. + *Note:
+ * Table name must be sanitized. Otherwise, a warning will be
+ * emitted and false will be returned.
\n"; - //print_r($delete_array); - //echo "\n"; - //exit; - //set the message id $m = 0; //loop through the array $checked = false; - if (is_array($array)) { + $x = 0; + foreach ($array as $parent_name => $tables) { + if (is_array($tables)) { + foreach ($tables as $id => $row) { - $x = 0; - foreach ($array as $parent_name => $tables) { - if (is_array($tables)) { - foreach ($tables as $id => $row) { + //prepare the variables + $parent_name = self::sanitize($parent_name); + $parent_key_name = self::singular($parent_name)."_uuid"; - //prepare the variables - $parent_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_name); - $parent_key_name = $this->singular($parent_name)."_uuid"; + //build the delete array + if ($row['checked'] == 'true') { + //set checked to true + $checked = true; - //build the delete array - if ($row['checked'] == 'true') { - //set checked to true - $checked = true; - - //delete the child data - if (isset($row[$parent_key_name])) { - $new_array[$parent_name][$x][$parent_key_name] = $row[$parent_key_name]; - } - - //remove the row from the main array - unset($array[$parent_name][$x]); + //delete the child data + if (isset($row[$parent_key_name])) { + $new_array[$parent_name][$x][$parent_key_name] = $row[$parent_key_name]; } - //loop through the fields - foreach($row as $field_name => $field_value) { + //remove the row from the main array + unset($array[$parent_name][$x]); + } - //find the child tables - $y = 0; - if (is_array($field_value)) { - //prepare the variables - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); - $child_key_name = $this->singular($child_name)."_uuid"; + //loop through the fields + foreach($row as $field_name => $field_value) { - //loop through the child rows - foreach ($field_value as $sub_row) { + //find the child tables + $y = 0; + if (is_array($field_value)) { + //prepare the variables + $child_name = self::sanitize($field_name); + $child_key_name = self::singular($child_name)."_uuid"; - //build the delete array - if ($row['checked'] == 'true') { - //set checked to true - $checked = true; + //loop through the child rows + foreach ($field_value as $sub_row) { - //delete the child data - $new_array[$child_name][][$child_key_name] = $sub_row[$child_key_name]; + //build the delete array + if ($row['checked'] == 'true') { + //set checked to true + $checked = true; - //remove the row from the main array - unset($array[$parent_name][$x][$child_name][$y]); - } + //delete the child data + $new_array[$child_name][][$child_key_name] = $sub_row[$child_key_name]; - //increment the value - $y++; + //remove the row from the main array + unset($array[$parent_name][$x][$child_name][$y]); } + + //increment the value + $y++; } } + } - //increment the value - $x++; + //increment the value + $x++; - } } } } @@ -823,7 +1134,7 @@ include "root.php"; } //get the current data - if (is_array($new_array) && count($new_array) > 0) { + if (count($new_array) > 0) { //build an array of tables, fields, and values foreach($new_array as $table_name => $rows) { foreach($rows as $row) { @@ -836,15 +1147,15 @@ include "root.php"; //use the array to get a copy of the parent data before deleting it foreach($new_array as $table_name => $rows) { foreach($rows as $row) { - $table_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $table_name); - $sql = "select * from ".$table_prefix.$table_name." "; + $table_name = self::sanitize($table_name); + $sql = "select * from ".self::TABLE_PREFIX.$table_name." "; $i = 0; foreach($row as $field_name => $field_value) { if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; } $sql .= $field_name." in ( "; $i = 0; foreach($keys[$table_name][$field_name] as $field_value) { - $field_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); + $field_name = self::sanitize($field_name); if ($i > 0) { $sql .= " ,"; } $sql .= " :".$field_name."_".$i." "; $i++; @@ -867,12 +1178,12 @@ include "root.php"; } //get relations array - $relations = $this->get_relations($parent_name); + $relations = self::get_relations($parent_name); //add child data to the old array foreach($old_array as $parent_name => $rows) { //get relations array - $relations = $this->get_relations($parent_name); + $relations = self::get_relations($parent_name); //loop through the rows $x = 0; @@ -884,12 +1195,12 @@ include "root.php"; $child_table = $relation['table']; //remove the v_ prefix - if (substr($child_table, 0, 2) == "v_") { - $child_table = substr($child_table, 2); + if (substr($child_table, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX) { + $child_table = substr($child_table, strlen(self::TABLE_PREFIX)); } //get the child data - $sql = "select * from ".$table_prefix.$child_table." "; + $sql = "select * from ".self::TABLE_PREFIX.$child_table." "; $sql .= "where ".$relation['field']." = :".$relation['field']; $parameters[$relation['field']] = $row[$relation['field']]; $results = $this->execute($sql, $parameters, 'all'); @@ -900,7 +1211,7 @@ include "root.php"; //delete the child data if (isset($row[$relation['field']]) && strlen($row[$relation['field']]) > 0) { - $sql = "delete from ".$table_prefix.$child_table." "; + $sql = "delete from ".self::TABLE_PREFIX.$child_table." "; $sql .= "where ".$relation['field']." = :".$relation['field']; $parameters[$relation['field']] = $row[$relation['field']]; // $this->execute($sql, $parameters); @@ -918,54 +1229,53 @@ include "root.php"; $this->db->beginTransaction(); //delete the current data - if (is_array($new_array)) { - foreach($new_array as $table_name => $rows) { - //echo "table: ".$table_name."\n"; - foreach($rows as $row) { - if (permission_exists($this->singular($table_name).'_delete')) { - $sql = "delete from ".$table_prefix.$table_name." "; - $i = 0; - foreach($row as $field_name => $field_value) { - //echo "field: ".$field_name." = ".$field_value."\n"; - if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; } - $sql .= $field_name." = :".$field_name." "; - $parameters[$field_name] = $field_value; - $i++; + foreach($new_array as $table_name => $rows) { + //echo "table: ".$table_name."\n"; + foreach($rows as $row) { + if (permission_exists(self::singular($table_name).'_delete')) { + $sql = "delete from ".self::TABLE_PREFIX.$table_name." "; + $i = 0; + foreach($row as $field_name => $field_value) { + //echo "field: ".$field_name." = ".$field_value."\n"; + if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; } + $sql .= $field_name." = :".$field_name." "; + $parameters[$field_name] = $field_value; + $i++; + } + try { + $this->execute($sql, $parameters); + $message["message"] = "OK"; + $message["code"] = "200"; + $message["uuid"] = $id; + $message["details"][$m]["name"] = $this->name; + $message["details"][$m]["message"] = "OK"; + $message["details"][$m]["code"] = "200"; + //$message["details"][$m]["uuid"] = $parent_key_value; + if ($this->debug["sql"]) { + $message["details"][$m]["sql"] = $sql; } - try { - $this->execute($sql, $parameters); - $message["message"] = "OK"; - $message["code"] = "200"; - $message["uuid"] = $id; - $message["details"][$m]["name"] = $this->name; - $message["details"][$m]["message"] = "OK"; - $message["details"][$m]["code"] = "200"; - //$message["details"][$m]["uuid"] = $parent_key_value; - if ($this->debug["sql"]) { - $message["details"][$m]["sql"] = $sql; - } - $this->message = $message; - $m++; - unset($sql); - unset($statement); + $this->message = $message; + $m++; + unset($sql); + unset($statement); + } + catch(PDOException $e) { + $retval = false; + $message["message"] = "Bad Request"; + $message["code"] = "400"; + $message["details"][$m]["name"] = $this->name; + $message["details"][$m]["message"] = $e->getMessage(); + $message["details"][$m]["code"] = "400"; + if ($this->debug["sql"]) { + $message["details"][$m]["sql"] = $sql; } - catch(PDOException $e) { - $message["message"] = "Bad Request"; - $message["code"] = "400"; - $message["details"][$m]["name"] = $this->name; - $message["details"][$m]["message"] = $e->getMessage(); - $message["details"][$m]["code"] = "400"; - if ($this->debug["sql"]) { - $message["details"][$m]["sql"] = $sql; - } - $this->message = $message; - $m++; - } - unset($parameters); - } //if permission - } //foreach rows - } //foreach $array - } + $this->message = $message; + $m++; + } + unset($parameters); + } //if permission + } //foreach rows + } //foreach $array //commit the atomic transaction $this->db->commit(); @@ -978,7 +1288,7 @@ include "root.php"; //log the transaction results if (file_exists($_SERVER["PROJECT_ROOT"]."/app/database_transactions/app_config.php")) { - $sql = "insert into v_database_transactions "; + $sql = "insert into ".self::TABLE_PREFIX."database_transactions "; $sql .= "("; $sql .= "database_transaction_uuid, "; if (isset($this->domain_uuid) && is_uuid($this->domain_uuid)) { @@ -1058,17 +1368,21 @@ include "root.php"; $statement->execute(); unset($sql); } - + return $retval; } //delete - public function count() { + /** + * Counts the number of rows. + * @return int Represents the number of counted rows or -1 if failed. + */ + public function count() : int { //connect to the database if needed if (!$this->db) { $this->connect(); } //sanitize the table name - $this->table = preg_replace('#[^a-zA-Z0-9_\-]#', '', $this->table); + //$this->table = self::sanitize($this->table); // no longer needed //get the number of rows $sql = "select count(*) as num_rows from ".$this->table." "; @@ -1077,7 +1391,7 @@ include "root.php"; if (is_array($this->where)) { foreach($this->where as $row) { //sanitize the name - $row['name'] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $row['name']); + $row['name'] = self::sanitize($row['name']); //validate the operator switch ($row['operator']) { @@ -1086,21 +1400,18 @@ include "root.php"; case "<=": break; case ">=": break; case "=": break; - case ">=": break; case "<>": break; case "!=": break; default: //invalid operator - return false; + return -1; } //build the sql if ($i == 0) { - //$sql .= $row['name']." ".$row['operator']." '".$row['value']."' "; $sql .= "where ".$row['name']." ".$row['operator']." :".$row['name']." "; } else { - //$sql .= $row['name']." ".$row['operator']." '".$row['value']."' "; $sql .= "and ".$row['name']." ".$row['operator']." :".$row['name']." "; } @@ -1112,7 +1423,7 @@ include "root.php"; } } } - unset($this->where); + //unset($this->where); //should not be objects resposibility $prep_statement = $this->db->prepare($sql); if ($prep_statement) { $prep_statement->execute($params); @@ -1128,6 +1439,13 @@ include "root.php"; } //count + /** + * Performs a select query on database using the $sql statement supplied. + * @param type $sql Valid SQL statement. + * @param type $parameters Value can be array, empty string, or null. + * @param type $return_type Values can be set to all, row, or column. + * @return mixed Returned values can be array, string, boolean, int, or false. This is dependent on $return_type. + */ public function select($sql, $parameters = '', $return_type = 'all') { //connect to the database if needed @@ -1187,220 +1505,197 @@ include "root.php"; } } //select - public function find_new() { + /** + * Sets the object $result to sql array + * @param array $array Array containing the table name, uuid, SQL and where clause. + * @return database Returns the database object or null. + */ + public function find_new(array $array): ?database { //connect to the database if needed - if (!$this->db) { - $this->connect(); - } + if (!$this->db) { + $this->connect(); + } //set the name - if (isset($array['name'])) { - $this->name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $array['name']); - } + if (isset($array['name'])) { + $this->name = $array['name']; + } //set the uuid - if (isset($array['uuid']) and $this->is_uuid($array['uuid'])) { - $this->uuid = $array['uuid']; - } + if (isset($array['uuid'])) { + $this->uuid = $array['uuid']; + } //build the query - $sql = "SELECT * FROM v_".$this->name." "; - if (isset($this->uuid)) { - //get the specific uuid - $sql .= "WHERE ".$this->singular($this->name)."_uuid = '".$this->uuid."' "; - } - else { - //where - $i = 0; - if (is_array($array)) { - foreach($array['where'] as $row) { - //sanitize the name - $array['name'] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $array['name']); + $sql = "SELECT * FROM ".self::TABLE_PREFIX . $this->name . " "; + if (isset($this->uuid)) { + //get the specific uuid + $sql .= "WHERE " . self::singular($this->name) . "_uuid = '" . $this->uuid . "' "; + } else { + //where + $i = 0; + if (isset($array['where'])) { + foreach ($array['where'] as $row) { + if (isset($row['operator'])) { + //validate the operator + switch ($row['operator']) { + case "<": break; + case ">": break; + case "<=": break; + case ">=": break; + case "=": break; + case "<>": break; + case "!=": break; + default: + //invalid operator + return null; + } - //validate the operator - switch ($row['operator']) { - case "<": break; - case ">": break; - case "<=": break; - case ">=": break; - case "=": break; - case ">=": break; - case "<>": break; - case "!=": break; - default: - //invalid operator - return false; - } - - //build the sql - if ($i == 0) { - //$sql .= "WHERE ".$row['name']." ".$row['operator']." '".$row['value']."' "; - $sql .= "WHERE ".$row['name']." ".$row['operator']." :".$row['value']." "; - } - else { - //$sql .= "AND ".$row['name']." ".$row['operator']." '".$row['value']."' "; - $sql .= "AND ".$row['name']." ".$row['operator']." :".$row['value']." "; - } - - //add the name and value to the params array - $params[$row['name']] = $row['value']; - - //increment $i - $i++; + //build the sql + if ($i == 0) { + $sql .= "WHERE " . $row['name'] . " " . $row['operator'] . " :" . $row['value'] . " "; + } else { + $sql .= "AND " . $row['name'] . " " . $row['operator'] . " :" . $row['value'] . " "; } } - //order by - if (isset($array['order_by'])) { - $array['order_by'] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $array['order_by']); - $sql .= "ORDER BY ".$array['order_by']." "; - } - //limit - if (isset($array['limit']) && is_numeric($array['limit'])) { - $sql .= "LIMIT ".$array['limit']." "; - } - //offset - if (isset($array['offset']) && is_numeric($array['offset'])) { - $sql .= "OFFSET ".$array['offset']." "; - } + //add the name and value to the params array + $params[$row['name']] = $row['value']; + + //increment $i + $i++; + } } + //order by + if (isset($array['order_by'])) { + $array['order_by'] = self::sanitize($array['order_by']); + $sql .= "ORDER BY " . $array['order_by'] . " "; + } + //limit + if (isset($array['limit']) && is_numeric($array['limit'])) { + $sql .= "LIMIT " . $array['limit'] . " "; + } + //offset + if (isset($array['offset']) && is_numeric($array['offset'])) { + $sql .= "OFFSET " . $array['offset'] . " "; + } + } //execute the query, and return the results - try { - $prep_statement = $this->db->prepare($sql); - $prep_statement->execute($params); - $message["message"] = "OK"; - $message["code"] = "200"; - $message["details"][$m]["name"] = $this->name; - $message["details"][$m]["message"] = "OK"; - $message["details"][$m]["code"] = "200"; - if ($this->debug["sql"]) { - $message["details"][$m]["sql"] = $sql; - } - $this->message = $message; - $this->result = $prep_statement->fetchAll(PDO::FETCH_NAMED); - unset($prep_statement); - $m++; - return $this; + try { + $prep_statement = $this->db->prepare($sql); + $prep_statement->execute($params); + $message["message"] = "OK"; + $message["code"] = "200"; + $message["details"][$m]["name"] = $this->name; + $message["details"][$m]["message"] = "OK"; + $message["details"][$m]["code"] = "200"; + if ($this->debug["sql"]) { + $message["details"][$m]["sql"] = $sql; } - catch(PDOException $e) { - $message["message"] = "Bad Request"; - $message["code"] = "400"; - $message["details"][$m]["name"] = $this->name; - $message["details"][$m]["message"] = $e->getMessage(); - $message["details"][$m]["code"] = "400"; - if ($this->debug["sql"]) { - $message["details"][$m]["sql"] = $sql; - } - $this->message = $message; - $this->result = ''; - $m++; - return $this; + $this->message = $message; + $this->result = $prep_statement->fetchAll(PDO::FETCH_NAMED); + unset($prep_statement); + $m++; + } catch (PDOException $e) { + $message["message"] = "Bad Request"; + $message["code"] = "400"; + $message["details"][$m]["name"] = $this->name; + $message["details"][$m]["message"] = $e->getMessage(); + $message["details"][$m]["code"] = "400"; + if ($this->debug["sql"]) { + $message["details"][$m]["sql"] = $sql; } + $this->message = $message; + $this->result = ''; + $m++; + } + return $this; } - private function normalize_array($array, $name) { - //get the depth of the array - $depth = $this->array_depth($array); - //before normalizing the array - //echo "before: ".$depth."
\n"; - //print_r($array); - //echo "\n"; - //normalize the array - if ($depth == 1) { - $return_array[$name][] = $array; - } else if ($depth == 2) { - $return_array[$name] = $array; - //} else if ($depth == 3) { - // $return_array[$name][] = $array; - } else { - $return_array = $array; - } - unset($array); - //after normalizing the array - $depth = $this->array_depth($new_array); - //echo "after: ".$depth."
\n"; - //print_r($new_array); - //echo "\n"; - //return the array - return $return_array; - } - - public function uuid($uuid) { + /** + * Stores the passed UUID in the object + * @param string $uuid A valid UUID must be passed + * @return database Returns this object + */ + public function uuid(string $uuid) : database { $this->uuid = $uuid; return $this; } - public function copy($array) { + /** + * Copies records and appends suffix to the column description data + * @param array $array Three dimensional Array. The first dimension is the table name without the prefix 'v_'. Second dimension in the row value as int. Third dimension is the column name. + * @return bool Returns true on success and false on failure. + */ + public function copy(array $array, $suffix = '(Copy)') : bool { + //set default return value + $retval = false; //return the array - if (!is_array($array)) { echo "not an array"; return false; } + if (!is_array($array)) { return $retval; } - //set the table prefix - $table_prefix = 'v_'; + //initialize array + $copy_array = []; //set the message id $m = 0; //loop through the array - if (is_array($array)) { - $x = 0; - foreach ($array as $parent_name => $tables) { - if (is_array($tables)) { - foreach ($tables as $id => $row) { + $x = 0; + foreach ($array as $parent_name => $tables) { + if (is_array($tables)) { + foreach ($tables as $id => $row) { - //prepare the variables - $parent_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_name); - $parent_key_name = $this->singular($parent_name)."_uuid"; + //prepare the variables + $parent_name = self::sanitize($parent_name); + $parent_key_name = self::singular($parent_name)."_uuid"; - //build the copy array - if ($row['checked'] == 'true') { - //set checked to true - $checked = true; + //build the copy array + if ($row['checked'] == 'true') { + //set checked to true + $checked = true; - //copy the child data - if (is_uuid($row[$parent_key_name])) { - $copy_array[$parent_name][$x][$parent_key_name] = $row[$parent_key_name]; - } + //copy the child data + if (is_uuid($row[$parent_key_name])) { + $copy_array[$parent_name][$x][$parent_key_name] = $row[$parent_key_name]; + } - //remove the row from the main array - unset($array[$parent_name][$x]); + //remove the row from the main array + unset($array[$parent_name][$x]); - //loop through the fields + //loop through the fields - foreach($row as $field_name => $field_value) { - //find the child tables - if (is_array($field_value)) { + foreach($row as $field_name => $field_value) { + //find the child tables + if (is_array($field_value)) { - //prepare the variables - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); - $child_key_name = $this->singular($child_name)."_uuid"; + //prepare the variables + $child_name = self::sanitize($field_name); + $child_key_name = self::singular($child_name)."_uuid"; - //loop through the child rows - $y = 0; - foreach ($field_value as $sub_row) { + //loop through the child rows + $y = 0; + foreach ($field_value as $sub_row) { - //delete the child data - $copy_array[$child_name][][$child_key_name] = $sub_row[$child_key_name]; + //delete the child data + $copy_array[$child_name][][$child_key_name] = $sub_row[$child_key_name]; - //remove the row from the main array - unset($array[$parent_name][$x][$child_name][$y]); + //remove the row from the main array + unset($array[$parent_name][$x][$child_name][$y]); - //increment the value - $y++; - } + //increment the value + $y++; } } } + } - //increment the value - $x++; + //increment the value + $x++; - } } } } //get the current data - if (is_array($copy_array) && count($copy_array) > 0) { + if (count($copy_array) > 0) { //build an array of tables, fields, and values foreach($copy_array as $table_name => $rows) { @@ -1417,15 +1712,15 @@ include "root.php"; //use the array to get a copy of the paent data before deleting it foreach($copy_array as $table_name => $rows) { foreach($rows as $row) { - $table_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $table_name); - $sql = "select * from ".$table_prefix.$table_name." "; + $table_name = self::sanitize($table_name); + $sql = "select * from ".self::TABLE_PREFIX.$table_name." "; $i = 0; foreach($row as $field_name => $field_value) { if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; } $sql .= $field_name." in ( "; $i = 0; foreach($keys[$table_name][$field_name] as $field_value) { - $field_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); + $field_name = self::sanitize($field_name); if ($i > 0) { $sql .= " ,"; } $sql .= " :".$field_name."_".$i." "; $i++; @@ -1449,7 +1744,7 @@ include "root.php"; //add child data to the old array foreach($copy_array as $parent_name => $rows) { //get relations array - $relations = $this->get_relations($parent_name); + $relations = self::get_relations($parent_name); //loop through the rows $x = 0; @@ -1460,12 +1755,12 @@ include "root.php"; $child_table = $relation['table']; //remove the v_ prefix - if (substr($child_table, 0, 2) == "v_") { - $child_table = substr($child_table, 2); + if (substr($child_table, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX) { + $child_table = substr($child_table, strlen(self::TABLE_PREFIX)); } //get the child data - $sql = "select * from ".$table_prefix.$child_table." "; + $sql = "select * from ".self::TABLE_PREFIX.$child_table." "; $sql .= "where ".$relation['field']." = :".$relation['field']; $parameters[$relation['field']] = $row[$relation['field']]; $results = $this->execute($sql, $parameters, 'all'); @@ -1482,70 +1777,74 @@ include "root.php"; //update the parent and child keys $checked = false; - if (is_array($array)) { - $x = 0; - foreach ($array as $parent_name => $tables) { - if (is_array($tables)) { - foreach ($tables as $id => $row) { + $x = 0; + foreach ($array as $parent_name => $tables) { + if (is_array($tables)) { + foreach ($tables as $id => $row) { - //prepare the variables - $parent_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_name); - $parent_key_name = $this->singular($parent_name)."_uuid"; - $parent_key_value = uuid(); + //prepare the variables + $parent_name = self::sanitize($parent_name); + $parent_key_name = self::singular($parent_name)."_uuid"; + $parent_key_value = uuid(); - //update the parent key id - $array[$parent_name][$x][$parent_key_name] = $parent_key_value; + //update the parent key id + $array[$parent_name][$x][$parent_key_name] = $parent_key_value; - //add copy to the description - if (isset($array[$parent_name][$x][$this->singular($parent_name).'_description'])) { - $array[$parent_name][$x][$this->singular($parent_name).'_description'] = '(Copy) '.$array[$parent_name][$x][$this->singular($parent_name).'_description']; - } + //add copy to the description + if (isset($array[$parent_name][$x][self::singular($parent_name).'_description'])) { + $array[$parent_name][$x][self::singular($parent_name).'_description'] = $suffix.$array[$parent_name][$x][self::singular($parent_name).'_description']; + } - //loop through the fields - foreach($row as $field_name => $field_value) { + //loop through the fields + foreach($row as $field_name => $field_value) { - //find the child tables - $y = 0; - if (is_array($field_value)) { - //prepare the variables - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); - $child_key_name = $this->singular($child_name)."_uuid"; + //find the child tables + $y = 0; + if (is_array($field_value)) { + //prepare the variables + $child_name = self::sanitize($field_name); + $child_key_name = self::singular($child_name)."_uuid"; - //loop through the child rows - foreach ($field_value as $sub_row) { - //update the parent key id - $array[$parent_name][$x][$child_name][$y][$parent_key_name] = $parent_key_value; + //loop through the child rows + foreach ($field_value as $sub_row) { + //update the parent key id + $array[$parent_name][$x][$child_name][$y][$parent_key_name] = $parent_key_value; - //udpate the child key id - $array[$parent_name][$x][$child_name][$y][$child_key_name] = uuid(); + //udpate the child key id + $array[$parent_name][$x][$child_name][$y][$child_key_name] = uuid(); - //increment the value - $y++; - } + //increment the value + $y++; } } + } - //increment the value - $x++; + //increment the value + $x++; - } } } } //save the copy of the data if (is_array($array) && count($array) > 0) { - $this->save($array); + $retval = $this->save($array); unset($array); } - + return $retval; } //end function copy - - public function toggle($array) { + /** + * Toggles fields on a table using the toggle_field array values within the app object. + * @param array $array Three dimensional Array. The first dimension is the table name without the prefix 'v_'. Second dimension in the row value as int. Third dimension is the column name. + * @return bool Returns true on success and false on failure. + * @depends database::save() + * @depends database::get_apps() + */ + public function toggle(array $array) : bool { //return the array - if (!is_array($array)) { echo "not an array"; return false; } + if (!is_array($array)) { return false; } //set the message id $m = 0; @@ -1558,8 +1857,8 @@ include "root.php"; foreach ($tables as $id => $row) { //prepare the variables - $parent_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_name); - $parent_key_name = $this->singular($parent_name)."_uuid"; + $parent_name = self::sanitize($parent_name); + $parent_key_name = self::singular($parent_name)."_uuid"; //build the toggle array if ($row['checked'] == 'true') { @@ -1578,8 +1877,8 @@ include "root.php"; $y = 0; if (is_array($field_value)) { //prepare the variables - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $field_name); - $child_key_name = $this->singular($child_name)."_uuid"; + $child_name = self::sanitize($field_name); + $child_key_name = self::singular($child_name)."_uuid"; //loop through the child rows foreach ($field_value as $sub_row) { @@ -1612,7 +1911,7 @@ include "root.php"; //get the $apps array from the installed apps from the core and mod directories if (!is_array($_SESSION['apps'])) { - $this->get_apps(); + self::get_apps(); } //search through all fields to see if toggle field exists @@ -1626,7 +1925,7 @@ include "root.php"; else { $table_name = $row['table']['name']; } - if ($table_name === 'v_'.$parent_name) { + if ($table_name === self::TABLE_PREFIX.$parent_name) { if (is_array($row['fields'])) { foreach ($row['fields'] as $field) { if (isset($field['toggle'])) { @@ -1645,8 +1944,8 @@ include "root.php"; foreach ($toggle_array as $table_name => $table) { $x = 0; foreach($table as $row) { - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $table_name); - $child_key_name = $this->singular($child_name)."_uuid"; + $child_name = self::sanitize($table_name); + $child_key_name = self::singular($child_name)."_uuid"; $array[$table_name][$x][$child_key_name] = $row[$child_key_name]; $array[$table_name][$x][$toggle_field] = ($row[$toggle_field] === $toggle_values[0]) ? $toggle_values[1] : $toggle_values[0]; @@ -1656,25 +1955,25 @@ include "root.php"; unset($toggle_array); //save the array - $this->save($array); - //view_array($this->message); + return $this->save($array); } //end function toggle - - public function save($array, $transaction_save = true) { - + /** + *
Save an array to the database.
+ *Usage Example:$database = new database();
$database->app_name = "MyApp";
$database->app_uuid = "12345678-1234-1234-1234-123456789abc";
$row = 0;
$array['mytable'][$row]['mycolumn'] = "myvalue";
if ($database->save($array)) {
echo "Saved Successfully.";
} else {
echo "Save Failed.";
}
\n"; - //print_r($new_array); - //echo "\n"; - //exit; - //loop through the array - if (is_array($new_array)) foreach ($new_array as $schema_name => $schema_array) { + if (is_array($array)) foreach ($array as $schema_name => $schema_array) { - $this->name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $schema_name); + $this->name = $schema_name; if (is_array($schema_array)) foreach ($schema_array as $schema_id => $array) { //set the variables - $table_name = "v_".$this->name; - $parent_key_name = $this->singular($this->name)."_uuid"; - $parent_key_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_key_name); + $table_name = self::TABLE_PREFIX.$this->name; + $parent_key_name = self::singular($this->name)."_uuid"; + $parent_key_name = self::sanitize($parent_key_name); //if the uuid is set then set parent key exists and value //determine if the parent_key_exists @@ -1726,14 +2014,14 @@ include "root.php"; } //allow characters found in the uuid only. - $parent_key_value = preg_replace('#[^a-zA-Z0-9_\-]#', '', $parent_key_value); + $parent_key_value = self::sanitize($parent_key_value); //get the parent field names $parent_field_names = array(); if (is_array($array)) { foreach ($array as $key => $value) { if (!is_array($value)) { - $parent_field_names[] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $key); + $parent_field_names[] = self::sanitize($key); } } } @@ -1774,10 +2062,10 @@ include "root.php"; //add a record if ($action == "add") { - if (permission_exists($this->singular($this->name).'_add')) { + if (permission_exists(self::singular($this->name).'_add')) { $params = array(); - $sql = "INSERT INTO v_".$this->name." "; + $sql = "INSERT INTO ".self::TABLE_PREFIX.$this->name." "; $sql .= "("; if (!$parent_key_exists) { $sql .= $parent_key_name.", "; @@ -1785,7 +2073,7 @@ include "root.php"; if (is_array($array)) { foreach ($array as $array_key => $array_value) { if (!is_array($array_value)) { - $array_key = preg_replace('#[^a-zA-Z0-9_\-]#', '', $array_key); + $array_key = self::sanitize($array_key); $sql .= $array_key.", "; } } @@ -1855,6 +2143,7 @@ include "root.php"; $m++; } catch(PDOException $e) { + $retval = false; $message["message"] = "Bad Request"; $message["code"] = "400"; $message["details"][$m]["name"] = $this->name; @@ -1874,8 +2163,9 @@ include "root.php"; unset($sql); } else { + $retval = false; $message["name"] = $this->name; - $message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_add'"; + $message["message"] = "Forbidden, does not have '".self::singular($this->name)."_add'"; $message["code"] = "403"; $message["line"] = __line__; $this->message[] = $message; @@ -1885,15 +2175,15 @@ include "root.php"; //edit a specific uuid if ($action == "update") { - if (permission_exists($this->singular($this->name).'_edit')) { + if (permission_exists(self::singular($this->name).'_edit')) { //parent data $params = array(); - $sql = "UPDATE v_".$this->name." SET "; + $sql = "UPDATE ".self::TABLE_PREFIX.$this->name." SET "; if (is_array($array)) { foreach ($array as $array_key => $array_value) { if (!is_array($array_value) && $array_key != $parent_key_name) { - $array_key = preg_replace('#[^a-zA-Z0-9_\-]#', '', $array_key); + $array_key = self::sanitize($array_key); if (strlen($array_value) == 0) { $sql .= $array_key." = null, "; } @@ -1950,6 +2240,7 @@ include "root.php"; unset($sql); } catch(PDOException $e) { + $retval = false; $message["message"] = "Bad Request"; $message["code"] = "400"; $message["details"][$m]["name"] = $this->name; @@ -1967,8 +2258,8 @@ include "root.php"; } } else { - $message["name"] = $this->name; - $message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_edit'"; + $retval = false; + $message["message"] = "Forbidden, does not have '".self::singular($this->name)."_edit'"; $message["code"] = "403"; $message["line"] = __line__; $this->message = $message; @@ -1984,12 +2275,12 @@ include "root.php"; foreach ($array as $key => $value) { if (is_array($value)) { - $table_name = "v_".$key; - $table_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $table_name); + $table_name = self::TABLE_PREFIX.$key; + $table_name = self::sanitize($table_name); foreach ($value as $id => $row) { //prepare the variables - $child_name = $this->singular($key); - $child_name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $child_name); + $child_name = self::singular($key); + $child_name = self::sanitize($child_name); $child_key_name = $child_name."_uuid"; //determine if the parent key exists in the child array @@ -2014,14 +2305,14 @@ include "root.php"; } //allow characters found in the uuid only. - $child_key_value = preg_replace('#[^a-zA-Z0-9_\-]#', '', $child_key_value); + $child_key_value = self::sanitize($child_key_value); //get the child field names $child_field_names = array(); if (is_array($row)) { foreach ($row as $k => $v) { if (!is_array($v) && $k !== 'checked') { - $child_field_names[] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $k); + $child_field_names[] = self::sanitize($k); } } } @@ -2062,7 +2353,7 @@ include "root.php"; if (is_array($row)) { foreach ($row as $k => $v) { if (!is_array($v) && ($k != $parent_key_name || $k != $child_key_name)) { - $k = preg_replace('#[^a-zA-Z0-9_\-]#', '', $k); + $k = self::sanitize($k); if (strlen($v) == 0) { $sql .= $k." = null, "; } @@ -2117,6 +2408,7 @@ include "root.php"; $m++; } catch(PDOException $e) { + $retval = false; if ($message["code"] = "200") { $message["message"] = "Bad Request"; $message["code"] = "400"; @@ -2136,6 +2428,7 @@ include "root.php"; } } else { + $retval = false; $message["name"] = $child_name; $message["message"] = "Forbidden, does not have '${child_name}_edit'"; $message["code"] = "403"; @@ -2170,15 +2463,15 @@ include "root.php"; $sql = "INSERT INTO ".$table_name." "; $sql .= "("; if (!$parent_key_exists) { - $sql .= $this->singular($parent_key_name).", "; + $sql .= self::singular($parent_key_name).", "; } if (!$child_key_exists) { - $sql .= $this->singular($child_key_name).", "; + $sql .= self::singular($child_key_name).", "; } if (is_array($row)) { foreach ($row as $k => $v) { if (!is_array($v)) { - $k = preg_replace('#[^a-zA-Z0-9_\-]#', '', $k); + $k = self::sanitize($k); $sql .= $k.", "; } } @@ -2210,7 +2503,7 @@ include "root.php"; $params[$k] = $_SERVER['REMOTE_ADDR']; } else { - $k = preg_replace('#[^a-zA-Z0-9_\-]#', '', $k); + $k = self::sanitize($k); $sql .= ':'.$k.", "; $params[$k] = trim($v); } @@ -2248,6 +2541,7 @@ include "root.php"; $m++; } catch(PDOException $e) { + $retval = false; if ($message["code"] = "200") { $message["message"] = "Bad Request"; $message["code"] = "400"; @@ -2267,6 +2561,7 @@ include "root.php"; } } else { + $retval = false; $message["name"] = $child_name; $message["message"] = "Forbidden, does not have '${child_name}_add'"; $message["code"] = "403"; @@ -2287,20 +2582,6 @@ include "root.php"; } // foreach schema_array } // foreach main array - //return the before and after data - //log this in the future - //if (is_array($old_array)) { - //normalize the array structure - //$old_array = $this->normalize_array($old_array, $this->name); - - //debug info - //echo "
\n"; - //print_r($old_array); - //echo "\n"; - //exit; - //} - //$message["new"] = $new_array; - //$message["new"]["md5"] = md5(json_encode($new_array)); $this->message = $message; //commit the atomic transaction @@ -2325,7 +2606,7 @@ include "root.php"; //log the transaction results if ($transaction_save && file_exists($_SERVER["PROJECT_ROOT"]."/app/database_transactions/app_config.php")) { try { - $sql = "insert into v_database_transactions "; + $sql = "insert into ".self::TABLE_PREFIX."database_transactions "; $sql .= "("; $sql .= "database_transaction_uuid, "; $sql .= "domain_uuid, "; @@ -2374,7 +2655,7 @@ include "root.php"; else { $sql .= "null, "; } - if (is_array($new_array)) { + if (is_array($array)) { $sql .= ":transaction_new, "; } else { @@ -2397,8 +2678,8 @@ include "root.php"; $old_json = json_encode($old_array, JSON_PRETTY_PRINT); $statement->bindParam(':transaction_old', $old_json); } - if (is_array($new_array)) { - $new_json = json_encode($new_array, JSON_PRETTY_PRINT); + if (is_array($array)) { + $new_json = json_encode($array, JSON_PRETTY_PRINT); $statement->bindParam(':transaction_new', $new_json); } $message = json_encode($this->message, JSON_PRETTY_PRINT); @@ -2411,11 +2692,16 @@ include "root.php"; exit; } } - + return $retval; } //save method - //define singular function to convert a word in english to singular - public function singular($word) { + /** + * Converts a plural English word to singular. + * @param string $word English word + * @return string Singular version of English word + * @internal Moved to class to conserve resources. + */ + public static function singular(string $word) : string { //"-es" is used for words that end in "-x", "-s", "-z", "-sh", "-ch" in which case you add if (substr($word, -2) == "es") { if (substr($word, -4) == "sses") { // eg. 'addresses' to 'address' @@ -2451,7 +2737,14 @@ include "root.php"; } } - public function get_apps() { + /** + * Gets the $apps array from the installed apps from the core and mod directories and writes it to $_SESSION['apps'] overwriting previous values. + * @uses $_SERVER['DOCUMENT_ROOT'] Global variable + * @uses PROJECT_PATH Global variable + * @return null Does not return any values + * @internal Moved to class to conserve resources. + */ + public static function get_apps() { //get the $apps array from the installed apps from the core and mod directories $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php"); $x = 0; @@ -2464,25 +2757,36 @@ include "root.php"; $_SESSION['apps'] = $apps; } - public function array_depth($array) { + /** + * Returns the depth of an array + * @param array $array Reference to array + * @return int Depth of array + * @internal Moved to class to conserve resources. + */ + public static function array_depth(array &$array) : int { + $depth = 0; if (is_array($array)) { + $depth++; foreach ($array as $value) { - if (!isset($depth)) { $depth = 1; } if (is_array($value)) { - $depth = $this->array_depth($value) + 1; + $depth = self::array_depth($value) + 1; } } } - else { - $depth = 0; - } return $depth; } - public function domain_uuid_exists($name) { + /** + * Searches through all fields to see if domain_uuid exists + * @param string $name + * @uses $_SESSION['apps'] directly + * @return boolean true on success and false on failure + * @see database::get_apps() + */ + public static function domain_uuid_exists($name) { //get the $apps array from the installed apps from the core and mod directories if (!is_array($_SESSION['apps'])) { - $this->get_apps(); + self::get_apps(); } //search through all fields to see if domain_uuid exists @@ -2497,7 +2801,7 @@ include "root.php"; else { $table_name = $row['table']['name']; } - if ($table_name === 'v_'.$name) { + if ($table_name === self::TABLE_PREFIX.$name) { if (is_array($row['fields'])) { foreach ($row['fields'] as $field) { if ($field['name'] == "domain_uuid") { @@ -2515,18 +2819,24 @@ include "root.php"; return false; } - public function get_relations($schema) { + /** + * Get Relations searches through all fields to find relations + * @param string $schema Table name + * @return array Returns array or false + * @internal Moved to class to conserve resources. + */ + public static function get_relations($schema) { //remove the v_ prefix - if (substr($schema, 0, 2) == "v_") { - $schema = substr($schema, 2); + if (substr($schema, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX) { + $schema = substr($schema, strlen(self::TABLE_PREFIX)); } //sanitize the values - $schema = preg_replace('#[^a-zA-Z0-9_\-]#', '', $schema); + $schema = self::sanitize($schema); //get the apps array - $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/{core,app}/{".$schema.",".$this->singular($schema)."}/app_config.php", GLOB_BRACE); + $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/{core,app}/{".$schema.",".self::singular($schema)."}/app_config.php", GLOB_BRACE); foreach ($config_list as &$config_path) { include($config_path); } @@ -2538,7 +2848,7 @@ include "root.php"; foreach ($row['fields'] as $z => $field) { if ($field['deprecated'] != "true") { if ($field['key']['type'] == "foreign") { - if ($row['table']['name'] == "v_".$schema || $field['key']['reference']['table'] == "v_".$schema) { + if ($row['table']['name'] == self::TABLE_PREFIX.$schema || $field['key']['reference']['table'] == self::TABLE_PREFIX.$schema) { //get the field name if (is_array($field['name'])) { $field_name = trim($field['name']['text']); @@ -2574,6 +2884,33 @@ include "root.php"; } } + /** + * Returns a sanitized string value safe for database or table name. + * @param string $value To be sanitized + * @return string Sanitized using preg_replace('#[^a-zA-Z0-9_\-]#', '') + * @see preg_replace() + */ + public static function sanitize(string $value) : string { + return preg_replace('#[^a-zA-Z0-9_\-]#', '', $value); + } + + /** + * Returns a new connected database object.
This allows a shortcut for a common syntax. For more information + * on how the connection happens see {@link database::__construct()} and + * {@link database::connect()}
+ *Usage:
+ * $database_object = database::new();