. */ define('SQL_DEF_TEXT', 0); define('SQL_DEF_BOOLEAN', 1); define('SQL_DEF_INT', 2); define('SQL_DEF_DATE', 3); // Wrapper for SQL database interactions class ServerDatabase { var $hostname = ''; var $username = ''; var $password = ''; var $database = ''; var $_connection = Null; function ServerDatabase($host='', $user='', $passwd='', $dbname='') { if (($host != '') && ($user != '') && ($dbname != '')) { $this->hostname = $host; $this->username = $user; $this->password = $passwd; $this->database = $dbname; } if (($this->hostname != '') && ($this->username != '') && ($this->database != '')) $this->_connection = new mysqli($this->hostname, $this->username, $this->password, $this->database); } function close() { $this->_connection->close(); } function query($sql_statement) { $result = $this->_connection->query($sql_statement); if (!$result) alert('MYSQL', $this->get_error(), 2); return $result; } function select_db($dbname) { $this->database = $dbname; $this->_connection->select_db($dbname); } function num_rows($result) { return $result->num_rows; } function fetch_row($result, $result_type=MYSQLI_BOTH) { if (gettype($result) == "object") return $result->fetch_array($result_type); return NULL; } function fetch_assoc($result) { if (gettype($result) == "object") return $result->fetch_assoc(); return NULL; } function query_single_row($sql_statement) { $result = $this->query($sql_statement); if (gettype($result) == "object") return $result->fetch_array(); return NULL; } function free_result($result) { $result->free(); } function get_error() { return $this->_connection->errno.': '.$this->_connection->error; } function last_insert_id() { return $this->_connection->insert_id; } function escape_string($escapestr) { return $this->_connection->real_escape_string($escapestr); } function change_to($host,$user,$pass,$dbname) { /*$this->close(); $this->hostname = $host; $this->username = $user; $this->password = $pass; $this->database = $dbname; $this->ServerDatabase();*/ } } class ryDB { private static $_instances = array(); private $db; private $defs = array(); private $errors = ''; private function __construct($db_name) { global $_RYZOM_API_CONFIG; $this->db_name = $db_name; $this->db = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, $db_name); $this->db->query("SET NAMES utf8"); } public static function getInstance($db_name) { if (!array_key_exists($db_name, self::$_instances)) self::$_instances[$db_name] = new ryDB($db_name); self::$_instances[$db_name]->db->select_db($db_name); return self::$_instances[$db_name]; } function setDbDefs($table, $defs, $check=true) { if ($check) { $result = $this->db->query('SHOW FIELDS FROM '.$table); if (!$result) { die("Table [$table] not found in database [$this->db_name]"); } $fields = array_keys($defs); while ($row = $this->db->fetch_row($result)) { if (in_array($row['Field'], $fields)) unset($fields[array_search($row['Field'], $fields)]); else alert('DbLib', 'Missing field '.$row['Field']." on DbDef of table [$table] of database [$this->db_name] !", 2); } if ($fields) die('Missing fields ['.implode('] [', $fields)."] in table [$table] of database [$this->db_name] !"); } $this->defs[$table] = $defs; } function getDefs($table) { if ($this->hasDbDefs($table)) return $this->defs[$table]; alert('DBLIB', "Please add tables to '$this->db_name' defs using setDbDefs('$table', \$defs)", 2); } function hasDbDefs($table) { return array_key_exists($table, $this->defs); } function getErrors() { return $this->db->get_error(); } function now() { return date('Y-m-d H:i:s', time()); } function toDate($timestamp) { return date('Y-m-d H:i:s', $timestamp); } function fromDate($string_date) { return strtotime($string_date); } function addDbTableProp($table, $props) { $this->props[$table] = $props; } function sqlEscape($escapestr) { return $this->db->escape_string($escapestr); } function insertID() { return $this->db->last_insert_id(); } /// DIRECT QUERY function sqlQuery($sql, $index = false, $result_type = MYSQLI_BOTH) { $result = $this->db->query($sql); if (!$result) return NULL; if($index !== false && !is_array($index)){ $index = array($index); } $ret = array(); while ($row = $this->db->fetch_row($result, $result_type)) { if($index !== false) { // if $index is ['id1', 'id2'], then this code executes as // $ret[$row['id1']][$row['id2']] = $row $current = &$ret; foreach($index as $key){ if(!isset($row[$key])) alert('DBLIB', "Requested index field ($key) was not selected from db"); $current = &$current[$row[$key]]; } $current = $row; } else $ret[] = $row; } return $ret; } /// QUERY /// function sqlSelect($table, $props, $values=array(), $extra='') { if ($table) { $sql = "SELECT\n\t"; $params = array(); $test = array(); if (!$props) alert('DBLIB', "Bad Select on [$table] : missing props"); foreach($props as $name => $type) $params[] = '`'.$this->sqlEscape($name).'`'; foreach($values as $name => $value) { if ($name[0] == '=') $test[] = '('.$this->sqlEscape(substr($name, 1)).' LIKE '.var_export($value, true).')'; else $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')'; } $sql .= implode(",\n\t", $params)."\nFROM\n\t".$table."\n"; if ($test) $sql .= "WHERE\n\t".implode("\nAND\n\t", $test); } if ($extra) $sql .= "\n".$extra; return $sql.';'; } function querySingle($table, $values=array(), $extra='') { $sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra); $result = $this->sqlQuery($sql, false, MYSQLI_BOTH); if(empty($result)) return NULL; return $result[0]; } function querySingleAssoc($table, $values=array(), $extra='') { $sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra); $result = $this->sqlQuery($sql, false, MYSQLI_ASSOC); if(empty($result)) return NULL; return $result[0]; } function query($table, $values=array(), $extra='', $index = false, $result_type = MYSQLI_BOTH) { $sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra); return $this->sqlQuery($sql, $index, $result_type); } function queryAssoc($table, $values=array(), $extra='', $index = false) { return $this->query($table, $values, $extra, $index, MYSQLI_ASSOC); } function queryIndex($table, $index, $values=array(), $extra='') { return $this->query($table, $values, $extra, $index, MYSQLI_ASSOC); } /// INSERT /// function sqlInsert($table, $props, $vals) { $sql = 'INSERT INTO '.$table.' '; $params = array(); $values = array(); foreach($props as $name => $type) { if (!isset($vals[$name])) continue; $params[] = '`'.$name.'`'; switch ($type) { case SQL_DEF_BOOLEAN: $values[] = $vals[$name]?1:0; break; case SQL_DEF_INT: $values[] = $vals[$name]; break; case SQL_DEF_DATE: // date if (is_string($vals[$name])) $values[] = "'".$this->sqlEscape($vals[$name])."'"; else $values[] = "'".$this->toDate($vals[$name])."'"; break; default: $values[] = "'".$this->sqlEscape($vals[$name])."'"; break; } } $sql .= "(\n\t".implode(",\n\t", $params)."\n) VALUES (\n\t".implode(",\n\t", $values)."\n);"; return $sql; } function insert($table, $values) { $sql = $this->sqlInsert($table, $this->getDefs($table), $values); $this->db->query($sql); return $this->db->last_insert_id(); } /// DELETE /// function sqlDelete($table, $values=array(), $where='') { $sql = "DELETE FROM\n\t".$table."\n"; $test = array(); foreach($values as $name => $value) $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')'; if ($test or $where) $sql .= "WHERE\n\t"; if ($test) $sql .= implode("\nAND\n\t", $test); if ($where) $sql .= "\n".$where; return $sql.';'; } function delete($table, $values=array(), $where='') { $sql = $this->sqlDelete($table, $values, $where); $result = $this->db->query($sql); return $result; } /// UPDATE /// function sqlUpdate($table, $props, $vals, $tests, $extra) { $sql = 'UPDATE '.$table.' SET '; $params = array(); $test = array(); $values = array(); foreach($props as $name => $type) { if (!array_key_exists($name, $vals)) continue; switch ($type) { case SQL_DEF_BOOLEAN: $values[] = '`'.$name.'` = '.($vals[$name]?'1':'0'); break; case SQL_DEF_DATE: if (is_string($vals[$name])) $values[] = '`'.$name.'` = \''.$this->sqlEscape($vals[$name]).'\''; else $values[] = '`'.$name.'` = \''.$this->toDate($vals[$name]).'\''; break; default: $values[] = '`'.$name.'` = \''.$this->sqlEscape($vals[$name]).'\''; break; } } $sql .= "\n\t".implode(",\n\t", $values)."\n"; foreach($tests as $name => $value) { $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')'; } if ($test) $sql .= "WHERE\n\t".implode("\nAND\n\t", $test); $sql .= "\n".$extra; return $sql; } function update($table, $values=array(), $test=array(), $extra='') { $sql = $this->sqlUpdate($table, $this->getDefs($table), $values, $test, $extra); $result = $this->db->query($sql); return $result; } function sqlInsertOrUpdate($table, $props, $vals) { $sql = $this->sqlInsert($table, $props, $vals); $sql = substr($sql, 0, strlen($sql)-1); $params = array(); $test = array(); $values = array(); foreach($props as $prop) { if (!array_key_exists($prop[2], $vals)) continue; $type = $prop[0]; $check = $prop[1]; $name = $prop[2]; if ($type{0} == '#') $type = substr($type, 1); if (($type{0} == '>') or ($type == 'id')) continue; switch ($type) { case 'trad': $values[] = '`'.$name."` = '".$this->sqlEscape($vals[$name])."'"; break; case 'textarea': case 'string': case 'option': $values[] = '`'.$name."` = '".$this->sqlEscape($vals[$name])."'"; break; case 'id': case 'int': case 'float': $values[] = '`'.$name.'` = '.$this->sqlEscape($vals[$name]); break; case 'bool': $values[] = '`'.$name.'` = '.($vals[$name]?'1':'0'); break; } } $sql .= "\nON DUPLICATE KEY UPDATE\n\t".implode(",\n\t", $values)."\n"; return $sql; } function insertOrUpdate($table, $values) { $sql = $this->sqlInsertOrUpdate($table, $this->getDefs($table), $values); return $result; } /// Display function getTableHtml($name, $params, $values, $order_by='') { $ret = ''; $tr_header = ''; $ret .= _s('t header', $tr_header); $i = 0; if (!$values) return ''; $current_section = ''; foreach ($values as $rows) { if ($order_by && $rows[$order_by] != $current_section) { $current_section = $rows[$order_by]; if ($current_section != '0') $ret .= _s('t row ', ''.str_repeat('', count($params)-1)); } $td = ''; foreach ($params as $test => $param) $td .= ''; $ret .= _s('t row '.strval($i % 2), $td); $i++; } $ret .= '
 '; $tr_header .= implode(' ', array_keys($params)).''._s('section', $current_section).''._s('section', ' ').' '.$rows[$param].'
'; return $ret; } /// Update Database Structure static function updateDatabaseStruct($defs) { if (file_exists(RYAPP_PATH.'database.versions')) $versions = unserialize(file_get_contents(RYAPP_PATH.'database.versions')); else $versions = array(); $c = "Updating DB Structure...\n"; foreach ($defs as $dbname => $tables) { $db = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, $dbname); $db->query("SET NAMES utf8"); $c .= "\n Selected DB '$dbname'\n"; foreach ($tables as $table => $sql) { $version = count($sql); if (array_key_exists($table, $versions)) $diff = $version - $versions[$table]; else { $versions[$table] = 0; $diff = $version; } $c .= " Table '$table' need v$version (current v".strval($versions[$table].') => '); if ($diff > 0) { $sql_to_run = array_slice($sql, $versions[$table], $diff); foreach($sql_to_run as $sql_run) { if ($sql_run) { $c .= "Run sql... "; $result = $db->query($sql_run); } else $c .= "KO!!!"; } if ($result) { $c .= "OK"; $versions[$table] = $version; } } else $c .= "OK"; $c .= "\n"; } $c .= "\n"; $db->close(); } file_put_contents(RYAPP_PATH.'database.versions', serialize($versions)); return '
'.$c.'
';
	}
}

?>