mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-11-25 00:26:17 +00:00
be9704a768
TODO: add files to database TODO: hash folder to stick files in
522 lines
14 KiB
PHP
522 lines
14 KiB
PHP
<?php
|
|
/* Copyright (C) 2009 Winch Gate Property Limited
|
|
*
|
|
* This file is part of ryzom_api.
|
|
* ryzom_api is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* ryzom_api is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with ryzom_api. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
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 = '<table cellpadding="0" cellspacing="0" width="100%">';
|
|
$tr_header = '<td align="left" height="32px"> ';
|
|
$tr_header .= implode('</td><td align="left"> ', array_keys($params)).'</td>';
|
|
$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 ', '<td>'._s('section', $current_section).'</td>'.str_repeat('<td>'._s('section', ' ').'</td>', count($params)-1));
|
|
}
|
|
$td = '';
|
|
foreach ($params as $test => $param)
|
|
$td .= '<td align="left" height="22px"> '.$rows[$param].'</td>';
|
|
$ret .= _s('t row '.strval($i % 2), $td);
|
|
$i++;
|
|
}
|
|
$ret .= '</table>';
|
|
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 '<pre>'.$c.'<pre>';
|
|
}
|
|
}
|
|
|
|
?>
|