Update base libraries, fix E_NOTICEs
parent
2c595b01aa
commit
ea2cd9e5e0
|
@ -0,0 +1,641 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Very stable interface for MySQL - object-oriented at last :)
|
||||
* Select builder is inspired by MediaWiki's one.
|
||||
* (c) Vitaliy Filippov, 2012
|
||||
*/
|
||||
|
||||
if (!defined('MS_HASH'))
|
||||
{
|
||||
define('MS_HASH', 0);
|
||||
define('MS_LIST', 1);
|
||||
define('MS_ROW', 2);
|
||||
define('MS_ONE', 2);
|
||||
define('MS_COL', 4);
|
||||
define('MS_VALUE', 6);
|
||||
define('MS_RESULT', 8);
|
||||
}
|
||||
|
||||
class DatabaseException extends Exception {}
|
||||
|
||||
if (!interface_exists('Database'))
|
||||
{
|
||||
interface Database {}
|
||||
}
|
||||
|
||||
class DatabaseMysql implements Database
|
||||
{
|
||||
var $host, $port, $socket, $username, $password, $dbname;
|
||||
|
||||
var $tableNames = array();
|
||||
var $queryLogFile;
|
||||
var $reconnect = true;
|
||||
|
||||
var $queryCount = 0;
|
||||
var $link;
|
||||
var $transactions;
|
||||
|
||||
/**
|
||||
* Creates a MySQL connection object.
|
||||
*
|
||||
* @param array $options Possible options:
|
||||
* host Host name or IP address to connect to [localhost]
|
||||
* socket Path to UNIX socket to connect to [/var/run/mysqld/mysqld.sock]
|
||||
* port TCP port to connect to [3306]
|
||||
* dbname DB name to use
|
||||
* username Username
|
||||
* password Password
|
||||
* reconnect Whether to reconnect on idle timeout [true]
|
||||
* queryLogFile Path to query log file
|
||||
*/
|
||||
function __construct($options)
|
||||
{
|
||||
$defOpts = array(
|
||||
'host' => 'localhost',
|
||||
'port' => 3306,
|
||||
'socket' => '/var/run/mysqld/mysqld.sock',
|
||||
'dbname' => '',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'reconnect' => true,
|
||||
'queryLogFile' => '',
|
||||
);
|
||||
$options += $defOpts;
|
||||
if ($options['socket'])
|
||||
{
|
||||
$options['host'] = 'localhost';
|
||||
}
|
||||
foreach ($defOpts as $k => $v)
|
||||
{
|
||||
$this->$k = $options[$k];
|
||||
}
|
||||
}
|
||||
|
||||
function connect()
|
||||
{
|
||||
if ($this->socket !== NULL)
|
||||
{
|
||||
$this->link = new mysqli($this->host, $this->username, $this->password, $this->dbname, $this->port, $this->socket);
|
||||
}
|
||||
elseif ($this->port !== NULL)
|
||||
{
|
||||
$this->link = new mysqli($this->host, $this->username, $this->password, $this->dbname, $this->port);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->link = new mysqli($this->host, $this->username, $this->password, $this->dbname);
|
||||
}
|
||||
$errno = $this->link->connect_errno;
|
||||
$error = $this->link->connect_error;
|
||||
if ($errno)
|
||||
{
|
||||
$this->link = NULL;
|
||||
throw new DatabaseException($error, $errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->link->set_charset('utf8');
|
||||
}
|
||||
}
|
||||
|
||||
function getDBName()
|
||||
{
|
||||
return $this->dbname;
|
||||
}
|
||||
|
||||
function quoteId($name)
|
||||
{
|
||||
return "`".str_replace("`", "``", $name)."`";
|
||||
}
|
||||
|
||||
function quote($value)
|
||||
{
|
||||
if ($value === NULL)
|
||||
{
|
||||
return "NULL";
|
||||
}
|
||||
if (!$this->link)
|
||||
{
|
||||
$this->connect();
|
||||
}
|
||||
return "'" . $this->link->real_escape_string($value) . "'";
|
||||
}
|
||||
|
||||
function query($sql, $fetchMode = MYSQLI_STORE_RESULT)
|
||||
{
|
||||
$this->queryCount++;
|
||||
if ($this->queryLogFile)
|
||||
{
|
||||
file_put_contents($this->queryLogFile, date("[Y-m-d H:i:s] ").$sql."\n", FILE_APPEND);
|
||||
}
|
||||
if (!$this->link)
|
||||
{
|
||||
$this->connect();
|
||||
}
|
||||
$r = $this->link->query($sql, $fetchMode);
|
||||
if (!$r)
|
||||
{
|
||||
if ($this->link->errno == 2006 && $this->reconnect)
|
||||
{
|
||||
// "MySQL server has gone away"
|
||||
$this->link = false;
|
||||
}
|
||||
throw new DatabaseException($this->link->error, $this->link->errno);
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a transaction, supports nested calls and savepoints.
|
||||
* @param boolean $savepoint Creates savepoints only this parameter is true.
|
||||
*/
|
||||
function begin($savepoint = false)
|
||||
{
|
||||
$this->transactions[] = $savepoint;
|
||||
$n = count($this->transactions);
|
||||
if ($n == 1)
|
||||
{
|
||||
return $this->query("BEGIN");
|
||||
}
|
||||
elseif ($savepoint)
|
||||
{
|
||||
return $this->query("SAVEPOINT sp$n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits transaction or releases last savepoint.
|
||||
* If there is no last savepoint, just returns true.
|
||||
*/
|
||||
function commit()
|
||||
{
|
||||
$savepoint = array_pop($this->transactions);
|
||||
if (!$this->transactions)
|
||||
{
|
||||
return $this->query("COMMIT");
|
||||
}
|
||||
elseif ($savepoint)
|
||||
{
|
||||
return $this->query("RELEASE SAVEPOINT sp".count($this->transactions));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollbacks transaction or last savepoint.
|
||||
* If there is no savepoint, returns false.
|
||||
*/
|
||||
function rollback()
|
||||
{
|
||||
$savepoint = array_pop($this->transactions);
|
||||
if (!$this->transactions)
|
||||
{
|
||||
return $this->query("ROLLBACK");
|
||||
}
|
||||
elseif ($savepoint)
|
||||
{
|
||||
return $this->query("ROLLBACK TO SAVEPOINT sp".count($this->transactions));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function errno()
|
||||
{
|
||||
return $this->link->errno;
|
||||
}
|
||||
|
||||
function error()
|
||||
{
|
||||
return $this->link->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds WHERE-part of an SQL query.
|
||||
* $where can also be a string - then it's passed as-is.
|
||||
*
|
||||
* @param array $where Query conditions:
|
||||
* array(
|
||||
* 'conditional expression',
|
||||
* 'field_name' => 'value',
|
||||
* 'field_name' => array('one', 'of', 'values'),
|
||||
* 'field1,field2' => array(array(1, 2), array(3, 4)),
|
||||
* )
|
||||
*/
|
||||
function where_builder($where)
|
||||
{
|
||||
if (!is_array($where))
|
||||
return $where;
|
||||
$wh = array();
|
||||
foreach ($where as $k => $v)
|
||||
{
|
||||
if (ctype_digit("$k"))
|
||||
$wh[] = $v;
|
||||
elseif (is_array($v))
|
||||
{
|
||||
if (!$v)
|
||||
{
|
||||
throw new DatabaseException("Error: empty array for '$k IN (...)', don't know what to do");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($v[0]))
|
||||
foreach ($v as &$l)
|
||||
$l = "(" . implode(",", array_map(array($this, 'quote'), $l)) . ")";
|
||||
else
|
||||
$v = array_map(array($this, 'quote'), $v);
|
||||
$wh[] = "$k IN (" . implode(",", $v) . ")";
|
||||
}
|
||||
}
|
||||
elseif ($v !== NULL)
|
||||
$wh[] = "$k=".$this->quote($v);
|
||||
else
|
||||
$wh[] = "$k IS NULL";
|
||||
}
|
||||
if (!$wh)
|
||||
$where = '1';
|
||||
else
|
||||
$where = '(' . join(') AND (', $wh) . ')';
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds SQL query text.
|
||||
*
|
||||
* @param mixed $tables see $this->tablesBuilder()
|
||||
* @param mixed $fields Field definitions - either a string or an array.
|
||||
* Strings are passed to resulting query text as-is.
|
||||
* Arrays have the following format:
|
||||
* array('field1', 'alias2' => 'expression2', ...)
|
||||
* @param mixed $where see $this->whereBuilder()
|
||||
* @param array $options query options - array of:
|
||||
* 'CALC_FOUND_ROWS'
|
||||
* 'NO_CACHE' or 'CACHE'
|
||||
* 'FOR UPDATE' or 'LOCK IN SHARE MODE'
|
||||
* 'GROUP BY' => array($groupby_field1 => 'ASC', $groupby_field2 => 'DESC')
|
||||
* 'ORDER BY' => array($orderby_field1 => 'ASC', $orderby_field2 => 'DESC')
|
||||
* 'LIMIT' => array($limit, $offset) or array($limit) or just $limit
|
||||
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
|
||||
*/
|
||||
function select_builder($tables, $fields, $where, $options = NULL)
|
||||
{
|
||||
if (!$options)
|
||||
$options = array();
|
||||
else
|
||||
{
|
||||
foreach ($options as $k => $v)
|
||||
if (ctype_digit("$k"))
|
||||
$options[$v] = true;
|
||||
}
|
||||
if (is_array($fields))
|
||||
{
|
||||
foreach ($fields as $k => $v)
|
||||
if (!ctype_digit("$k"))
|
||||
$fields[$k] = "$v AS ".$this->quoteId($k);
|
||||
$fields = join(',', $fields);
|
||||
}
|
||||
$where = $this->where_builder($where);
|
||||
$tables = $this->tables_builder($tables);
|
||||
$sql = 'SELECT ';
|
||||
if (isset($options['CALC_FOUND_ROWS']) || isset($options['SQL_CALC_FOUND_ROWS']))
|
||||
$sql .= 'SQL_CALC_FOUND_ROWS ';
|
||||
if (isset($options['NO_CACHE']) || isset($options['SQL_NO_CACHE']))
|
||||
$sql .= 'SQL_NO_CACHE ';
|
||||
elseif (isset($options['CACHE']) || isset($options['SQL_CACHE']))
|
||||
$sql .= 'SQL_CACHE ';
|
||||
$sql .= "$fields FROM $tables WHERE $where";
|
||||
if (isset($options['GROUP BY']))
|
||||
{
|
||||
$g = $options['GROUP BY'];
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (ctype_digit("$k"))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " GROUP BY $g";
|
||||
}
|
||||
if (isset($options['ORDER BY']))
|
||||
{
|
||||
$g = $options['ORDER BY'];
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (ctype_digit("$k"))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " ORDER BY $g";
|
||||
}
|
||||
$sql .= $this->limit_option($options);
|
||||
if (isset($options['FOR UPDATE']))
|
||||
$sql .= ' FOR UPDATE';
|
||||
elseif (isset($options['LOCK IN SHARE MODE']))
|
||||
$sql .= ' LOCK IN SHARE MODE';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a single LIMIT or LIMIT and OFFSET options.
|
||||
*/
|
||||
function limit_option($options)
|
||||
{
|
||||
if (isset($options['LIMIT']))
|
||||
{
|
||||
$g = $options['LIMIT'];
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
elseif ($g && isset($options['OFFSET']))
|
||||
$g = "$options[OFFSET], $g";
|
||||
if ($g)
|
||||
return " LIMIT $g";
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds FROM-part of an SQL query.
|
||||
*
|
||||
* $tables = array(
|
||||
* 'table',
|
||||
* 'alias' => 'table',
|
||||
* 'alias' => array('INNER', 'table_name', $where_for_on_clause),
|
||||
* 'alias' => array('INNER', $nested_tables),
|
||||
* )
|
||||
* or just a string "`table1` INNER JOIN `table2` ON ..."
|
||||
* names taken into `backticks` will be transformed using $this->tableNames
|
||||
*/
|
||||
function tables_builder($tables)
|
||||
{
|
||||
if (is_array($tables))
|
||||
{
|
||||
$t = '';
|
||||
foreach ($tables as $k => $v)
|
||||
{
|
||||
if (!ctype_digit("$k"))
|
||||
{
|
||||
if (is_array($v))
|
||||
{
|
||||
$join = strtolower(substr($v[0], 0, 4));
|
||||
if ($join == 'righ')
|
||||
$join = 'RIGHT';
|
||||
elseif ($join == 'left')
|
||||
$join = 'LEFT';
|
||||
else /* if (!$join || $join == 'inne' || $join == 'join') */
|
||||
$join = 'INNER';
|
||||
if (is_array($v[1])) // nested join (left join (A join B on ...) on ...)
|
||||
$table = '('.$this->tables_builder($v[1]).')';
|
||||
else
|
||||
$table = (isset($this->tableNames[$v[1]]) ? $this->quoteId($this->tableNames[$v[1]]) : $v[1]) . ' ' . $k;
|
||||
if ($t)
|
||||
$t .= " $join JOIN $table ON ".$this->where_builder($v[2]);
|
||||
else
|
||||
$t = $table;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
$v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]) : $v) . ' ' . $k;
|
||||
}
|
||||
else
|
||||
$v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]).' '.$v : $v);
|
||||
if ($t)
|
||||
$t .= " INNER JOIN $v";
|
||||
else
|
||||
$t = $v;
|
||||
}
|
||||
$tables = $t;
|
||||
}
|
||||
else
|
||||
$tables = preg_replace_callback('/((?:,|JOIN)\s*`)([^`]+)/s', array($this, 'tables_builder_pregcb1'), $tables);
|
||||
return $tables;
|
||||
}
|
||||
|
||||
function tables_builder_pregcb1($m)
|
||||
{
|
||||
if (isset($this->tableNames[$m[2]]))
|
||||
return $m[1].$this->tableNames[$m[2]];
|
||||
return $m[1].$m[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a SELECT query and return results.
|
||||
*
|
||||
* Usage: either
|
||||
* $this->select($tables, $fields, $where, $options, $format)
|
||||
* using $this->select_builder() or
|
||||
* $this->select($sql_text, $format)
|
||||
* using query text.
|
||||
*
|
||||
* @param int $format Return format, bitmask of MS_XX constants:
|
||||
* MS_RESULT = return mysqli result object to manually fetch from
|
||||
* MS_LIST = return rows as indexed arrays
|
||||
* MS_HASH = return rows as associative arrays (default)
|
||||
* MS_ROW = only return the first row
|
||||
* MS_COL = only return the first column
|
||||
* MS_VALUE = only return the first cell (just 1 value)
|
||||
*/
|
||||
function select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0)
|
||||
{
|
||||
if (is_int($fields) || is_string($fields) && ctype_digit($fields))
|
||||
{
|
||||
$sql = $tables;
|
||||
$format = $fields;
|
||||
}
|
||||
else
|
||||
$sql = $this->select_builder($tables, $fields, $where, $options);
|
||||
if ($format & MS_RESULT)
|
||||
return $this->query($sql, MYSQLI_USE_RESULT);
|
||||
if ($format & MS_LIST)
|
||||
$r = $this->get_rows($sql);
|
||||
else
|
||||
$r = $this->get_assocs($sql);
|
||||
if (!$r)
|
||||
$r = array();
|
||||
if ($format & MS_ROW)
|
||||
{
|
||||
if (!count($r))
|
||||
return NULL;
|
||||
if ($format & MS_COL)
|
||||
{
|
||||
$r = $r[0];
|
||||
$k = array_keys($r);
|
||||
$r = $r[$k[0]];
|
||||
}
|
||||
else
|
||||
$r = $r[0];
|
||||
}
|
||||
elseif ($format & MS_COL)
|
||||
{
|
||||
foreach ($r as $i => $v)
|
||||
{
|
||||
if (!$k)
|
||||
{
|
||||
$k = array_keys($v);
|
||||
$k = $k[0];
|
||||
}
|
||||
$r[$i] = $v[$k];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function found_rows()
|
||||
{
|
||||
return $this->select('SELECT FOUND_ROWS()', MS_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a set of rows.
|
||||
* @param mixed $tables see $this->tables_builder()
|
||||
* @param mixed $where see $this->where_builder()
|
||||
* @param array $options Options for query:
|
||||
* 'LIMIT' => array($limit, $offset) or array($limit) or just $limit
|
||||
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
|
||||
*/
|
||||
function delete($tables, $where, $options = NULL)
|
||||
{
|
||||
$tables = $this->tables_builder($tables);
|
||||
$where = $this->where_builder($where);
|
||||
$sql = "DELETE FROM $tables WHERE $where";
|
||||
$sql .= $this->limit_option($options);
|
||||
$this->query($sql);
|
||||
return $this->link->affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an INSERT query.
|
||||
* @param string $table Table name to insert rows to.
|
||||
* @param array $rows Array of table rows to be inserted.
|
||||
* @param boolean $onduplicatekey If true, include
|
||||
* ON DUPLICATE KEY UPDATE column=VALUES(column) for all columns.
|
||||
*/
|
||||
function insert_builder($table, $rows, $onduplicatekey = false, $replace = false)
|
||||
{
|
||||
if (isset($this->tableNames[$table]))
|
||||
{
|
||||
$table = $this->tableNames[$table];
|
||||
}
|
||||
$key = array_keys($rows[0]);
|
||||
foreach ($rows as &$r)
|
||||
{
|
||||
$rs = array();
|
||||
foreach ($key as &$k)
|
||||
$rs[] = $this->quote($r[$k]);
|
||||
$r = "(".implode(",", $rs).")";
|
||||
}
|
||||
foreach ($key as &$k)
|
||||
if (strpos($k, '`') === false)
|
||||
$k = $this->quoteId($k);
|
||||
$sql = ($replace ? "REPLACE" : "INSERT").
|
||||
" INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows);
|
||||
if ($onduplicatekey)
|
||||
{
|
||||
foreach ($key as &$k)
|
||||
$k = "$k=VALUES($k)";
|
||||
$sql .= " ON DUPLICATE KEY UPDATE ".implode(",",$key);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single row into $table and return inserted ID.
|
||||
* @param string $table Table name to insert row to.
|
||||
* @param array $rows Row to be inserted.
|
||||
* @return int $insert_id Autoincrement ID of inserted row (if appropriate).
|
||||
*/
|
||||
function insert_row($table, $row)
|
||||
{
|
||||
$sql = $this->insert_builder($table, array($row));
|
||||
if ($this->query($sql))
|
||||
return $this->link->insert_id;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function insert_id()
|
||||
{
|
||||
return $this->link->insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update or insert rows into $table.
|
||||
* Update query: $this->update($table, $set, $where, $options);
|
||||
* Insert-or-update query: $this->update($table, $rows);
|
||||
*
|
||||
* @param string $table Table name to update.
|
||||
* @param array $rows One row or array of rows for insert-or-update query.
|
||||
* @param array $set Assoc array with values for update query.
|
||||
* @param array $where Conditions for update query, see $this->where_builder().
|
||||
* @param array $options Options for update query:
|
||||
* 'LIMIT' => array($limit, $offset) or array($limit) or just $limit
|
||||
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
|
||||
* 'REPLACE' => true to use REPLACE instead of INSERT
|
||||
*/
|
||||
function update($table, $rows, $where = NULL, $options = NULL)
|
||||
{
|
||||
if (!$rows)
|
||||
return false;
|
||||
if (is_null($where))
|
||||
{
|
||||
if (!is_array($rows))
|
||||
return false;
|
||||
if (!is_array(@$rows[0]))
|
||||
$rows = array($rows);
|
||||
$sql = $this->insert_builder($table, $rows, true, !empty($options['replace']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = array();
|
||||
if (!is_array($rows))
|
||||
$rows = array($rows);
|
||||
foreach ($rows as $k => $v)
|
||||
{
|
||||
if (!ctype_digit("$k"))
|
||||
$sql[] = $k.'='.$this->quote($v);
|
||||
else
|
||||
$sql[] = $v;
|
||||
}
|
||||
$where = $this->where_builder($where);
|
||||
$sql = 'UPDATE ' . $this->tables_builder($table) . ' SET ' . implode(', ', $sql) . ' WHERE ' . $where;
|
||||
$sql .= $this->limit_option($options);
|
||||
}
|
||||
if ($this->query($sql))
|
||||
return $this->link->affected_rows;
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_rows($sql)
|
||||
{
|
||||
$r = array();
|
||||
if ($res = $this->query($sql))
|
||||
{
|
||||
while ($row = $res->fetch_row())
|
||||
$r[] = $row;
|
||||
$res->free();
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function get_assocs($sql)
|
||||
{
|
||||
$r = array();
|
||||
if ($res = $this->query($sql))
|
||||
{
|
||||
while ($row = $res->fetch_assoc())
|
||||
$r[] = $row;
|
||||
$res->free();
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
}
|
|
@ -1,24 +1,28 @@
|
|||
<?php
|
||||
|
||||
# Всякие константы
|
||||
# (c) VitaliF 2006-2010
|
||||
# (c) VitaliF 2006-2013
|
||||
|
||||
define ('IN_CONFIG', true);
|
||||
define('IN_CONFIG', true);
|
||||
|
||||
setlocale(LC_ALL, 'ru_RU.UTF-8');
|
||||
setlocale(LC_NUMERIC, 'C');
|
||||
mb_internal_encoding('utf-8');
|
||||
|
||||
include_once 'loconfig.php';
|
||||
|
||||
$db = array(
|
||||
'host' => 'localhost',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
'dbname' => '',
|
||||
);
|
||||
$image_path = '/images/';
|
||||
$template_path = '/templates/';
|
||||
$cache_path = '/tplcache';
|
||||
|
||||
$cfgTables = array();
|
||||
$mysqlThrowError = true;
|
||||
$mysqlNoSiteConfig = true;
|
||||
|
||||
include_once 'loconfig.php';
|
||||
|
||||
$LoginSession = 'RTV'.md5('http://' . $Domain);
|
||||
|
||||
require_once 'lib.php';
|
||||
|
|
557
lib/lib.php
557
lib/lib.php
|
@ -1,16 +1,19 @@
|
|||
<?php
|
||||
|
||||
# Утилитные функции
|
||||
# (c) VitaliF 2006-2010
|
||||
# (c) VitaliF 2006+
|
||||
|
||||
$AutoloadClasses['DatabaseMysql'] = dirname(__FILE__).'/DatabaseMysql.php';
|
||||
$AutoloadClasses['LinguaStemRu'] = dirname(__FILE__).'/stem_ru.php';
|
||||
$AutoloadClasses['VMXTemplate'] = dirname(__FILE__).'/template.php';
|
||||
$AutoloadClasses['Mailer'] = dirname(__FILE__).'/mailing.php';
|
||||
|
||||
function __autoload($class_name)
|
||||
{
|
||||
global $AutoloadClasses;
|
||||
if ($f = $AutoloadClasses[$class_name])
|
||||
if (isset($AutoloadClasses[$class_name]))
|
||||
{
|
||||
require_once $f;
|
||||
require_once $AutoloadClasses[$class_name];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -52,34 +55,7 @@ class PopulatedRow implements ArrayAccess
|
|||
}
|
||||
}
|
||||
|
||||
function get_include_contents($filename)
|
||||
{
|
||||
if (is_file($filename))
|
||||
{
|
||||
ob_start();
|
||||
include $filename;
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $contents;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function str_starts_with ($str, $sub)
|
||||
{
|
||||
if (strcmp (substr ($str, 0, strlen ($sub)), $sub) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function str_ends_with ($str, $sub)
|
||||
{
|
||||
if (strcmp (substr ($str, strlen ($str) - strlen ($sub)), $sub) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalize_domain ($st)
|
||||
function normalize_domain($st)
|
||||
{
|
||||
$dom = '';
|
||||
if (!empty($st))
|
||||
|
@ -95,7 +71,7 @@ function normalize_domain ($st)
|
|||
return $dom;
|
||||
}
|
||||
|
||||
function normalize_link ($l, $pre)
|
||||
function normalize_link($l, $pre)
|
||||
{
|
||||
if (!empty ($l) && !empty ($pre))
|
||||
{
|
||||
|
@ -109,7 +85,7 @@ function normalize_link ($l, $pre)
|
|||
$pre .= '/';
|
||||
$l = $pre . $l;
|
||||
}
|
||||
else if (($sch = strpos($pre, '://')) !== false)
|
||||
elseif (($sch = strpos($pre, '://')) !== false)
|
||||
$l = substr($pre, 0, strpos($pre, '/', $sch+3)) . $l;
|
||||
}
|
||||
return $l;
|
||||
|
@ -119,57 +95,57 @@ function normalize_link ($l, $pre)
|
|||
|
||||
function strlimit($str, $maxlen)
|
||||
{
|
||||
if (!$maxlen || $maxlen < 1 || strlen($str) <= $maxlen)
|
||||
if (!$maxlen || $maxlen < 1 || mb_strlen($str) <= $maxlen)
|
||||
return $str;
|
||||
$str = substr($str, 0, $maxlen);
|
||||
$p = strrpos($str, ' ');
|
||||
if (!$p || ($pt = strrpos($str, "\t")) > $ps)
|
||||
$str = mb_substr($str, 0, $maxlen);
|
||||
$p = mb_strrpos($str, ' ');
|
||||
if (!$p || ($pt = mb_strrpos($str, "\t")) > $ps)
|
||||
$p = $pt;
|
||||
if ($p)
|
||||
$str = substr($str, 0, $p);
|
||||
$str = mb_substr($str, 0, $p);
|
||||
return $str . '...';
|
||||
}
|
||||
|
||||
function html_pbr($str)
|
||||
{
|
||||
return str_replace ("\n", "<br>", htmlspecialchars($str));
|
||||
return nl2br(htmlspecialchars($str));
|
||||
}
|
||||
|
||||
function html_strip_pbr ($str)
|
||||
function html_strip_pbr($str)
|
||||
{
|
||||
global $allowed_html;
|
||||
if (!($a = $allowed_html))
|
||||
$a = '<div> <span> <a> <b> <i> <u> <p> <h1> <h2> <h3> <h4> <h5> <h6> <strike> <strong> <small> <big> <blink> <center> <ol> <pre> <sub> <sup> <font> <br> <table> <tr> <td> <th> <tbody> <tfoot> <thead> <tt> <ul> <li> <em> <img> <marquee>';
|
||||
return nl2br (strip_tags ($str, $a));
|
||||
return nl2br(strip_tags($str, $a));
|
||||
}
|
||||
|
||||
function html_strip ($str)
|
||||
function html_strip($str)
|
||||
{
|
||||
global $allowed_html;
|
||||
if (!($a = $allowed_html))
|
||||
$a = '<div> <span> <a> <b> <i> <u> <p> <h1> <h2> <h3> <h4> <h5> <h6> <strike> <strong> <small> <big> <blink> <center> <ol> <pre> <sub> <sup> <font> <br> <table> <tr> <td> <th> <tbody> <tfoot> <thead> <tt> <ul> <li> <em> <img> <marquee>';
|
||||
return strip_tags ($str, $a);
|
||||
return strip_tags($str, $a);
|
||||
}
|
||||
|
||||
function unhtmlentity ($s)
|
||||
function unhtmlentity($s)
|
||||
{
|
||||
$s = html_entity_decode ($s);
|
||||
preg_match_all ('/&#([0-9]*);/', $s, $ce, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
|
||||
$s = html_entity_decode($s);
|
||||
preg_match_all('/&#([0-9]*);/', $s, $ce, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
|
||||
$c = count($ce);
|
||||
for ($i = $c-1; $i >= 0; $i--)
|
||||
$s = substr ($s, 0, $ce[$i][0][1]) . chr($ce[$i][1][0]) . substr ($s, $ce[$i][0][1]+strlen($ce[$i][0][0]));
|
||||
$s = substr($s, 0, $ce[$i][0][1]) . chr($ce[$i][1][0]) . substr($s, $ce[$i][0][1]+strlen($ce[$i][0][0]));
|
||||
return $s;
|
||||
}
|
||||
|
||||
function process_array ($arr, $kfunc, $vfunc)
|
||||
function process_array($arr, $kfunc, $vfunc)
|
||||
{
|
||||
$na = array ();
|
||||
$na = array();
|
||||
foreach ($arr as $k => $v)
|
||||
{
|
||||
if (is_callable($kfunc))
|
||||
$k = $kfunc ($k);
|
||||
$k = $kfunc($k);
|
||||
if (is_callable($vfunc))
|
||||
$v = $vfunc ($v);
|
||||
$v = $vfunc($v);
|
||||
$na [$k] = $v;
|
||||
}
|
||||
return $na;
|
||||
|
@ -214,57 +190,6 @@ function array_hashtree($a, $ka = NULL, $value = NULL)
|
|||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Составление HTML кода картинки или flash-файла (возможно со ссылкой и alt)
|
||||
* Если $link начинается с popup:// - тогда запишется javascript-код для popup-а ссылки
|
||||
* Если $link начинается с popupwh:// - тогда дальше идёт WIDTH:HEIGHT:
|
||||
*/
|
||||
function banner ($path, $alt = false, $link = false, $width = false, $height = false, $target = false)
|
||||
{
|
||||
if (!$path)
|
||||
return '';
|
||||
$code = '';
|
||||
$wh = '';
|
||||
if ($width !== false && $width > 0)
|
||||
$wh .= ' width="' . $width . '"';
|
||||
if ($height !== false && $height > 0)
|
||||
$wh .= ' height="' . $height . '"';
|
||||
if (str_ends_with ($path, ".swf")) // flash
|
||||
{
|
||||
$code .= "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0\"$wh>
|
||||
<param name=\"movie\" value=\"$path\">
|
||||
<param name=\"play\" value=\"true\">
|
||||
<param name=\"loop\" value=\"true\">
|
||||
<param name=\"quality\" value=\"high\">
|
||||
<param name=\"WMode\" value=\"Window\">
|
||||
<embed$wh src=\"$path\" play=\"true\" loop=\"true\" quality=\"high\" WMode=\"Window\" pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\"></embed>
|
||||
</object>";
|
||||
}
|
||||
else // картинка
|
||||
{
|
||||
if ($link !== false && str_starts_with ($link, 'popup://'))
|
||||
{
|
||||
$link = substr ($link, 8);
|
||||
$link = "javascript: void window.open('$link', 'newWin', 'width=640,height=480,menubar=no,location=no,resizable=yes,scrollbars=yes').focus();";
|
||||
}
|
||||
else if ($link !== false && str_starts_with ($link, 'popupwh://'))
|
||||
{
|
||||
$link = substr ($link, 10);
|
||||
list ($popupw, $popuph, $link) = explode (':', $link, 3);
|
||||
$link = "javascript: void window.open('$link', 'newWin', 'width=$popupw,height=$popuph,menubar=no,location=no,resizable=yes,scrollbars=yes').focus();";
|
||||
}
|
||||
if ($link !== false)
|
||||
$code .= '<a href="'.$link.'"'.($target !== false ? ' target="'.$target.'"' : '').'>';
|
||||
if ($alt !== false)
|
||||
$alttag = ' alt="'.htmlspecialchars($alt).'" title="'.htmlspecialchars($alt).'"';
|
||||
else $alttag = '';
|
||||
$code .= "<img src=\"$path\" border=\"0\"$alttag$wh />";
|
||||
if ($link !== false)
|
||||
$code .= '</a>';
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/* Уложить ширину и высоту изображения пропорционально в рамки maxw/maxh */
|
||||
function fit_width_height($cw, $ch, $maxw, $maxh)
|
||||
{
|
||||
|
@ -275,12 +200,41 @@ function fit_width_height($cw, $ch, $maxw, $maxh)
|
|||
$nw = $maxw;
|
||||
$nh = $ch * $maxw / $cw;
|
||||
}
|
||||
else if ($maxh > 0 && ($maxw <= 0 || $maxh/$ch < $maxw/$cw))
|
||||
elseif ($maxh > 0 && ($maxw <= 0 || $maxh/$ch < $maxw/$cw))
|
||||
{
|
||||
$nw = $cw * $maxh / $ch;
|
||||
$nh = $maxh;
|
||||
}
|
||||
return array($nw, $nh);
|
||||
return array(intval($nw), intval($nh));
|
||||
}
|
||||
|
||||
function convertBMP($from, $to, $quality = 90)
|
||||
{
|
||||
static $class;
|
||||
$fp = fopen($from, "rb");
|
||||
if (!$fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$sign = fread($fp, 2);
|
||||
fclose($fp);
|
||||
if ($sign != 'BM')
|
||||
{
|
||||
return $from;
|
||||
}
|
||||
$class = class_exists('Gmagick') ? 'Gmagick' : 'Imagick';
|
||||
try
|
||||
{
|
||||
$im = new $class();
|
||||
$im->readImage($from);
|
||||
$im->setCompressionQuality($quality);
|
||||
$im->writeImage($to);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return $from;
|
||||
}
|
||||
return $to;
|
||||
}
|
||||
|
||||
function loadimagebyext($from)
|
||||
|
@ -290,9 +244,9 @@ function loadimagebyext($from)
|
|||
$ext = strtolower(substr($from, strrpos($from, '.')+1));
|
||||
if (function_exists("imagejpeg") && ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'jfif' || $ext == 'jpe'))
|
||||
$img = @imagecreatefromjpeg($from);
|
||||
else if (function_exists("imagepng") && ($ext == 'png'))
|
||||
elseif (function_exists("imagepng") && ($ext == 'png'))
|
||||
$img = @imagecreatefrompng($from);
|
||||
else if (function_exists("imagegif") && ($ext == 'gif'))
|
||||
elseif (function_exists("imagegif") && ($ext == 'gif'))
|
||||
$img = @imagecreatefromgif($from);
|
||||
}
|
||||
return $img;
|
||||
|
@ -309,9 +263,9 @@ function saveimagebyext($img, $to)
|
|||
$ext = strtolower(substr($to, strrpos($to, '.')+1));
|
||||
if ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'jfif' || $ext == 'jpe')
|
||||
@imagejpeg($img, $to, $qual);
|
||||
else if ($ext == 'png')
|
||||
elseif ($ext == 'png')
|
||||
@imagepng($img, $to);
|
||||
else if ($ext == 'gif')
|
||||
elseif ($ext == 'gif')
|
||||
@imagegif($img, $to);
|
||||
else
|
||||
return false;
|
||||
|
@ -410,9 +364,9 @@ function get_image_size($from, &$w, &$h)
|
|||
$ext = strtolower (substr ($from, strrpos ($from, '.')+1));
|
||||
if (function_exists ("imagejpeg") && ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'jfif' || $ext == 'jpe'))
|
||||
$img = @imagecreatefromjpeg ($from);
|
||||
else if (function_exists ("imagepng") && ($ext == 'png'))
|
||||
elseif (function_exists ("imagepng") && ($ext == 'png'))
|
||||
$img = @imagecreatefrompng ($from);
|
||||
else if (function_exists ("imagegif") && ($ext == 'gif'))
|
||||
elseif (function_exists ("imagegif") && ($ext == 'gif'))
|
||||
$img = @imagecreatefromgif ($from);
|
||||
if ($img)
|
||||
{
|
||||
|
@ -449,8 +403,10 @@ function load_image ($filevarname, $newfilename, &$imgvar, &$thumbvar, &$imgw, &
|
|||
@unlink ($local_path . $fn_t); // !!!
|
||||
if ((@move_uploaded_file ($_FILES [$filevarname]['tmp_name'], $local_path . $fn_i)))
|
||||
{
|
||||
$imgw = 0+config_var ($maxdim_config.'img_maxw');
|
||||
$imgh = 0+config_var ($maxdim_config.'img_maxh');
|
||||
if (!$imgw)
|
||||
$imgw = 0+config_var ($maxdim_config.'img_maxw');
|
||||
if (!$imgh)
|
||||
$imgh = 0+config_var ($maxdim_config.'img_maxh');
|
||||
if ($imgw <= 0)
|
||||
$imgw = false;
|
||||
if ($imgh <= 0)
|
||||
|
@ -502,37 +458,55 @@ function load_file ($filevarname, $newfilename)
|
|||
return $ret;
|
||||
}
|
||||
|
||||
function file_size ($filename)
|
||||
function mkpath($path, $throw_error = true)
|
||||
{
|
||||
if (is_dir($path) || @mkdir($path, 0777, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ($throw_error)
|
||||
{
|
||||
$error = error_get_last();
|
||||
throw new Exception("Failed to create path $path: ".$error['message']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function file_size($filename)
|
||||
{
|
||||
global $local_path;
|
||||
$r = false;
|
||||
if ($filename{0} == '/' &&
|
||||
file_exists($local_path . $filename))
|
||||
$r = filesize ($local_path . $filename);
|
||||
else if (str_starts_with ($filename, 'http://') ||
|
||||
str_starts_with ($filename, 'ftp://'))
|
||||
{
|
||||
$a = @get_headers ($filename, 1);
|
||||
if (isset ($a ['Content-Length']))
|
||||
$r = $a ['Content-Length'];
|
||||
$r = filesize($local_path . $filename);
|
||||
}
|
||||
elseif (str_starts_with($filename, 'http://') ||
|
||||
str_starts_with($filename, 'ftp://'))
|
||||
{
|
||||
$a = @get_headers($filename, 1);
|
||||
if (isset($a['Content-Length']))
|
||||
{
|
||||
$r = $a['Content-Length'];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function file_size_string ($bytes)
|
||||
function file_size_string($bytes)
|
||||
{
|
||||
$r = $bytes;
|
||||
if (is_numeric ($r))
|
||||
{
|
||||
if ($r >= 0 && $r < 1024)
|
||||
$r = $r . ' байт';
|
||||
else if ($r >= 1024 && $r < 1024*1024)
|
||||
elseif ($r >= 1024 && $r < 1024*1024)
|
||||
$r = sprintf ('%.2f Кб', $r/1024);
|
||||
else if ($r >= 1024*1024 && $r < 1024*1024*1024)
|
||||
elseif ($r >= 1024*1024 && $r < 1024*1024*1024)
|
||||
$r = sprintf ('%.2f Мб', $r/1024/1024);
|
||||
else if ($r >= 1024*1024*1024)
|
||||
elseif ($r >= 1024*1024*1024)
|
||||
$r = sprintf ('%.2f Гб', $r/1024/1024/1024);
|
||||
else if ($r < 0)
|
||||
elseif ($r < 0)
|
||||
$r = sprintf ('%.2f Гб', 2-($r/1024/1024/1024));
|
||||
}
|
||||
return $r;
|
||||
|
@ -543,113 +517,109 @@ function file_size_string ($bytes)
|
|||
* HTTP аутентификация с логином и паролем, указанными в $userpwd как login:password.
|
||||
* Если данные являются gzip-сжатыми - они будут автоматически распакованы.
|
||||
*/
|
||||
function http_get_contents ($url, $userpwd = false)
|
||||
function curl_get_contents($url, $options = array())
|
||||
{
|
||||
global $local_path, $cache_path;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt ($ch, CURLOPT_URL, $url);
|
||||
curl_setopt ($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt ($ch, CURLOPT_USERAGENT, 'CommercialRealty/1.0');
|
||||
|
||||
mt_srand ((float)microtime() * 1000000);
|
||||
$eh = $local_path . $cache_path . '/php-' . md5(mt_rand(0,mt_getrandmax())) . '.gz';
|
||||
$fd = fopen ($eh, 'wb');
|
||||
curl_setopt ($ch, CURLOPT_FILE, $fd);
|
||||
|
||||
if (!empty ($userpwd))
|
||||
curl_setopt ($ch, CURLOPT_USERPWD, $userpwd);
|
||||
|
||||
@curl_exec ($ch);
|
||||
curl_close ($ch);
|
||||
fclose ($fd);
|
||||
|
||||
ob_start ();
|
||||
readgzfile ($eh);
|
||||
$data = ob_get_clean ();
|
||||
unlink ($eh);
|
||||
curl_setopt_array($ch, $options+array(
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_ENCODING => 'gzip,deflate',
|
||||
CURLOPT_RETURNTRANSFER => 1,
|
||||
));
|
||||
$data = @curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/* Преобразовать имена некоторых строк в ID некоторых строк */
|
||||
/* Получить некоторые строки по именам с автоматическим добавлением,
|
||||
если $add_unknown=true (например, теги) */
|
||||
function get_tags($tags, $add_unknown = true, $table = 'tags', $id_field = 'id', $name_field = 'name')
|
||||
{
|
||||
$tagids = array_hashtree(mysql_select($table, "$id_field, LOWER($name_field) $name_field", array($name_field => $tags)), $name_field);
|
||||
global $mysql, $_TagCache;
|
||||
if (!$tags)
|
||||
return $tags;
|
||||
$unk = array();
|
||||
foreach ($tags as $t)
|
||||
if (!$tagids[mb_strtolower($t, 'utf-8')])
|
||||
$unk[] = array($name_field => $t);
|
||||
{
|
||||
$t = mb_strtolower($t, 'utf-8');
|
||||
if (!$_TagCache[$t])
|
||||
$unk[] = $t;
|
||||
}
|
||||
if ($unk)
|
||||
{
|
||||
$tagids = array_hashtree($mysql->select($table, "$id_field, LOWER($name_field) $name_field", array($name_field => $unk)), $name_field);
|
||||
$unk = array();
|
||||
foreach ($tags as $t)
|
||||
{
|
||||
if (!$tagids[mb_strtolower($t, 'utf-8')])
|
||||
$unk[] = array($name_field => $t);
|
||||
}
|
||||
}
|
||||
if ($unk && $add_unknown)
|
||||
{
|
||||
mysql_update($table, $unk);
|
||||
$tagids = array_hashtree(mysql_select($table, "$id_field, LOWER($name_field) $name_field", array($name_field => $tags)), $name_field);
|
||||
$mysql->update($table, $unk);
|
||||
$tagids = array_hashtree($mysql->select($table, "$id_field, LOWER($name_field) $name_field", array($name_field => $tags)), $name_field);
|
||||
}
|
||||
foreach ($tags as &$t)
|
||||
if ($tt = $tagids[mb_strtolower($t, 'utf-8')])
|
||||
{
|
||||
$t = mb_strtolower($t, 'utf-8');
|
||||
if ($_TagCache[$t])
|
||||
$t = $_TagCache[$t];
|
||||
elseif ($tt = $tagids[$t])
|
||||
{
|
||||
$_TagCache[$t] = $tt[0];
|
||||
$t = $tt[0];
|
||||
}
|
||||
}
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Функция возвращает ID значения $v поля $stringfield (по умолчанию поля name), при дополнительных
|
||||
* требованиях $adds = array (поле => значение, ...) и, если такого значения нету, добавляет его в БД.
|
||||
*
|
||||
* Функция работает так:
|
||||
* - если $v пусто (empty($v)==true) - функция возвращает 0 (ибо нефиг);
|
||||
* - ищет, есть ли заданное значение там, где удовлетворены все требования, если есть - всё ок, возвращает его ID;
|
||||
* - по одному с конца ослабляет требования, и если находит соответствующую строку - редактирует её таким образом,
|
||||
* чтобы она соответствовала всем заданным требованиям, и возвращает её ID;
|
||||
* - если такая строка не найдена - добавляет её и возвращает её ID.
|
||||
* - если произошла какая-либо ошибка, она возвращает 0.
|
||||
* - если в найденной записи поле stop != 0 => функция возвращает 0.
|
||||
* полезно, если мы хотим "обучать" функцию не совершать ошибки повторно.
|
||||
*/
|
||||
function stringtable_get_id ($v, $table, $adds, $stringfield = 'name')
|
||||
function site_setcookie($name, $value, $expire, $secure = false, $httponly = false)
|
||||
{
|
||||
$rid = 0;
|
||||
if (!empty ($v))
|
||||
{
|
||||
$v = mysql_ecranize ($v);
|
||||
$addset = array ();
|
||||
if (is_array ($adds))
|
||||
foreach ($adds as $pk => $pf)
|
||||
$addset [] = "`$pk`=" . mysql_ecranize($pf);
|
||||
$search = array_merge (array ("`$stringfield`=$v"), $addset);
|
||||
$change = array ();
|
||||
while (count ($search) > 0)
|
||||
{
|
||||
if (($rid = 0+amquery1x1 ("SELECT `id` FROM `$table` WHERE " . implode (' AND ', $search) . ' LIMIT 1')) > 0)
|
||||
{
|
||||
if (!empty ($change))
|
||||
amysql_query ("UPDATE `$table` SET " . implode (', ', $change) . " WHERE `id`=$rid");
|
||||
break;
|
||||
}
|
||||
$change [] = array_pop ($search);
|
||||
}
|
||||
if (!$rid && amysql_query ("INSERT INTO `$table` SET " . implode (', ', $change)))
|
||||
{
|
||||
$rid = mysql_insert_id ();
|
||||
if (!$rid)
|
||||
$rid = 0+amquery1x1 ("SELECT id FROM `$table` WHERE " . implode (' AND ', $change) . ' LIMIT 1');
|
||||
}
|
||||
if ($rid && acmget ($table, $rid, 'stop') > 0)
|
||||
$rid = 0;
|
||||
}
|
||||
return $rid;
|
||||
global $Domain;
|
||||
list($dom, $path) = explode('/', $Domain, 2);
|
||||
$path = "/$path";
|
||||
return setcookie($name, $value, $expire ? time()+$expire : 0, $path, '.'.$dom, $secure, $httponly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Начало сессии :)
|
||||
* @param boolean $always Если true, то начинать сессию всегда, иначе - только если она существует
|
||||
* @param int $lifetime Необязательное время жизни сессии
|
||||
*/
|
||||
function session_begin($lifetime = -1)
|
||||
function session_begin($always = true, $lifetime = NULL)
|
||||
{
|
||||
global $Domain, $LoginSession;
|
||||
session_name($LoginSession);
|
||||
list($dom, $path) = explode('/', $Domain, 2);
|
||||
$path = "/$path";
|
||||
session_set_cookie_params($lifetime, $path, '.' . $dom);
|
||||
@session_start();
|
||||
if (isset($_COOKIE[$LoginSession]) || $always)
|
||||
{
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
$lifetime = 0;
|
||||
}
|
||||
session_name($LoginSession);
|
||||
list($dom, $path) = explode('/', $Domain, 2);
|
||||
$path = "/$path";
|
||||
$dom = (strtolower($dom) == 'localhost' ? '' : ".$dom");
|
||||
session_set_cookie_params($lifetime, $path, $dom);
|
||||
return @session_start();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function session_terminate()
|
||||
{
|
||||
$_SESSION = array();
|
||||
$params = session_get_cookie_params();
|
||||
if (session_begin())
|
||||
{
|
||||
session_destroy();
|
||||
}
|
||||
setcookie(
|
||||
session_name(), '', -1, $params['path'], $params['domain'],
|
||||
$params['secure'], $params['httponly']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,21 +629,22 @@ function session_begin($lifetime = -1)
|
|||
* Функция предназначена для присваивания блоков <select>...</select>
|
||||
* и присвоит "выделено" той опции, которая задана ID-ом $sel_id
|
||||
*/
|
||||
function option_block ($sql, $arr, $sel_id = NULL)
|
||||
function option_block($sql, $arr, $sel_id = NULL)
|
||||
{
|
||||
global $mysql;
|
||||
$vars = array();
|
||||
if (is_array ($arr))
|
||||
foreach ($arr as $id => $name)
|
||||
$vars[] = array (
|
||||
$vars[] = array(
|
||||
'ID' => $id,
|
||||
'NAME' => $name,
|
||||
'SEL' => !is_null($sel_id) && $id == $sel_id ? 'selected' : '',
|
||||
);
|
||||
if (is_string($sql) && ($rows = mysql_get_rows($sql)))
|
||||
if (is_string($sql) && ($rows = $mysql->get_rows($sql)))
|
||||
{
|
||||
foreach ($rows as $row)
|
||||
{
|
||||
$vars[] = array (
|
||||
$vars[] = array(
|
||||
'ID' => $row[0],
|
||||
'NAME' => $row[1],
|
||||
'SEL' => !is_null($sel_id) && $row[0] == $sel_id ? 'selected' : '',
|
||||
|
@ -686,16 +657,15 @@ function option_block ($sql, $arr, $sel_id = NULL)
|
|||
/**
|
||||
* Данные постраничной навигации внутри $allcount элементов по
|
||||
* $perpage на странице, при том условии что текущий первый отображённый - это $start.
|
||||
* Ссылка на страницу будет getURL($component, $args+array(page => НОМЕР_СТРАНИЦЫ)).
|
||||
* Ссылка на страницу будет App::url($component, $args+array(page => НОМЕР_СТРАНИЦЫ)).
|
||||
* Если задано $eps, то отобразится не более 2*$eps соседних страниц.
|
||||
*/
|
||||
function page_nav3 ($total, $perpage, $start, $component, $args = array(), $eps = NULL, $metanext = 'METAS', $pagearg = 'page')
|
||||
function page_nav3($total, $perpage, $curpage, $component, $args = array(), $eps = NULL, $metanext = 'METAS', $pagearg = 'page')
|
||||
{
|
||||
if ($perpage <= 0 && $total > 0)
|
||||
$perpage = $total;
|
||||
if ($perpage <= 0)
|
||||
$perpage = 1;
|
||||
$curpage = floor($start / $perpage);
|
||||
$pagecount = ceil($total / $perpage);
|
||||
if ($curpage >= $pagecount)
|
||||
$curpage = $pagecount-1;
|
||||
|
@ -705,21 +675,23 @@ function page_nav3 ($total, $perpage, $start, $component, $args = array(), $eps
|
|||
$vars = array (
|
||||
'total' => $total,
|
||||
'perpage' => $perpage,
|
||||
'list_start' => $start+1,
|
||||
'list_start' => min($total, $curpage*$perpage+1),
|
||||
'page_count' => $pagecount,
|
||||
'list_end' => min($total, $start+$perpage),
|
||||
'list_end' => min($total, $curpage*$perpage+$perpage),
|
||||
'page' => array(),
|
||||
'current_page' => $curpage+1,
|
||||
);
|
||||
if ($pagecount < 2)
|
||||
{
|
||||
return $vars;
|
||||
}
|
||||
|
||||
if ($curpage > 0)
|
||||
{
|
||||
$args[$pagearg] = $curpage-1;
|
||||
$vars['page'][] = array (
|
||||
'name' => '<',
|
||||
'href' => getURL($component, $args),
|
||||
'href' => App::url($component, $args),
|
||||
'nc' => true,
|
||||
);
|
||||
}
|
||||
|
@ -727,13 +699,13 @@ function page_nav3 ($total, $perpage, $start, $component, $args = array(), $eps
|
|||
$eps = config_var('page_nav_eps', 10);
|
||||
if ($eps && $eps > 0)
|
||||
{
|
||||
$ppend = min ($pagecount, $curpage + $eps + 1);
|
||||
for ($i = max (0, $curpage - $eps); $i < $ppend; $i++)
|
||||
$ppend = min($pagecount, $curpage + $eps + 1);
|
||||
for ($i = max(0, $curpage - $eps); $i < $ppend; $i++)
|
||||
{
|
||||
$args[$pagearg] = $i;
|
||||
$vars['page'][] = array (
|
||||
$vars['page'][] = array(
|
||||
'name' => $i+1,
|
||||
'href' => getURL($component, $args),
|
||||
'href' => App::url($component, $args),
|
||||
'nc' => $i != $curpage,
|
||||
);
|
||||
}
|
||||
|
@ -743,9 +715,9 @@ function page_nav3 ($total, $perpage, $start, $component, $args = array(), $eps
|
|||
for ($i = 0; $i < $pagecount; $i++)
|
||||
{
|
||||
$args[$pagearg] = $i;
|
||||
$vars['page'][] = array (
|
||||
$vars['page'][] = array(
|
||||
'name' => $i+1,
|
||||
'href' => getURL($component, $args),
|
||||
'href' => App::url($component, $args),
|
||||
'nc' => $i != $curpage,
|
||||
);
|
||||
}
|
||||
|
@ -756,43 +728,17 @@ function page_nav3 ($total, $perpage, $start, $component, $args = array(), $eps
|
|||
if ($metanext)
|
||||
{
|
||||
global $template;
|
||||
$template->tpldata[$metanext] .= '<link rel="next" title="Следующая страница" href="'.getURL($component, $args).'"/>';
|
||||
$template->tpldata[$metanext] .= '<link rel="next" title="Следующая страница" href="'.App::url($component, $args).'"/>';
|
||||
}
|
||||
$vars['page'][] = array (
|
||||
$vars['page'][] = array(
|
||||
'name' => '>',
|
||||
'href' => getURL($component, $args),
|
||||
'href' => App::url($component, $args),
|
||||
'nc' => true,
|
||||
);
|
||||
}
|
||||
return $vars;
|
||||
}
|
||||
|
||||
function php2js($a)
|
||||
{
|
||||
if (is_null($a)) return 'null';
|
||||
if ($a === false) return 'false';
|
||||
if ($a === true) return 'true';
|
||||
if (is_scalar($a)) {
|
||||
$a = addslashes($a);
|
||||
$a = str_replace("\n", '\n', $a);
|
||||
$a = str_replace("\r", '\r', $a);
|
||||
$a = preg_replace('{(</)(script)}i', "$1'+'$2", $a);
|
||||
return "'$a'";
|
||||
}
|
||||
$isList = true;
|
||||
for ($i=0, reset($a); $i<count($a); $i++, next($a))
|
||||
if (key($a) !== $i) { $isList = false; break; }
|
||||
$result = array();
|
||||
if ($isList) {
|
||||
foreach ($a as $v) $result[] = php2js($v);
|
||||
return '[ ' . join(', ', $result) . ' ]';
|
||||
} else {
|
||||
foreach ($a as $k=>$v)
|
||||
$result[] = php2js($k) . ': ' . php2js($v);
|
||||
return '{ ' . join(', ', $result) . ' }';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists("quoted_printable_encode"))
|
||||
{
|
||||
define('QP_LINE_LENGTH', 75);
|
||||
|
@ -862,11 +808,6 @@ if (!function_exists("quoted_printable_encode"))
|
|||
}
|
||||
}
|
||||
|
||||
function is_intval($a)
|
||||
{
|
||||
return (is_string($a) || is_int($a)) && !strcmp(intval($a), $a);
|
||||
}
|
||||
|
||||
function litsplit($re, $s)
|
||||
{
|
||||
$r = array();
|
||||
|
@ -932,3 +873,113 @@ function extract_video_frame($from, $time, $w, $h, $to)
|
|||
scaleimage($to, $to, $w, $h);
|
||||
return true;
|
||||
}
|
||||
|
||||
function array_id_name($assoc)
|
||||
{
|
||||
$r = array();
|
||||
foreach($assoc as $k => $v)
|
||||
$r[] = array('id' => $k, 'name' => $v);
|
||||
return $r;
|
||||
}
|
||||
|
||||
function urandom($nbytes = 16, $hex = false)
|
||||
{
|
||||
$pr_bits = '';
|
||||
// Unix/Linux platform?
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
if ($fp !== FALSE)
|
||||
{
|
||||
$pr_bits = @fread($fp, $nbytes);
|
||||
@fclose($fp);
|
||||
}
|
||||
// MS-Windows platform?
|
||||
elseif (@class_exists('COM'))
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
|
||||
try
|
||||
{
|
||||
$com = new COM('CAPICOM.Utilities.1');
|
||||
if (method_exists($com, 'GetRandom'))
|
||||
$pr_bits = base64_decode($com->GetRandom($nbytes,0));
|
||||
else
|
||||
{
|
||||
$com = new COM('System.Security.Cryptography.RNGCryptoServiceProvider');
|
||||
if (method_exists($com, 'GetBytes'))
|
||||
$pr_bits = base64_decode($com->GetBytes($nbytes));
|
||||
}
|
||||
}
|
||||
catch (Exception $ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
if (!strlen($pr_bits))
|
||||
for ($i = 0; $i < $nbytes; $i++)
|
||||
$pr_bits .= chr(mt_rand(0, 255));
|
||||
if ($hex)
|
||||
{
|
||||
$pr_bits = unpack('H*', $pr_bits);
|
||||
$pr_bits = $pr_bits[1];
|
||||
}
|
||||
return $pr_bits;
|
||||
}
|
||||
|
||||
// Convert all UTF8 characters except ASCII and &"'<>
|
||||
// to HTML entities (& " ' < > &#xHEX;)
|
||||
function htmlentities_utf8($s)
|
||||
{
|
||||
$s = unpack('C*', mb_convert_encoding($s, 'UTF-16BE', 'UTF-8'));
|
||||
$r = '';
|
||||
for ($i = 1, $n = count($s); $i <= $n; $i += 2)
|
||||
{
|
||||
if (!$s[$i])
|
||||
{
|
||||
if ($s[$i+1] == 0x26)
|
||||
$r .= '&';
|
||||
elseif ($s[$i+1] == 0x22)
|
||||
$r .= '"';
|
||||
elseif ($s[$i+1] == 0x27)
|
||||
$r .= ''';
|
||||
elseif ($s[$i+1] == 0x3C)
|
||||
$r .= '<';
|
||||
elseif ($s[$i+1] == 0x3E)
|
||||
$r .= '>';
|
||||
else
|
||||
$r .= chr($s[$i+1]);
|
||||
}
|
||||
else
|
||||
$r .= sprintf("&#x%x;", ($s[$i]<<8) + ($s[$i+1]));
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function load_config()
|
||||
{
|
||||
global $mysql, $engine_configuration, $mysqlNoSiteConfig, $mysqlSiteConfigQuery;
|
||||
if ($mysqlNoSiteConfig)
|
||||
return;
|
||||
$engine_configuration = array();
|
||||
if ($mysqlSiteConfigQuery)
|
||||
$rows = $mysql->select($mysqlSiteConfigQuery, MS_LIST);
|
||||
else
|
||||
$rows = $mysql->select('config', array('name', 'value'), 1, array(), MS_LIST);
|
||||
foreach ($rows as $row)
|
||||
$engine_configuration[$row[0]] = $row[1];
|
||||
}
|
||||
|
||||
function is_intval($v)
|
||||
{
|
||||
return is_int($v) || is_string($v) && ctype_digit($v);
|
||||
}
|
||||
|
||||
function config_var($name, $default = NULL)
|
||||
{
|
||||
global $engine_configuration;
|
||||
if (!$engine_configuration)
|
||||
load_config();
|
||||
$v = @$engine_configuration[$name];
|
||||
if (!is_null($default) && !strlen($v) || is_intval($default) && $v <= 0)
|
||||
$v = $default;
|
||||
elseif (is_intval($default))
|
||||
$v = intval($v);
|
||||
return $v;
|
||||
}
|
||||
|
|
521
lib/mysql.php
521
lib/mysql.php
|
@ -1,521 +0,0 @@
|
|||
<?php
|
||||
|
||||
# Утилитные функции работы с MySQL
|
||||
# (c) VitaliF 2006-2010
|
||||
|
||||
require_once 'config.php';
|
||||
|
||||
define('MS_HASH', 0);
|
||||
define('MS_LIST', 1);
|
||||
define('MS_ROW', 2);
|
||||
define('MS_ONE', 2);
|
||||
define('MS_COL', 4);
|
||||
define('MS_VALUE', 6);
|
||||
define('MS_RESULT', 8);
|
||||
|
||||
$mysql_db_stack = array();
|
||||
$mds_count = 0;
|
||||
|
||||
function mysql_start($allow_nodb = false)
|
||||
{
|
||||
global $mysql_primary_link, $dbhost, $dbuser, $dbpwd, $db;
|
||||
if ($mysql_primary_link) // уже соединено
|
||||
return true;
|
||||
// Соединяемся с MySQL
|
||||
$mysql_primary_link = mysql_pconnect ($dbhost, $dbuser, $dbpwd);
|
||||
if (!$mysql_primary_link)
|
||||
die ('Could not connect to the database: ' . mysql_errno() . ": " . mysql_error());
|
||||
if (!mysql_usedb($db) && !$allow_nodb)
|
||||
return false;
|
||||
amysql_query("SET NAMES utf8");
|
||||
return true;
|
||||
}
|
||||
|
||||
function mysql_usedb($dbn)
|
||||
{
|
||||
global $mysql_db_stack, $mysql_primary_link;
|
||||
$r = true;
|
||||
if (!count($mysql_db_stack) || $mysql_db_stack[count($mysql_db_stack)-1] != $dbn)
|
||||
$r = mysql_select_db ($dbn, $mysql_primary_link);
|
||||
$mysql_db_stack[] = $dbn;
|
||||
return $r;
|
||||
}
|
||||
|
||||
function mysql_unusedb()
|
||||
{
|
||||
global $mysql_db_stack, $mysql_primary_link;
|
||||
if (($n = count($mysql_db_stack)) < 1)
|
||||
return false;
|
||||
$pop = array_pop($mysql_db_stack);
|
||||
if ($n > 1 && $pop != $mysql_db_stack[$n-2])
|
||||
return mysql_select_db($mysql_db_stack[$n-2], $mysql_primary_link);
|
||||
return false;
|
||||
}
|
||||
|
||||
function mysql_started()
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
return is_resource($mysql_primary_link);
|
||||
}
|
||||
|
||||
function amysql_query($q)
|
||||
{
|
||||
global $amy_query_count, $mysql_primary_link, $mysqlQueryLogFile, $mysqlThrowError;
|
||||
if (!mysql_started())
|
||||
mysql_start(false);
|
||||
if (!isset($amy_query_count))
|
||||
$amy_query_count = 0;
|
||||
$amy_query_count++;
|
||||
if ($mysqlQueryLogFile && ($fp = fopen($mysqlQueryLogFile, "ab")))
|
||||
$start = microtime(true);
|
||||
$result = mysql_query($q, $mysql_primary_link);
|
||||
if (!$result && $mysqlThrowError)
|
||||
{
|
||||
debug_print_backtrace();
|
||||
die(mysql_errno().': '.mysql_error());
|
||||
}
|
||||
if ($fp)
|
||||
{
|
||||
$t = microtime(true)-$start;
|
||||
fwrite($fp, date("[Y-m-d H:i:s] ").sprintf("%.3f sec ", $t).$q.(mysql_errno() ? ': ERROR! '.mysql_errno().': '.mysql_error() : '')."\n");
|
||||
fclose($fp);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function amysql_queries($qs, $ignore_errors = true)
|
||||
{
|
||||
$r = true;
|
||||
$qs = explode(';', $qs);
|
||||
foreach ($qs as $q)
|
||||
{
|
||||
$q = trim($q);
|
||||
if ($q != '' && !amysql_query($q))
|
||||
{
|
||||
$r = false;
|
||||
if (!$ignore_errors)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function amquery1x1($s)
|
||||
{
|
||||
if (($r = amysql_query($s)) && ($r = mysql_fetch_row($r)))
|
||||
return $r[0];
|
||||
return false;
|
||||
}
|
||||
|
||||
function mysql_ecranize($s)
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
if (!$mysql_primary_link)
|
||||
mysql_start();
|
||||
if (is_null($s))
|
||||
return "NULL";
|
||||
return "'" . mysql_real_escape_string($s) . "'";
|
||||
}
|
||||
|
||||
function mysql_time($dat, $tim, $format)
|
||||
{
|
||||
return @date($format, mktime (substr ($tim, 0, 2), substr ($tim, 3, 2), substr ($tim, 6, 2), substr($dat,5,2), substr($dat,8,2), substr($dat,0,4)));
|
||||
}
|
||||
|
||||
// Дополнить кэш таблицы $table с помощью запроса $q
|
||||
function cmcache($table, $q)
|
||||
{
|
||||
global $mysql_php_cache;
|
||||
$cnt = 0;
|
||||
$r = amysql_query($q);
|
||||
if ($r)
|
||||
{
|
||||
while ($row = mysql_fetch_assoc ($r))
|
||||
{
|
||||
$mysql_php_cache [$table][$row['id']] = $row;
|
||||
$cnt++;
|
||||
}
|
||||
}
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
// Функция кэширующего чтения поля field из записи номер id таблицы table: "table/id/field"
|
||||
// Кэш можно заполнять предыдущей функцией, хотя эта и сама может кэшировать записи по одной
|
||||
function acmget($table, $id, $field)
|
||||
{
|
||||
global $mysql_php_cache, $cfgTables;
|
||||
if ($cfgTables[$table])
|
||||
$table = $cfgTables[$table];
|
||||
if (!isset ($mysql_php_cache[$table][$id][$field]) &&
|
||||
cmcache ($table, "SELECT * FROM `$table` WHERE `id`=$id LIMIT 1") < 1)
|
||||
return false;
|
||||
return $mysql_php_cache[$table][$id][$field];
|
||||
}
|
||||
|
||||
function cmchainmatch($table, $parent_field, $start, $field, $value)
|
||||
{
|
||||
while (($new = acmget($table, $start, $field)) != $value && $start > 0)
|
||||
$start = $new;
|
||||
if (acmget($table, $start, $field) == $value)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function mysql_where_builder($where)
|
||||
{
|
||||
if (!is_array($where))
|
||||
return $where;
|
||||
$wh = array();
|
||||
foreach ($where as $k => $v)
|
||||
{
|
||||
if (is_numeric($k))
|
||||
$wh[] = $v;
|
||||
else if (is_array($v))
|
||||
{
|
||||
if (!$v)
|
||||
{
|
||||
debug_print_backtrace();
|
||||
die("Error: empty array for '$k IN (...)', don't know what to do");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($v[0]))
|
||||
foreach ($v as &$l)
|
||||
$l = "(" . implode(",", array_map('mysql_ecranize', $l)) . ")";
|
||||
else
|
||||
$v = array_map('mysql_ecranize', $v);
|
||||
$wh[] = "$k IN (" . implode(",", $v) . ")";
|
||||
}
|
||||
}
|
||||
elseif (!is_null($v))
|
||||
$wh[] = "$k=".mysql_ecranize($v);
|
||||
else
|
||||
$wh[] = "$k IS NULL";
|
||||
}
|
||||
if (!$wh)
|
||||
$where = '1';
|
||||
else
|
||||
$where = '(' . join(') AND (', $wh) . ')';
|
||||
return $where;
|
||||
}
|
||||
|
||||
function mysql_select_builder($tables, $fields, $where, $options = NULL)
|
||||
{
|
||||
if (!$options)
|
||||
$options = array();
|
||||
else
|
||||
{
|
||||
foreach ($options as $k => $v)
|
||||
if (is_intval($k))
|
||||
$options[$v] = true;
|
||||
}
|
||||
if (is_array($fields))
|
||||
$fields = join(',', $fields);
|
||||
$where = mysql_where_builder($where);
|
||||
$tables = mysql_tables_builder($tables);
|
||||
$sql = 'SELECT ';
|
||||
if ($options['CALC_FOUND_ROWS'] || $options['SQL_CALC_FOUND_ROWS'])
|
||||
$sql .= 'SQL_CALC_FOUND_ROWS ';
|
||||
if ($options['NO_CACHE'] || $options['SQL_NO_CACHE'])
|
||||
$sql .= 'SQL_NO_CACHE ';
|
||||
elseif ($options['CACHE'] || $options['SQL_CACHE'])
|
||||
$sql .= 'SQL_CACHE ';
|
||||
$sql .= "$fields FROM $tables WHERE $where";
|
||||
if ($g = $options['GROUP BY'])
|
||||
{
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (is_numeric($k))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " GROUP BY $g";
|
||||
}
|
||||
if ($g = $options['ORDER BY'])
|
||||
{
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (is_numeric($k))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " ORDER BY $g";
|
||||
}
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
if ($options['FOR UPDATE'])
|
||||
$sql .= ' FOR UPDATE';
|
||||
elseif ($options['LOCK IN SHARE MODE'])
|
||||
$sql .= ' LOCK IN SHARE MODE';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function mysql_tables_builder($tables)
|
||||
{
|
||||
global $cfgTables;
|
||||
if (is_array($tables))
|
||||
{
|
||||
$t = '';
|
||||
foreach ($tables as $k => $v)
|
||||
{
|
||||
if (!is_numeric($k))
|
||||
{
|
||||
if (is_array($v))
|
||||
{
|
||||
$join = substr(strtolower($v[0]), 0, 4);
|
||||
if ($join == 'righ')
|
||||
$join = 'RIGHT';
|
||||
elseif ($join == 'left')
|
||||
$join = 'LEFT';
|
||||
else /* if (!$join || $join == 'inne' || $join == 'join') */
|
||||
$join = 'INNER';
|
||||
if (is_array($v[1])) // nested join (left join (A join B on ...) on ...)
|
||||
$table = '('.mysql_tables_builder($v[1]).')';
|
||||
else
|
||||
$table = ($cfgTables[$v[1]] ? '`'.$cfgTables[$v[1]].'`' : $v[1]) . ' ' . $k;
|
||||
if ($t)
|
||||
$t .= " $join JOIN $table ON ".mysql_where_builder($v[2]);
|
||||
else
|
||||
$t = $table;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
$v = ($cfgTables[$v] ? '`'.$cfgTables[$v].'`' : $v) . ' ' . $k;
|
||||
}
|
||||
else
|
||||
$v = ($cfgTables[$v] ? '`'.$cfgTables[$v].'` '.$v : $v);
|
||||
if ($t)
|
||||
$t .= " INNER JOIN $v";
|
||||
else
|
||||
$t = $v;
|
||||
}
|
||||
$tables = $t;
|
||||
}
|
||||
else
|
||||
$tables = preg_replace_callback('/((?:,|JOIN)\s*`)([^`]+)/s', 'mysql_tables_builder_pregcb1', $tables);
|
||||
return $tables;
|
||||
}
|
||||
|
||||
function mysql_tables_builder_pregcb1($m)
|
||||
{
|
||||
global $cfgTables;
|
||||
$t = $cfgTables[$m[2]];
|
||||
if (!$t)
|
||||
$t = $m[2];
|
||||
return $m[1].$t;
|
||||
}
|
||||
|
||||
function mysql_select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0)
|
||||
{
|
||||
if (!strcmp(intval($fields), "$fields"))
|
||||
{
|
||||
$sql = $tables;
|
||||
$format = $fields;
|
||||
}
|
||||
else
|
||||
$sql = mysql_select_builder($tables, $fields, $where, $options);
|
||||
if ($format & MS_RESULT)
|
||||
return amysql_query($sql);
|
||||
if ($format & MS_LIST)
|
||||
$r = mysql_get_rows($sql);
|
||||
else
|
||||
$r = mysql_get_assocs($sql);
|
||||
if (!$r)
|
||||
$r = array();
|
||||
if ($format & MS_ROW)
|
||||
{
|
||||
if ($format & MS_COL)
|
||||
{
|
||||
if (!count($r))
|
||||
return NULL;
|
||||
$r = $r[0];
|
||||
$k = array_keys($r);
|
||||
$r = $r[$k[0]];
|
||||
}
|
||||
else
|
||||
$r = $r[0];
|
||||
}
|
||||
elseif ($format & MS_COL)
|
||||
{
|
||||
foreach ($r as $i => $v)
|
||||
{
|
||||
if (!$k)
|
||||
{
|
||||
$k = array_keys($v);
|
||||
$k = $k[0];
|
||||
}
|
||||
$r[$i] = $v[$k];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function mysql_found_rows()
|
||||
{
|
||||
return mysql_select('SELECT FOUND_ROWS()', MS_VALUE);
|
||||
}
|
||||
|
||||
function mysql_delete($tables, $where, $options = NULL)
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
$tables = mysql_tables_builder($tables);
|
||||
$where = mysql_where_builder($where);
|
||||
$sql = "DELETE FROM $tables WHERE $where";
|
||||
if (is_array($options))
|
||||
{
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
}
|
||||
amysql_query($sql);
|
||||
return mysql_affected_rows($mysql_primary_link);
|
||||
}
|
||||
|
||||
function mysql_insert_builder($table, $rows, $onduplicatekey = false)
|
||||
{
|
||||
global $cfgTables;
|
||||
if ($cfgTables[$table])
|
||||
$table = $cfgTables[$table];
|
||||
$key = array_keys($rows[0]);
|
||||
foreach ($rows as &$r)
|
||||
{
|
||||
$rs = array();
|
||||
foreach ($key as &$k)
|
||||
$rs[] = mysql_ecranize($r[$k]);
|
||||
$r = "(".implode(",", $rs).")";
|
||||
}
|
||||
foreach ($key as &$k)
|
||||
if (strpos($k, '`') === false)
|
||||
$k = "`$k`";
|
||||
$sql = "INSERT INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows);
|
||||
if ($onduplicatekey)
|
||||
{
|
||||
foreach ($key as &$k)
|
||||
$k = "$k=VALUES($k)";
|
||||
$sql .= " ON DUPLICATE KEY UPDATE ".implode(",",$key);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function mysql_insert_row($table, $row)
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
$sql = mysql_insert_builder($table, array($row));
|
||||
if (amysql_query($sql))
|
||||
return mysql_insert_id($mysql_primary_link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function mysql_update($table, $rows, $where = NULL, $options = NULL)
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
if (!$rows)
|
||||
return false;
|
||||
if (is_null($where))
|
||||
{
|
||||
if (!is_array($rows))
|
||||
return false;
|
||||
if (!is_array($rows[0]))
|
||||
$rows = array($rows);
|
||||
$sql = mysql_insert_builder($table, $rows, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = array();
|
||||
if (!is_array($rows))
|
||||
$rows = array($rows);
|
||||
foreach ($rows as $k => $v)
|
||||
{
|
||||
if (!is_intval($k))
|
||||
$sql[] = $k.'='.mysql_ecranize($v);
|
||||
else
|
||||
$sql[] = $v;
|
||||
}
|
||||
$where = mysql_where_builder($where);
|
||||
$sql = 'UPDATE ' . mysql_tables_builder($table) . ' SET ' . implode(', ', $sql) . ' WHERE ' . $where;
|
||||
if (is_array($options))
|
||||
{
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (amysql_query($sql))
|
||||
return mysql_affected_rows($mysql_primary_link);
|
||||
return false;
|
||||
}
|
||||
|
||||
function mysql_get_rows($sql)
|
||||
{
|
||||
$r = array();
|
||||
if (is_resource($res = $sql) || ($res = amysql_query ($sql)))
|
||||
while ($row = mysql_fetch_row ($res))
|
||||
$r[] = $row;
|
||||
return $r;
|
||||
}
|
||||
|
||||
function mysql_get_assocs($sql)
|
||||
{
|
||||
$r = array();
|
||||
if (is_resource($res = $sql) || ($res = amysql_query ($sql)))
|
||||
while ($row = mysql_fetch_assoc ($res))
|
||||
$r[] = $row;
|
||||
return $r;
|
||||
}
|
||||
|
||||
function load_config()
|
||||
{
|
||||
global $engine_configuration, $mysqlNoSiteConfig;
|
||||
if ($mysqlNoSiteConfig)
|
||||
return;
|
||||
$engine_configuration = array();
|
||||
if ($rows = mysql_select('config', array('name', 'value'), 1, array(), MS_LIST))
|
||||
foreach ($rows as $row)
|
||||
$engine_configuration[$row[0]] = $row[1];
|
||||
}
|
||||
|
||||
function config_var($name, $default = NULL)
|
||||
{
|
||||
global $engine_configuration;
|
||||
if (!$engine_configuration)
|
||||
load_config();
|
||||
$v = @$engine_configuration[$name];
|
||||
if (!is_null($default) && !strlen($v) || is_intval($default) && $v <= 0)
|
||||
$v = $default;
|
||||
elseif (is_intval($default))
|
||||
$v = intval($v);
|
||||
return $v;
|
||||
}
|
||||
|
||||
function mysql_finish()
|
||||
{
|
||||
global $mysql_primary_link;
|
||||
if (mysql_started())
|
||||
mysql_close($mysql_primary_link);
|
||||
$mysql_primary_link = NULL;
|
||||
}
|
2892
lib/template.php
2892
lib/template.php
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,6 @@
|
|||
|
||||
require_once 'config.php';
|
||||
require_once 'template.php';
|
||||
require_once 'mysql.php';
|
||||
|
||||
if (!defined('LIGHTWEIGHT'))
|
||||
{
|
||||
|
@ -17,10 +16,11 @@ if (!defined('LIGHTWEIGHT'))
|
|||
$tpl = config_var('template');
|
||||
if ($tpl == '')
|
||||
$tpl = 'default';
|
||||
$template = new Template (array(
|
||||
$template = new VMXTemplate (array(
|
||||
'root' => $local_path . $template_path . $tpl,
|
||||
'cache_dir' => $local_path . $cache_path,
|
||||
'print_error' => 1,
|
||||
'strip_space' => true,
|
||||
));
|
||||
$template->vars(array(
|
||||
'DOMAIN' => "http://$Domain",
|
||||
|
|
103
olap.php
103
olap.php
|
@ -10,6 +10,7 @@ require_once 'lib/templating.php';
|
|||
|
||||
require_once 'olap_config.php';
|
||||
|
||||
$modified = false;
|
||||
foreach ($_REQUEST as $k => $v)
|
||||
{
|
||||
if ($v === "")
|
||||
|
@ -35,6 +36,18 @@ class OLAP
|
|||
{
|
||||
static $initialised;
|
||||
static $sources;
|
||||
static $mwTimestampSql = array(
|
||||
'year' => 'SUBSTR($,1,4)',
|
||||
'ym' => 'CONCAT(SUBSTR($,1,4),"-",SUBSTR($,5,2))',
|
||||
'month' => 'SUBSTR($,5,2)',
|
||||
'ymd' => 'CONCAT(SUBSTR($,1,4),"-",SUBSTR($,5,2),"-",SUBSTR($,7,2))',
|
||||
'day' => 'SUBSTR($,7,2)',
|
||||
'weekday' => 'WEEKDAY(CONCAT(SUBSTR($,1,4),"-",SUBSTR($,5,2),"-",SUBSTR($,7,2)))',
|
||||
'week' => 'WEEK(CONCAT(SUBSTR($,1,4),"-",SUBSTR($,5,2),"-",SUBSTR($,7,2)))',
|
||||
'hour' => 'SUBSTR($,9,2)',
|
||||
'minute' => 'SUBSTR($,11,2)',
|
||||
'second' => 'SUBSTR($,13,2)',
|
||||
);
|
||||
static $functions = array(
|
||||
'year' => array('name' => 'Год', 'time_format' => 'Y', 'sql' => 'SUBSTR($,1,4)'),
|
||||
'ym' => array('name' => 'Год-месяц', 'time_format' => 'Y-m', 'sql' => 'SUBSTR($,1,7)'),
|
||||
|
@ -94,6 +107,7 @@ class OLAP
|
|||
if (empty($s['where']))
|
||||
$s['where'] = array();
|
||||
}
|
||||
$i = 0;
|
||||
foreach (self::$group_types as $k => $v)
|
||||
self::$group_types[$k] = array('id' => $k, 'num' => $i++, 'name' => $v);
|
||||
foreach (self::$functions as $k => &$v)
|
||||
|
@ -103,22 +117,28 @@ class OLAP
|
|||
self::$initialised = true;
|
||||
}
|
||||
|
||||
function mysql()
|
||||
{
|
||||
static $mysql;
|
||||
if (!$mysql)
|
||||
{
|
||||
global $db;
|
||||
$mysql = new DatabaseMysql(!empty($this->current_src['db']) ? $this->current_src['db'] : $db);
|
||||
}
|
||||
return $mysql;
|
||||
}
|
||||
|
||||
function parse_request()
|
||||
{
|
||||
$request = &$this->request;
|
||||
|
||||
// выбираем источник данных
|
||||
$this->current_srcid = $request['datasource'];
|
||||
$this->current_src = self::$sources[$this->current_srcid];
|
||||
$this->current_srcid = @$request['datasource'];
|
||||
$this->current_src = @self::$sources[$this->current_srcid];
|
||||
if (!$this->current_src)
|
||||
return;
|
||||
|
||||
// задаём параметры соединения с БД из источника
|
||||
global $db, $dbhost, $dbuser, $dbpwd;
|
||||
if (!empty($this->current_src['db']))
|
||||
list($db, $dbhost, $dbuser, $dbpwd) = $this->current_src['db'];
|
||||
|
||||
// Дополняем всяким бредом всякий бред
|
||||
// дополняем всяким бредом всякий бред
|
||||
foreach ($this->current_src['fielddescs'] as $k => &$v)
|
||||
{
|
||||
$v['id'] = $k;
|
||||
|
@ -127,7 +147,7 @@ class OLAP
|
|||
$f = $v['sql'];
|
||||
if (!$f)
|
||||
$f = $k;
|
||||
$v['options'] = mysql_select(
|
||||
$v['options'] = $this->mysql()->select(
|
||||
$this->current_src['tables'],
|
||||
"$f id, $f name",
|
||||
$this->current_src['where'],
|
||||
|
@ -148,7 +168,7 @@ class OLAP
|
|||
$this->where = array();
|
||||
$this->where_nosql = array();
|
||||
$this->group_fields = array();
|
||||
if ($request['graph_log'])
|
||||
if (!empty($request['graph_log']))
|
||||
{
|
||||
$this->graph_logarithmic = true;
|
||||
$this->request['graph_log'] = 1;
|
||||
|
@ -179,7 +199,7 @@ class OLAP
|
|||
if (empty($fd['nosql']))
|
||||
{
|
||||
$dn = !empty($fd['sql']) ? $fd['sql'] : $f;
|
||||
$ve = mysql_ecranize($v);
|
||||
$ve = $this->mysql()->quote($v);
|
||||
if ($t == 'eq')
|
||||
{
|
||||
if ($fd['sql_eq'])
|
||||
|
@ -199,8 +219,8 @@ class OLAP
|
|||
$i = substr($k, 11);
|
||||
$gf = array();
|
||||
foreach(array('type', 'field', 'func', 'sort_dir', 'sort_field', 'sort_aggr', 'sort_func') as $k)
|
||||
$gf[$k] = $request["group-$k-$i"];
|
||||
if ($request['csv'] && $gf['type'] == 'graph')
|
||||
$gf[$k] = @$request["group-$k-$i"];
|
||||
if (!empty($request['csv']) && $gf['type'] == 'graph')
|
||||
$gf['type'] = 'tr';
|
||||
if (self::$group_types[$gf['type']] && $gf['field'] !== '')
|
||||
{
|
||||
|
@ -213,7 +233,7 @@ class OLAP
|
|||
usort($this->group_fields, 'OLAP::group_type_cmp');
|
||||
|
||||
// Число мест под поля группировки
|
||||
$this->nfields = intval($request['field_count']);
|
||||
$this->nfields = intval(@$request['field_count']);
|
||||
if ($this->nfields <= 0)
|
||||
$this->nfields = 5;
|
||||
if (count($this->group_fields) > $this->nfields)
|
||||
|
@ -221,10 +241,10 @@ class OLAP
|
|||
|
||||
// Описание показателя
|
||||
foreach(array('field', 'func', 'aggr') as $x)
|
||||
$this->cell[$x] = $request["cell_$x"];
|
||||
$this->cell['field_name'] = $this->current_src['fielddescs'][$this->cell['field']]['name'];
|
||||
$this->cell['func_name'] = self::$functions[$this->cell['func']]['name'];
|
||||
$this->cell['aggr_name'] = self::$aggregates[$this->cell['aggr']]['name'];
|
||||
$this->cell[$x] = @$request["cell_$x"];
|
||||
$this->cell['field_name'] = isset($this->cell['field']) ? $this->current_src['fielddescs'][$this->cell['field']]['name'] : NULL;
|
||||
$this->cell['func_name'] = isset($this->cell['func']) ? self::$functions[$this->cell['func']]['name'] : NULL;
|
||||
$this->cell['aggr_name'] = isset($this->cell['aggr']) ? self::$aggregates[$this->cell['aggr']]['name'] : NULL;
|
||||
$this->cell['value_desc'] = $this->cell['field_name'];
|
||||
if ($this->cell['func_name'])
|
||||
$this->cell['value_desc'] = $this->cell['func_name'].'('.$this->cell['value_desc'].')';
|
||||
|
@ -269,7 +289,7 @@ class OLAP
|
|||
'field_count' => $this->nfields,
|
||||
'srcid' => $this->current_srcid,
|
||||
'src' => $this->current_src,
|
||||
'fielddescs' => $this->current_src['fielddescs'],
|
||||
'fielddescs' => array_values($this->current_src['fielddescs']),
|
||||
'group_types' => array_values(self::$group_types),
|
||||
'functions' => array_values(self::$functions),
|
||||
'aggregates' => array_values(self::$aggregates),
|
||||
|
@ -379,7 +399,7 @@ class OLAP
|
|||
$sql = $this->sql_trans_field($field, $func);
|
||||
$fields[] = str_replace('$', $sql, self::$aggregates[$aggr]['sql']).' c';
|
||||
|
||||
$code = 'while($r = mysql_fetch_assoc($result)) { ';
|
||||
$code = 'while($r = $result->fetch_assoc()) { ';
|
||||
foreach ($output as $k => $o)
|
||||
{
|
||||
$asgn = '$output['.intval($k).'][\'output\']';
|
||||
|
@ -389,7 +409,7 @@ class OLAP
|
|||
}
|
||||
$code .= '}';
|
||||
|
||||
$result = mysql_select(
|
||||
$result = $this->mysql()->select(
|
||||
$this->current_src['tables'], $fields,
|
||||
array_merge($this->current_src['where'], $this->where),
|
||||
array('GROUP BY' => $group_by),
|
||||
|
@ -433,12 +453,12 @@ class OLAP
|
|||
// Важно, что функция потоковая, чтобы память не хавала
|
||||
// В начале и конце дёргается с NULL'ом вместо строки:
|
||||
// В начале типа "конструктора", в конце типа "выплюнуть запомненное"
|
||||
$code = $call.'(NULL, $this); while($row = mysql_fetch_assoc($result)) { foreach('.
|
||||
$code = $call.'(NULL, $this); while($row = $result->fetch_assoc()) { foreach('.
|
||||
$call.'($row, $this) as $r) { '.$code.'} } '.
|
||||
'foreach('.$call.'(NULL, $this) as $r) { '.$code.'}';
|
||||
}
|
||||
else
|
||||
$code = 'while($r = mysql_fetch_assoc($result)) { ' . $code . '}';
|
||||
$code = 'while($r = $result->fetch_assoc()) { ' . $code . '}';
|
||||
|
||||
// "Завершение" вычисления агрегата
|
||||
if (is_callable('self::aggr_finish_'.$aggr))
|
||||
|
@ -485,7 +505,7 @@ class OLAP
|
|||
else
|
||||
{
|
||||
// SQL
|
||||
$result = mysql_select(
|
||||
$result = $this->mysql()->select(
|
||||
$this->current_src['tables'], $fields,
|
||||
array_merge($this->current_src['where'], $this->where),
|
||||
$this->current_src['sql_options'],
|
||||
|
@ -574,7 +594,7 @@ class OLAP
|
|||
// Масштабируем график до целых чисел с точностью $this->graph_scale
|
||||
if ($gr['max'] > $gr['min'])
|
||||
{
|
||||
if ($gr['bi_sign'])
|
||||
if (!empty($gr['bi_sign']))
|
||||
{
|
||||
foreach ($gr['data'] as &$d)
|
||||
{
|
||||
|
@ -843,9 +863,14 @@ class OLAP
|
|||
$field = '1';
|
||||
$fd = &$this->current_src['fielddescs'][$field];
|
||||
$c = "\$r['$field']";
|
||||
if (!empty($fd['is_time']) && $fd['format'] == Template::TS_UNIX &&
|
||||
(!self::$functions[$func] || self::$functions[$func]['time_format']))
|
||||
$c = "date('Y-m-d',$c)";
|
||||
if (!empty($fd['is_time']) &&
|
||||
!self::$functions[$func] || self::$functions[$func]['time_format'])
|
||||
{
|
||||
if ($fd['format'] == VMXTemplate::TS_UNIX)
|
||||
$c = "date('Y-m-d', $c)";
|
||||
elseif ($fd['format'] == VMXTemplate::TS_MW)
|
||||
$c = "VMXTemplate::timestamp($c, VMXTemplate::TS_DB)";
|
||||
}
|
||||
if ($func)
|
||||
$c = "self::fn_$func($c)";
|
||||
return $c;
|
||||
|
@ -859,13 +884,22 @@ class OLAP
|
|||
else
|
||||
{
|
||||
$sql = $field;
|
||||
if ($fd['sql'])
|
||||
if (isset($fd['sql']))
|
||||
$sql = $fd['sql'];
|
||||
}
|
||||
if ($fd['is_time'] && $fd['format'] == TS_UNIX &&
|
||||
(!self::$functions[$func] || self::$functions[$func]['time_format']))
|
||||
$sql = "FROM_UNIXTIME($sql)";
|
||||
if (self::$functions[$func])
|
||||
if (!empty($fd['is_time']) &&
|
||||
empty(self::$functions[$func]) || self::$functions[$func]['time_format'])
|
||||
{
|
||||
if ($fd['format'] == VMXTemplate::TS_UNIX)
|
||||
$sql = "FROM_UNIXTIME($sql)";
|
||||
elseif ($fd['format'] == VMXTemplate::TS_MW)
|
||||
{
|
||||
if (isset(self::$mwTimestampSql[$func]))
|
||||
$sql = str_replace('$', $sql, self::$mwTimestampSql[$func]);
|
||||
$func = NULL;
|
||||
}
|
||||
}
|
||||
if (isset(self::$functions[$func]))
|
||||
$sql = str_replace('$', $sql, self::$functions[$func]['sql']);
|
||||
return $sql;
|
||||
}
|
||||
|
@ -880,7 +914,7 @@ class OLAP
|
|||
$value = number_format($value, self::$decimal[0], self::$decimal[1], self::$decimal[2]);
|
||||
return $value;
|
||||
}
|
||||
elseif (($proc = $this->current_src['fielddescs'][$field]['format_func']) &&
|
||||
elseif (($proc = @$this->current_src['fielddescs'][$field]['format_func']) &&
|
||||
is_callable($proc))
|
||||
{
|
||||
return $proc($value, $this->is_html_format);
|
||||
|
@ -1016,6 +1050,7 @@ class OLAP
|
|||
function tpl_jsgraphs($graphs)
|
||||
{
|
||||
$groups = array();
|
||||
$group = false;
|
||||
foreach ($graphs as $i => $graph)
|
||||
{
|
||||
$min_ne = count($graph['desc']);
|
||||
|
|
|
@ -6,6 +6,21 @@ function v2tags_get_tags()
|
|||
}
|
||||
|
||||
OLAP::$sources = array(
|
||||
'mediawiki_history' => array(
|
||||
'id' => 'mediawiki_history',
|
||||
'name' => 'Ревизии MediaWiki',
|
||||
'tables' => array('r' => 'revision'),
|
||||
'fields' => 't.rev_timestamp',
|
||||
'where' => array(),
|
||||
'fielddescs' => array(
|
||||
'rev_timestamp' => array(
|
||||
'name' => 'Время',
|
||||
'le_ge' => true,
|
||||
'is_time' => true,
|
||||
'format' => TS_MW,
|
||||
),
|
||||
),
|
||||
),
|
||||
'v2tags' => array(
|
||||
'id' => 'v2tags',
|
||||
'name' => 'VitaphotoV2, статистика по тегам',
|
||||
|
|
|
@ -5,6 +5,6 @@ AjexFileManager.init({
|
|||
});
|
||||
</script>-->
|
||||
</div>
|
||||
<p id="admpoweredby" style="color: #d0d0d0; margin: 20px 0 0 20px">Powered by VitaliF, 2010</p>
|
||||
<p id="admpoweredby" style="color: #d0d0d0; margin: 20px 0 0 20px">Powered by VitaliF, 2010-2013</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>{title/s}</title>
|
||||
<title>{s title}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
{METAS}
|
||||
<style>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<script language="javascript" type="text/javascript" src="{DOMAIN}/tpldata/jqplot.logAxisRenderer.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{DOMAIN}/tpldata/jquery.jqplot.css" />
|
||||
<!-- END -->
|
||||
<!-- INCLUDE admin_header.tpl -->
|
||||
<!-- INCLUDE "admin_header.tpl" -->
|
||||
<!-- IF NOT srcid -->
|
||||
<p>Добро пожаловать в простую OLAPообразную статистику. Выберите источник данных:</p>
|
||||
<form action="?" method="GET">
|
||||
|
@ -36,7 +36,7 @@
|
|||
<!-- FOR f = aggregates -->
|
||||
<option value="{s f.id}"<!-- IF eq(cell.aggr, f.id) --> selected="selected"<!-- END -->>{s f.name}</option>
|
||||
<!-- END -->
|
||||
</select>
|
||||
</select>
|
||||
<select style="width:100px" name="cell_field">
|
||||
<option value="">---</option>
|
||||
<!-- FOR f = fielddescs -->
|
||||
|
@ -61,7 +61,7 @@
|
|||
<option value="{g.id}"<!-- IF eq(gf.type,g.id) --> selected="selected" <!-- END -->>{s g.name}</option>
|
||||
<!-- END -->
|
||||
</select>
|
||||
<!-- INCLUDE admin_olap_field.tpl -->
|
||||
<!-- INCLUDE "admin_olap_field.tpl" -->
|
||||
</p>
|
||||
<p><select style="width:100px" name="group-sort_dir-{fld}">
|
||||
<option value="asc">По возрастанию</option>
|
||||
|
@ -75,7 +75,7 @@
|
|||
<!-- END -->
|
||||
<!-- END -->
|
||||
</select>
|
||||
<!-- SET ft = 'sort_' --><!-- INCLUDE admin_olap_field.tpl --><!-- SET ft = '' -->
|
||||
<!-- SET ft = 'sort_' --><!-- INCLUDE "admin_olap_field.tpl" --><!-- SET ft = '' -->
|
||||
</p>
|
||||
</li>
|
||||
<!-- END -->
|
||||
|
@ -122,11 +122,11 @@
|
|||
<p>Отчёт занял {time_elapsed} сек. Использовано {memory} памяти для работы.</p>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
<!-- INCLUDE admin_footer.tpl -->
|
||||
<!-- INCLUDE "admin_footer.tpl" -->
|
||||
|
||||
<!-- FUNCTION block_groups -->
|
||||
<!-- FOR group = groups -->
|
||||
<div style="width: 900px; height: 400px; margin-top: 20px" id="group{group#}"></div>
|
||||
<div style="width: 900px; height: 400px; margin-top: 20px" id="group{group_index}"></div>
|
||||
<!-- END -->
|
||||
<p>
|
||||
<input type="checkbox" name="graph_log" id="graph_log" value="1"
|
||||
|
@ -135,24 +135,24 @@
|
|||
</p>
|
||||
<script language="javascript" type="text/javascript">
|
||||
var g = [
|
||||
<!-- FOR group = groups -->{yesno(group#,',','')}
|
||||
<!-- FOR group = groups -->{yesno(group_index,',','')}
|
||||
{
|
||||
id: "group{group#}",
|
||||
id: "group{group_index}",
|
||||
desc: "{q join(', ',group.full_desc)}",
|
||||
numeric: {yesno(group.numeric,'true','false')},
|
||||
data: [
|
||||
<!-- FOR graph = group.graphs -->{yesno(graph#,',','')}
|
||||
<!-- FOR graph = group.graphs -->{yesno(graph_index,',','')}
|
||||
[
|
||||
<!-- FOR g = graph.data -->
|
||||
[ {yesno(group.numeric,g.0,concat("'",q(g.0),"'"))}, {g.1} ],
|
||||
[ {yesno(group.numeric,g[0],concat("'",q(g[0]),"'"))}, {g[1]} ],
|
||||
<!-- END -->
|
||||
]
|
||||
<!-- END -->
|
||||
],
|
||||
x: "{q group.graphs.0.field}<!-- IF group.graphs.0.func --> ({q group.graphs.0.func})<!-- END -->",
|
||||
x: "{q group.graphs[0].field}<!-- IF group.graphs[0].func --> ({q group.graphs[0].func})<!-- END -->",
|
||||
dateAxis: '{group.date_axis}',
|
||||
titles: [
|
||||
<!-- FOR graph = group.graphs -->{yesno(graph#,',','')}
|
||||
<!-- FOR graph = group.graphs -->{yesno(graph_index,',','')}
|
||||
'{q graph.last_desc}'
|
||||
<!-- END -->
|
||||
]
|
||||
|
@ -236,9 +236,9 @@ function doPlot(logarithmic)
|
|||
<!-- SET o = 0 -->
|
||||
<!-- FOR d = graph.desc -->
|
||||
<!--# Описание графика (поле: значение, ..., только значения, не равные значениям предыдущего графика) -->
|
||||
<!-- SET o = or(o, not(graph#), ne(get(get(get(get(graphs,sub(graph#,1)),'desc'),d#),'value'),d.value)) -->
|
||||
<!-- SET o = or(o, not(graph_index), ne(get(get(get(get(graphs,sub(graph_index,1)),'desc'),d_index),'value'),d.value)) -->
|
||||
<!-- IF o -->
|
||||
<p style="margin-left: {mul(d#,20)}px">{d.field}<!-- IF d.func --> ({lc d.func})<!-- END -->: {d.value}</p>
|
||||
<p style="margin-left: {mul(d_index,20)}px">{d.field}<!-- IF d.func --> ({lc d.func})<!-- END -->: {d.value}</p>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
<div style="margin-left: {mul(count(graph.desc),20)}px">
|
||||
|
@ -248,15 +248,15 @@ function doPlot(logarithmic)
|
|||
<tr><th colspan="4">- {graph.field}<!-- IF graph.func --> ({lc graph.func})<!-- END --> +</th></tr>
|
||||
<!-- FOR g = graph.data -->
|
||||
<tr>
|
||||
<td><div style="float: right; background: red; height: 7px; width: {g.3}px"></div></td>
|
||||
<td>{s g.0}: </td><td>{s g.1}</td>
|
||||
<td><div style="background: blue; height: 7px; width: {g.2}px"></div></td>
|
||||
<td><div style="float: right; background: red; height: 7px; width: {g[3]}px"></div></td>
|
||||
<td>{s g[0]}: </td><td>{s g[1]}</td>
|
||||
<td><div style="background: blue; height: 7px; width: {g[2]}px"></div></td>
|
||||
</tr>
|
||||
<!-- END -->
|
||||
<!-- ELSE -->
|
||||
<tr><th style="text-align: left" colspan="2">{graph.field}<!-- IF graph.func --> ({lc graph.func})<!-- END --></th></tr>
|
||||
<!-- FOR g = graph.data -->
|
||||
<tr><td>{s g.0}: </td><td>{s g.1}</td><td><div style="background: blue; height: 7px; width: {g.2}px"></div></td></tr>
|
||||
<tr><td>{s g[0]}: </td><td>{s g[1]}</td><td><div style="background: blue; height: 7px; width: {g[2]}px"></div></td></tr>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
</table>
|
||||
|
@ -271,9 +271,9 @@ function doPlot(logarithmic)
|
|||
<!-- IF table.desc -->
|
||||
<!-- SET o = 0 -->
|
||||
<!-- FOR d = table.desc -->
|
||||
<!-- SET o = or(o, not(table#), ne(get(get(get(get(tables,sub(table#,1)),'desc'),d#),'value'),d.value)) -->
|
||||
<!-- SET o = or(o, not(table_index), ne(get(get(get(get(tables,sub(table_index,1)),'desc'),d_index),'value'),d.value)) -->
|
||||
<!-- IF o -->
|
||||
<p style="margin-left: {mul(d#,20)}px">{d.field}<!-- IF d.func --> ({lc d.func})<!-- END -->: {d.value}</p>
|
||||
<p style="margin-left: {mul(d_index,20)}px">{d.field}<!-- IF d.func --> ({lc d.func})<!-- END -->: {d.value}</p>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
<div style="margin-left: {mul(count(table.desc),20)}px">
|
||||
|
|
Loading…
Reference in New Issue